Tests_Feeds_RSS2::test_item_elements()   C
last analyzed

Complexity

Conditions 8
Paths 33

Size

Total Lines 88
Code Lines 45

Duplication

Lines 4
Ratio 4.55 %

Importance

Changes 0
Metric Value
cc 8
eloc 45
nc 33
nop 0
dl 4
loc 88
rs 5.6862
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Test the RSS 2.0 feed by generating a feed, parsing it, and checking that the
5
 * parsed contents match the contents of the posts stored in the database.  Since
6
 * we're using a real XML parser, this confirms that the feed is valid, well formed,
7
 * and contains the right stuff.
8
 *
9
 * @group feed
10
 */
11
class Tests_Feeds_RSS2 extends WP_UnitTestCase
12
{
13
    static $user_id;
14
    static $posts;
15
    static $category;
16
    static $post_date;
17
18
    /**
19
     * Setup a new user and attribute some posts.
20
     */
21
    public static function wpSetUpBeforeClass( $factory ) 
0 ignored issues
show
Coding Style introduced by
The function name wpSetUpBeforeClass is in camel caps, but expected wp_set_up_before_class instead as per the coding standard.
Loading history...
22
    {
23
        // Create a user
24
        self::$user_id = $factory->user->create(
25
            array(
26
            'role'         => 'author',
27
            'user_login'   => 'test_author',
28
            'display_name' => 'Test A. Uthor',
29
            ) 
30
        );
31
32
        // Create a taxonomy
33
        self::$category = $factory->category->create_and_get(
34
            array(
35
            'name' => 'Foo Category',
36
            'slug' => 'foo',
37
            ) 
38
        );
39
40
        // Set a predictable time for testing date archives.
41
        self::$post_date = '2003-05-27 10:07:53';
42
43
        $count = get_option('posts_per_rss') + 1;
44
45
        // Create a few posts
46
        self::$posts = $factory->post->create_many(
47
            $count, array(
48
            'post_author'  => self::$user_id,
49
            'post_date'    => self::$post_date,
50
            'post_content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec velit massa, ultrices eu est suscipit, mattis posuere est. Donec vitae purus lacus. Cras vitae odio odio.',
51
            'post_excerpt' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
52
            ) 
53
        );
54
55
        // Assign a category to those posts
56
        foreach ( self::$posts as $post ) {
57
            wp_set_object_terms($post, self::$category->slug, 'category');
58
        }
59
    }
60
61
    /**
62
     * Setup.
63
     */
64 View Code Duplication
    public function setUp() 
0 ignored issues
show
Coding Style introduced by
The function name setUp is in camel caps, but expected set_up instead as per the coding standard.
Loading history...
65
    {
66
        parent::setUp();
67
68
        $this->post_count = (int) get_option('posts_per_rss');
69
        $this->excerpt_only = get_option('rss_use_excerpt');
70
        // this seems to break something
71
        update_option('use_smilies', false);
72
73
        $this->set_permalink_structure('/%year%/%monthnum%/%day%/%postname%/');
74
        create_initial_taxonomies();
75
    }
76
77
    /**
78
     * This is a bit of a hack used to buffer feed content.
79
     */
80 View Code Duplication
    function do_rss2() 
81
    {
82
        ob_start();
83
        // Nasty hack! In the future it would better to leverage do_feed( 'rss2' ).
84
        global $post;
85
        try {
86
            @include ABSPATH . 'wp-includes/feed-rss2.php';
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Coding Style introduced by
Silencing errors is discouraged
Loading history...
87
            $out = ob_get_clean();
88
        } catch (Exception $e) {
89
            $out = ob_get_clean();
90
            throw($e);
91
        }
92
        return $out;
93
    }
94
95
    /**
96
     * Test the <rss> element to make sure its present and populated
97
     * with the expected child elements and attributes.
98
     */
99
    function test_rss_element() 
100
    {
101
        $this->go_to('/?feed=rss2');
102
        $feed = $this->do_rss2();
103
        $xml = xml_to_array($feed);
104
105
        // Get the <rss> child element of <xml>.
106
        $rss = xml_find($xml, 'rss');
107
108
        // There should only be one <rss> child element.
109
        $this->assertEquals(1, count($rss));
110
111
        $this->assertEquals('2.0', $rss[0]['attributes']['version']);
112
        $this->assertEquals('http://purl.org/rss/1.0/modules/content/', $rss[0]['attributes']['xmlns:content']);
113
        $this->assertEquals('http://wellformedweb.org/CommentAPI/', $rss[0]['attributes']['xmlns:wfw']);
114
        $this->assertEquals('http://purl.org/dc/elements/1.1/', $rss[0]['attributes']['xmlns:dc']);
115
116
        // rss should have exactly one child element (channel)
117
        $this->assertEquals(1, count($rss[0]['child']));
118
    }
119
120
    /**
121
     * [test_channel_element description]
122
  *
123
     * @return [type] [description]
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
124
     */
125
    function test_channel_element() 
126
    {
127
        $this->go_to('/?feed=rss2');
128
        $feed = $this->do_rss2();
129
        $xml = xml_to_array($feed);
130
131
        // get the rss -> channel element
132
        $channel = xml_find($xml, 'rss', 'channel');
133
134
        // The channel should be free of attributes
135
        $this->assertTrue(empty($channel[0]['attributes']));
136
137
        // Verify the channel is present and contains a title child element
138
        $title = xml_find($xml, 'rss', 'channel', 'title');
139
        $this->assertEquals(get_option('blogname'), $title[0]['content']);
140
141
        $desc = xml_find($xml, 'rss', 'channel', 'description');
142
        $this->assertEquals(get_option('blogdescription'), $desc[0]['content']);
143
144
        $link = xml_find($xml, 'rss', 'channel', 'link');
145
        $this->assertEquals(get_option('siteurl'), $link[0]['content']);
146
147
        $pubdate = xml_find($xml, 'rss', 'channel', 'lastBuildDate');
148
        $this->assertEquals(strtotime(get_lastpostmodified()), strtotime($pubdate[0]['content']));
149
    }
150
151
    /**
152
     * @ticket UT32
153
     */
154
    function test_item_elements() 
155
    {
156
        $this->go_to('/?feed=rss2');
157
        $feed = $this->do_rss2();
158
        $xml = xml_to_array($feed);
159
160
        // Get all the <item> child elements of the <channel> element
161
        $items = xml_find($xml, 'rss', 'channel', 'item');
162
163
        // Verify we are displaying the correct number of posts.
164
        $this->assertCount($this->post_count, $items);
165
166
        // We Really only need to test X number of items unless the content is different
167
        $items = array_slice($items, 1);
168
169
        // Check each of the desired entries against the known post data
170
        foreach ( $items as $key => $item ) {
171
172
            // Get post for comparison
173
            $guid = xml_find($items[$key]['child'], 'guid');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
174
            preg_match('/\?p=(\d+)/', $guid[0]['content'], $matches);
175
            $post = get_post($matches[1]);
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
176
177
            // Title
178
            $title = xml_find($items[$key]['child'], 'title');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
179
            $this->assertEquals($post->post_title, $title[0]['content']);
180
181
            // Link
182
            $link = xml_find($items[$key]['child'], 'link');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
183
            $this->assertEquals(get_permalink($post), $link[0]['content']);
184
185
            // Comment link
186
            $comments_link = xml_find($items[$key]['child'], 'comments');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
187
            $this->assertEquals(get_permalink($post) . '#respond', $comments_link[0]['content']);
188
189
            // Pub date
190
            $pubdate = xml_find($items[$key]['child'], 'pubDate');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
191
            $this->assertEquals(strtotime($post->post_date_gmt), strtotime($pubdate[0]['content']));
192
193
            // Author
194
            $creator = xml_find($items[$key]['child'], 'dc:creator');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
195
            $user = new WP_User($post->post_author);
196
            $this->assertEquals($user->display_name, $creator[0]['content']);
197
198
            // Categories (perhaps multiple)
199
            $categories = xml_find($items[$key]['child'], 'category');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
200
            $cats = array();
201
            foreach ( get_the_category($post->ID) as $term ) {
202
                $cats[] = $term->name;
203
            }
204
205
            $tags = get_the_tags($post->ID);
206
            if ($tags ) {
207
                foreach ( get_the_tags($post->ID) as $term ) {
208
                    $cats[] = $term->name;
209
                }
210
            }
211
            $cats = array_filter($cats);
212
            // Should be the same number of categories
213
            $this->assertEquals(count($cats), count($categories));
214
215
            // ..with the same names
216
            foreach ( $cats as $id => $cat ) {
217
                $this->assertEquals($cat, $categories[$id]['content']);
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
218
            }
219
220
            // GUID
221
            $guid = xml_find($items[$key]['child'], 'guid');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
222
            $this->assertEquals('false', $guid[0]['attributes']['isPermaLink']);
223
            $this->assertEquals($post->guid, $guid[0]['content']);
224
225
            // Description / Excerpt
226
            if (! empty($post->post_excerpt) ) {
0 ignored issues
show
introduced by
Expected 1 space before "!"; 0 found
Loading history...
227
                $description = xml_find($items[$key]['child'], 'description');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
228
                $this->assertEquals(trim($post->post_excerpt), trim($description[0]['content']));
229
            }
230
231
            // Post content
232 View Code Duplication
            if (! $this->excerpt_only ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
introduced by
Expected 1 space before "!"; 0 found
Loading history...
233
                $content = xml_find($items[$key]['child'], 'content:encoded');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
234
                $this->assertEquals(trim(apply_filters('the_content', $post->post_content)), trim($content[0]['content']));
235
            }
236
237
            // Comment rss
238
            $comment_rss = xml_find($items[$key]['child'], 'wfw:commentRss');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
239
            $this->assertEquals(html_entity_decode(get_post_comments_feed_link($post->ID)), $comment_rss[0]['content']);
240
        }
241
    }
242
243
    /**
244
     * @ticket 9134
245
     */
246
    function test_items_comments_closed() 
247
    {
248
        add_filter('comments_open', '__return_false');
249
250
        $this->go_to('/?feed=rss2');
251
        $feed = $this->do_rss2();
252
        $xml = xml_to_array($feed);
253
254
        // get all the rss -> channel -> item elements
255
        $items = xml_find($xml, 'rss', 'channel', 'item');
256
257
        // check each of the items against the known post data
258
        foreach ( $items as $key => $item ) {
259
            // Get post for comparison
260
            $guid = xml_find($items[$key]['child'], 'guid');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
261
            preg_match('/\?p=(\d+)/', $guid[0]['content'], $matches);
262
            $post = get_post($matches[1]);
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
263
264
            // comment link
265
            $comments_link = xml_find($items[ $key ]['child'], 'comments');
266
            $this->assertEmpty($comments_link);
267
268
            // comment rss
269
            $comment_rss = xml_find($items[ $key ]['child'], 'wfw:commentRss');
270
            $this->assertEmpty($comment_rss);
271
        }
272
273
        remove_filter('comments_open', '__return_false');
274
    }
275
276
    /*
277
    * Check to make sure we are rendering feed templates for the home feed.
278
    * e.g. https://example.com/feed/
279
    *
280
    * @ticket 30210
281
    */
282
    function test_valid_home_feed_endpoint() 
283
    {
284
        // An example of a valid home feed endpoint.
285
        $this->go_to('feed/');
286
287
        // Verify the query object is a feed.
288
        $this->assertQueryTrue('is_feed');
289
290
        // Queries performed on valid feed endpoints should contain posts.
291
        $this->assertTrue(have_posts());
292
293
        // Check to see if we have the expected XML output from the feed template.
294
        $feed = $this->do_rss2();
295
296
        $xml = xml_to_array($feed);
297
298
        // Get the <rss> child element of <xml>.
299
        $rss = xml_find($xml, 'rss');
300
301
        // There should only be one <rss> child element.
302
        $this->assertEquals(1, count($rss));
303
    }
304
305
    /*
306
    * Check to make sure we are rendering feed templates for the taxonomy feeds.
307
    * e.g. https://example.com/category/foo/feed/
308
    *
309
    * @ticket 30210
310
    */
311 View Code Duplication
    function test_valid_taxonomy_feed_endpoint() 
312
    {
313
        // An example of an valid taxonomy feed endpoint.
314
        $this->go_to('category/foo/feed/');
315
316
        // Verify the query object is a feed.
317
        $this->assertQueryTrue('is_feed', 'is_archive', 'is_category');
318
319
        // Queries performed on valid feed endpoints should contain posts.
320
        $this->assertTrue(have_posts());
321
322
        // Check to see if we have the expected XML output from the feed template.
323
        $feed = $this->do_rss2();
324
325
        $xml = xml_to_array($feed);
326
327
        // Get the <rss> child element of <xml>.
328
        $rss = xml_find($xml, 'rss');
329
330
        // There should only be one <rss> child element.
331
        $this->assertEquals(1, count($rss));
332
    }
333
334
    /*
335
    * Check to make sure we are rendering feed templates for the main comment feed.
336
    * e.g. https://example.com/comments/feed/
337
    *
338
    * @ticket 30210
339
    */
340
    function test_valid_main_comment_feed_endpoint() 
341
    {
342
        // Generate a bunch of comments
343
        foreach ( self::$posts as $post ) {
344
            self::factory()->comment->create_post_comments($post, 3);
345
        }
346
347
        // An example of an valid main comment feed endpoint.
348
        $this->go_to('comments/feed/');
349
350
        // Verify the query object is a feed.
351
        $this->assertQueryTrue('is_feed', 'is_comment_feed');
352
353
        // Queries performed on valid feed endpoints should contain comments.
354
        $this->assertTrue(have_comments());
355
356
        // Check to see if we have the expected XML output from the feed template.
357
        $feed = $this->do_rss2();
358
359
        $xml = xml_to_array($feed);
360
361
        // Get the <rss> child element of <xml>.
362
        $rss = xml_find($xml, 'rss');
363
364
        // There should only be one <rss> child element.
365
        $this->assertEquals(1, count($rss));
366
    }
367
368
    /*
369
    * Check to make sure we are rendering feed templates for the date archive feeds.
370
    * e.g. https://example.com/2003/05/27/feed/
371
    *
372
    * @ticket 30210
373
    */
374 View Code Duplication
    function test_valid_archive_feed_endpoint() 
375
    {
376
        // An example of an valid date archive feed endpoint.
377
        $this->go_to('2003/05/27/feed/');
378
379
        // Verify the query object is a feed.
380
        $this->assertQueryTrue('is_feed', 'is_archive', 'is_day', 'is_date');
381
382
        // Queries performed on valid feed endpoints should contain posts.
383
        $this->assertTrue(have_posts());
384
385
        // Check to see if we have the expected XML output from the feed template.
386
        $feed = $this->do_rss2();
387
388
        $xml = xml_to_array($feed);
389
390
        // Get the <rss> child element of <xml>.
391
        $rss = xml_find($xml, 'rss');
392
393
        // There should only be one <rss> child element.
394
        $this->assertEquals(1, count($rss));
395
    }
396
397
    /*
398
    * Check to make sure we are rendering feed templates for single post comment feeds.
399
    * e.g. https://example.com/2003/05/27/post-name/feed/
400
    *
401
    * @ticket 30210
402
    */
403 View Code Duplication
    function test_valid_single_post_comment_feed_endpoint() 
404
    {
405
        // An example of an valid date archive feed endpoint.
406
        $this->go_to(get_post_comments_feed_link(self::$posts[0]));
407
408
        // Verify the query object is a feed.
409
        $this->assertQueryTrue('is_feed', 'is_comment_feed', 'is_single', 'is_singular');
410
411
        // Queries performed on valid feed endpoints should contain posts.
412
        $this->assertTrue(have_posts());
413
414
        // Check to see if we have the expected XML output from the feed template.
415
        $feed = $this->do_rss2();
416
417
        $xml = xml_to_array($feed);
418
419
        // Get the <rss> child element of <xml>.
420
        $rss = xml_find($xml, 'rss');
421
422
        // There should only be one <rss> child element.
423
        $this->assertEquals(1, count($rss));
424
    }
425
426
    /*
427
    * Check to make sure we are rendering feed templates for the search archive feeds.
428
    * e.g. https://example.com/?s=Lorem&feed=rss
429
    *
430
    * @ticket 30210
431
    */
432
    function test_valid_search_feed_endpoint() 
433
    {
434
        // An example of an valid search feed endpoint
435
        $this->go_to('?s=Lorem&feed=rss');
436
437
        // Verify the query object is a feed.
438
        $this->assertQueryTrue('is_feed', 'is_search');
439
440
        // Queries performed on valid feed endpoints should contain posts.
441
        $this->assertTrue(have_posts());
442
443
        // Check to see if we have the expected XML output from the feed template.
444
        $feed = $this->do_rss2();
445
446
        $xml = xml_to_array($feed);
447
448
        // Get the <rss> child element of <xml>.
449
        $rss = xml_find($xml, 'rss');
450
451
        // There should only be one <rss> child element.
452
        $this->assertEquals(1, count($rss));
453
    }
454
455
    /*
456
    * Check to make sure we are not rendering feed templates for invalid feed endpoints.
457
    * e.g. https://example.com/wp-content/feed/
458
    *
459
    * @ticket 30210
460
    */
461
    function test_invalid_feed_endpoint() 
462
    {
463
        // An example of an invalid feed endpoint
464
        $this->go_to('wp-content/feed/');
465
466
        // Queries performed on invalid feed endpoints should never contain posts.
467
        $this->assertFalse(have_posts());
468
469
        // This is the assertion. Once the exception is thrown in do_feed, execution stops, preventing futher assertions.
470
        $this->setExpectedException('WPDieException', 'ERROR: This is not a valid feed.');
471
        do_feed();
472
    }
473
474
    /*
475
    * Make sure the requested feed is registered before rendering the requested template.
476
    *
477
    * @ticket 30210
478
    */
479
    function test_nonexistent_feeds() 
480
    {
481
        global $wp_rewrite;
482
        $badfeed = 'badfeed';
483
484
        $this->assertNotContains($badfeed, $wp_rewrite->feeds);
485
486
        $this->go_to('/?feed=' . $badfeed);
487
488
        // This is the assertion. Once the exception is thrown in do_feed, execution stops, preventing futher assertions.
489
        $this->setExpectedException('WPDieException', 'ERROR: This is not a valid feed template.');
490
        do_feed();
491
    }
492
493
}
494