Wordpress/tests/phpunit/includes/factory.php

430 lines
12 KiB
PHP
Raw Normal View History

<?php
class WP_UnitTest_Factory {
/**
* @var WP_UnitTest_Factory_For_Post
*/
public $post;
/**
* @var WP_UnitTest_Factory_For_Attachment
*/
public $attachment;
/**
* @var WP_UnitTest_Factory_For_Comment
*/
public $comment;
/**
* @var WP_UnitTest_Factory_For_User
*/
public $user;
/**
* @var WP_UnitTest_Factory_For_Term
*/
public $term;
/**
* @var WP_UnitTest_Factory_For_Term
*/
public $category;
/**
* @var WP_UnitTest_Factory_For_Term
*/
public $tag;
/**
* @var WP_UnitTest_Factory_For_Blog
*/
public $blog;
/**
* @var WP_UnitTest_Factory_For_Network
*/
public $network;
function __construct() {
$this->post = new WP_UnitTest_Factory_For_Post( $this );
$this->attachment = new WP_UnitTest_Factory_For_Attachment( $this );
$this->comment = new WP_UnitTest_Factory_For_Comment( $this );
$this->user = new WP_UnitTest_Factory_For_User( $this );
$this->term = new WP_UnitTest_Factory_For_Term( $this );
$this->category = new WP_UnitTest_Factory_For_Term( $this, 'category' );
$this->tag = new WP_UnitTest_Factory_For_Term( $this, 'post_tag' );
if ( is_multisite() ) {
$this->blog = new WP_UnitTest_Factory_For_Blog( $this );
$this->network = new WP_UnitTest_Factory_For_Network( $this );
}
}
}
class WP_UnitTest_Factory_For_Post extends WP_UnitTest_Factory_For_Thing {
function __construct( $factory = null ) {
parent::__construct( $factory );
$this->default_generation_definitions = array(
'post_status' => 'publish',
'post_title' => new WP_UnitTest_Generator_Sequence( 'Post title %s' ),
'post_content' => new WP_UnitTest_Generator_Sequence( 'Post content %s' ),
'post_excerpt' => new WP_UnitTest_Generator_Sequence( 'Post excerpt %s' ),
'post_type' => 'post'
);
}
function create_object( $args ) {
return wp_insert_post( $args );
}
function update_object( $post_id, $fields ) {
$fields['ID'] = $post_id;
return wp_update_post( $fields );
}
function get_object_by_id( $post_id ) {
return get_post( $post_id );
}
}
class WP_UnitTest_Factory_For_Attachment extends WP_UnitTest_Factory_For_Post {
function create_object( $file, $parent = 0, $args = array() ) {
return wp_insert_attachment( $args, $file, $parent );
}
Merge the Responsive Images feature plugin into core, initial commit. See: https://github.com/ResponsiveImagesCG/wp-tevko-responsive-images/ New functions in `media.php`: * `wp_get_attachment_image_srcset_array()` - Returns an array of image candidate string data used to build a `srcset` value for an attachment given an `$attachement_id` and `$size`. * `wp_get_attachment_image_srcset()` - Returns the `srcset` value for an attachment given an `$attachement_id` and `$size`. * `wp_get_attachment_image_sizes()` - Returns the `sizes` value for an attachment given an `$attachement_id` and `$size` and optional arguments used to alter its output. * `wp_make_content_images_responsive()` - A display filter for adding `srcset` and `sizes` to images embedded in content. * `wp_img_add_srcset_and_sizes()` - A utility function used by `wp_make_content_images_responsive()` to add `srcset` and `sizes` to a single `<img>` element. Modifies existing core functions: * Modify `wp_get_attachment_image()` so the HTML returned for an image includes `srcset` and `sizes`. * Modify `get_media_embedded_in_content()` (sup, 3.6 leftover) by adding `<img>` to the list of accepted tags that can be matched in content. This is used in `wp_make_content_images_responsive()` to find all of the images embedded in content before passing them off to `wp_img_add_srcset_and_sizes()`. Tests: * Add a new factory method to `WP_UnitTest_Factory_For_Attachment` named `create_upload_object()` * Adds unit tests * Updates unit tests Props joemcgill, tevko, jaspermdegroot, mdmcginn, barryceelen, peterwilsoncc, fsylum, wonderboymusic, chriscoyier, benjaminpick, jrfnl, #12kingkool68, janhenckens, ryanmarkel, side777, ryelle, wturrell, micahmills, mattbagwell, coliff, DrewAPicture. See #33641. git-svn-id: https://develop.svn.wordpress.org/trunk@34855 602fd350-edb4-49c9-b593-d223f7449a82
2015-10-06 06:58:21 +02:00
function create_upload_object( $file, $parent = 0 ) {
$contents = file_get_contents($file);
$upload = wp_upload_bits(basename($file), null, $contents);
$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_mime_type' => $type,
'guid' => $upload[ 'url' ],
);
// Save the data
$id = wp_insert_attachment( $attachment, $upload[ 'file' ], $parent );
wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $upload['file'] ) );
return $id;
}
}
class WP_UnitTest_Factory_For_User extends WP_UnitTest_Factory_For_Thing {
function __construct( $factory = null ) {
parent::__construct( $factory );
$this->default_generation_definitions = array(
'user_login' => new WP_UnitTest_Generator_Sequence( 'User %s' ),
'user_pass' => 'password',
'user_email' => new WP_UnitTest_Generator_Sequence( 'user_%s@example.org' ),
);
}
function create_object( $args ) {
return wp_insert_user( $args );
}
function update_object( $user_id, $fields ) {
$fields['ID'] = $user_id;
return wp_update_user( $fields );
}
function get_object_by_id( $user_id ) {
return new WP_User( $user_id );
}
}
class WP_UnitTest_Factory_For_Comment extends WP_UnitTest_Factory_For_Thing {
function __construct( $factory = null ) {
parent::__construct( $factory );
$this->default_generation_definitions = array(
'comment_author' => new WP_UnitTest_Generator_Sequence( 'Commenter %s' ),
'comment_author_url' => new WP_UnitTest_Generator_Sequence( 'http://example.com/%s/' ),
'comment_approved' => 1,
'comment_content' => 'This is a comment'
);
}
function create_object( $args ) {
return wp_insert_comment( $this->addslashes_deep( $args ) );
}
function update_object( $comment_id, $fields ) {
$fields['comment_ID'] = $comment_id;
return wp_update_comment( $this->addslashes_deep( $fields ) );
}
function create_post_comments( $post_id, $count = 1, $args = array(), $generation_definitions = null ) {
$args['comment_post_ID'] = $post_id;
return $this->create_many( $count, $args, $generation_definitions );
}
function get_object_by_id( $comment_id ) {
return get_comment( $comment_id );
}
}
class WP_UnitTest_Factory_For_Blog extends WP_UnitTest_Factory_For_Thing {
function __construct( $factory = null ) {
global $current_site, $base;
parent::__construct( $factory );
$this->default_generation_definitions = array(
'domain' => $current_site->domain,
'path' => new WP_UnitTest_Generator_Sequence( $base . 'testpath%s' ),
'title' => new WP_UnitTest_Generator_Sequence( 'Site %s' ),
'site_id' => $current_site->id,
);
}
function create_object( $args ) {
global $wpdb;
$meta = isset( $args['meta'] ) ? $args['meta'] : array();
$user_id = isset( $args['user_id'] ) ? $args['user_id'] : get_current_user_id();
// temp tables will trigger db errors when we attempt to reference them as new temp tables
$suppress = $wpdb->suppress_errors();
$blog = wpmu_create_blog( $args['domain'], $args['path'], $args['title'], $user_id, $meta, $args['site_id'] );
$wpdb->suppress_errors( $suppress );
Use `wp_installing()` instead of `WP_INSTALLING` constant. The `WP_INSTALLING` constant is a flag that WordPress sets in a number of places, telling the system that options should be fetched directly from the database instead of from the cache, that WP should not ping wordpress.org for updates, that the normal "not installed" checks should be bypassed, and so on. A constant is generally necessary for this purpose, because the flag is typically set before the WP bootstrap, meaning that WP functions are not yet available. However, it is possible - notably, during `wpmu_create_blog()` - for the "installing" flag to be set after WP has already loaded. In these cases, `WP_INSTALLING` would be set for the remainder of the process, since there's no way to change a constant once it's defined. This, in turn, polluted later function calls that ought to have been outside the scope of site creation, particularly the non-caching of option data. The problem was particularly evident in the case of the automated tests, where `WP_INSTALLING` was set the first time a site was created, and remained set for the rest of the suite. The new `wp_installing()` function allows developers to fetch the current installation status (when called without any arguments) or to set the installation status (when called with a boolean `true` or `false`). Use of the `WP_INSTALLING` constant is still supported; `wp_installing()` will default to `true` if the constant is defined during the bootstrap. Props boonebgorges, jeremyfelt. See #31130. git-svn-id: https://develop.svn.wordpress.org/trunk@34828 602fd350-edb4-49c9-b593-d223f7449a82
2015-10-05 17:05:26 +02:00
// Tell WP we're done installing.
wp_installing( false );
return $blog;
}
function update_object( $blog_id, $fields ) {}
function get_object_by_id( $blog_id ) {
return get_blog_details( $blog_id, false );
}
}
class WP_UnitTest_Factory_For_Network extends WP_UnitTest_Factory_For_Thing {
function __construct( $factory = null ) {
parent::__construct( $factory );
$this->default_generation_definitions = array(
'domain' => WP_TESTS_DOMAIN,
'title' => new WP_UnitTest_Generator_Sequence( 'Network %s' ),
'path' => new WP_UnitTest_Generator_Sequence( '/testpath%s/' ),
'network_id' => new WP_UnitTest_Generator_Sequence( '%s', 2 ),
'subdomain_install' => false,
);
}
function create_object( $args ) {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
if ( ! isset( $args['user'] ) ) {
$email = WP_TESTS_EMAIL;
} else {
$email = get_userdata( $args['user'] )->user_email;
}
populate_network( $args['network_id'], $args['domain'], $email, $args['title'], $args['path'], $args['subdomain_install'] );
return $args['network_id'];
}
function update_object( $network_id, $fields ) {}
function get_object_by_id( $network_id ) {
return wp_get_network( $network_id );
}
}
class WP_UnitTest_Factory_For_Term extends WP_UnitTest_Factory_For_Thing {
private $taxonomy;
const DEFAULT_TAXONOMY = 'post_tag';
function __construct( $factory = null, $taxonomy = null ) {
parent::__construct( $factory );
$this->taxonomy = $taxonomy ? $taxonomy : self::DEFAULT_TAXONOMY;
$this->default_generation_definitions = array(
'name' => new WP_UnitTest_Generator_Sequence( 'Term %s' ),
'taxonomy' => $this->taxonomy,
'description' => new WP_UnitTest_Generator_Sequence( 'Term description %s' ),
);
}
function create_object( $args ) {
$args = array_merge( array( 'taxonomy' => $this->taxonomy ), $args );
$term_id_pair = wp_insert_term( $args['name'], $args['taxonomy'], $args );
if ( is_wp_error( $term_id_pair ) )
return $term_id_pair;
return $term_id_pair['term_id'];
}
function update_object( $term, $fields ) {
$fields = array_merge( array( 'taxonomy' => $this->taxonomy ), $fields );
if ( is_object( $term ) )
$taxonomy = $term->taxonomy;
$term_id_pair = wp_update_term( $term, $taxonomy, $fields );
return $term_id_pair['term_id'];
}
function add_post_terms( $post_id, $terms, $taxonomy, $append = true ) {
return wp_set_post_terms( $post_id, $terms, $taxonomy, $append );
}
function create_and_get( $args = array(), $generation_definitions = null ) {
$term_id = $this->create( $args, $generation_definitions );
$taxonomy = isset( $args['taxonomy'] ) ? $args['taxonomy'] : $this->taxonomy;
return get_term( $term_id, $taxonomy );
}
function get_object_by_id( $term_id ) {
return get_term( $term_id, $this->taxonomy );
}
}
abstract class WP_UnitTest_Factory_For_Thing {
var $default_generation_definitions;
var $factory;
/**
* Creates a new factory, which will create objects of a specific Thing
*
* @param object $factory Global factory that can be used to create other objects on the system
* @param array $default_generation_definitions Defines what default values should the properties of the object have. The default values
* can be generators -- an object with next() method. There are some default generators: {@link WP_UnitTest_Generator_Sequence},
* {@link WP_UnitTest_Generator_Locale_Name}, {@link WP_UnitTest_Factory_Callback_After_Create}.
*/
function __construct( $factory, $default_generation_definitions = array() ) {
$this->factory = $factory;
$this->default_generation_definitions = $default_generation_definitions;
}
abstract function create_object( $args );
abstract function update_object( $object, $fields );
function create( $args = array(), $generation_definitions = null ) {
if ( is_null( $generation_definitions ) )
$generation_definitions = $this->default_generation_definitions;
$generated_args = $this->generate_args( $args, $generation_definitions, $callbacks );
$created = $this->create_object( $generated_args );
if ( !$created || is_wp_error( $created ) )
return $created;
if ( $callbacks ) {
$updated_fields = $this->apply_callbacks( $callbacks, $created );
$save_result = $this->update_object( $created, $updated_fields );
if ( !$save_result || is_wp_error( $save_result ) )
return $save_result;
}
return $created;
}
function create_and_get( $args = array(), $generation_definitions = null ) {
$object_id = $this->create( $args, $generation_definitions );
return $this->get_object_by_id( $object_id );
}
abstract function get_object_by_id( $object_id );
function create_many( $count, $args = array(), $generation_definitions = null ) {
$results = array();
for ( $i = 0; $i < $count; $i++ ) {
$results[] = $this->create( $args, $generation_definitions );
}
return $results;
}
function generate_args( $args = array(), $generation_definitions = null, &$callbacks = null ) {
$callbacks = array();
if ( is_null( $generation_definitions ) )
$generation_definitions = $this->default_generation_definitions;
foreach( array_keys( $generation_definitions ) as $field_name ) {
if ( !isset( $args[$field_name] ) ) {
$generator = $generation_definitions[$field_name];
if ( is_scalar( $generator ) )
$args[$field_name] = $generator;
elseif ( is_object( $generator ) && method_exists( $generator, 'call' ) ) {
$callbacks[$field_name] = $generator;
} elseif ( is_object( $generator ) )
$args[$field_name] = $generator->next();
else
return new WP_Error( 'invalid_argument', 'Factory default value should be either a scalar or an generator object.' );
}
}
return $args;
}
function apply_callbacks( $callbacks, $created ) {
$updated_fields = array();
foreach( $callbacks as $field_name => $generator ) {
$updated_fields[$field_name] = $generator->call( $created );
}
return $updated_fields;
}
function callback( $function ) {
return new WP_UnitTest_Factory_Callback_After_Create( $function );
}
function addslashes_deep($value) {
if ( is_array( $value ) ) {
$value = array_map( array( $this, 'addslashes_deep' ), $value );
} elseif ( is_object( $value ) ) {
$vars = get_object_vars( $value );
foreach ($vars as $key=>$data) {
$value->{$key} = $this->addslashes_deep( $data );
}
} elseif ( is_string( $value ) ) {
$value = addslashes( $value );
}
return $value;
}
}
class WP_UnitTest_Generator_Sequence {
var $next;
var $template_string;
function __construct( $template_string = '%s', $start = 1 ) {
$this->next = $start;
$this->template_string = $template_string;
}
function next() {
$generated = sprintf( $this->template_string , $this->next );
$this->next++;
return $generated;
}
}
class WP_UnitTest_Factory_Callback_After_Create {
var $callback;
function __construct( $callback ) {
$this->callback = $callback;
}
function call( $object ) {
return call_user_func( $this->callback, $object );
}
}