Tests_Feeds_Atom::test_entry_elements()   C
last analyzed

Complexity

Conditions 10
Paths 73

Size

Total Lines 77
Code Lines 39

Duplication

Lines 4
Ratio 5.19 %

Importance

Changes 0
Metric Value
cc 10
eloc 39
nc 73
nop 0
dl 4
loc 77
rs 5.6756
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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 Atom 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_Atom extends WP_UnitTestCase
12
{
13
    static $user_id;
14
    static $posts;
15
    static $category;
16
17
    /**
18
     * Setup a new user and attribute some posts.
19
     */
20
    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...
21
    {
22
        // Create a user
23
        self::$user_id = $factory->user->create(
24
            array(
25
            'role'         => 'author',
26
            'user_login'   => 'test_author',
27
            'display_name' => 'Test A. Uthor',
28
            ) 
29
        );
30
31
        // Create a taxonomy
32
        self::$category = self::factory()->category->create_and_get(
33
            array(
34
            'name' => 'Test Category',
35
            'slug' => 'test-cat',
36
            ) 
37
        );
38
39
        $count = get_option('posts_per_rss') + 1;
40
41
        // Create a few posts
42
        self::$posts = $factory->post->create_many(
43
            $count, array(
44
            'post_author'  => self::$user_id,
45
            '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.',
46
            'post_excerpt' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
47
            ) 
48
        );
49
50
        // Assign a category to those posts
51
        foreach ( self::$posts as $post ) {
52
            wp_set_object_terms($post, self::$category->slug, 'category');
53
        }
54
55
    }
56
57
    /**
58
     * Setup.
59
     */
60
    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...
61
    {
62
        parent::setUp();
63
64
        $this->post_count = (int) get_option('posts_per_rss');
65
        $this->excerpt_only = get_option('rss_use_excerpt');
66
    }
67
68
    /**
69
     * This is a bit of a hack used to buffer feed content.
70
     */
71 View Code Duplication
    function do_atom() 
72
    {
73
        ob_start();
74
        // Nasty hack! In the future it would better to leverage do_feed( 'atom' ).
75
        global $post;
76
        try {
77
            @include ABSPATH . 'wp-includes/feed-atom.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...
78
            $out = ob_get_clean();
79
        } catch ( Exception $e ) {
80
            $out = ob_get_clean();
81
            throw( $e );
82
        }
83
        return $out;
84
    }
85
86
    /**
87
     * Test the <feed> element to make sure its present and populated
88
     * with the expected child elements and attributes.
89
     */
90
    function test_feed_element() 
91
    {
92
        $this->go_to('/?feed=atom');
93
        $feed = $this->do_atom();
94
        $xml = xml_to_array($feed);
95
96
        // Get the <feed> child element of <xml>.
97
        $atom = xml_find($xml, 'feed');
98
99
        // There should only be one <feed> child element.
100
        $this->assertCount(1, $atom);
101
102
        // Verify attributes.
103
        $this->assertEquals('http://www.w3.org/2005/Atom', $atom[0]['attributes']['xmlns']);
104
        $this->assertEquals('http://purl.org/syndication/thread/1.0', $atom[0]['attributes']['xmlns:thr']);
105
        $this->assertEquals(site_url('/wp-atom.php'), $atom[0]['attributes']['xml:base']);
106
107
        // Verify the <feed> element is present and contains a <title> child element.
108
        $title = xml_find($xml, 'feed', 'title');
109
        $this->assertEquals(get_option('blogname'), $title[0]['content']);
110
111
        // Verify the <feed> element is present and contains a <updated> child element.
112
        $updated = xml_find($xml, 'feed', 'updated');
113
        $this->assertEquals(strtotime(get_lastpostmodified()), strtotime($updated[0]['content']));
114
115
        // Verify the <feed> element is present and contains a <subtitle> child element.
116
        $subtitle = xml_find($xml, 'feed', 'subtitle');
117
        $this->assertEquals(get_option('blogdescription'), $subtitle[0]['content']);
118
119
        // Verify the <feed> element is present and contains two <link> child elements.
120
        $link = xml_find($xml, 'feed', 'link');
121
        $this->assertCount(2, $link);
122
123
        // Verify the <feed> element is present and contains a <link rel="alternate"> child element.
124
        $this->assertEquals('alternate', $link[0]['attributes']['rel']);
125
        $this->assertEquals(home_url(), $link[0]['attributes']['href']);
126
127
        // Verify the <feed> element is present and contains a <link rel="href"> child element.
128
        $this->assertEquals('self', $link[1]['attributes']['rel']);
129
        $this->assertEquals(home_url('/?feed=atom'), $link[1]['attributes']['href']);
130
    }
131
132
    /**
133
     * Validate <entry> child elements.
134
     */
135
    function test_entry_elements() 
136
    {
137
        $this->go_to('/?feed=atom');
138
        $feed = $this->do_atom();
139
        $xml = xml_to_array($feed);
140
141
        // Get all the <entry> child elements of the <feed> element.
142
        $entries = xml_find($xml, 'feed', 'entry');
143
144
        // Verify we are displaying the correct number of posts.
145
        $this->assertCount($this->post_count, $entries);
146
147
        // We Really only need to test X number of entries unless the content is different
148
        $entries = array_slice($entries, 1);
149
150
        // Check each of the desired entries against the known post data.
151
        foreach ( $entries as $key => $entry ) {
152
153
            // Get post for comparison
154
            $id = xml_find($entries[$key]['child'], 'id');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
155
            preg_match('/\?p=(\d+)/', $id[0]['content'], $matches);
156
            $post = get_post($matches[1]);
0 ignored issues
show
introduced by
Overridding WordPress globals is prohibited
Loading history...
157
158
            // Author
159
            $author = xml_find($entries[$key]['child'], 'author', 'name');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
160
            $user = new WP_User($post->post_author);
161
            $this->assertEquals($user->display_name, $author[0]['content']);
162
163
            // Title
164
            $title = xml_find($entries[$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...
165
            $this->assertEquals($post->post_title, $title[0]['content']);
166
167
            // Link rel="alternate"
168
            $link_alts = xml_find($entries[$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...
169
            foreach ( $link_alts as $link_alt ) {
170
                if ('alternate' == $link_alt['attributes']['rel'] ) {
171
                    $this->assertEquals(get_permalink($post), $link_alt['attributes']['href']);
172
                }
173
            }
174
175
            // Id
176
            $guid = xml_find($entries[$key]['child'], 'id');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
177
            $this->assertEquals($post->guid, $id[0]['content']);
178
179
            // Updated
180
            $updated = xml_find($entries[$key]['child'], 'updated');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
181
            $this->assertEquals(strtotime($post->post_modified_gmt), strtotime($updated[0]['content']));
182
183
            // Published
184
            $published = xml_find($entries[$key]['child'], 'published');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
185
            $this->assertEquals(strtotime($post->post_date_gmt), strtotime($published[0]['content']));
186
187
            // Category
188
            foreach ( get_the_category($post->ID) as $term ) {
189
                $terms[] = $term->name;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$terms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $terms = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
190
            }
191
            $categories = xml_find($entries[$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...
192
            foreach ( $categories as $category ) {
193
                $this->assertTrue(in_array($category['attributes']['term'], $terms));
0 ignored issues
show
Bug introduced by
The variable $terms does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
194
            }
195
            unset($terms);
196
197
            // Content
198 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...
199
                $content = xml_find($entries[$key]['child'], 'content');
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
200
                $this->assertEquals(trim(apply_filters('the_content', $post->post_content)), trim($content[0]['content']));
201
            }
202
203
            // Link rel="replies"
204
            $link_replies = xml_find($entries[$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...
205
            foreach ( $link_replies as $link_reply ) {
206
                if ('replies' == $link_reply['attributes']['rel'] && 'application/atom+xml' == $link_reply['attributes']['type'] ) {
207
                    $this->assertEquals(get_post_comments_feed_link($post->ID, 'atom'), $link_reply['attributes']['href']);
208
                }
209
            }
210
        }
211
    }
212
}
213