Completed
Push — master ( c6a753...e758eb )
by Mike
02:16
created

Post::delete()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 64
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 32
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 64
rs 8.6346

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
namespace testContent\Types;
3
use testContent as Main;
4
use testContent\TestContent as TestContent;
5
use testContent\Delete as Delete;
6
use testContent\Abstracts as Abs;
7
8
9
/**
10
 * Class to build test data for custom post types.
11
 *
12
 * @package    WordPress
13
 * @subpackage Evans
14
 * @author     Old Town Media
15
 */
16
class Post extends Abs\Type{
17
18
	/**
19
	 * metaboxes
20
	 * Easy access for the Metaboxes class.
21
	 *
22
	 * @var string
23
	 * @access private
24
	 */
25
	private $metaboxes;
26
27
	protected $type = 'post';
28
29
	/**
30
	 * Constructor to load in the Metaboxes class.
31
	 *
32
	 * @see Metaboxes
33
	 */
34
	public function __construct(){
35
36
		$this->metaboxes = new Main\Metaboxes;
0 ignored issues
show
Documentation Bug introduced by
It seems like new \testContent\Metaboxes() of type object<testContent\Metaboxes> is incompatible with the declared type string of property $metaboxes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
37
38
	}
39
40
	/**
41
	 * Create test data posts.
42
	 *
43
	 * This is where the magic begins. We accept a cpt id (slug) and potntially
44
	 * a number of posts to create. We then fetch the supports & metaboxes
45
	 * for that cpt and feed them into a function to create each post individually.
46
	 *
47
	 * @access private
48
	 *
49
	 * @see $this->get_cpt_supports, $this->get_metaboxes, $this->create_test_object
50
	 *
51
	 * @param string $slug a custom post type ID.
52
	 * @param boolean $connection Whether or not we're connected to the Internet.
53
	 * @param boolean $echo Whether or not to echo. Optional.
54
	 * @param int $num Optional. Number of posts to create.
55
	 */
56
	public function create_objects( $slug, $connection, $echo = false, $num = '' ){
57
58
		// If we're missing a custom post type id - don't do anything
59
		if ( empty( $slug ) ){
60
			return;
61
		}
62
63
		// Gather the necessary data to create the posts
64
		$supports 	= $this->get_cpt_supports( $slug );
65
		$metaboxes	= $this->metaboxes->get_metaboxes( $slug );
0 ignored issues
show
Bug introduced by
The method get_metaboxes cannot be called on $this->metaboxes (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
66
67
		// Set our connection status for the rest of the methods
68
		$this->connected = $connection;
0 ignored issues
show
Bug introduced by
The property connected does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
69
70
		// If we forgot to put in a quantity, make one for us
71
		if ( empty( $num ) ){
72
			$num = rand( 5, 30 );
73
		}
74
75
		// Create test posts
76 View Code Duplication
		for( $i = 0; $i < $num; $i++ ){
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...
77
78
			$return = $this->create_test_object( $slug, $supports, $metaboxes );
79
80
			if ( $echo === true ){
81
				echo \json_encode( $return );
82
			}
83
84
		}
85
86
	}
87
88
89
	/**
90
	 * Creates the individual test data post.
91
	 *
92
	 * Create individual posts for testing with. Gathers basic information such
93
	 * as title, content, thumbnail, etc. and inserts them with the post. Also
94
	 * adds metaboxes if applicable .
95
	 *
96
	 * @access private
97
	 *
98
	 * @see TestContent, wp_insert_post, add_post_meta, update_post_meta, $this->random_metabox_content
99
	 *
100
	 * @param string $slug a custom post type ID.
101
	 * @param array $supports Features that the post type supports.
102
	 * @param array $supports All CMB2 metaboxes attached to the post type.
103
	 */
104
	private function create_test_object( $slug, $supports, $metaboxes ){
105
		$return = '';
106
107
		// Get a random title
108
		$title = apply_filters( "tc_{$slug}_post_title", TestContent::title() );
109
110
		// First, insert our post
111
		$post = array(
112
		  'post_name'      => sanitize_title( $title ),
113
		  'post_status'    => 'publish',
114
		  'post_type'      => $slug,
115
		  'ping_status'    => 'closed',
116
		  'comment_status' => 'closed',
117
		);
118
119
		// Add title if supported
120
		if ( $supports['title'] === true ){
121
			$post['post_title'] = $title;
122
		}
123
124
		// Add main content if supported
125
		if ( $supports['editor'] === true ){
126
			$post['post_content'] = apply_filters( "tc_{$slug}_post_content", TestContent::paragraphs() );
127
		}
128
129
		// Add excerpt content if supported
130
		if ( $supports['excerpt'] === true ){
131
			$post['post_excerpt'] = apply_filters( "tc_{$slug}_post_excerpt", TestContent::plain_text() );
132
		}
133
134
		// Insert then post object
135
		$post_id = wp_insert_post( apply_filters( "tc_{$slug}_post_arguments", $post ) );
136
137
		// Then, set a test content flag on the new post for later deletion
138
		add_post_meta( $post_id, 'evans_test_content', '__test__', true );
139
140
		// Add thumbnail if supported
141
		if ( $this->connected == true && ( $supports['thumbnail'] === true || in_array( $slug, array( 'post', 'page' ) ) ) ){
142
			 update_post_meta( $post_id, '_thumbnail_id', TestContent::image( $post_id ) );
143
		}
144
145
		$taxonomies = get_object_taxonomies( $slug );
146
147
		// Assign the post to terms
148
		if ( !empty( $taxonomies ) ){
149
			$return .= $this->assign_terms( $post_id, $taxonomies );
150
		}
151
152
		// Spin up metaboxes
153
		if ( !empty( $metaboxes ) ){
154
			foreach ( $metaboxes as $cmb ) :
155
				$return .= $this->metaboxes->random_metabox_content( $post_id, $cmb, $this->connected );
0 ignored issues
show
Bug introduced by
The method random_metabox_content cannot be called on $this->metaboxes (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
156
			endforeach;
157
		}
158
159
		// Check if we have errors and return them or created message
160
		if ( is_wp_error( $return ) ){
161
			error_log( $return->get_error_message() );
0 ignored issues
show
Bug introduced by
The method get_error_message cannot be called on $return (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
162
			return $return;
163
		} else {
164
			return array(
165
				'type'		=> 'created',
166
				'object'	=> 'post',
167
				'pid'		=> $post_id,
168
				'post_type'	=> get_post_type( $post_id ),
169
				'link_edit'	=> admin_url( '/post.php?post='.$post_id.'&action=edit' ),
170
				'link_view'	=> get_permalink( $post_id ),
171
			);
172
		}
173
174
	}
175
176
177
	/**
178
	 * Assemble supports statements for a particular post type.
179
	 *
180
	 * @access private
181
	 *
182
	 * @see post_type_supports
183
	 *
184
	 * @param string $slug a custom post type ID.
185
	 * @return array Array of necessary supports booleans.
186
	 */
187
	private function get_cpt_supports( $slug ){
188
189
		$supports = array(
190
			'title'		=> post_type_supports( $slug, 'title' ),
191
			'editor'	=> post_type_supports( $slug, 'editor' ),
192
			'excerpt'	=> post_type_supports( $slug, 'excerpt' ),
193
			'thumbnail'	=> post_type_supports( $slug, 'thumbnail' )
194
		);
195
196
		return $supports;
197
198
	}
199
200
201
	/**
202
	 * Assigns taxonomies to the new post.
203
	 *
204
	 * Loop through every taxonomy type associated with a custom post type &
205
	 * assign the post to a random item out of each taxonomy. Taxonomies must
206
	 * have at least one term in them for this to work.
207
	 *
208
	 * @access private
209
	 *
210
	 * @param int $post_id a custom post type ID.
211
	 * @param array $taxonomies taxonomies assigned to this cpt.
212
	 * @return object WP Error if there is one.
213
	 */
214
	private function assign_terms( $post_id, $taxonomies ){
215
216
		// Make sure it's an array & has items
217
		if ( empty( $taxonomies ) || !is_array( $taxonomies ) ){
218
			return;
219
		}
220
221
		foreach ( $taxonomies as $tax ){
222
223
			// Get the individual terms already existing
224
			$terms = get_terms( $tax, array( 'hide_empty'	=> false ) );
225
			$count = count( $terms ) - 1;
226
227
			// If there are no terms, skip to the next taxonomy
228
			if ( empty( $terms ) ){
229
				continue;
230
			}
231
232
			// Get a random index to use
233
			$index = rand( 0, $count );
234
235
			// Initialize our array
236
			$post_data = array(
237
				'ID'	=> $post_id
238
			);
239
240
			// Set the term data to update
241
			$post_data['tax_input'][ $tax ] = array( $terms[$index]->term_id );
242
243
			// Update the post with the taxonomy info
244
			$return = wp_update_post( $post_data );
245
246
			// Return the error if it exists
247
			if ( is_wp_error( $return ) ){
248
				error_log( $return->get_error_messages() );
249
				return $return->get_error_messages();
250
			}
251
252
		}
253
254
	}
255
256
	/**
257
	 * Delete test data posts.
258
	 *
259
	 * This function will search for all posts of a particular post type ($slug)
260
	 * and delete them all using a particular cmb flag that we set when creating
261
	 * the posts. Validates the user first.
262
	 *
263
	 * @see WP_Query, wp_delete_post
264
	 *
265
	 * @param string $slug a custom post type ID.
266
	 * @param boolean $echo Whether or not to echo the result
267
	 */
268
	public function delete( $slug, $echo = false ){
269
270
		$delete =  new Delete;
271
272
		// Make sure that the current user is logged in & has full permissions.
273
		if ( !$delete->user_can_delete() ){
274
			return;
275
		}
276
277
		// Check that $cptslg has a string.
278
		if ( empty( $slug ) ){
279
			return;
280
		}
281
282
		// Find our test data by the unique flag we set when we created the data
283
		$query = array(
284
			'post_type' 		=> $slug,
285
			'posts_per_page'	=> 500,
286
			'meta_query' 		=> array(
287
				array(
288
					'key'     => 'evans_test_content',
289
					'value'   => '__test__',
290
					'compare' => '=',
291
				),
292
			),
293
		);
294
295
		$objects = new \WP_Query( $query );
296
297
		if ( $objects->have_posts() ){
298
299
			$events = array();
300
301
			while ( $objects->have_posts() ) : $objects->the_post();
302
303
				// Find any media associated with the test post and delete it as well
304
				$this->delete_associated_media( get_the_id() );
305
306
				if ( $echo === true ){
307
					$events[] = array(
308
						'type'		=> 'deleted',
309
						'pid'		=> get_the_id(),
310
						'post_type'	=> get_post_type( get_the_id() ),
311
						'link'		=> ''
312
					);
313
				}
314
315
				// Force delete the post
316
				wp_delete_post( get_the_id(), true );
317
318
			endwhile;
319
320
			$obj = get_post_type_object( $slug );
321
322
			$events[] = array(
323
				'type'		=> 'general',
324
				'message'	=> __( 'Deleted', 'otm-test-content' ) . ' ' . $obj->labels->all_items
325
			);
326
327
			echo \json_encode( $events );
328
329
		}
330
331
	}
332
333
334
	/**
335
	 * Find and delete attachments associated with a post ID.
336
	 *
337
	 * This function finds each attachment that is associated with a post ID
338
	 * and deletes it completely from the site. This is to prevent leftover
339
	 * random images from sitting on the site forever.
340
	 *
341
	 * @access private
342
	 *
343
	 * @see get_attached_media, wp_delete_attachment
344
	 *
345
	 * @param int $pid a custom post type ID.
346
	 */
347
	private function delete_associated_media( $pid ){
348
349
		$delete =  new Delete;
350
351
		// Make sure that the current user is logged in & has full permissions.
352
		if ( !$delete->user_can_delete() ){
353
			return;
354
		}
355
356
		// Make sure $pid is, in fact, an ID
357
		if ( !is_int( $pid ) ){
358
			return;
359
		}
360
361
		// Get our images
362
		$media = get_attached_media( 'image', $pid );
363
364
		if ( !empty( $media ) ){
365
366
			// Loop through the media & delete each one
367
			foreach ( $media as $attachment ){
368
				wp_delete_attachment( $attachment->ID, true );
369
			}
370
371
		}
372
373
	}
374
375
376
}
377