Make WordPress Core

source: trunk/tests/phpunit/includes/factory.php @ 34828

Last change on this file since 34828 was 34828, checked in by boonebgorges, 10 years ago

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.

File size: 11.7 KB
Line 
1<?php
2
3class WP_UnitTest_Factory {
4
5        /**
6         * @var WP_UnitTest_Factory_For_Post
7         */
8        public $post;
9
10        /**
11         * @var WP_UnitTest_Factory_For_Attachment
12         */
13        public $attachment;
14
15        /**
16         * @var WP_UnitTest_Factory_For_Comment
17         */
18        public $comment;
19
20        /**
21         * @var WP_UnitTest_Factory_For_User
22         */
23        public $user;
24
25        /**
26         * @var WP_UnitTest_Factory_For_Term
27         */
28        public $term;
29
30        /**
31         * @var WP_UnitTest_Factory_For_Term
32         */
33        public $category;
34
35        /**
36         * @var WP_UnitTest_Factory_For_Term
37         */
38        public $tag;
39
40        /**
41         * @var WP_UnitTest_Factory_For_Blog
42         */
43        public $blog;
44
45        /**
46         * @var WP_UnitTest_Factory_For_Network
47         */
48        public $network;
49
50        function __construct() {
51                $this->post = new WP_UnitTest_Factory_For_Post( $this );
52                $this->attachment = new WP_UnitTest_Factory_For_Attachment( $this );
53                $this->comment = new WP_UnitTest_Factory_For_Comment( $this );
54                $this->user = new WP_UnitTest_Factory_For_User( $this );
55                $this->term = new WP_UnitTest_Factory_For_Term( $this );
56                $this->category = new WP_UnitTest_Factory_For_Term( $this, 'category' );
57                $this->tag = new WP_UnitTest_Factory_For_Term( $this, 'post_tag' );
58                if ( is_multisite() ) {
59                        $this->blog = new WP_UnitTest_Factory_For_Blog( $this );
60                        $this->network = new WP_UnitTest_Factory_For_Network( $this );
61                }
62        }
63}
64
65class WP_UnitTest_Factory_For_Post extends WP_UnitTest_Factory_For_Thing {
66
67        function __construct( $factory = null ) {
68                parent::__construct( $factory );
69                $this->default_generation_definitions = array(
70                        'post_status' => 'publish',
71                        'post_title' => new WP_UnitTest_Generator_Sequence( 'Post title %s' ),
72                        'post_content' => new WP_UnitTest_Generator_Sequence( 'Post content %s' ),
73                        'post_excerpt' => new WP_UnitTest_Generator_Sequence( 'Post excerpt %s' ),
74                        'post_type' => 'post'
75                );
76        }
77
78        function create_object( $args ) {
79                return wp_insert_post( $args );
80        }
81
82        function update_object( $post_id, $fields ) {
83                $fields['ID'] = $post_id;
84                return wp_update_post( $fields );
85        }
86
87        function get_object_by_id( $post_id ) {
88                return get_post( $post_id );
89        }
90}
91
92class WP_UnitTest_Factory_For_Attachment extends WP_UnitTest_Factory_For_Post {
93
94        function create_object( $file, $parent = 0, $args = array() ) {
95                return wp_insert_attachment( $args, $file, $parent );
96        }
97}
98
99class WP_UnitTest_Factory_For_User extends WP_UnitTest_Factory_For_Thing {
100
101        function __construct( $factory = null ) {
102                parent::__construct( $factory );
103                $this->default_generation_definitions = array(
104                        'user_login' => new WP_UnitTest_Generator_Sequence( 'User %s' ),
105                        'user_pass' => 'password',
106                        'user_email' => new WP_UnitTest_Generator_Sequence( 'user_%[email protected]' ),
107                );
108        }
109
110        function create_object( $args ) {
111                return wp_insert_user( $args );
112        }
113
114        function update_object( $user_id, $fields ) {
115                $fields['ID'] = $user_id;
116                return wp_update_user( $fields );
117        }
118
119        function get_object_by_id( $user_id ) {
120                return new WP_User( $user_id );
121        }
122}
123
124class WP_UnitTest_Factory_For_Comment extends WP_UnitTest_Factory_For_Thing {
125
126        function __construct( $factory = null ) {
127                parent::__construct( $factory );
128                $this->default_generation_definitions = array(
129                        'comment_author' => new WP_UnitTest_Generator_Sequence( 'Commenter %s' ),
130                        'comment_author_url' => new WP_UnitTest_Generator_Sequence( 'http://example.com/%s/' ),
131                        'comment_approved' => 1,
132                        'comment_content' => 'This is a comment'
133                );
134        }
135
136        function create_object( $args ) {
137                return wp_insert_comment( $this->addslashes_deep( $args ) );
138        }
139
140        function update_object( $comment_id, $fields ) {
141                $fields['comment_ID'] = $comment_id;
142                return wp_update_comment( $this->addslashes_deep( $fields ) );
143        }
144
145        function create_post_comments( $post_id, $count = 1, $args = array(), $generation_definitions = null ) {
146                $args['comment_post_ID'] = $post_id;
147                return $this->create_many( $count, $args, $generation_definitions );
148        }
149
150        function get_object_by_id( $comment_id ) {
151                return get_comment( $comment_id );
152        }
153}
154
155class WP_UnitTest_Factory_For_Blog extends WP_UnitTest_Factory_For_Thing {
156
157        function __construct( $factory = null ) {
158                global $current_site, $base;
159                parent::__construct( $factory );
160                $this->default_generation_definitions = array(
161                        'domain' => $current_site->domain,
162                        'path' => new WP_UnitTest_Generator_Sequence( $base . 'testpath%s' ),
163                        'title' => new WP_UnitTest_Generator_Sequence( 'Site %s' ),
164                        'site_id' => $current_site->id,
165                );
166        }
167
168        function create_object( $args ) {
169                global $wpdb;
170                $meta = isset( $args['meta'] ) ? $args['meta'] : array();
171                $user_id = isset( $args['user_id'] ) ? $args['user_id'] : get_current_user_id();
172                // temp tables will trigger db errors when we attempt to reference them as new temp tables
173                $suppress = $wpdb->suppress_errors();
174                $blog = wpmu_create_blog( $args['domain'], $args['path'], $args['title'], $user_id, $meta, $args['site_id'] );
175                $wpdb->suppress_errors( $suppress );
176
177                // Tell WP we're done installing.
178                wp_installing( false );
179
180                return $blog;
181        }
182
183        function update_object( $blog_id, $fields ) {}
184
185        function get_object_by_id( $blog_id ) {
186                return get_blog_details( $blog_id, false );
187        }
188}
189
190
191class WP_UnitTest_Factory_For_Network extends WP_UnitTest_Factory_For_Thing {
192
193        function __construct( $factory = null ) {
194                parent::__construct( $factory );
195                $this->default_generation_definitions = array(
196                        'domain' => WP_TESTS_DOMAIN,
197                        'title' => new WP_UnitTest_Generator_Sequence( 'Network %s' ),
198                        'path' => new WP_UnitTest_Generator_Sequence( '/testpath%s/' ),
199                        'network_id' => new WP_UnitTest_Generator_Sequence( '%s', 2 ),
200                        'subdomain_install' => false,
201                );
202        }
203
204        function create_object( $args ) {
205                require_once ABSPATH . 'wp-admin/includes/upgrade.php';
206
207                if ( ! isset( $args['user'] ) ) {
208                        $email = WP_TESTS_EMAIL;
209                } else {
210                        $email = get_userdata( $args['user'] )->user_email;
211                }
212
213                populate_network( $args['network_id'], $args['domain'], $email, $args['title'], $args['path'], $args['subdomain_install'] );
214                return $args['network_id'];
215        }
216
217        function update_object( $network_id, $fields ) {}
218
219        function get_object_by_id( $network_id ) {
220                return wp_get_network( $network_id );
221        }
222}
223
224class WP_UnitTest_Factory_For_Term extends WP_UnitTest_Factory_For_Thing {
225
226        private $taxonomy;
227        const DEFAULT_TAXONOMY = 'post_tag';
228
229        function __construct( $factory = null, $taxonomy = null ) {
230                parent::__construct( $factory );
231                $this->taxonomy = $taxonomy ? $taxonomy : self::DEFAULT_TAXONOMY;
232                $this->default_generation_definitions = array(
233                        'name' => new WP_UnitTest_Generator_Sequence( 'Term %s' ),
234                        'taxonomy' => $this->taxonomy,
235                        'description' => new WP_UnitTest_Generator_Sequence( 'Term description %s' ),
236                );
237        }
238
239        function create_object( $args ) {
240                $args = array_merge( array( 'taxonomy' => $this->taxonomy ), $args );
241                $term_id_pair = wp_insert_term( $args['name'], $args['taxonomy'], $args );
242                if ( is_wp_error( $term_id_pair ) )
243                        return $term_id_pair;
244                return $term_id_pair['term_id'];
245        }
246
247        function update_object( $term, $fields ) {
248                $fields = array_merge( array( 'taxonomy' => $this->taxonomy ), $fields );
249                if ( is_object( $term ) )
250                        $taxonomy = $term->taxonomy;
251                $term_id_pair = wp_update_term( $term, $taxonomy, $fields );
252                return $term_id_pair['term_id'];
253        }
254
255        function add_post_terms( $post_id, $terms, $taxonomy, $append = true ) {
256                return wp_set_post_terms( $post_id, $terms, $taxonomy, $append );
257        }
258
259        function create_and_get( $args = array(), $generation_definitions = null ) {
260                $term_id = $this->create( $args, $generation_definitions );
261                $taxonomy = isset( $args['taxonomy'] ) ? $args['taxonomy'] : $this->taxonomy;
262                return get_term( $term_id, $taxonomy );
263        }
264
265        function get_object_by_id( $term_id ) {
266                return get_term( $term_id, $this->taxonomy );
267        }
268}
269
270abstract class WP_UnitTest_Factory_For_Thing {
271
272        var $default_generation_definitions;
273        var $factory;
274
275        /**
276         * Creates a new factory, which will create objects of a specific Thing
277         *
278         * @param object $factory Global factory that can be used to create other objects on the system
279         * @param array $default_generation_definitions Defines what default values should the properties of the object have. The default values
280         * can be generators -- an object with next() method. There are some default generators: {@link WP_UnitTest_Generator_Sequence},
281         * {@link WP_UnitTest_Generator_Locale_Name}, {@link WP_UnitTest_Factory_Callback_After_Create}.
282         */
283        function __construct( $factory, $default_generation_definitions = array() ) {
284                $this->factory = $factory;
285                $this->default_generation_definitions = $default_generation_definitions;
286        }
287
288        abstract function create_object( $args );
289        abstract function update_object( $object, $fields );
290
291        function create( $args = array(), $generation_definitions = null ) {
292                if ( is_null( $generation_definitions ) )
293                        $generation_definitions = $this->default_generation_definitions;
294
295                $generated_args = $this->generate_args( $args, $generation_definitions, $callbacks );
296                $created = $this->create_object( $generated_args );
297                if ( !$created || is_wp_error( $created ) )
298                        return $created;
299
300                if ( $callbacks ) {
301                        $updated_fields = $this->apply_callbacks( $callbacks, $created );
302                        $save_result = $this->update_object( $created, $updated_fields );
303                        if ( !$save_result || is_wp_error( $save_result ) )
304                                return $save_result;
305                }
306                return $created;
307        }
308
309        function create_and_get( $args = array(), $generation_definitions = null ) {
310                $object_id = $this->create( $args, $generation_definitions );
311                return $this->get_object_by_id( $object_id );
312        }
313
314        abstract function get_object_by_id( $object_id );
315
316        function create_many( $count, $args = array(), $generation_definitions = null ) {
317                $results = array();
318                for ( $i = 0; $i < $count; $i++ ) {
319                        $results[] = $this->create( $args, $generation_definitions );
320                }
321                return $results;
322        }
323
324        function generate_args( $args = array(), $generation_definitions = null, &$callbacks = null ) {
325                $callbacks = array();
326                if ( is_null( $generation_definitions ) )
327                        $generation_definitions = $this->default_generation_definitions;
328
329                foreach( array_keys( $generation_definitions ) as $field_name ) {
330                        if ( !isset( $args[$field_name] ) ) {
331                                $generator = $generation_definitions[$field_name];
332                                if ( is_scalar( $generator ) )
333                                        $args[$field_name] = $generator;
334                                elseif ( is_object( $generator ) && method_exists( $generator, 'call' ) ) {
335                                        $callbacks[$field_name] = $generator;
336                                } elseif ( is_object( $generator ) )
337                                        $args[$field_name] = $generator->next();
338                                else
339                                        return new WP_Error( 'invalid_argument', 'Factory default value should be either a scalar or an generator object.' );
340                        }
341                }
342                return $args;
343        }
344
345        function apply_callbacks( $callbacks, $created ) {
346                $updated_fields = array();
347                foreach( $callbacks as $field_name => $generator ) {
348                        $updated_fields[$field_name] = $generator->call( $created );
349                }
350                return $updated_fields;
351        }
352
353        function callback( $function ) {
354                return new WP_UnitTest_Factory_Callback_After_Create( $function );
355        }
356
357        function addslashes_deep($value) {
358                if ( is_array( $value ) ) {
359                        $value = array_map( array( $this, 'addslashes_deep' ), $value );
360                } elseif ( is_object( $value ) ) {
361                        $vars = get_object_vars( $value );
362                        foreach ($vars as $key=>$data) {
363                                $value->{$key} = $this->addslashes_deep( $data );
364                        }
365                } elseif ( is_string( $value ) ) {
366                        $value = addslashes( $value );
367                }
368
369                return $value;
370        }
371
372}
373
374class WP_UnitTest_Generator_Sequence {
375        var $next;
376        var $template_string;
377
378        function __construct( $template_string = '%s', $start = 1 ) {
379                $this->next = $start;
380                $this->template_string = $template_string;
381        }
382
383        function next() {
384                $generated = sprintf( $this->template_string , $this->next );
385                $this->next++;
386                return $generated;
387        }
388}
389
390class WP_UnitTest_Factory_Callback_After_Create {
391        var $callback;
392
393        function __construct( $callback ) {
394                $this->callback = $callback;
395        }
396
397        function call( $object ) {
398                return call_user_func( $this->callback, $object );
399        }
400}
Note: See TracBrowser for help on using the repository browser.