PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/load.php

http://github.com/markjaquith/WordPress
PHP | 1560 lines | 709 code | 176 blank | 675 comment | 178 complexity | da93e499eaf111eeed030108adb39171 MD5 | raw file
Possible License(s): 0BSD
  1. <?php
  2. /**
  3. * These functions are needed to load WordPress.
  4. *
  5. * @package WordPress
  6. */
  7. /**
  8. * Return the HTTP protocol sent by the server.
  9. *
  10. * @since 4.4.0
  11. *
  12. * @return string The HTTP protocol. Default: HTTP/1.0.
  13. */
  14. function wp_get_server_protocol() {
  15. $protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : '';
  16. if ( ! in_array( $protocol, array( 'HTTP/1.1', 'HTTP/2', 'HTTP/2.0' ), true ) ) {
  17. $protocol = 'HTTP/1.0';
  18. }
  19. return $protocol;
  20. }
  21. /**
  22. * Fix `$_SERVER` variables for various setups.
  23. *
  24. * @since 3.0.0
  25. * @access private
  26. *
  27. * @global string $PHP_SELF The filename of the currently executing script,
  28. * relative to the document root.
  29. */
  30. function wp_fix_server_vars() {
  31. global $PHP_SELF;
  32. $default_server_values = array(
  33. 'SERVER_SOFTWARE' => '',
  34. 'REQUEST_URI' => '',
  35. );
  36. $_SERVER = array_merge( $default_server_values, $_SERVER );
  37. // Fix for IIS when running with PHP ISAPI.
  38. if ( empty( $_SERVER['REQUEST_URI'] ) || ( PHP_SAPI != 'cgi-fcgi' && preg_match( '/^Microsoft-IIS\//', $_SERVER['SERVER_SOFTWARE'] ) ) ) {
  39. if ( isset( $_SERVER['HTTP_X_ORIGINAL_URL'] ) ) {
  40. // IIS Mod-Rewrite.
  41. $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
  42. } elseif ( isset( $_SERVER['HTTP_X_REWRITE_URL'] ) ) {
  43. // IIS Isapi_Rewrite.
  44. $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
  45. } else {
  46. // Use ORIG_PATH_INFO if there is no PATH_INFO.
  47. if ( ! isset( $_SERVER['PATH_INFO'] ) && isset( $_SERVER['ORIG_PATH_INFO'] ) ) {
  48. $_SERVER['PATH_INFO'] = $_SERVER['ORIG_PATH_INFO'];
  49. }
  50. // Some IIS + PHP configurations put the script-name in the path-info (no need to append it twice).
  51. if ( isset( $_SERVER['PATH_INFO'] ) ) {
  52. if ( $_SERVER['PATH_INFO'] == $_SERVER['SCRIPT_NAME'] ) {
  53. $_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO'];
  54. } else {
  55. $_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'] . $_SERVER['PATH_INFO'];
  56. }
  57. }
  58. // Append the query string if it exists and isn't null.
  59. if ( ! empty( $_SERVER['QUERY_STRING'] ) ) {
  60. $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
  61. }
  62. }
  63. }
  64. // Fix for PHP as CGI hosts that set SCRIPT_FILENAME to something ending in php.cgi for all requests.
  65. if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && ( strpos( $_SERVER['SCRIPT_FILENAME'], 'php.cgi' ) == strlen( $_SERVER['SCRIPT_FILENAME'] ) - 7 ) ) {
  66. $_SERVER['SCRIPT_FILENAME'] = $_SERVER['PATH_TRANSLATED'];
  67. }
  68. // Fix for Dreamhost and other PHP as CGI hosts.
  69. if ( strpos( $_SERVER['SCRIPT_NAME'], 'php.cgi' ) !== false ) {
  70. unset( $_SERVER['PATH_INFO'] );
  71. }
  72. // Fix empty PHP_SELF.
  73. $PHP_SELF = $_SERVER['PHP_SELF'];
  74. if ( empty( $PHP_SELF ) ) {
  75. $_SERVER['PHP_SELF'] = preg_replace( '/(\?.*)?$/', '', $_SERVER['REQUEST_URI'] );
  76. $PHP_SELF = $_SERVER['PHP_SELF'];
  77. }
  78. }
  79. /**
  80. * Check for the required PHP version, and the MySQL extension or
  81. * a database drop-in.
  82. *
  83. * Dies if requirements are not met.
  84. *
  85. * @since 3.0.0
  86. * @access private
  87. *
  88. * @global string $required_php_version The required PHP version string.
  89. * @global string $wp_version The WordPress version string.
  90. */
  91. function wp_check_php_mysql_versions() {
  92. global $required_php_version, $wp_version;
  93. $php_version = phpversion();
  94. if ( version_compare( $required_php_version, $php_version, '>' ) ) {
  95. $protocol = wp_get_server_protocol();
  96. header( sprintf( '%s 500 Internal Server Error', $protocol ), true, 500 );
  97. header( 'Content-Type: text/html; charset=utf-8' );
  98. printf( 'Your server is running PHP version %1$s but WordPress %2$s requires at least %3$s.', $php_version, $wp_version, $required_php_version );
  99. exit( 1 );
  100. }
  101. if ( ! extension_loaded( 'mysql' ) && ! extension_loaded( 'mysqli' ) && ! extension_loaded( 'mysqlnd' ) && ! file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
  102. require_once ABSPATH . WPINC . '/functions.php';
  103. wp_load_translations_early();
  104. $args = array(
  105. 'exit' => false,
  106. 'code' => 'mysql_not_found',
  107. );
  108. wp_die(
  109. __( 'Your PHP installation appears to be missing the MySQL extension which is required by WordPress.' ),
  110. __( 'Requirements Not Met' ),
  111. $args
  112. );
  113. exit( 1 );
  114. }
  115. }
  116. /**
  117. * Don't load all of WordPress when handling a favicon.ico request.
  118. *
  119. * Instead, send the headers for a zero-length favicon and bail.
  120. *
  121. * @since 3.0.0
  122. * @deprecated 5.4.0 Deprecated in favor of do_favicon().
  123. */
  124. function wp_favicon_request() {
  125. if ( '/favicon.ico' == $_SERVER['REQUEST_URI'] ) {
  126. header( 'Content-Type: image/vnd.microsoft.icon' );
  127. exit;
  128. }
  129. }
  130. /**
  131. * Die with a maintenance message when conditions are met.
  132. *
  133. * The default message can be replaced by using a drop-in (maintenance.php in
  134. * the wp-content directory).
  135. *
  136. * @since 3.0.0
  137. * @access private
  138. */
  139. function wp_maintenance() {
  140. // Return if maintenance mode is disabled.
  141. if ( ! wp_in_maintenance_mode() ) {
  142. return;
  143. }
  144. if ( file_exists( WP_CONTENT_DIR . '/maintenance.php' ) ) {
  145. require_once WP_CONTENT_DIR . '/maintenance.php';
  146. die();
  147. }
  148. require_once ABSPATH . WPINC . '/functions.php';
  149. wp_load_translations_early();
  150. header( 'Retry-After: 600' );
  151. wp_die(
  152. __( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ),
  153. __( 'Maintenance' ),
  154. 503
  155. );
  156. }
  157. /**
  158. * Check if maintenance mode is enabled.
  159. *
  160. * Checks for a file in the WordPress root directory named ".maintenance".
  161. * This file will contain the variable $upgrading, set to the time the file
  162. * was created. If the file was created less than 10 minutes ago, WordPress
  163. * is in maintenance mode.
  164. *
  165. * @since 5.5.0
  166. *
  167. * @global int $upgrading The Unix timestamp marking when upgrading WordPress began.
  168. *
  169. * @return bool True if maintenance mode is enabled, false otherwise.
  170. */
  171. function wp_in_maintenance_mode() {
  172. global $upgrading;
  173. if ( ! file_exists( ABSPATH . '.maintenance' ) || wp_installing() ) {
  174. return false;
  175. }
  176. require ABSPATH . '.maintenance';
  177. // If the $upgrading timestamp is older than 10 minutes, consider maintenance over.
  178. if ( ( time() - $upgrading ) >= 600 ) {
  179. return false;
  180. }
  181. /**
  182. * Filters whether to enable maintenance mode.
  183. *
  184. * This filter runs before it can be used by plugins. It is designed for
  185. * non-web runtimes. If this filter returns true, maintenance mode will be
  186. * active and the request will end. If false, the request will be allowed to
  187. * continue processing even if maintenance mode should be active.
  188. *
  189. * @since 4.6.0
  190. *
  191. * @param bool $enable_checks Whether to enable maintenance mode. Default true.
  192. * @param int $upgrading The timestamp set in the .maintenance file.
  193. */
  194. if ( ! apply_filters( 'enable_maintenance_mode', true, $upgrading ) ) {
  195. return false;
  196. }
  197. return true;
  198. }
  199. /**
  200. * Start the WordPress micro-timer.
  201. *
  202. * @since 0.71
  203. * @access private
  204. *
  205. * @global float $timestart Unix timestamp set at the beginning of the page load.
  206. * @see timer_stop()
  207. *
  208. * @return bool Always returns true.
  209. */
  210. function timer_start() {
  211. global $timestart;
  212. $timestart = microtime( true );
  213. return true;
  214. }
  215. /**
  216. * Retrieve or display the time from the page start to when function is called.
  217. *
  218. * @since 0.71
  219. *
  220. * @global float $timestart Seconds from when timer_start() is called.
  221. * @global float $timeend Seconds from when function is called.
  222. *
  223. * @param int|bool $display Whether to echo or return the results. Accepts 0|false for return,
  224. * 1|true for echo. Default 0|false.
  225. * @param int $precision The number of digits from the right of the decimal to display.
  226. * Default 3.
  227. * @return string The "second.microsecond" finished time calculation. The number is formatted
  228. * for human consumption, both localized and rounded.
  229. */
  230. function timer_stop( $display = 0, $precision = 3 ) {
  231. global $timestart, $timeend;
  232. $timeend = microtime( true );
  233. $timetotal = $timeend - $timestart;
  234. $r = ( function_exists( 'number_format_i18n' ) ) ? number_format_i18n( $timetotal, $precision ) : number_format( $timetotal, $precision );
  235. if ( $display ) {
  236. echo $r;
  237. }
  238. return $r;
  239. }
  240. /**
  241. * Set PHP error reporting based on WordPress debug settings.
  242. *
  243. * Uses three constants: `WP_DEBUG`, `WP_DEBUG_DISPLAY`, and `WP_DEBUG_LOG`.
  244. * All three can be defined in wp-config.php. By default, `WP_DEBUG` and
  245. * `WP_DEBUG_LOG` are set to false, and `WP_DEBUG_DISPLAY` is set to true.
  246. *
  247. * When `WP_DEBUG` is true, all PHP notices are reported. WordPress will also
  248. * display internal notices: when a deprecated WordPress function, function
  249. * argument, or file is used. Deprecated code may be removed from a later
  250. * version.
  251. *
  252. * It is strongly recommended that plugin and theme developers use `WP_DEBUG`
  253. * in their development environments.
  254. *
  255. * `WP_DEBUG_DISPLAY` and `WP_DEBUG_LOG` perform no function unless `WP_DEBUG`
  256. * is true.
  257. *
  258. * When `WP_DEBUG_DISPLAY` is true, WordPress will force errors to be displayed.
  259. * `WP_DEBUG_DISPLAY` defaults to true. Defining it as null prevents WordPress
  260. * from changing the global configuration setting. Defining `WP_DEBUG_DISPLAY`
  261. * as false will force errors to be hidden.
  262. *
  263. * When `WP_DEBUG_LOG` is true, errors will be logged to `wp-content/debug.log`.
  264. * When `WP_DEBUG_LOG` is a valid path, errors will be logged to the specified file.
  265. *
  266. * Errors are never displayed for XML-RPC, REST, and Ajax requests.
  267. *
  268. * @since 3.0.0
  269. * @since 5.1.0 `WP_DEBUG_LOG` can be a file path.
  270. * @access private
  271. */
  272. function wp_debug_mode() {
  273. /**
  274. * Filters whether to allow the debug mode check to occur.
  275. *
  276. * This filter runs before it can be used by plugins. It is designed for
  277. * non-web run-times. Returning false causes the `WP_DEBUG` and related
  278. * constants to not be checked and the default PHP values for errors
  279. * will be used unless you take care to update them yourself.
  280. *
  281. * @since 4.6.0
  282. *
  283. * @param bool $enable_debug_mode Whether to enable debug mode checks to occur. Default true.
  284. */
  285. if ( ! apply_filters( 'enable_wp_debug_mode_checks', true ) ) {
  286. return;
  287. }
  288. if ( WP_DEBUG ) {
  289. error_reporting( E_ALL );
  290. if ( WP_DEBUG_DISPLAY ) {
  291. ini_set( 'display_errors', 1 );
  292. } elseif ( null !== WP_DEBUG_DISPLAY ) {
  293. ini_set( 'display_errors', 0 );
  294. }
  295. if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) {
  296. $log_path = WP_CONTENT_DIR . '/debug.log';
  297. } elseif ( is_string( WP_DEBUG_LOG ) ) {
  298. $log_path = WP_DEBUG_LOG;
  299. } else {
  300. $log_path = false;
  301. }
  302. if ( $log_path ) {
  303. ini_set( 'log_errors', 1 );
  304. ini_set( 'error_log', $log_path );
  305. }
  306. } else {
  307. error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );
  308. }
  309. if ( defined( 'XMLRPC_REQUEST' ) || defined( 'REST_REQUEST' ) || ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) || wp_doing_ajax() || wp_is_json_request() ) {
  310. ini_set( 'display_errors', 0 );
  311. }
  312. }
  313. /**
  314. * Set the location of the language directory.
  315. *
  316. * To set directory manually, define the `WP_LANG_DIR` constant
  317. * in wp-config.php.
  318. *
  319. * If the language directory exists within `WP_CONTENT_DIR`, it
  320. * is used. Otherwise the language directory is assumed to live
  321. * in `WPINC`.
  322. *
  323. * @since 3.0.0
  324. * @access private
  325. */
  326. function wp_set_lang_dir() {
  327. if ( ! defined( 'WP_LANG_DIR' ) ) {
  328. if ( file_exists( WP_CONTENT_DIR . '/languages' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) || ! @is_dir( ABSPATH . WPINC . '/languages' ) ) {
  329. /**
  330. * Server path of the language directory.
  331. *
  332. * No leading slash, no trailing slash, full path, not relative to ABSPATH
  333. *
  334. * @since 2.1.0
  335. */
  336. define( 'WP_LANG_DIR', WP_CONTENT_DIR . '/languages' );
  337. if ( ! defined( 'LANGDIR' ) ) {
  338. // Old static relative path maintained for limited backward compatibility - won't work in some cases.
  339. define( 'LANGDIR', 'wp-content/languages' );
  340. }
  341. } else {
  342. /**
  343. * Server path of the language directory.
  344. *
  345. * No leading slash, no trailing slash, full path, not relative to `ABSPATH`.
  346. *
  347. * @since 2.1.0
  348. */
  349. define( 'WP_LANG_DIR', ABSPATH . WPINC . '/languages' );
  350. if ( ! defined( 'LANGDIR' ) ) {
  351. // Old relative path maintained for backward compatibility.
  352. define( 'LANGDIR', WPINC . '/languages' );
  353. }
  354. }
  355. }
  356. }
  357. /**
  358. * Load the database class file and instantiate the `$wpdb` global.
  359. *
  360. * @since 2.5.0
  361. *
  362. * @global wpdb $wpdb WordPress database abstraction object.
  363. */
  364. function require_wp_db() {
  365. global $wpdb;
  366. require_once ABSPATH . WPINC . '/wp-db.php';
  367. if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
  368. require_once WP_CONTENT_DIR . '/db.php';
  369. }
  370. if ( isset( $wpdb ) ) {
  371. return;
  372. }
  373. $dbuser = defined( 'DB_USER' ) ? DB_USER : '';
  374. $dbpassword = defined( 'DB_PASSWORD' ) ? DB_PASSWORD : '';
  375. $dbname = defined( 'DB_NAME' ) ? DB_NAME : '';
  376. $dbhost = defined( 'DB_HOST' ) ? DB_HOST : '';
  377. $wpdb = new wpdb( $dbuser, $dbpassword, $dbname, $dbhost );
  378. }
  379. /**
  380. * Set the database table prefix and the format specifiers for database
  381. * table columns.
  382. *
  383. * Columns not listed here default to `%s`.
  384. *
  385. * @since 3.0.0
  386. * @access private
  387. *
  388. * @global wpdb $wpdb WordPress database abstraction object.
  389. * @global string $table_prefix The database table prefix.
  390. */
  391. function wp_set_wpdb_vars() {
  392. global $wpdb, $table_prefix;
  393. if ( ! empty( $wpdb->error ) ) {
  394. dead_db();
  395. }
  396. $wpdb->field_types = array(
  397. 'post_author' => '%d',
  398. 'post_parent' => '%d',
  399. 'menu_order' => '%d',
  400. 'term_id' => '%d',
  401. 'term_group' => '%d',
  402. 'term_taxonomy_id' => '%d',
  403. 'parent' => '%d',
  404. 'count' => '%d',
  405. 'object_id' => '%d',
  406. 'term_order' => '%d',
  407. 'ID' => '%d',
  408. 'comment_ID' => '%d',
  409. 'comment_post_ID' => '%d',
  410. 'comment_parent' => '%d',
  411. 'user_id' => '%d',
  412. 'link_id' => '%d',
  413. 'link_owner' => '%d',
  414. 'link_rating' => '%d',
  415. 'option_id' => '%d',
  416. 'blog_id' => '%d',
  417. 'meta_id' => '%d',
  418. 'post_id' => '%d',
  419. 'user_status' => '%d',
  420. 'umeta_id' => '%d',
  421. 'comment_karma' => '%d',
  422. 'comment_count' => '%d',
  423. // Multisite:
  424. 'active' => '%d',
  425. 'cat_id' => '%d',
  426. 'deleted' => '%d',
  427. 'lang_id' => '%d',
  428. 'mature' => '%d',
  429. 'public' => '%d',
  430. 'site_id' => '%d',
  431. 'spam' => '%d',
  432. );
  433. $prefix = $wpdb->set_prefix( $table_prefix );
  434. if ( is_wp_error( $prefix ) ) {
  435. wp_load_translations_early();
  436. wp_die(
  437. sprintf(
  438. /* translators: 1: $table_prefix, 2: wp-config.php */
  439. __( '<strong>Error</strong>: %1$s in %2$s can only contain numbers, letters, and underscores.' ),
  440. '<code>$table_prefix</code>',
  441. '<code>wp-config.php</code>'
  442. )
  443. );
  444. }
  445. }
  446. /**
  447. * Toggle `$_wp_using_ext_object_cache` on and off without directly
  448. * touching global.
  449. *
  450. * @since 3.7.0
  451. *
  452. * @global bool $_wp_using_ext_object_cache
  453. *
  454. * @param bool $using Whether external object cache is being used.
  455. * @return bool The current 'using' setting.
  456. */
  457. function wp_using_ext_object_cache( $using = null ) {
  458. global $_wp_using_ext_object_cache;
  459. $current_using = $_wp_using_ext_object_cache;
  460. if ( null !== $using ) {
  461. $_wp_using_ext_object_cache = $using;
  462. }
  463. return $current_using;
  464. }
  465. /**
  466. * Start the WordPress object cache.
  467. *
  468. * If an object-cache.php file exists in the wp-content directory,
  469. * it uses that drop-in as an external object cache.
  470. *
  471. * @since 3.0.0
  472. * @access private
  473. *
  474. * @global array $wp_filter Stores all of the filters.
  475. */
  476. function wp_start_object_cache() {
  477. global $wp_filter;
  478. static $first_init = true;
  479. // Only perform the following checks once.
  480. if ( $first_init ) {
  481. if ( ! function_exists( 'wp_cache_init' ) ) {
  482. /*
  483. * This is the normal situation. First-run of this function. No
  484. * caching backend has been loaded.
  485. *
  486. * We try to load a custom caching backend, and then, if it
  487. * results in a wp_cache_init() function existing, we note
  488. * that an external object cache is being used.
  489. */
  490. if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
  491. require_once WP_CONTENT_DIR . '/object-cache.php';
  492. if ( function_exists( 'wp_cache_init' ) ) {
  493. wp_using_ext_object_cache( true );
  494. }
  495. // Re-initialize any hooks added manually by object-cache.php.
  496. if ( $wp_filter ) {
  497. $wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
  498. }
  499. }
  500. } elseif ( ! wp_using_ext_object_cache() && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
  501. /*
  502. * Sometimes advanced-cache.php can load object-cache.php before
  503. * this function is run. This breaks the function_exists() check
  504. * above and can result in wp_using_ext_object_cache() returning
  505. * false when actually an external cache is in use.
  506. */
  507. wp_using_ext_object_cache( true );
  508. }
  509. }
  510. if ( ! wp_using_ext_object_cache() ) {
  511. require_once ABSPATH . WPINC . '/cache.php';
  512. }
  513. /*
  514. * If cache supports reset, reset instead of init if already
  515. * initialized. Reset signals to the cache that global IDs
  516. * have changed and it may need to update keys and cleanup caches.
  517. */
  518. if ( ! $first_init && function_exists( 'wp_cache_switch_to_blog' ) ) {
  519. wp_cache_switch_to_blog( get_current_blog_id() );
  520. } elseif ( function_exists( 'wp_cache_init' ) ) {
  521. wp_cache_init();
  522. }
  523. if ( function_exists( 'wp_cache_add_global_groups' ) ) {
  524. wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'site-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'blog_meta' ) );
  525. wp_cache_add_non_persistent_groups( array( 'counts', 'plugins' ) );
  526. }
  527. $first_init = false;
  528. }
  529. /**
  530. * Redirect to the installer if WordPress is not installed.
  531. *
  532. * Dies with an error message when Multisite is enabled.
  533. *
  534. * @since 3.0.0
  535. * @access private
  536. */
  537. function wp_not_installed() {
  538. if ( is_multisite() ) {
  539. if ( ! is_blog_installed() && ! wp_installing() ) {
  540. nocache_headers();
  541. wp_die( __( 'The site you have requested is not installed properly. Please contact the system administrator.' ) );
  542. }
  543. } elseif ( ! is_blog_installed() && ! wp_installing() ) {
  544. nocache_headers();
  545. require ABSPATH . WPINC . '/kses.php';
  546. require ABSPATH . WPINC . '/pluggable.php';
  547. $link = wp_guess_url() . '/wp-admin/install.php';
  548. wp_redirect( $link );
  549. die();
  550. }
  551. }
  552. /**
  553. * Retrieve an array of must-use plugin files.
  554. *
  555. * The default directory is wp-content/mu-plugins. To change the default
  556. * directory manually, define `WPMU_PLUGIN_DIR` and `WPMU_PLUGIN_URL`
  557. * in wp-config.php.
  558. *
  559. * @since 3.0.0
  560. * @access private
  561. *
  562. * @return string[] Array of absolute paths of files to include.
  563. */
  564. function wp_get_mu_plugins() {
  565. $mu_plugins = array();
  566. if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
  567. return $mu_plugins;
  568. }
  569. $dh = opendir( WPMU_PLUGIN_DIR );
  570. if ( ! $dh ) {
  571. return $mu_plugins;
  572. }
  573. while ( ( $plugin = readdir( $dh ) ) !== false ) {
  574. if ( substr( $plugin, -4 ) == '.php' ) {
  575. $mu_plugins[] = WPMU_PLUGIN_DIR . '/' . $plugin;
  576. }
  577. }
  578. closedir( $dh );
  579. sort( $mu_plugins );
  580. return $mu_plugins;
  581. }
  582. /**
  583. * Retrieve an array of active and valid plugin files.
  584. *
  585. * While upgrading or installing WordPress, no plugins are returned.
  586. *
  587. * The default directory is `wp-content/plugins`. To change the default
  588. * directory manually, define `WP_PLUGIN_DIR` and `WP_PLUGIN_URL`
  589. * in `wp-config.php`.
  590. *
  591. * @since 3.0.0
  592. * @access private
  593. *
  594. * @return string[] $plugin_file Array of paths to plugin files relative to the plugins directory.
  595. */
  596. function wp_get_active_and_valid_plugins() {
  597. $plugins = array();
  598. $active_plugins = (array) get_option( 'active_plugins', array() );
  599. // Check for hacks file if the option is enabled.
  600. if ( get_option( 'hack_file' ) && file_exists( ABSPATH . 'my-hacks.php' ) ) {
  601. _deprecated_file( 'my-hacks.php', '1.5.0' );
  602. array_unshift( $plugins, ABSPATH . 'my-hacks.php' );
  603. }
  604. if ( empty( $active_plugins ) || wp_installing() ) {
  605. return $plugins;
  606. }
  607. $network_plugins = is_multisite() ? wp_get_active_network_plugins() : false;
  608. foreach ( $active_plugins as $plugin ) {
  609. if ( ! validate_file( $plugin ) // $plugin must validate as file.
  610. && '.php' == substr( $plugin, -4 ) // $plugin must end with '.php'.
  611. && file_exists( WP_PLUGIN_DIR . '/' . $plugin ) // $plugin must exist.
  612. // Not already included as a network plugin.
  613. && ( ! $network_plugins || ! in_array( WP_PLUGIN_DIR . '/' . $plugin, $network_plugins, true ) )
  614. ) {
  615. $plugins[] = WP_PLUGIN_DIR . '/' . $plugin;
  616. }
  617. }
  618. /*
  619. * Remove plugins from the list of active plugins when we're on an endpoint
  620. * that should be protected against WSODs and the plugin is paused.
  621. */
  622. if ( wp_is_recovery_mode() ) {
  623. $plugins = wp_skip_paused_plugins( $plugins );
  624. }
  625. return $plugins;
  626. }
  627. /**
  628. * Filters a given list of plugins, removing any paused plugins from it.
  629. *
  630. * @since 5.2.0
  631. *
  632. * @param string[] $plugins Array of absolute plugin main file paths.
  633. * @return string[] Filtered array of plugins, without any paused plugins.
  634. */
  635. function wp_skip_paused_plugins( array $plugins ) {
  636. $paused_plugins = wp_paused_plugins()->get_all();
  637. if ( empty( $paused_plugins ) ) {
  638. return $plugins;
  639. }
  640. foreach ( $plugins as $index => $plugin ) {
  641. list( $plugin ) = explode( '/', plugin_basename( $plugin ) );
  642. if ( array_key_exists( $plugin, $paused_plugins ) ) {
  643. unset( $plugins[ $index ] );
  644. // Store list of paused plugins for displaying an admin notice.
  645. $GLOBALS['_paused_plugins'][ $plugin ] = $paused_plugins[ $plugin ];
  646. }
  647. }
  648. return $plugins;
  649. }
  650. /**
  651. * Retrieves an array of active and valid themes.
  652. *
  653. * While upgrading or installing WordPress, no themes are returned.
  654. *
  655. * @since 5.1.0
  656. * @access private
  657. *
  658. * @return string[] Array of absolute paths to theme directories.
  659. */
  660. function wp_get_active_and_valid_themes() {
  661. global $pagenow;
  662. $themes = array();
  663. if ( wp_installing() && 'wp-activate.php' !== $pagenow ) {
  664. return $themes;
  665. }
  666. if ( TEMPLATEPATH !== STYLESHEETPATH ) {
  667. $themes[] = STYLESHEETPATH;
  668. }
  669. $themes[] = TEMPLATEPATH;
  670. /*
  671. * Remove themes from the list of active themes when we're on an endpoint
  672. * that should be protected against WSODs and the theme is paused.
  673. */
  674. if ( wp_is_recovery_mode() ) {
  675. $themes = wp_skip_paused_themes( $themes );
  676. // If no active and valid themes exist, skip loading themes.
  677. if ( empty( $themes ) ) {
  678. add_filter( 'wp_using_themes', '__return_false' );
  679. }
  680. }
  681. return $themes;
  682. }
  683. /**
  684. * Filters a given list of themes, removing any paused themes from it.
  685. *
  686. * @since 5.2.0
  687. *
  688. * @param string[] $themes Array of absolute theme directory paths.
  689. * @return string[] Filtered array of absolute paths to themes, without any paused themes.
  690. */
  691. function wp_skip_paused_themes( array $themes ) {
  692. $paused_themes = wp_paused_themes()->get_all();
  693. if ( empty( $paused_themes ) ) {
  694. return $themes;
  695. }
  696. foreach ( $themes as $index => $theme ) {
  697. $theme = basename( $theme );
  698. if ( array_key_exists( $theme, $paused_themes ) ) {
  699. unset( $themes[ $index ] );
  700. // Store list of paused themes for displaying an admin notice.
  701. $GLOBALS['_paused_themes'][ $theme ] = $paused_themes[ $theme ];
  702. }
  703. }
  704. return $themes;
  705. }
  706. /**
  707. * Is WordPress in Recovery Mode.
  708. *
  709. * In this mode, plugins or themes that cause WSODs will be paused.
  710. *
  711. * @since 5.2.0
  712. *
  713. * @return bool
  714. */
  715. function wp_is_recovery_mode() {
  716. return wp_recovery_mode()->is_active();
  717. }
  718. /**
  719. * Determines whether we are currently on an endpoint that should be protected against WSODs.
  720. *
  721. * @since 5.2.0
  722. *
  723. * @return bool True if the current endpoint should be protected.
  724. */
  725. function is_protected_endpoint() {
  726. // Protect login pages.
  727. if ( isset( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) {
  728. return true;
  729. }
  730. // Protect the admin backend.
  731. if ( is_admin() && ! wp_doing_ajax() ) {
  732. return true;
  733. }
  734. // Protect AJAX actions that could help resolve a fatal error should be available.
  735. if ( is_protected_ajax_action() ) {
  736. return true;
  737. }
  738. /**
  739. * Filters whether the current request is against a protected endpoint.
  740. *
  741. * This filter is only fired when an endpoint is requested which is not already protected by
  742. * WordPress core. As such, it exclusively allows providing further protected endpoints in
  743. * addition to the admin backend, login pages and protected AJAX actions.
  744. *
  745. * @since 5.2.0
  746. *
  747. * @param bool $is_protected_endpoint Whether the currently requested endpoint is protected. Default false.
  748. */
  749. return (bool) apply_filters( 'is_protected_endpoint', false );
  750. }
  751. /**
  752. * Determines whether we are currently handling an AJAX action that should be protected against WSODs.
  753. *
  754. * @since 5.2.0
  755. *
  756. * @return bool True if the current AJAX action should be protected.
  757. */
  758. function is_protected_ajax_action() {
  759. if ( ! wp_doing_ajax() ) {
  760. return false;
  761. }
  762. if ( ! isset( $_REQUEST['action'] ) ) {
  763. return false;
  764. }
  765. $actions_to_protect = array(
  766. 'edit-theme-plugin-file', // Saving changes in the core code editor.
  767. 'heartbeat', // Keep the heart beating.
  768. 'install-plugin', // Installing a new plugin.
  769. 'install-theme', // Installing a new theme.
  770. 'search-plugins', // Searching in the list of plugins.
  771. 'search-install-plugins', // Searching for a plugin in the plugin install screen.
  772. 'update-plugin', // Update an existing plugin.
  773. 'update-theme', // Update an existing theme.
  774. );
  775. /**
  776. * Filters the array of protected AJAX actions.
  777. *
  778. * This filter is only fired when doing AJAX and the AJAX request has an 'action' property.
  779. *
  780. * @since 5.2.0
  781. *
  782. * @param string[] $actions_to_protect Array of strings with AJAX actions to protect.
  783. */
  784. $actions_to_protect = (array) apply_filters( 'wp_protected_ajax_actions', $actions_to_protect );
  785. if ( ! in_array( $_REQUEST['action'], $actions_to_protect, true ) ) {
  786. return false;
  787. }
  788. return true;
  789. }
  790. /**
  791. * Set internal encoding.
  792. *
  793. * In most cases the default internal encoding is latin1, which is
  794. * of no use, since we want to use the `mb_` functions for `utf-8` strings.
  795. *
  796. * @since 3.0.0
  797. * @access private
  798. */
  799. function wp_set_internal_encoding() {
  800. if ( function_exists( 'mb_internal_encoding' ) ) {
  801. $charset = get_option( 'blog_charset' );
  802. // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
  803. if ( ! $charset || ! @mb_internal_encoding( $charset ) ) {
  804. mb_internal_encoding( 'UTF-8' );
  805. }
  806. }
  807. }
  808. /**
  809. * Add magic quotes to `$_GET`, `$_POST`, `$_COOKIE`, and `$_SERVER`.
  810. *
  811. * Also forces `$_REQUEST` to be `$_GET + $_POST`. If `$_SERVER`,
  812. * `$_COOKIE`, or `$_ENV` are needed, use those superglobals directly.
  813. *
  814. * @since 3.0.0
  815. * @access private
  816. */
  817. function wp_magic_quotes() {
  818. // Escape with wpdb.
  819. $_GET = add_magic_quotes( $_GET );
  820. $_POST = add_magic_quotes( $_POST );
  821. $_COOKIE = add_magic_quotes( $_COOKIE );
  822. $_SERVER = add_magic_quotes( $_SERVER );
  823. /*
  824. * Revert the type change to string for two indexes which should retain their proper type.
  825. * Among other things, this preserves compatibility of WP with PHPUnit Code Coverage generation.
  826. */
  827. if ( isset( $_SERVER['REQUEST_TIME'] ) ) {
  828. $_SERVER['REQUEST_TIME'] = (int) $_SERVER['REQUEST_TIME'];
  829. }
  830. if ( isset( $_SERVER['REQUEST_TIME_FLOAT'] ) ) {
  831. $_SERVER['REQUEST_TIME_FLOAT'] = (float) $_SERVER['REQUEST_TIME_FLOAT'];
  832. }
  833. // Force REQUEST to be GET + POST.
  834. $_REQUEST = array_merge( $_GET, $_POST );
  835. }
  836. /**
  837. * Runs just before PHP shuts down execution.
  838. *
  839. * @since 1.2.0
  840. * @access private
  841. */
  842. function shutdown_action_hook() {
  843. /**
  844. * Fires just before PHP shuts down execution.
  845. *
  846. * @since 1.2.0
  847. */
  848. do_action( 'shutdown' );
  849. wp_cache_close();
  850. }
  851. /**
  852. * Copy an object.
  853. *
  854. * @since 2.7.0
  855. * @deprecated 3.2.0
  856. *
  857. * @param object $object The object to clone.
  858. * @return object The cloned object.
  859. */
  860. function wp_clone( $object ) {
  861. // Use parens for clone to accommodate PHP 4. See #17880.
  862. return clone( $object );
  863. }
  864. /**
  865. * Determines whether the current request is for an administrative interface page.
  866. *
  867. * Does not check if the user is an administrator; use current_user_can()
  868. * for checking roles and capabilities.
  869. *
  870. * For more information on this and similar theme functions, check out
  871. * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
  872. * Conditional Tags} article in the Theme Developer Handbook.
  873. *
  874. * @since 1.5.1
  875. *
  876. * @global WP_Screen $current_screen WordPress current screen object.
  877. *
  878. * @return bool True if inside WordPress administration interface, false otherwise.
  879. */
  880. function is_admin() {
  881. if ( isset( $GLOBALS['current_screen'] ) ) {
  882. return $GLOBALS['current_screen']->in_admin();
  883. } elseif ( defined( 'WP_ADMIN' ) ) {
  884. return WP_ADMIN;
  885. }
  886. return false;
  887. }
  888. /**
  889. * Whether the current request is for a site's administrative interface.
  890. *
  891. * e.g. `/wp-admin/`
  892. *
  893. * Does not check if the user is an administrator; use current_user_can()
  894. * for checking roles and capabilities.
  895. *
  896. * @since 3.1.0
  897. *
  898. * @global WP_Screen $current_screen WordPress current screen object.
  899. *
  900. * @return bool True if inside WordPress blog administration pages.
  901. */
  902. function is_blog_admin() {
  903. if ( isset( $GLOBALS['current_screen'] ) ) {
  904. return $GLOBALS['current_screen']->in_admin( 'site' );
  905. } elseif ( defined( 'WP_BLOG_ADMIN' ) ) {
  906. return WP_BLOG_ADMIN;
  907. }
  908. return false;
  909. }
  910. /**
  911. * Whether the current request is for the network administrative interface.
  912. *
  913. * e.g. `/wp-admin/network/`
  914. *
  915. * Does not check if the user is an administrator; use current_user_can()
  916. * for checking roles and capabilities.
  917. *
  918. * Does not check if the site is a Multisite network; use is_multisite()
  919. * for checking if Multisite is enabled.
  920. *
  921. * @since 3.1.0
  922. *
  923. * @global WP_Screen $current_screen WordPress current screen object.
  924. *
  925. * @return bool True if inside WordPress network administration pages.
  926. */
  927. function is_network_admin() {
  928. if ( isset( $GLOBALS['current_screen'] ) ) {
  929. return $GLOBALS['current_screen']->in_admin( 'network' );
  930. } elseif ( defined( 'WP_NETWORK_ADMIN' ) ) {
  931. return WP_NETWORK_ADMIN;
  932. }
  933. return false;
  934. }
  935. /**
  936. * Whether the current request is for a user admin screen.
  937. *
  938. * e.g. `/wp-admin/user/`
  939. *
  940. * Does not check if the user is an administrator; use current_user_can()
  941. * for checking roles and capabilities.
  942. *
  943. * @since 3.1.0
  944. *
  945. * @global WP_Screen $current_screen WordPress current screen object.
  946. *
  947. * @return bool True if inside WordPress user administration pages.
  948. */
  949. function is_user_admin() {
  950. if ( isset( $GLOBALS['current_screen'] ) ) {
  951. return $GLOBALS['current_screen']->in_admin( 'user' );
  952. } elseif ( defined( 'WP_USER_ADMIN' ) ) {
  953. return WP_USER_ADMIN;
  954. }
  955. return false;
  956. }
  957. /**
  958. * If Multisite is enabled.
  959. *
  960. * @since 3.0.0
  961. *
  962. * @return bool True if Multisite is enabled, false otherwise.
  963. */
  964. function is_multisite() {
  965. if ( defined( 'MULTISITE' ) ) {
  966. return MULTISITE;
  967. }
  968. if ( defined( 'SUBDOMAIN_INSTALL' ) || defined( 'VHOST' ) || defined( 'SUNRISE' ) ) {
  969. return true;
  970. }
  971. return false;
  972. }
  973. /**
  974. * Retrieve the current site ID.
  975. *
  976. * @since 3.1.0
  977. *
  978. * @global int $blog_id
  979. *
  980. * @return int Site ID.
  981. */
  982. function get_current_blog_id() {
  983. global $blog_id;
  984. return absint( $blog_id );
  985. }
  986. /**
  987. * Retrieves the current network ID.
  988. *
  989. * @since 4.6.0
  990. *
  991. * @return int The ID of the current network.
  992. */
  993. function get_current_network_id() {
  994. if ( ! is_multisite() ) {
  995. return 1;
  996. }
  997. $current_network = get_network();
  998. if ( ! isset( $current_network->id ) ) {
  999. return get_main_network_id();
  1000. }
  1001. return absint( $current_network->id );
  1002. }
  1003. /**
  1004. * Attempt an early load of translations.
  1005. *
  1006. * Used for errors encountered during the initial loading process, before
  1007. * the locale has been properly detected and loaded.
  1008. *
  1009. * Designed for unusual load sequences (like setup-config.php) or for when
  1010. * the script will then terminate with an error, otherwise there is a risk
  1011. * that a file can be double-included.
  1012. *
  1013. * @since 3.4.0
  1014. * @access private
  1015. *
  1016. * @global WP_Locale $wp_locale WordPress date and time locale object.
  1017. *
  1018. * @staticvar bool $loaded
  1019. */
  1020. function wp_load_translations_early() {
  1021. global $wp_locale;
  1022. static $loaded = false;
  1023. if ( $loaded ) {
  1024. return;
  1025. }
  1026. $loaded = true;
  1027. if ( function_exists( 'did_action' ) && did_action( 'init' ) ) {
  1028. return;
  1029. }
  1030. // We need $wp_local_package.
  1031. require ABSPATH . WPINC . '/version.php';
  1032. // Translation and localization.
  1033. require_once ABSPATH . WPINC . '/pomo/mo.php';
  1034. require_once ABSPATH . WPINC . '/l10n.php';
  1035. require_once ABSPATH . WPINC . '/class-wp-locale.php';
  1036. require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php';
  1037. // General libraries.
  1038. require_once ABSPATH . WPINC . '/plugin.php';
  1039. $locales = array();
  1040. $locations = array();
  1041. while ( true ) {
  1042. if ( defined( 'WPLANG' ) ) {
  1043. if ( '' == WPLANG ) {
  1044. break;
  1045. }
  1046. $locales[] = WPLANG;
  1047. }
  1048. if ( isset( $wp_local_package ) ) {
  1049. $locales[] = $wp_local_package;
  1050. }
  1051. if ( ! $locales ) {
  1052. break;
  1053. }
  1054. if ( defined( 'WP_LANG_DIR' ) && @is_dir( WP_LANG_DIR ) ) {
  1055. $locations[] = WP_LANG_DIR;
  1056. }
  1057. if ( defined( 'WP_CONTENT_DIR' ) && @is_dir( WP_CONTENT_DIR . '/languages' ) ) {
  1058. $locations[] = WP_CONTENT_DIR . '/languages';
  1059. }
  1060. if ( @is_dir( ABSPATH . 'wp-content/languages' ) ) {
  1061. $locations[] = ABSPATH . 'wp-content/languages';
  1062. }
  1063. if ( @is_dir( ABSPATH . WPINC . '/languages' ) ) {
  1064. $locations[] = ABSPATH . WPINC . '/languages';
  1065. }
  1066. if ( ! $locations ) {
  1067. break;
  1068. }
  1069. $locations = array_unique( $locations );
  1070. foreach ( $locales as $locale ) {
  1071. foreach ( $locations as $location ) {
  1072. if ( file_exists( $location . '/' . $locale . '.mo' ) ) {
  1073. load_textdomain( 'default', $location . '/' . $locale . '.mo' );
  1074. if ( defined( 'WP_SETUP_CONFIG' ) && file_exists( $location . '/admin-' . $locale . '.mo' ) ) {
  1075. load_textdomain( 'default', $location . '/admin-' . $locale . '.mo' );
  1076. }
  1077. break 2;
  1078. }
  1079. }
  1080. }
  1081. break;
  1082. }
  1083. $wp_locale = new WP_Locale();
  1084. }
  1085. /**
  1086. * Check or set whether WordPress is in "installation" mode.
  1087. *
  1088. * If the `WP_INSTALLING` constant is defined during the bootstrap, `wp_installing()` will default to `true`.
  1089. *
  1090. * @since 4.4.0
  1091. *
  1092. * @staticvar bool $installing
  1093. *
  1094. * @param bool $is_installing Optional. True to set WP into Installing mode, false to turn Installing mode off.
  1095. * Omit this parameter if you only want to fetch the current status.
  1096. * @return bool True if WP is installing, otherwise false. When a `$is_installing` is passed, the function will
  1097. * report whether WP was in installing mode prior to the change to `$is_installing`.
  1098. */
  1099. function wp_installing( $is_installing = null ) {
  1100. static $installing = null;
  1101. // Support for the `WP_INSTALLING` constant, defined before WP is loaded.
  1102. if ( is_null( $installing ) ) {
  1103. $installing = defined( 'WP_INSTALLING' ) && WP_INSTALLING;
  1104. }
  1105. if ( ! is_null( $is_installing ) ) {
  1106. $old_installing = $installing;
  1107. $installing = $is_installing;
  1108. return (bool) $old_installing;
  1109. }
  1110. return (bool) $installing;
  1111. }
  1112. /**
  1113. * Determines if SSL is used.
  1114. *
  1115. * @since 2.6.0
  1116. * @since 4.6.0 Moved from functions.php to load.php.
  1117. *
  1118. * @return bool True if SSL, otherwise false.
  1119. */
  1120. function is_ssl() {
  1121. if ( isset( $_SERVER['HTTPS'] ) ) {
  1122. if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) {
  1123. return true;
  1124. }
  1125. if ( '1' == $_SERVER['HTTPS'] ) {
  1126. return true;
  1127. }
  1128. } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
  1129. return true;
  1130. }
  1131. return false;
  1132. }
  1133. /**
  1134. * Converts a shorthand byte value to an integer byte value.
  1135. *
  1136. * @since 2.3.0
  1137. * @since 4.6.0 Moved from media.php to load.php.
  1138. *
  1139. * @link https://www.php.net/manual/en/function.ini-get.php
  1140. * @link https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
  1141. *
  1142. * @param string $value A (PHP ini) byte value, either shorthand or ordinary.
  1143. * @return int An integer byte value.
  1144. */
  1145. function wp_convert_hr_to_bytes( $value ) {
  1146. $value = strtolower( trim( $value ) );
  1147. $bytes = (int) $value;
  1148. if ( false !== strpos( $value, 'g' ) ) {
  1149. $bytes *= GB_IN_BYTES;
  1150. } elseif ( false !== strpos( $value, 'm' ) ) {
  1151. $bytes *= MB_IN_BYTES;
  1152. } elseif ( false !== strpos( $value, 'k' ) ) {
  1153. $bytes *= KB_IN_BYTES;
  1154. }
  1155. // Deal with large (float) values which run into the maximum integer size.
  1156. return min( $bytes, PHP_INT_MAX );
  1157. }
  1158. /**
  1159. * Determines whether a PHP ini value is changeable at runtime.
  1160. *
  1161. * @since 4.6.0
  1162. *
  1163. * @staticvar array $ini_all
  1164. *
  1165. * @link https://www.php.net/manual/en/function.ini-get-all.php
  1166. *
  1167. * @param string $setting The name of the ini setting to check.
  1168. * @return bool True if the value is changeable at runtime. False otherwise.
  1169. */
  1170. function wp_is_ini_value_changeable( $setting ) {
  1171. static $ini_all;
  1172. if ( ! isset( $ini_all ) ) {
  1173. $ini_all = false;
  1174. // Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".
  1175. if ( function_exists( 'ini_get_all' ) ) {
  1176. $ini_all = ini_get_all();
  1177. }
  1178. }
  1179. // Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17.
  1180. if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === ( $ini_all[ $setting ]['access'] & 7 ) || INI_USER === ( $ini_all[ $setting ]['access'] & 7 ) ) ) {
  1181. return true;
  1182. }
  1183. // If we were unable to retrieve the details, fail gracefully to assume it's changeable.
  1184. if ( ! is_array( $ini_all ) ) {
  1185. return true;
  1186. }
  1187. return false;
  1188. }
  1189. /**
  1190. * Determines whether the current request is a WordPress Ajax request.
  1191. *
  1192. * @since 4.7.0
  1193. *
  1194. * @return bool True if it's a WordPress Ajax request, false otherwise.
  1195. */
  1196. function wp_doing_ajax() {
  1197. /**
  1198. * Filters whether the current request is a WordPress Ajax request.
  1199. *
  1200. * @since 4.7.0
  1201. *
  1202. * @param bool $wp_doing_ajax Whether the current request is a WordPress Ajax request.
  1203. */
  1204. return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
  1205. }
  1206. /**
  1207. * Determines whether the current request should use themes.
  1208. *
  1209. * @since 5.1.0
  1210. *
  1211. * @return bool True if themes should be used, false otherwise.
  1212. */
  1213. function wp_using_themes() {
  1214. /**
  1215. * Filters whether the current request should use themes.
  1216. *
  1217. * @since 5.1.0
  1218. *
  1219. * @param bool $wp_using_themes Whether the current request should use themes.
  1220. */
  1221. return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES );
  1222. }
  1223. /**
  1224. * Determines whether the current request is a WordPress cron request.
  1225. *
  1226. * @since 4.8.0
  1227. *
  1228. * @return bool True if it's a WordPress cron request, false otherwise.
  1229. */
  1230. function wp_doing_cron() {
  1231. /**
  1232. * Filters whether the current request is a WordPress cron request.
  1233. *
  1234. * @since 4.8.0
  1235. *
  1236. * @param bool $wp_doing_cron Whether the current request is a WordPress cron request.
  1237. */
  1238. return apply_filters( 'wp_doing_cron', defined( 'DOING_CRON' ) && DOING_CRON );
  1239. }
  1240. /**
  1241. * Check whether variable is a WordPress Error.
  1242. *
  1243. * Returns true if $thing is an object of the WP_Error class.
  1244. *
  1245. * @since 2.1.0
  1246. *
  1247. * @param mixed $thing Check if unknown variable is a WP_Error object.
  1248. * @return bool True, if WP_Error. False, if not WP_Error.
  1249. */
  1250. function is_wp_error( $thing ) {
  1251. return ( $thing instanceof WP_Error );
  1252. }
  1253. /**
  1254. * Determines whether file modifications are allowed.
  1255. *
  1256. * @since 4.8.0
  1257. *
  1258. * @param string $context The usage context.
  1259. * @return bool True if file modification is allowed, false otherwise.
  1260. */
  1261. function wp_is_file_mod_allowed( $context ) {
  1262. /**
  1263. * Filters whether file modifications are allowed.
  1264. *
  1265. * @since 4.8.0
  1266. *
  1267. * @param bool $file_mod_allowed Whether file modifications are allowed.
  1268. * @param string $context The usage context.
  1269. */
  1270. return apply_filters( 'file_mod_allowed', ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS, $context );
  1271. }
  1272. /**
  1273. * Start scraping edited file errors.
  1274. *
  1275. * @since 4.9.0
  1276. */
  1277. function wp_start_scraping_edited_file_errors() {
  1278. if ( ! isset( $_REQUEST['wp_scrape_key'] ) || ! isset( $_REQUEST['wp_scrape_nonce'] ) ) {
  1279. return;
  1280. }
  1281. $key = substr( sanitize_key( wp_unslash( $_REQUEST['wp_scrape_key'] ) ), 0, 32 );
  1282. $nonce = wp_unslash( $_REQUEST['wp_scrape_nonce'] );
  1283. if ( get_transient( 'scrape_key_' . $key ) !== $nonce ) {
  1284. echo "###### wp_scraping_result_start:$key ######";
  1285. echo wp_json_encode(
  1286. array(
  1287. 'code' => 'scrape_nonce_failure',
  1288. 'message' => __( 'Scrape nonce check failed. Please try again.' ),
  1289. )
  1290. );
  1291. echo "###### wp_scraping_result_end:$key ######";
  1292. die();
  1293. }
  1294. if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
  1295. define( 'WP_SANDBOX_SCRAPING', true );
  1296. }
  1297. register_shutdown_function( 'wp_finalize_scraping_edited_file_errors', $key );
  1298. }
  1299. /**
  1300. * Finalize scraping for edited file errors.
  1301. *
  1302. * @since 4.9.0
  1303. *
  1304. * @param string $scrape_key Scrape key.
  1305. */
  1306. function wp_finalize_scraping_edited_file_errors( $scrape_key ) {
  1307. $error = error_get_last();
  1308. echo "\n###### wp_scraping_result_start:$scrape_key ######\n";
  1309. if ( ! empty( $error ) && in_array( $error['type'], array( E_CORE_ERROR, E_COMPILE_ERROR, E_ERROR, E_PARSE, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) {
  1310. $error = str_replace( ABSPATH, '', $error );
  1311. echo wp_json_encode( $error );
  1312. } else {
  1313. echo wp_json_encode( true );
  1314. }
  1315. echo "\n###### wp_scraping_result_end:$scrape_key ######\n";
  1316. }
  1317. /**
  1318. * Checks whether current request is a JSON request, or is expecting a JSON response.
  1319. *
  1320. * @since 5.0.0
  1321. *
  1322. * @return bool True if `Accepts` or `Content-Type` headers contain `application/json`.
  1323. * False otherwise.
  1324. */
  1325. function wp_is_json_request() {
  1326. if ( isset( $_SERVER['HTTP_ACCEPT'] ) && false !== strpos( $_SERVER['HTTP_ACCEPT'], 'application/json' ) ) {
  1327. return true;
  1328. }
  1329. if ( isset( $_SERVER['CONTENT_TYPE'] ) && 'application/json' === $_SERVER['CONTENT_TYPE'] ) {
  1330. return true;
  1331. }
  1332. return false;
  1333. }
  1334. /**
  1335. * Checks whether current request is a JSONP request, or is expecting a JSONP response.
  1336. *
  1337. * @since 5.2.0
  1338. *
  1339. * @return bool True if JSONP request, false otherwise.
  1340. */
  1341. function wp_is_jsonp_request() {
  1342. if ( ! isset( $_GET['_jsonp'] ) ) {
  1343. return false;
  1344. }
  1345. if ( ! function_exists( 'wp_check_jsonp_callback' ) ) {
  1346. require_once ABSPATH . WPINC . '/functions.php';
  1347. }
  1348. $jsonp_callback = $_GET['_jsonp'];
  1349. if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
  1350. return false;
  1351. }
  1352. /** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */
  1353. $jsonp_enabled = apply_filters( 'rest_jsonp_enabled', true );
  1354. return $jsonp_enabled;
  1355. }
  1356. /**
  1357. * Checks whether current request is an XML request, or is expecting an XML response.
  1358. *
  1359. * @since 5.2.0
  1360. *
  1361. * @return bool True if `Accepts` or `Content-Type` headers contain `text/xml`
  1362. * or one of the related MIME types. False otherwise.
  1363. */
  1364. function wp_is_xml_request() {
  1365. $accepted = array(
  1366. 'text/xml',
  1367. 'application/rss+xml',
  1368. 'application/atom+xml',
  1369. 'application/rdf+xml',
  1370. 'text/xml+oembed',
  1371. 'application/xml+oembed',
  1372. );
  1373. if ( isset( $_SERVER['HTTP_ACCEPT'] ) ) {
  1374. foreach ( $accepted as $type ) {
  1375. if ( false !== strpos( $_SERVER['HTTP_ACCEPT'], $type ) ) {
  1376. return true;
  1377. }
  1378. }
  1379. }
  1380. if ( isset( $_SERVER['CONTENT_TYPE'] ) && in_array( $_SERVER['CONTENT_TYPE'], $accepted, true ) ) {
  1381. return true;
  1382. }
  1383. return false;
  1384. }