Completed
Push — master ( 20a49a...0f8d46 )
by Evan
03:05
created

Post::__get()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 16
rs 9.2
cc 4
eloc 8
nc 4
nop 1
1
<?php
2
3
namespace Silk\Models;
4
5
use stdClass;
6
use WP_Post;
7
use Illuminate\Support\Collection;
8
use Silk\WP_ErrorException;
9
use Silk\Meta\ObjectMeta;
10
use Silk\Models\Exceptions\PostNotFoundException;
11
use Silk\Models\Exceptions\ModelPostTypeMismatchException;
12
13
class Post
14
{
15
    /**
16
     * The post
17
     * @var WP_Post
18
     */
19
    protected $post;
20
21
    /**
22
     * Post ID
23
     * @var int
24
     */
25
    protected $id;
26
27
    /**
28
     * The post type of the post this model wraps
29
     * @var string
30
     */
31
    const POST_TYPE = 'post';
32
33
34
    /**
35
     * [__construct description]
36
     * @param WP_Post $post [description]
37
     */
38
    public function __construct(WP_Post $post = null)
39
    {
40
        if (! $post) {
41
            $post = new WP_Post(new StdClass);
42
            $post->post_type = static::POST_TYPE;
43
        }
44
45
        $this->post = $post;
46
        $this->id   = $post->ID;
47
    }
48
49
    public static function fromWpPost(WP_Post $post)
50
    {
51
        if ($post->post_type !== static::POST_TYPE) {
52
            throw new ModelPostTypeMismatchException(static::class, $post);
53
        }
54
55
        return new static($post);
56
    }
57
58
    /**
59
     * Make new instance from a Post with the given ID
60
     *
61
     * @param  int|string $id [description]
62
     *
63
     * @return static
64
     */
65
    public static function fromID($id)
66
    {
67
        $post = WP_Post::get_instance($id);
68
69
        if (false === $post) {
70
            throw new PostNotFoundException("No post found with ID {$id}");
71
        }
72
73
        return static::fromWpPost($post);
74
    }
75
76
    /**
77
     * Make new instance from a Post slug
78
     *
79
     * @param  string $slug  the post slug
80
     *
81
     * @return static
82
     */
83
    public static function fromSlug($slug)
84
    {
85
        $posts = (array) get_posts([
86
            'name'           => $slug,
87
            'post_type'      => static::POST_TYPE,
88
            'post_status'    => 'any',
89
            'posts_per_page' => 1
90
        ]);
91
92
        if (! $post = reset($posts)) {
93
            throw new PostNotFoundException("No post found with slug {$slug}");
94
        }
95
96
        return static::fromWpPost($post);
97
    }
98
99
    /**
100
     * Make new instance from the global $post
101
     *
102
     * @return static
103
     */
104
    public static function fromGlobal()
105
    {
106
        $post = get_post();
107
108
        if (! $post instanceof WP_Post) {
1 ignored issue
show
Bug introduced by
The class WP_Post does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
109
            throw new PostNotFoundException('Global $post not an instance of WP_Post');
110
        }
111
112
        return static::fromWpPost($post);
113
    }
114
115
    /**
116
     * Create a new post of the model's type
117
     *
118
     * @param  [type] $attributes [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...
119
     * @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...
120
     */
121
    public static function create($attributes = [])
122
    {
123
        unset($attributes['ID']);
124
125
        $post = new WP_Post((object) $attributes);
126
        $model = static::fromWpPost($post);
127
128
        return $model->save();
129
    }
130
131
    /**
132
     * Meta API for this post
133
     *
134
     * @param  string $key [description]
135
     * @return Meta
136
     */
137
    public function meta($key = '')
138
    {
139
        $meta = new ObjectMeta('post', $this->id);
140
141
        if ($key) {
142
            return $meta->get($key);
143
        }
144
145
        return $meta;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $meta; (Silk\Meta\ObjectMeta) is incompatible with the return type documented by Silk\Models\Post::meta of type Silk\Models\Meta.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
146
    }
147
148
    /**
149
     * Send the post to the trash
150
     *
151
     * If trash is disabled, the post or page is permanently deleted.
152
     *
153
     * @return false|array|WP_Post|null Post data array, otherwise false.
154
     */
155
    public function trash()
156
    {
157
        if (wp_trash_post($this->id)) {
158
            $this->refresh();
159
        }
160
161
        return $this;
162
    }
163
164
    /**
165
     * Restore a post or page from the Trash
166
     *
167
     * @return WP_Post|false WP_Post object. False on failure.
168
     */
169
    public function untrash()
170
    {
171
        if (wp_untrash_post($this->id)) {
172
            $this->refresh();
173
        }
174
175
        return $this;
176
    }
177
178
    /**
179
     * Permanently deletes the post and related objects
180
     *
181
     * When the post and page is permanently deleted, everything that is
182
     * tied to it is deleted also. This includes comments, post meta fields,
183
     * and terms associated with the post.
184
     *
185
     * @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...
186
     */
187
    public function delete()
188
    {
189
        if (wp_delete_post($this->id, true)) {
190
            $this->refresh();
191
        }
192
193
        return $this;
194
    }
195
196
    /**
197
     * Refresh the post object from cache/database
198
     *
199
     * @return static
200
     */
201
    public function refresh()
202
    {
203
        $this->post = WP_Post::get_instance($this->id);
204
205
        return $this;
206
    }
207
208
    /**
209
     * Update the post in the database
210
     *
211
     * @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...
212
     */
213
    public function save()
214
    {
215
        if (! $this->id) {
216
            $result = wp_insert_post($this->post->to_array(), true);
217
        } else {
218
            $result = wp_update_post($this->post, true);
219
        }
220
221
        if (is_wp_error($result)) {
222
            throw new WP_ErrorException($result);
223
        }
224
225
        $this->id = (int) $result;
226
227
        return $this->refresh();
228
    }
229
230
    /**
231
     * [__get description]
232
     * @param  [type] $property [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...
233
     * @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...
234
     */
235
    public function __get($property)
236
    {
237
        if ('id' === $property) {
238
            return $this->id;
239
        }
240
        
241
        if (isset($this->$property)) {
242
            return $this->$property;
243
        }
244
245
        if (isset($this->post->$property)) {
246
            return $this->post->$property;
247
        }
248
249
        throw new \InvalidArgumentException(static::class . " has no property: {$property}");
250
    }
251
252
    /**
253
     * [__set description]
254
     * @param [type] $property [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...
255
     * @param [type] $value    [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...
256
     */
257
    public function __set($property, $value)
258
    {
259
        if (isset($this->post->$property)) {
260
            $this->post->$property = $value;
261
        }
262
    }
263
}
264