2013-08-07 08:38:38 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
require_once dirname( __FILE__ ) . '/factory.php';
|
|
|
|
require_once dirname( __FILE__ ) . '/trac.php';
|
|
|
|
|
2016-03-05 20:47:41 +01:00
|
|
|
/**
|
|
|
|
* Defines a basic fixture to run multiple tests.
|
|
|
|
*
|
|
|
|
* Resets the state of the WordPress installation before and after every test.
|
|
|
|
*
|
|
|
|
* Includes utility functions and assertions useful for testing WordPress.
|
|
|
|
*
|
|
|
|
* All WordPress unit tests should inherit from this class.
|
|
|
|
*/
|
2013-08-07 08:38:38 +02:00
|
|
|
class WP_UnitTestCase extends PHPUnit_Framework_TestCase {
|
|
|
|
|
|
|
|
protected static $forced_tickets = array();
|
2013-09-12 20:37:00 +02:00
|
|
|
protected $expected_deprecated = array();
|
|
|
|
protected $caught_deprecated = array();
|
2013-10-15 16:30:02 +02:00
|
|
|
protected $expected_doing_it_wrong = array();
|
|
|
|
protected $caught_doing_it_wrong = array();
|
2013-08-07 08:38:38 +02:00
|
|
|
|
2014-07-23 04:22:57 +02:00
|
|
|
protected static $hooks_saved = array();
|
2014-07-12 09:08:15 +02:00
|
|
|
protected static $ignore_files;
|
|
|
|
|
2015-10-17 20:02:16 +02:00
|
|
|
function __isset( $name ) {
|
|
|
|
return 'factory' === $name;
|
|
|
|
}
|
|
|
|
|
|
|
|
function __get( $name ) {
|
|
|
|
if ( 'factory' === $name ) {
|
|
|
|
return self::factory();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static function factory() {
|
|
|
|
static $factory = null;
|
|
|
|
if ( ! $factory ) {
|
|
|
|
$factory = new WP_UnitTest_Factory();
|
|
|
|
}
|
|
|
|
return $factory;
|
|
|
|
}
|
2015-10-15 06:43:37 +02:00
|
|
|
|
|
|
|
public static function get_called_class() {
|
|
|
|
if ( function_exists( 'get_called_class' ) ) {
|
|
|
|
return get_called_class();
|
|
|
|
}
|
|
|
|
|
|
|
|
// PHP 5.2 only
|
|
|
|
$backtrace = debug_backtrace();
|
|
|
|
// [0] WP_UnitTestCase::get_called_class()
|
|
|
|
// [1] WP_UnitTestCase::setUpBeforeClass()
|
|
|
|
if ( 'call_user_func' === $backtrace[2]['function'] ) {
|
|
|
|
return $backtrace[2]['args'][0][0];
|
|
|
|
}
|
|
|
|
return $backtrace[2]['class'];
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function setUpBeforeClass() {
|
2016-12-21 05:58:47 +01:00
|
|
|
global $wpdb;
|
|
|
|
|
|
|
|
$wpdb->suppress_errors = false;
|
|
|
|
$wpdb->show_errors = true;
|
|
|
|
$wpdb->db_connect();
|
|
|
|
ini_set('display_errors', 1 );
|
|
|
|
|
2015-10-15 06:43:37 +02:00
|
|
|
parent::setUpBeforeClass();
|
|
|
|
|
|
|
|
$c = self::get_called_class();
|
|
|
|
if ( ! method_exists( $c, 'wpSetUpBeforeClass' ) ) {
|
2016-08-27 10:35:16 +02:00
|
|
|
self::commit_transaction();
|
2015-10-15 06:43:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-17 20:02:16 +02:00
|
|
|
call_user_func( array( $c, 'wpSetUpBeforeClass' ), self::factory() );
|
2015-10-15 06:43:37 +02:00
|
|
|
|
|
|
|
self::commit_transaction();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function tearDownAfterClass() {
|
|
|
|
parent::tearDownAfterClass();
|
|
|
|
|
2016-08-27 10:35:16 +02:00
|
|
|
_delete_all_data();
|
|
|
|
self::flush_cache();
|
|
|
|
|
2015-10-15 06:43:37 +02:00
|
|
|
$c = self::get_called_class();
|
|
|
|
if ( ! method_exists( $c, 'wpTearDownAfterClass' ) ) {
|
2016-08-27 10:35:16 +02:00
|
|
|
self::commit_transaction();
|
2015-10-15 06:43:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
call_user_func( array( $c, 'wpTearDownAfterClass' ) );
|
|
|
|
|
|
|
|
self::commit_transaction();
|
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
function setUp() {
|
|
|
|
set_time_limit(0);
|
|
|
|
|
2014-07-12 09:08:15 +02:00
|
|
|
if ( ! self::$ignore_files ) {
|
|
|
|
self::$ignore_files = $this->scan_user_uploads();
|
|
|
|
}
|
|
|
|
|
2014-07-20 01:58:07 +02:00
|
|
|
if ( ! self::$hooks_saved ) {
|
|
|
|
$this->_backup_hooks();
|
|
|
|
}
|
|
|
|
|
2016-12-21 05:58:47 +01:00
|
|
|
global $wp_rewrite;
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
$this->clean_up_global_scope();
|
2014-10-10 22:25:39 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* When running core tests, ensure that post types and taxonomies
|
|
|
|
* are reset for each test. We skip this step for non-core tests,
|
|
|
|
* given the large number of plugins that register post types and
|
|
|
|
* taxonomies at 'init'.
|
|
|
|
*/
|
|
|
|
if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) {
|
|
|
|
$this->reset_post_types();
|
|
|
|
$this->reset_taxonomies();
|
2015-01-04 21:05:53 +01:00
|
|
|
$this->reset_post_statuses();
|
2016-02-26 03:08:47 +01:00
|
|
|
$this->reset__SERVER();
|
2015-10-13 17:21:20 +02:00
|
|
|
|
|
|
|
if ( $wp_rewrite->permalink_structure ) {
|
|
|
|
$this->set_permalink_structure( '' );
|
|
|
|
}
|
2014-10-10 22:25:39 +02:00
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
$this->start_transaction();
|
2013-09-12 20:37:00 +02:00
|
|
|
$this->expectDeprecated();
|
2013-08-07 08:38:38 +02:00
|
|
|
add_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) );
|
|
|
|
}
|
|
|
|
|
2015-02-17 17:11:09 +01:00
|
|
|
/**
|
|
|
|
* Detect post-test failure conditions.
|
|
|
|
*
|
|
|
|
* We use this method to detect expectedDeprecated and expectedIncorrectUsage annotations.
|
|
|
|
*
|
|
|
|
* @since 4.2.0
|
|
|
|
*/
|
|
|
|
protected function assertPostConditions() {
|
|
|
|
$this->expectedDeprecated();
|
|
|
|
}
|
|
|
|
|
2016-03-05 20:47:41 +01:00
|
|
|
/**
|
|
|
|
* After a test method runs, reset any state in WordPress the test method might have changed.
|
|
|
|
*/
|
2013-08-07 08:38:38 +02:00
|
|
|
function tearDown() {
|
2016-09-30 05:15:36 +02:00
|
|
|
global $wpdb, $wp_query, $wp;
|
2013-08-07 08:38:38 +02:00
|
|
|
$wpdb->query( 'ROLLBACK' );
|
2014-07-01 20:51:46 +02:00
|
|
|
if ( is_multisite() ) {
|
|
|
|
while ( ms_is_switched() ) {
|
|
|
|
restore_current_blog();
|
|
|
|
}
|
|
|
|
}
|
2014-02-17 22:03:43 +01:00
|
|
|
$wp_query = new WP_Query();
|
2015-10-18 07:00:40 +02:00
|
|
|
$wp = new WP();
|
2016-09-30 05:15:36 +02:00
|
|
|
|
|
|
|
// Reset globals related to the post loop and `setup_postdata()`.
|
|
|
|
$post_globals = array( 'post', 'id', 'authordata', 'currentday', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages' );
|
|
|
|
foreach ( $post_globals as $global ) {
|
|
|
|
$GLOBALS[ $global ] = null;
|
|
|
|
}
|
|
|
|
|
2014-03-27 21:54:08 +01:00
|
|
|
remove_theme_support( 'html5' );
|
2014-02-03 23:39:47 +01:00
|
|
|
remove_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
|
|
|
remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );
|
2013-08-07 08:38:38 +02:00
|
|
|
remove_filter( 'wp_die_handler', array( $this, 'get_wp_die_handler' ) );
|
2014-07-20 01:58:07 +02:00
|
|
|
$this->_restore_hooks();
|
2014-10-24 02:58:35 +02:00
|
|
|
wp_set_current_user( 0 );
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function clean_up_global_scope() {
|
|
|
|
$_GET = array();
|
|
|
|
$_POST = array();
|
2016-08-27 10:35:16 +02:00
|
|
|
self::flush_cache();
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
2017-03-08 01:06:12 +01:00
|
|
|
/**
|
|
|
|
* Allow tests to be skipped on some automated runs
|
|
|
|
*
|
|
|
|
* For test runs on Travis for something other than trunk/master
|
|
|
|
* we want to skip tests that only need to run for master.
|
|
|
|
*/
|
|
|
|
public function skipOnAutomatedBranches() {
|
|
|
|
// gentenv can be disabled
|
|
|
|
if ( ! function_exists( 'getenv' ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
|
|
|
|
$travis_branch = getenv( 'TRAVIS_BRANCH' );
|
|
|
|
$travis_pull_request = getenv( 'TRAVIS_PULL_REQUEST' );
|
|
|
|
|
|
|
|
if ( false !== $travis_pull_request && 'master' !== $travis_branch ) {
|
|
|
|
$this->markTestSkipped( 'For automated test runs, this test is only run on trunk/master' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 23:57:31 +02:00
|
|
|
/**
|
|
|
|
* Allow tests to be skipped when Multisite is not in use.
|
|
|
|
*
|
|
|
|
* Use in conjunction with the ms-required group.
|
|
|
|
*/
|
|
|
|
public function skipWithoutMultisite() {
|
|
|
|
if ( ! is_multisite() ) {
|
|
|
|
$this->markTestSkipped( 'Test only runs on Multisite' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allow tests to be skipped when Multisite is in use.
|
|
|
|
*
|
|
|
|
* Use in conjunction with the ms-excluded group.
|
|
|
|
*/
|
|
|
|
public function skipWithMultisite() {
|
|
|
|
if ( is_multisite() ) {
|
|
|
|
$this->markTestSkipped( 'Test does not run on Multisite' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-09 02:57:26 +02:00
|
|
|
/**
|
|
|
|
* Unregister existing post types and register defaults.
|
|
|
|
*
|
|
|
|
* Run before each test in order to clean up the global scope, in case
|
|
|
|
* a test forgets to unregister a post type on its own, or fails before
|
|
|
|
* it has a chance to do so.
|
|
|
|
*/
|
|
|
|
protected function reset_post_types() {
|
2017-01-16 17:21:00 +01:00
|
|
|
foreach ( get_post_types( array(), 'objects' ) as $pt ) {
|
|
|
|
if ( empty( $pt->tests_no_auto_unregister ) ) {
|
|
|
|
_unregister_post_type( $pt->name );
|
|
|
|
}
|
2014-10-09 02:57:26 +02:00
|
|
|
}
|
|
|
|
create_initial_post_types();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister existing taxonomies and register defaults.
|
|
|
|
*
|
|
|
|
* Run before each test in order to clean up the global scope, in case
|
|
|
|
* a test forgets to unregister a taxonomy on its own, or fails before
|
|
|
|
* it has a chance to do so.
|
|
|
|
*/
|
|
|
|
protected function reset_taxonomies() {
|
|
|
|
foreach ( get_taxonomies() as $tax ) {
|
|
|
|
_unregister_taxonomy( $tax );
|
|
|
|
}
|
|
|
|
create_initial_taxonomies();
|
|
|
|
}
|
|
|
|
|
2015-01-04 21:05:53 +01:00
|
|
|
/**
|
|
|
|
* Unregister non-built-in post statuses.
|
|
|
|
*/
|
|
|
|
protected function reset_post_statuses() {
|
|
|
|
foreach ( get_post_stati( array( '_builtin' => false ) ) as $post_status ) {
|
|
|
|
_unregister_post_status( $post_status );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-26 03:08:47 +01:00
|
|
|
/**
|
|
|
|
* Reset `$_SERVER` variables
|
|
|
|
*/
|
|
|
|
protected function reset__SERVER() {
|
|
|
|
tests_reset__SERVER();
|
|
|
|
}
|
|
|
|
|
2014-07-20 01:58:07 +02:00
|
|
|
/**
|
2014-08-15 17:40:48 +02:00
|
|
|
* Saves the action and filter-related globals so they can be restored later.
|
2014-07-20 01:58:07 +02:00
|
|
|
*
|
|
|
|
* Stores $merged_filters, $wp_actions, $wp_current_filter, and $wp_filter
|
2014-08-15 17:40:48 +02:00
|
|
|
* on a class variable so they can be restored on tearDown() using _restore_hooks().
|
|
|
|
*
|
2014-07-20 01:58:07 +02:00
|
|
|
* @global array $merged_filters
|
|
|
|
* @global array $wp_actions
|
|
|
|
* @global array $wp_current_filter
|
|
|
|
* @global array $wp_filter
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
protected function _backup_hooks() {
|
Hooks: Add the new class `WP_Hook`, and modify hook handling to make use of it.
Filters and actions have been the basis of WordPress' plugin functionality since time immemorial, they've always been a reliable method for acting upon the current state of WordPress, and will continue to be so.
Over the years, however, edge cases have cropped up. Particularly when it comes to recursively executing hooks, or a hook adding and removing itself, the existing implementation struggled to keep up with more complex use cases.
And so, we introduce `WP_Hook`. By changing `$wp_filter` from an array of arrays, to an array of objects, we reduce the complexity of the hook handling code, as the processing code (see `::apply_filters()`) only needs to be aware of itself, rather than the state of all hooks. At the same time, we're able te handle more complex use cases, as the object can more easily keep track of its own state than an array ever could.
Props jbrinley for the original architecture and design of this patch.
Props SergeyBiryukov, cheeserolls, Denis-de-Bernardy, leewillis77, wonderboymusic, nacin, jorbin, DrewAPicture, ocean90, dougwollison, khag7, pento, noplanman and aaroncampbell for their testing, suggestions, contributions, patch maintenance, cajoling and patience as we got through this.
Fixes #17817.
git-svn-id: https://develop.svn.wordpress.org/trunk@38571 602fd350-edb4-49c9-b593-d223f7449a82
2016-09-08 05:54:13 +02:00
|
|
|
$globals = array( 'wp_actions', 'wp_current_filter' );
|
2014-07-20 01:58:07 +02:00
|
|
|
foreach ( $globals as $key ) {
|
|
|
|
self::$hooks_saved[ $key ] = $GLOBALS[ $key ];
|
|
|
|
}
|
Hooks: Add the new class `WP_Hook`, and modify hook handling to make use of it.
Filters and actions have been the basis of WordPress' plugin functionality since time immemorial, they've always been a reliable method for acting upon the current state of WordPress, and will continue to be so.
Over the years, however, edge cases have cropped up. Particularly when it comes to recursively executing hooks, or a hook adding and removing itself, the existing implementation struggled to keep up with more complex use cases.
And so, we introduce `WP_Hook`. By changing `$wp_filter` from an array of arrays, to an array of objects, we reduce the complexity of the hook handling code, as the processing code (see `::apply_filters()`) only needs to be aware of itself, rather than the state of all hooks. At the same time, we're able te handle more complex use cases, as the object can more easily keep track of its own state than an array ever could.
Props jbrinley for the original architecture and design of this patch.
Props SergeyBiryukov, cheeserolls, Denis-de-Bernardy, leewillis77, wonderboymusic, nacin, jorbin, DrewAPicture, ocean90, dougwollison, khag7, pento, noplanman and aaroncampbell for their testing, suggestions, contributions, patch maintenance, cajoling and patience as we got through this.
Fixes #17817.
git-svn-id: https://develop.svn.wordpress.org/trunk@38571 602fd350-edb4-49c9-b593-d223f7449a82
2016-09-08 05:54:13 +02:00
|
|
|
self::$hooks_saved['wp_filter'] = array();
|
|
|
|
foreach ( $GLOBALS['wp_filter'] as $hook_name => $hook_object ) {
|
|
|
|
self::$hooks_saved['wp_filter'][ $hook_name ] = clone $hook_object;
|
|
|
|
}
|
2014-07-20 01:58:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Restores the hook-related globals to their state at setUp()
|
2014-08-15 17:40:48 +02:00
|
|
|
* so that future tests aren't affected by hooks set during this last test.
|
2014-07-20 01:58:07 +02:00
|
|
|
*
|
|
|
|
* @global array $merged_filters
|
|
|
|
* @global array $wp_actions
|
|
|
|
* @global array $wp_current_filter
|
|
|
|
* @global array $wp_filter
|
|
|
|
* @return void
|
|
|
|
*/
|
2014-08-15 17:40:48 +02:00
|
|
|
protected function _restore_hooks() {
|
Hooks: Add the new class `WP_Hook`, and modify hook handling to make use of it.
Filters and actions have been the basis of WordPress' plugin functionality since time immemorial, they've always been a reliable method for acting upon the current state of WordPress, and will continue to be so.
Over the years, however, edge cases have cropped up. Particularly when it comes to recursively executing hooks, or a hook adding and removing itself, the existing implementation struggled to keep up with more complex use cases.
And so, we introduce `WP_Hook`. By changing `$wp_filter` from an array of arrays, to an array of objects, we reduce the complexity of the hook handling code, as the processing code (see `::apply_filters()`) only needs to be aware of itself, rather than the state of all hooks. At the same time, we're able te handle more complex use cases, as the object can more easily keep track of its own state than an array ever could.
Props jbrinley for the original architecture and design of this patch.
Props SergeyBiryukov, cheeserolls, Denis-de-Bernardy, leewillis77, wonderboymusic, nacin, jorbin, DrewAPicture, ocean90, dougwollison, khag7, pento, noplanman and aaroncampbell for their testing, suggestions, contributions, patch maintenance, cajoling and patience as we got through this.
Fixes #17817.
git-svn-id: https://develop.svn.wordpress.org/trunk@38571 602fd350-edb4-49c9-b593-d223f7449a82
2016-09-08 05:54:13 +02:00
|
|
|
$globals = array( 'wp_actions', 'wp_current_filter' );
|
2014-07-20 01:58:07 +02:00
|
|
|
foreach ( $globals as $key ) {
|
2014-08-15 17:40:48 +02:00
|
|
|
if ( isset( self::$hooks_saved[ $key ] ) ) {
|
|
|
|
$GLOBALS[ $key ] = self::$hooks_saved[ $key ];
|
|
|
|
}
|
2014-07-20 01:58:07 +02:00
|
|
|
}
|
Hooks: Add the new class `WP_Hook`, and modify hook handling to make use of it.
Filters and actions have been the basis of WordPress' plugin functionality since time immemorial, they've always been a reliable method for acting upon the current state of WordPress, and will continue to be so.
Over the years, however, edge cases have cropped up. Particularly when it comes to recursively executing hooks, or a hook adding and removing itself, the existing implementation struggled to keep up with more complex use cases.
And so, we introduce `WP_Hook`. By changing `$wp_filter` from an array of arrays, to an array of objects, we reduce the complexity of the hook handling code, as the processing code (see `::apply_filters()`) only needs to be aware of itself, rather than the state of all hooks. At the same time, we're able te handle more complex use cases, as the object can more easily keep track of its own state than an array ever could.
Props jbrinley for the original architecture and design of this patch.
Props SergeyBiryukov, cheeserolls, Denis-de-Bernardy, leewillis77, wonderboymusic, nacin, jorbin, DrewAPicture, ocean90, dougwollison, khag7, pento, noplanman and aaroncampbell for their testing, suggestions, contributions, patch maintenance, cajoling and patience as we got through this.
Fixes #17817.
git-svn-id: https://develop.svn.wordpress.org/trunk@38571 602fd350-edb4-49c9-b593-d223f7449a82
2016-09-08 05:54:13 +02:00
|
|
|
if ( isset( self::$hooks_saved['wp_filter'] ) ) {
|
|
|
|
$GLOBALS['wp_filter'] = array();
|
|
|
|
foreach ( self::$hooks_saved['wp_filter'] as $hook_name => $hook_object ) {
|
|
|
|
$GLOBALS['wp_filter'][ $hook_name ] = clone $hook_object;
|
|
|
|
}
|
|
|
|
}
|
2014-07-20 01:58:07 +02:00
|
|
|
}
|
2014-11-13 23:03:15 +01:00
|
|
|
|
2016-08-27 10:35:16 +02:00
|
|
|
static function flush_cache() {
|
2013-08-07 08:38:38 +02:00
|
|
|
global $wp_object_cache;
|
|
|
|
$wp_object_cache->group_ops = array();
|
|
|
|
$wp_object_cache->stats = array();
|
|
|
|
$wp_object_cache->memcache_debug = array();
|
|
|
|
$wp_object_cache->cache = array();
|
|
|
|
if ( method_exists( $wp_object_cache, '__remoteset' ) ) {
|
|
|
|
$wp_object_cache->__remoteset();
|
|
|
|
}
|
|
|
|
wp_cache_flush();
|
2017-03-28 23:07:22 +02:00
|
|
|
wp_cache_add_global_groups( array( 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );
|
2013-08-07 08:38:38 +02:00
|
|
|
wp_cache_add_non_persistent_groups( array( 'comment', 'counts', 'plugins' ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
function start_transaction() {
|
|
|
|
global $wpdb;
|
|
|
|
$wpdb->query( 'SET autocommit = 0;' );
|
|
|
|
$wpdb->query( 'START TRANSACTION;' );
|
2014-02-03 23:39:47 +01:00
|
|
|
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
|
|
|
add_filter( 'query', array( $this, '_drop_temporary_tables' ) );
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
2014-11-08 16:29:31 +01:00
|
|
|
/**
|
|
|
|
* Commit the queries in a transaction.
|
|
|
|
*
|
|
|
|
* @since 4.1.0
|
|
|
|
*/
|
|
|
|
public static function commit_transaction() {
|
|
|
|
global $wpdb;
|
|
|
|
$wpdb->query( 'COMMIT;' );
|
|
|
|
}
|
|
|
|
|
2014-02-03 23:39:47 +01:00
|
|
|
function _create_temporary_tables( $query ) {
|
|
|
|
if ( 'CREATE TABLE' === substr( trim( $query ), 0, 12 ) )
|
|
|
|
return substr_replace( trim( $query ), 'CREATE TEMPORARY TABLE', 0, 12 );
|
2014-01-27 04:09:13 +01:00
|
|
|
return $query;
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
2014-02-03 23:39:47 +01:00
|
|
|
function _drop_temporary_tables( $query ) {
|
|
|
|
if ( 'DROP TABLE' === substr( trim( $query ), 0, 10 ) )
|
|
|
|
return substr_replace( trim( $query ), 'DROP TEMPORARY TABLE', 0, 10 );
|
2013-08-07 08:38:38 +02:00
|
|
|
return $query;
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_wp_die_handler( $handler ) {
|
|
|
|
return array( $this, 'wp_die_handler' );
|
|
|
|
}
|
|
|
|
|
|
|
|
function wp_die_handler( $message ) {
|
2016-03-23 20:00:38 +01:00
|
|
|
if ( ! is_scalar( $message ) ) {
|
|
|
|
$message = '0';
|
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
throw new WPDieException( $message );
|
|
|
|
}
|
|
|
|
|
2013-09-12 20:37:00 +02:00
|
|
|
function expectDeprecated() {
|
|
|
|
$annotations = $this->getAnnotations();
|
|
|
|
foreach ( array( 'class', 'method' ) as $depth ) {
|
|
|
|
if ( ! empty( $annotations[ $depth ]['expectedDeprecated'] ) )
|
|
|
|
$this->expected_deprecated = array_merge( $this->expected_deprecated, $annotations[ $depth ]['expectedDeprecated'] );
|
2013-10-15 16:30:02 +02:00
|
|
|
if ( ! empty( $annotations[ $depth ]['expectedIncorrectUsage'] ) )
|
|
|
|
$this->expected_doing_it_wrong = array_merge( $this->expected_doing_it_wrong, $annotations[ $depth ]['expectedIncorrectUsage'] );
|
2013-09-12 20:37:00 +02:00
|
|
|
}
|
|
|
|
add_action( 'deprecated_function_run', array( $this, 'deprecated_function_run' ) );
|
|
|
|
add_action( 'deprecated_argument_run', array( $this, 'deprecated_function_run' ) );
|
2016-06-25 21:56:19 +02:00
|
|
|
add_action( 'deprecated_hook_run', array( $this, 'deprecated_function_run' ) );
|
2013-10-15 16:30:02 +02:00
|
|
|
add_action( 'doing_it_wrong_run', array( $this, 'doing_it_wrong_run' ) );
|
2013-09-12 20:37:00 +02:00
|
|
|
add_action( 'deprecated_function_trigger_error', '__return_false' );
|
|
|
|
add_action( 'deprecated_argument_trigger_error', '__return_false' );
|
2016-06-25 21:56:19 +02:00
|
|
|
add_action( 'deprecated_hook_trigger_error', '__return_false' );
|
2013-10-15 16:30:02 +02:00
|
|
|
add_action( 'doing_it_wrong_trigger_error', '__return_false' );
|
2013-09-12 20:37:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function expectedDeprecated() {
|
2015-02-17 17:11:09 +01:00
|
|
|
$errors = array();
|
|
|
|
|
2013-09-12 20:37:00 +02:00
|
|
|
$not_caught_deprecated = array_diff( $this->expected_deprecated, $this->caught_deprecated );
|
|
|
|
foreach ( $not_caught_deprecated as $not_caught ) {
|
2015-02-17 17:11:09 +01:00
|
|
|
$errors[] = "Failed to assert that $not_caught triggered a deprecated notice";
|
2013-09-12 20:37:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$unexpected_deprecated = array_diff( $this->caught_deprecated, $this->expected_deprecated );
|
|
|
|
foreach ( $unexpected_deprecated as $unexpected ) {
|
2015-02-17 17:11:09 +01:00
|
|
|
$errors[] = "Unexpected deprecated notice for $unexpected";
|
2013-09-12 20:37:00 +02:00
|
|
|
}
|
2013-10-15 16:30:02 +02:00
|
|
|
|
|
|
|
$not_caught_doing_it_wrong = array_diff( $this->expected_doing_it_wrong, $this->caught_doing_it_wrong );
|
|
|
|
foreach ( $not_caught_doing_it_wrong as $not_caught ) {
|
2015-02-17 17:11:09 +01:00
|
|
|
$errors[] = "Failed to assert that $not_caught triggered an incorrect usage notice";
|
2013-10-15 16:30:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$unexpected_doing_it_wrong = array_diff( $this->caught_doing_it_wrong, $this->expected_doing_it_wrong );
|
|
|
|
foreach ( $unexpected_doing_it_wrong as $unexpected ) {
|
2015-02-17 17:11:09 +01:00
|
|
|
$errors[] = "Unexpected incorrect usage notice for $unexpected";
|
|
|
|
}
|
|
|
|
|
2017-04-23 23:34:37 +02:00
|
|
|
// Perform an assertion, but only if there are expected or unexpected deprecated calls or wrongdoings
|
|
|
|
if ( ! empty( $this->expected_deprecated ) ||
|
|
|
|
! empty( $this->expected_doing_it_wrong ) ||
|
|
|
|
! empty( $this->caught_deprecated ) ||
|
|
|
|
! empty( $this->caught_doing_it_wrong ) ) {
|
2017-04-23 23:28:44 +02:00
|
|
|
$this->assertEmpty( $errors, implode( "\n", $errors ) );
|
|
|
|
}
|
2013-09-12 20:37:00 +02:00
|
|
|
}
|
|
|
|
|
2015-01-30 17:47:44 +01:00
|
|
|
/**
|
|
|
|
* Declare an expected `_deprecated_function()` or `_deprecated_argument()` call from within a test.
|
|
|
|
*
|
|
|
|
* @since 4.2.0
|
|
|
|
*
|
|
|
|
* @param string $deprecated Name of the function, method, class, or argument that is deprecated. Must match
|
|
|
|
* first parameter of the `_deprecated_function()` or `_deprecated_argument()` call.
|
|
|
|
*/
|
|
|
|
public function setExpectedDeprecated( $deprecated ) {
|
|
|
|
array_push( $this->expected_deprecated, $deprecated );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Declare an expected `_doing_it_wrong()` call from within a test.
|
|
|
|
*
|
|
|
|
* @since 4.2.0
|
|
|
|
*
|
|
|
|
* @param string $deprecated Name of the function, method, or class that appears in the first argument of the
|
|
|
|
* source `_doing_it_wrong()` call.
|
|
|
|
*/
|
|
|
|
public function setExpectedIncorrectUsage( $doing_it_wrong ) {
|
|
|
|
array_push( $this->expected_doing_it_wrong, $doing_it_wrong );
|
|
|
|
}
|
|
|
|
|
2017-06-02 15:17:30 +02:00
|
|
|
/**
|
|
|
|
* PHPUnit 6+ compatibility shim.
|
|
|
|
*
|
|
|
|
* @param mixed $exception
|
|
|
|
* @param string $message
|
|
|
|
* @param int|string $code
|
|
|
|
*/
|
|
|
|
public function setExpectedException( $exception, $message = '', $code = null ) {
|
2017-06-02 16:10:56 +02:00
|
|
|
if ( method_exists( 'PHPUnit_Framework_TestCase', 'setExpectedException' ) ) {
|
2017-06-02 15:17:30 +02:00
|
|
|
parent::setExpectedException( $exception, $message, $code );
|
|
|
|
} else {
|
|
|
|
$this->expectException( $exception );
|
|
|
|
if ( '' !== $message ) {
|
|
|
|
$this->expectExceptionMessage( $message );
|
|
|
|
}
|
|
|
|
if ( null !== $code ) {
|
|
|
|
$this->expectExceptionCode( $code );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-12 20:37:00 +02:00
|
|
|
function deprecated_function_run( $function ) {
|
|
|
|
if ( ! in_array( $function, $this->caught_deprecated ) )
|
|
|
|
$this->caught_deprecated[] = $function;
|
|
|
|
}
|
|
|
|
|
2013-10-15 16:30:02 +02:00
|
|
|
function doing_it_wrong_run( $function ) {
|
|
|
|
if ( ! in_array( $function, $this->caught_doing_it_wrong ) )
|
|
|
|
$this->caught_doing_it_wrong[] = $function;
|
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
function assertWPError( $actual, $message = '' ) {
|
|
|
|
$this->assertInstanceOf( 'WP_Error', $actual, $message );
|
|
|
|
}
|
|
|
|
|
2015-09-27 23:28:26 +02:00
|
|
|
function assertNotWPError( $actual, $message = '' ) {
|
|
|
|
if ( is_wp_error( $actual ) && '' === $message ) {
|
|
|
|
$message = $actual->get_error_message();
|
|
|
|
}
|
|
|
|
$this->assertNotInstanceOf( 'WP_Error', $actual, $message );
|
|
|
|
}
|
|
|
|
|
2017-04-12 16:58:33 +02:00
|
|
|
function assertIXRError( $actual, $message = '' ) {
|
|
|
|
$this->assertInstanceOf( 'IXR_Error', $actual, $message );
|
|
|
|
}
|
|
|
|
|
|
|
|
function assertNotIXRError( $actual, $message = '' ) {
|
|
|
|
if ( $actual instanceof IXR_Error && '' === $message ) {
|
|
|
|
$message = $actual->message;
|
|
|
|
}
|
|
|
|
$this->assertNotInstanceOf( 'IXR_Error', $actual, $message );
|
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
function assertEqualFields( $object, $fields ) {
|
|
|
|
foreach( $fields as $field_name => $field_value ) {
|
|
|
|
if ( $object->$field_name != $field_value ) {
|
|
|
|
$this->fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function assertDiscardWhitespace( $expected, $actual ) {
|
|
|
|
$this->assertEquals( preg_replace( '/\s*/', '', $expected ), preg_replace( '/\s*/', '', $actual ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
function assertEqualSets( $expected, $actual ) {
|
2014-12-01 06:01:29 +01:00
|
|
|
sort( $expected );
|
|
|
|
sort( $actual );
|
|
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
}
|
|
|
|
|
|
|
|
function assertEqualSetsWithIndex( $expected, $actual ) {
|
|
|
|
ksort( $expected );
|
|
|
|
ksort( $actual );
|
|
|
|
$this->assertEquals( $expected, $actual );
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
2017-01-15 07:50:00 +01:00
|
|
|
/**
|
|
|
|
* Asserts that the given variable is a multidimensional array, and that all arrays are non-empty.
|
|
|
|
*
|
|
|
|
* @param array $array
|
|
|
|
*/
|
|
|
|
function assertNonEmptyMultidimensionalArray( $array ) {
|
|
|
|
$this->assertTrue( is_array( $array ) );
|
|
|
|
$this->assertNotEmpty( $array );
|
|
|
|
|
|
|
|
foreach( $array as $sub_array ) {
|
|
|
|
$this->assertTrue( is_array( $sub_array ) );
|
|
|
|
$this->assertNotEmpty( $sub_array );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-17 04:39:36 +01:00
|
|
|
/**
|
|
|
|
* Asserts that a condition is not false.
|
|
|
|
*
|
|
|
|
* @param bool $condition
|
|
|
|
* @param string $message
|
|
|
|
*
|
|
|
|
* @throws PHPUnit_Framework_AssertionFailedError
|
|
|
|
*/
|
|
|
|
public static function assertNotFalse( $condition, $message = '' ) {
|
|
|
|
self::assertThat( $condition, self::logicalNot( self::isFalse() ), $message );
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:24:34 +02:00
|
|
|
/**
|
|
|
|
* Modify WordPress's query internals as if a given URL has been requested.
|
|
|
|
*
|
|
|
|
* @param string $url The URL for the request.
|
|
|
|
*/
|
2013-08-07 08:38:38 +02:00
|
|
|
function go_to( $url ) {
|
|
|
|
// note: the WP and WP_Query classes like to silently fetch parameters
|
|
|
|
// from all over the place (globals, GET, etc), which makes it tricky
|
|
|
|
// to run them more than once without very carefully clearing everything
|
|
|
|
$_GET = $_POST = array();
|
|
|
|
foreach (array('query_string', 'id', 'postdata', 'authordata', 'day', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages', 'pagenow') as $v) {
|
|
|
|
if ( isset( $GLOBALS[$v] ) ) unset( $GLOBALS[$v] );
|
|
|
|
}
|
|
|
|
$parts = parse_url($url);
|
|
|
|
if (isset($parts['scheme'])) {
|
2015-02-23 02:07:18 +01:00
|
|
|
$req = isset( $parts['path'] ) ? $parts['path'] : '';
|
2013-08-07 08:38:38 +02:00
|
|
|
if (isset($parts['query'])) {
|
|
|
|
$req .= '?' . $parts['query'];
|
|
|
|
// parse the url query vars into $_GET
|
|
|
|
parse_str($parts['query'], $_GET);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$req = $url;
|
|
|
|
}
|
|
|
|
if ( ! isset( $parts['query'] ) ) {
|
|
|
|
$parts['query'] = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
$_SERVER['REQUEST_URI'] = $req;
|
|
|
|
unset($_SERVER['PATH_INFO']);
|
|
|
|
|
2016-08-27 10:35:16 +02:00
|
|
|
self::flush_cache();
|
2013-08-07 08:38:38 +02:00
|
|
|
unset($GLOBALS['wp_query'], $GLOBALS['wp_the_query']);
|
2013-08-08 04:55:44 +02:00
|
|
|
$GLOBALS['wp_the_query'] = new WP_Query();
|
|
|
|
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
|
2015-10-21 03:58:52 +02:00
|
|
|
|
2015-10-18 07:00:40 +02:00
|
|
|
$public_query_vars = $GLOBALS['wp']->public_query_vars;
|
|
|
|
$private_query_vars = $GLOBALS['wp']->private_query_vars;
|
|
|
|
|
2013-08-08 04:55:44 +02:00
|
|
|
$GLOBALS['wp'] = new WP();
|
2015-10-18 07:00:40 +02:00
|
|
|
$GLOBALS['wp']->public_query_vars = $public_query_vars;
|
|
|
|
$GLOBALS['wp']->private_query_vars = $private_query_vars;
|
|
|
|
|
2013-11-04 23:46:44 +01:00
|
|
|
_cleanup_query_vars();
|
2013-08-07 08:38:38 +02:00
|
|
|
|
|
|
|
$GLOBALS['wp']->main($parts['query']);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function checkRequirements() {
|
|
|
|
parent::checkRequirements();
|
2014-11-22 22:10:12 +01:00
|
|
|
|
2017-05-01 22:34:10 +02:00
|
|
|
$annotations = $this->getAnnotations();
|
|
|
|
|
|
|
|
if ( ! empty( $annotations['group'] ) ) {
|
|
|
|
if ( in_array( 'ms-required', $annotations['group'], true ) ) {
|
|
|
|
$this->skipWithoutMultisite();
|
|
|
|
}
|
|
|
|
if ( in_array( 'ms-excluded', $annotations['group'], true ) ) {
|
|
|
|
$this->skipWithMultisite();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-22 22:10:12 +01:00
|
|
|
// Core tests no longer check against open Trac tickets, but others using WP_UnitTestCase may do so.
|
|
|
|
if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-07 08:38:38 +02:00
|
|
|
if ( WP_TESTS_FORCE_KNOWN_BUGS )
|
|
|
|
return;
|
|
|
|
$tickets = PHPUnit_Util_Test::getTickets( get_class( $this ), $this->getName( false ) );
|
|
|
|
foreach ( $tickets as $ticket ) {
|
|
|
|
if ( is_numeric( $ticket ) ) {
|
|
|
|
$this->knownWPBug( $ticket );
|
|
|
|
} elseif ( 'Plugin' == substr( $ticket, 0, 6 ) ) {
|
|
|
|
$ticket = substr( $ticket, 6 );
|
|
|
|
if ( $ticket && is_numeric( $ticket ) )
|
|
|
|
$this->knownPluginBug( $ticket );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Skips the current test if there is an open WordPress ticket with id $ticket_id
|
|
|
|
*/
|
|
|
|
function knownWPBug( $ticket_id ) {
|
|
|
|
if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( $ticket_id, self::$forced_tickets ) )
|
|
|
|
return;
|
2014-01-06 19:09:12 +01:00
|
|
|
if ( ! TracTickets::isTracTicketClosed( 'https://core.trac.wordpress.org', $ticket_id ) )
|
2013-08-07 08:38:38 +02:00
|
|
|
$this->markTestSkipped( sprintf( 'WordPress Ticket #%d is not fixed', $ticket_id ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-04-22 21:38:42 +02:00
|
|
|
* @deprecated No longer used since the unit test Trac was merged into Core's.
|
2013-08-07 08:38:38 +02:00
|
|
|
*/
|
|
|
|
function knownUTBug( $ticket_id ) {
|
2017-04-22 21:38:42 +02:00
|
|
|
return;
|
2013-08-07 08:38:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Skips the current test if there is an open plugin ticket with id $ticket_id
|
|
|
|
*/
|
|
|
|
function knownPluginBug( $ticket_id ) {
|
|
|
|
if ( WP_TESTS_FORCE_KNOWN_BUGS || in_array( 'Plugin' . $ticket_id, self::$forced_tickets ) )
|
|
|
|
return;
|
2014-01-06 19:09:12 +01:00
|
|
|
if ( ! TracTickets::isTracTicketClosed( 'https://plugins.trac.wordpress.org', $ticket_id ) )
|
2013-08-07 08:38:38 +02:00
|
|
|
$this->markTestSkipped( sprintf( 'WordPress Plugin Ticket #%d is not fixed', $ticket_id ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function forceTicket( $ticket ) {
|
|
|
|
self::$forced_tickets[] = $ticket;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Define constants after including files.
|
|
|
|
*/
|
2013-08-08 04:55:44 +02:00
|
|
|
function prepareTemplate( Text_Template $template ) {
|
2013-08-07 08:38:38 +02:00
|
|
|
$template->setVar( array( 'constants' => '' ) );
|
|
|
|
$template->setVar( array( 'wp_constants' => PHPUnit_Util_GlobalState::getConstantsAsString() ) );
|
|
|
|
parent::prepareTemplate( $template );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the name of a temporary file
|
|
|
|
*/
|
|
|
|
function temp_filename() {
|
|
|
|
$tmp_dir = '';
|
|
|
|
$dirs = array( 'TMP', 'TMPDIR', 'TEMP' );
|
|
|
|
foreach( $dirs as $dir )
|
|
|
|
if ( isset( $_ENV[$dir] ) && !empty( $_ENV[$dir] ) ) {
|
|
|
|
$tmp_dir = $dir;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( empty( $tmp_dir ) ) {
|
|
|
|
$tmp_dir = '/tmp';
|
|
|
|
}
|
2014-11-07 02:36:05 +01:00
|
|
|
$tmp_dir = realpath( $tmp_dir );
|
2013-08-07 08:38:38 +02:00
|
|
|
return tempnam( $tmp_dir, 'wpunit' );
|
|
|
|
}
|
2013-11-04 22:55:12 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Check each of the WP_Query is_* functions/properties against expected boolean value.
|
|
|
|
*
|
2017-04-11 12:48:00 +02:00
|
|
|
* Any properties that are listed by name as parameters will be expected to be true; all others are
|
2013-11-04 22:55:12 +01:00
|
|
|
* expected to be false. For example, assertQueryTrue('is_single', 'is_feed') means is_single()
|
|
|
|
* and is_feed() must be true and everything else must be false to pass.
|
|
|
|
*
|
|
|
|
* @param string $prop,... Any number of WP_Query properties that are expected to be true for the current request.
|
|
|
|
*/
|
|
|
|
function assertQueryTrue(/* ... */) {
|
|
|
|
global $wp_query;
|
|
|
|
$all = array(
|
2015-10-18 06:50:15 +02:00
|
|
|
'is_404',
|
|
|
|
'is_admin',
|
|
|
|
'is_archive',
|
|
|
|
'is_attachment',
|
|
|
|
'is_author',
|
|
|
|
'is_category',
|
|
|
|
'is_comment_feed',
|
|
|
|
'is_date',
|
|
|
|
'is_day',
|
|
|
|
'is_embed',
|
|
|
|
'is_feed',
|
2016-08-27 17:27:35 +02:00
|
|
|
'is_front_page',
|
2015-10-18 06:50:15 +02:00
|
|
|
'is_home',
|
|
|
|
'is_month',
|
|
|
|
'is_page',
|
|
|
|
'is_paged',
|
|
|
|
'is_post_type_archive',
|
|
|
|
'is_posts_page',
|
|
|
|
'is_preview',
|
|
|
|
'is_robots',
|
|
|
|
'is_search',
|
|
|
|
'is_single',
|
|
|
|
'is_singular',
|
|
|
|
'is_tag',
|
|
|
|
'is_tax',
|
|
|
|
'is_time',
|
|
|
|
'is_trackback',
|
|
|
|
'is_year',
|
2013-11-04 22:55:12 +01:00
|
|
|
);
|
|
|
|
$true = func_get_args();
|
|
|
|
|
2016-08-27 17:27:35 +02:00
|
|
|
foreach ( $true as $true_thing ) {
|
2017-04-11 12:48:00 +02:00
|
|
|
$this->assertContains( $true_thing, $all, "Unknown conditional: {$true_thing}." );
|
2016-08-27 17:27:35 +02:00
|
|
|
}
|
|
|
|
|
2013-11-04 22:55:12 +01:00
|
|
|
$passed = true;
|
2017-04-11 12:48:00 +02:00
|
|
|
$message = '';
|
2013-11-04 22:55:12 +01:00
|
|
|
|
|
|
|
foreach ( $all as $query_thing ) {
|
|
|
|
$result = is_callable( $query_thing ) ? call_user_func( $query_thing ) : $wp_query->$query_thing;
|
|
|
|
|
|
|
|
if ( in_array( $query_thing, $true ) ) {
|
|
|
|
if ( ! $result ) {
|
2017-04-11 12:48:00 +02:00
|
|
|
$message .= $query_thing . ' is false but is expected to be true. ' . PHP_EOL;
|
2013-11-04 22:55:12 +01:00
|
|
|
$passed = false;
|
|
|
|
}
|
|
|
|
} else if ( $result ) {
|
2017-04-11 12:48:00 +02:00
|
|
|
$message .= $query_thing . ' is true but is expected to be false. ' . PHP_EOL;
|
2013-11-04 22:55:12 +01:00
|
|
|
$passed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-11 12:48:00 +02:00
|
|
|
if ( ! $passed ) {
|
|
|
|
$this->fail( $message );
|
|
|
|
}
|
2013-11-04 22:55:12 +01:00
|
|
|
}
|
2014-07-12 09:08:15 +02:00
|
|
|
|
|
|
|
function unlink( $file ) {
|
|
|
|
$exists = is_file( $file );
|
|
|
|
if ( $exists && ! in_array( $file, self::$ignore_files ) ) {
|
|
|
|
//error_log( $file );
|
|
|
|
unlink( $file );
|
|
|
|
} elseif ( ! $exists ) {
|
|
|
|
$this->fail( "Trying to delete a file that doesn't exist: $file" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function rmdir( $path ) {
|
|
|
|
$files = $this->files_in_dir( $path );
|
|
|
|
foreach ( $files as $file ) {
|
|
|
|
if ( ! in_array( $file, self::$ignore_files ) ) {
|
|
|
|
$this->unlink( $file );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function remove_added_uploads() {
|
|
|
|
// Remove all uploads.
|
|
|
|
$uploads = wp_upload_dir();
|
|
|
|
$this->rmdir( $uploads['basedir'] );
|
|
|
|
}
|
|
|
|
|
|
|
|
function files_in_dir( $dir ) {
|
|
|
|
$files = array();
|
|
|
|
|
|
|
|
$iterator = new RecursiveDirectoryIterator( $dir );
|
|
|
|
$objects = new RecursiveIteratorIterator( $iterator );
|
|
|
|
foreach ( $objects as $name => $object ) {
|
|
|
|
if ( is_file( $name ) ) {
|
|
|
|
$files[] = $name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $files;
|
|
|
|
}
|
|
|
|
|
|
|
|
function scan_user_uploads() {
|
|
|
|
static $files = array();
|
|
|
|
if ( ! empty( $files ) ) {
|
|
|
|
return $files;
|
|
|
|
}
|
|
|
|
|
|
|
|
$uploads = wp_upload_dir();
|
|
|
|
$files = $this->files_in_dir( $uploads['basedir'] );
|
|
|
|
return $files;
|
|
|
|
}
|
2014-11-13 23:03:15 +01:00
|
|
|
|
2014-11-30 20:05:52 +01:00
|
|
|
function delete_folders( $path ) {
|
|
|
|
$this->matched_dirs = array();
|
|
|
|
if ( ! is_dir( $path ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->scandir( $path );
|
|
|
|
foreach ( array_reverse( $this->matched_dirs ) as $dir ) {
|
|
|
|
rmdir( $dir );
|
|
|
|
}
|
|
|
|
rmdir( $path );
|
|
|
|
}
|
|
|
|
|
|
|
|
function scandir( $dir ) {
|
|
|
|
foreach ( scandir( $dir ) as $path ) {
|
|
|
|
if ( 0 !== strpos( $path, '.' ) && is_dir( $dir . '/' . $path ) ) {
|
|
|
|
$this->matched_dirs[] = $dir . '/' . $path;
|
|
|
|
$this->scandir( $dir . '/' . $path );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-13 23:03:15 +01:00
|
|
|
/**
|
|
|
|
* Helper to Convert a microtime string into a float
|
|
|
|
*/
|
|
|
|
protected function _microtime_to_float($microtime ){
|
|
|
|
$time_array = explode( ' ', $microtime );
|
|
|
|
return array_sum( $time_array );
|
|
|
|
}
|
2015-06-18 15:52:29 +02:00
|
|
|
|
2015-06-26 14:58:29 +02:00
|
|
|
/**
|
|
|
|
* Multisite-agnostic way to delete a user from the database.
|
|
|
|
*
|
|
|
|
* @since 4.3.0
|
|
|
|
*/
|
|
|
|
public static function delete_user( $user_id ) {
|
|
|
|
if ( is_multisite() ) {
|
|
|
|
return wpmu_delete_user( $user_id );
|
|
|
|
} else {
|
|
|
|
return wp_delete_user( $user_id );
|
|
|
|
}
|
|
|
|
}
|
2015-09-30 15:08:49 +02:00
|
|
|
|
2015-10-03 19:14:12 +02:00
|
|
|
/**
|
|
|
|
* Utility method that resets permalinks and flushes rewrites.
|
|
|
|
*
|
|
|
|
* @since 4.4.0
|
|
|
|
*
|
|
|
|
* @global WP_Rewrite $wp_rewrite
|
2015-10-03 22:54:11 +02:00
|
|
|
*
|
|
|
|
* @param string $structure Optional. Permalink structure to set. Default empty.
|
2015-10-03 19:14:12 +02:00
|
|
|
*/
|
2015-10-03 22:54:11 +02:00
|
|
|
public function set_permalink_structure( $structure = '' ) {
|
2015-10-03 19:14:12 +02:00
|
|
|
global $wp_rewrite;
|
|
|
|
|
2015-10-03 21:26:24 +02:00
|
|
|
$wp_rewrite->init();
|
2015-10-03 22:54:11 +02:00
|
|
|
$wp_rewrite->set_permalink_structure( $structure );
|
2015-10-03 19:14:12 +02:00
|
|
|
$wp_rewrite->flush_rules();
|
|
|
|
}
|
2015-10-21 03:58:52 +02:00
|
|
|
|
|
|
|
function _make_attachment($upload, $parent_post_id = 0) {
|
|
|
|
$type = '';
|
|
|
|
if ( !empty($upload['type']) ) {
|
|
|
|
$type = $upload['type'];
|
|
|
|
} else {
|
|
|
|
$mime = wp_check_filetype( $upload['file'] );
|
|
|
|
if ($mime)
|
|
|
|
$type = $mime['type'];
|
|
|
|
}
|
|
|
|
|
|
|
|
$attachment = array(
|
|
|
|
'post_title' => basename( $upload['file'] ),
|
|
|
|
'post_content' => '',
|
|
|
|
'post_type' => 'attachment',
|
|
|
|
'post_parent' => $parent_post_id,
|
|
|
|
'post_mime_type' => $type,
|
|
|
|
'guid' => $upload[ 'url' ],
|
|
|
|
);
|
|
|
|
|
|
|
|
// Save the data
|
|
|
|
$id = wp_insert_attachment( $attachment, $upload[ 'file' ], $parent_post_id );
|
|
|
|
wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
|
|
|
|
return $id;
|
|
|
|
}
|
2017-05-10 20:51:28 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* There's no way to change post_modified through WP functions.
|
|
|
|
*/
|
|
|
|
protected function update_post_modified( $post_id, $date ) {
|
|
|
|
global $wpdb;
|
|
|
|
return $wpdb->update(
|
|
|
|
$wpdb->posts,
|
|
|
|
array(
|
|
|
|
'post_modified' => $date,
|
|
|
|
'post_modified_gmt' => $date,
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'ID' => $post_id,
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'%s',
|
|
|
|
'%s',
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'%d',
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2014-11-13 23:03:15 +01:00
|
|
|
}
|