Completed
Branch BUG-9961-paypal-pro-items (52e78c)
by
unknown
49:07 queued 32:43
created

CptQueryModifier   C

Complexity

Total Complexity 63

Size/Duplication

Total Lines 544
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 0
loc 544
rs 5.8893
c 0
b 0
f 0
wmc 63
lcom 1
cbo 7

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A postType() 0 3 1
A setPostType() 0 3 1
A cptDetails() 0 3 1
A setCptDetails() 0 3 1
A modelTables() 0 3 1
A setModelTables() 0 3 1
A taxonomies() 0 6 2
A setTaxonomies() 0 3 1
A metaTable() 0 3 1
A setMetaTable() 0 3 1
A model() 0 3 1
A setModel() 0 3 1
A request() 0 3 1
A setRequest() 0 3 1
A WpQuery() 0 3 1
A setWpQuery() 0 3 1
B initializeTaxonomies() 0 21 5
B init() 0 33 2
B setAdditionalCptDetails() 0 18 5
B setRequestVarsIfCpt() 0 14 6
B setupModelsAndTables() 0 24 4
A cptStrategyClass() 0 16 2
A postsFields() 0 9 2
A postsJoin() 0 18 2
B thePosts() 0 13 5
A addTemplateFilters() 0 7 3
A singleCptTemplate() 0 15 4
B getEditPostLink() 0 25 5

How to fix   Complexity   

Complex Class

Complex classes like CptQueryModifier often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CptQueryModifier, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace EventEspresso\core\CPTs;
3
4
if ( ! defined( 'EVENT_ESPRESSO_VERSION' ) ) {
5
	exit( 'No direct script access allowed' );
6
}
7
8
9
10
/**
11
 * Class CptQueryModifier
12
 * Description
13
 *
14
 * @package       Event Espresso
15
 * @subpackage    core
16
 * @author        Brent Christensen
17
 * @since         $VID:$
18
 */
19
class CptQueryModifier {
20
21
	/**
22
	 * @var string $post_type
23
	 */
24
	protected $post_type = '';
25
26
	/**
27
	 * CPT details from \EE_Register_CPTs::get_CPTs() for specific post type
28
	 *
29
	 * @var array $cpt_details
30
	 */
31
	protected $cpt_details = array();
32
33
	/**
34
	 * @var \EE_Table_Base[] $model_tables
35
	 */
36
	protected $model_tables = array();
37
38
	/**
39
	 * @var array $taxonomies
40
	 */
41
	protected $taxonomies = array();
42
43
	/**
44
	 * meta table for the related CPT
45
	 *
46
	 * @var \EE_Secondary_Table $meta_table
47
	 */
48
	protected $meta_table;
49
50
	/**
51
	 * EEM_CPT_Base model for the related CPT
52
	 *
53
	 * @var \EEM_CPT_Base $model
54
	 */
55
	protected $model;
56
57
	/**
58
	 * @var \EE_Request_Handler $request
59
	 */
60
	protected $request;
61
62
	/**
63
	 * @var \WP_Query $wp_query
64
	 */
65
	protected $wp_query;
66
67
68
69
	/**
70
	 * CptQueryModifier constructor
71
	 *
72
	 * @param string $post_type
73
	 * @param array       $cpt_details
74
	 * @param \WP_Query           $WP_Query
75
	 * @param \EE_Request_Handler $request
76
	 */
77
	public function __construct(
78
		$post_type,
79
		array $cpt_details,
80
		\WP_Query $WP_Query,
81
		\EE_Request_Handler $request
82
	) {
83
		$this->setRequest( $request );
84
		$this->setWpQuery( $WP_Query );
85
		$this->setPostType( $post_type );
86
		$this->setCptDetails( $cpt_details );
87
		$this->init();
88
	}
89
90
91
92
	/**
93
	 * @return string
94
	 */
95
	public function postType() {
96
		return $this->post_type;
97
	}
98
99
100
101
	/**
102
	 * @param string $post_type
103
	 */
104
	protected function setPostType( $post_type ) {
105
		$this->post_type = $post_type;
106
	}
107
108
109
110
	/**
111
	 * @return array
112
	 */
113
	public function cptDetails() {
114
		return $this->cpt_details;
115
	}
116
117
118
119
	/**
120
	 * @param array $cpt_details
121
	 */
122
	protected function setCptDetails( $cpt_details ) {
123
		$this->cpt_details = $cpt_details;
124
	}
125
126
127
128
	/**
129
	 * @return \EE_Table_Base[]
130
	 */
131
	public function modelTables() {
132
		return $this->model_tables;
133
	}
134
135
136
137
	/**
138
	 * @param \EE_Table_Base[] $model_tables
139
	 */
140
	protected function setModelTables( $model_tables ) {
141
		$this->model_tables = $model_tables;
142
	}
143
144
145
146
	/**
147
	 * @return array
148
	 */
149
	public function taxonomies() {
150
		if ( empty( $this->taxonomies ) ) {
151
			$this->initializeTaxonomies();
152
		}
153
		return $this->taxonomies;
154
	}
155
156
157
158
	/**
159
	 * @param array $taxonomies
160
	 */
161
	protected function setTaxonomies( array $taxonomies ) {
162
		$this->taxonomies = $taxonomies;
163
	}
164
165
166
167
	/**
168
	 * @return \EE_Secondary_Table
169
	 */
170
	public function metaTable() {
171
		return $this->meta_table;
172
	}
173
174
175
176
	/**
177
	 * @param \EE_Secondary_Table $meta_table
178
	 */
179
	public function setMetaTable( \EE_Secondary_Table $meta_table ) {
180
		$this->meta_table = $meta_table;
181
	}
182
183
184
185
	/**
186
	 * @return \EEM_Base
187
	 */
188
	public function model() {
189
		return $this->model;
190
	}
191
192
193
194
	/**
195
	 * @param \EEM_Base $CPT_model
196
	 */
197
	protected function setModel( \EEM_Base $CPT_model ) {
198
		$this->model = $CPT_model;
0 ignored issues
show
Documentation Bug introduced by
$CPT_model is of type object<EEM_Base>, but the property $model was declared to be of type object<EEM_CPT_Base>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
199
	}
200
201
202
203
	/**
204
	 * @return \EE_Request_Handler
205
	 */
206
	public function request() {
207
		return $this->request;
208
	}
209
210
211
212
	/**
213
	 * @param \EE_Request_Handler $request
214
	 */
215
	protected function setRequest( \EE_Request_Handler $request ) {
216
		$this->request = $request;
217
	}
218
219
220
221
	/**
222
	 * @return \WP_Query
223
	 */
224
	public function WpQuery() {
225
		return $this->wp_query;
226
	}
227
228
229
230
	/**
231
	 * @param \WP_Query $wp_query
232
	 */
233
	public function setWpQuery( \WP_Query $wp_query ) {
234
		$this->wp_query = $wp_query;
235
	}
236
237
238
239
	/**
240
	 * initializeTaxonomies
241
	 *
242
	 * @access protected
243
	 * @return void
244
	 */
245
	protected function initializeTaxonomies() {
246
		// check if taxonomies have already been set and that this CPT has taxonomies registered for it
247
		if (
248
			empty( $this->taxonomies )
249
			&& isset( $this->cpt_details['args'], $this->cpt_details['args']['taxonomies'] )
250
		) {
251
			// if so then grab them, but we want the taxonomy name as the key
252
			$taxonomies = array_flip( $this->cpt_details['args']['taxonomies'] );
253
			// then grab the list of ALL taxonomies
254
			$all_taxonomies = \EE_Register_CPTs::get_taxonomies();
255
			foreach ( $taxonomies as $taxonomy => &$details ) {
256
				// add details to our taxonomies if they exist
257
				$details = isset( $all_taxonomies[ $taxonomy ] )
258
					? $all_taxonomies[ $taxonomy ]
259
					: array();
260
			}
261
			// ALWAYS unset() variables that were passed by reference
262
			unset( $details );
263
			$this->setTaxonomies( $taxonomies );
264
		}
265
	}
266
267
268
269
	protected function init() {
270
		$this->setAdditionalCptDetails();
271
		$this->setRequestVarsIfCpt();
272
		// convert post_type to model name
273
		$model_name = str_replace( 'EE_', '', $this->cpt_details['class_name'] );
274
		// load all tables related to CPT
275
		$this->setupModelsAndTables( $model_name );
276
		// load and instantiate CPT_*_Strategy
277
		$CPT_Strategy = $this->cptStrategyClass( $model_name );
278
		// !!!!!!!!!!  IMPORTANT !!!!!!!!!!!!
279
		// here's the list of available filters in the WP_Query object
280
		// 'posts_where_paged'
281
		// 'posts_groupby'
282
		// 'posts_join_paged'
283
		// 'posts_orderby'
284
		// 'posts_distinct'
285
		// 'post_limits'
286
		// 'posts_fields'
287
		// 'posts_join'
288
		add_filter( 'posts_fields', array( $this, 'postsFields' ) );
289
		add_filter( 'posts_join', array( $this, 'postsJoin' ) );
290
		add_filter(
291
			'get_' . $this->post_type . '_metadata',
292
			array( $CPT_Strategy, 'get_EE_post_type_metadata' ),
293
			1,
294
			4
295
		);
296
		add_filter( 'the_posts', array( $this, 'thePosts' ), 1, 1 );
297
		if ( $this->wp_query->is_main_query() ) {
298
			add_filter( 'get_edit_post_link', array( $this, 'getEditPostLink' ), 10, 2 );
299
			$this->addTemplateFilters();
300
		}
301
	}
302
303
304
305
	/**
306
	 * sets some basic query vars that pertain to the CPT
307
	 *
308
	 * @access protected
309
	 * @return void
310
	 */
311
	protected function setAdditionalCptDetails() {
312
		// the post or category or term that is triggering EE
313
		$this->cpt_details['espresso_page'] = $this->request->is_espresso_page();
314
		// requested post name
315
		$this->cpt_details['post_name'] = $this->request->get( 'post_name' );
316
		// add support for viewing 'private', 'draft', or 'pending' posts
317
		if (
318
			isset( $this->wp_query->query_vars['p'] )
319
			&& $this->wp_query->query_vars['p'] !== 0
320
			&& is_user_logged_in()
321
			&& current_user_can( 'edit_post', $this->wp_query->query_vars['p'] )
322
		) {
323
			// we can just inject directly into the WP_Query object
324
			$this->wp_query->query['post_status'] = array( 'publish', 'private', 'draft', 'pending' );
325
			// now set the main 'ee' request var so that the appropriate module can load the appropriate template(s)
326
			$this->request->set( 'ee', $this->cpt_details['singular_slug'] );
327
		}
328
	}
329
330
331
332
	/**
333
	 * Checks if we're on a EE-CPT archive-or-single page, and if we've never set the EE request var.
334
	 * If so, sets the 'ee' request variable
335
	 * so other parts of EE can know what CPT is getting queried.
336
	 * To Mike's knowledge, this must be called from during or after the pre_get_posts hook
337
	 * in order for is_archive() and is_single() methods to work properly.
338
	 *
339
	 * @return void
340
	 */
341
	public function setRequestVarsIfCpt() {
342
		// check if ee action var has been set
343
		if ( ! $this->request->is_set( 'ee' ) ) {
344
			// check that route exists for CPT archive slug
345
			if ( is_archive() && \EE_Config::get_route( $this->cpt_details['plural_slug'] ) ) {
346
				// ie: set "ee" to "events"
347
				$this->request->set( 'ee', $this->cpt_details['plural_slug'] );
348
				// or does it match a single page CPT like /event/
349
			} else if ( is_single() && \EE_Config::get_route( $this->cpt_details['singular_slug'] ) ) {
350
				// ie: set "ee" to "event"
351
				$this->request->set( 'ee', $this->cpt_details['singular_slug'] );
352
			}
353
		}
354
	}
355
356
357
358
	/**
359
	 * setupModelsAndTables
360
	 *
361
	 * @access protected
362
	 * @param string $model_name
363
	 * @throws \EE_Error
364
	 */
365
	protected function setupModelsAndTables( $model_name ) {
366
		// get CPT table data via CPT Model
367
		$model = \EE_Registry::instance()->load_model( $model_name );
368
		if ( ! $model instanceof \EEM_Base ) {
369
			throw new \EE_Error (
370
				sprintf(
371
					__(
372
						'The "%1$s" model could not be loaded.',
373
						'event_espresso'
374
					),
375
					$model_name
376
				)
377
			);
378
		}
379
		$this->setModel( $model );
380
		$this->setModelTables( $this->model->get_tables() );
381
		// is there a Meta Table for this CPT?
382
		if (
383
			isset( $this->cpt_details['tables'][ $model_name . '_Meta' ] )
384
			&& $this->cpt_details['tables'][ $model_name . '_Meta' ] instanceof \EE_Secondary_Table
385
		) {
386
			$this->setMetaTable( $this->cpt_details['tables'][ $model_name . '_Meta' ] );
387
		}
388
	}
389
390
391
392
	/**
393
	 * cptStrategyClass
394
	 *
395
	 * @access protected
396
	 * @param  string $model_name
397
	 * @return string
398
	 */
399
	protected function cptStrategyClass( $model_name ) {
400
		// creates classname like:  CPT_Event_Strategy
401
		$CPT_Strategy_class_name = 'CPT_' . $model_name . '_Strategy';
402
		// load and instantiate
403
		$CPT_Strategy = \EE_Registry::instance()->load_core(
404
			$CPT_Strategy_class_name,
405
			array( 'WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details )
406
		);
407
		if ( $CPT_Strategy === null ) {
408
			$CPT_Strategy = \EE_Registry::instance()->load_core(
409
				'CPT_Default_Strategy',
410
				array( 'WP_Query' => $this->wp_query, 'CPT' => $this->cpt_details )
411
			);
412
		}
413
		return $CPT_Strategy;
414
	}
415
416
417
418
	/**
419
	 * postsFields
420
	 *
421
	 * @access public
422
	 * @param  $SQL
423
	 * @return string
424
	 */
425
	public function postsFields( $SQL ) {
426
		// does this CPT have a meta table ?
427
		if ( $this->meta_table instanceof \EE_Secondary_Table ) {
428
			// adds something like ", wp_esp_event_meta.* " to WP Query SELECT statement
429
			$SQL .= ', ' . $this->meta_table->get_table_name() . '.* ';
430
		}
431
		remove_filter( 'posts_fields', array( $this, 'postsFields' ) );
432
		return $SQL;
433
	}
434
435
436
437
	/**
438
	 * postsJoin
439
	 *
440
	 * @access public
441
	 * @param  $SQL
442
	 * @return string
443
	 */
444
	public function postsJoin( $SQL ) {
445
		// does this CPT have a meta table ?
446
		if ( $this->meta_table instanceof \EE_Secondary_Table ) {
447
			global $wpdb;
448
			// adds something like " LEFT JOIN wp_esp_event_meta ON ( wp_esp_event_meta.EVT_ID = wp_posts.ID ) " to WP Query JOIN statement
449
			$SQL .= ' LEFT JOIN '
450
			        . $this->meta_table->get_table_name()
451
			        . ' ON ( '
452
			        . $this->meta_table->get_table_name()
453
			        . '.'
454
			        . $this->meta_table->get_fk_on_table()
455
			        . ' = '
456
			        . $wpdb->posts
457
			        . '.ID ) ';
458
		}
459
		remove_filter( 'posts_join', array( $this, 'postsJoin' ) );
460
		return $SQL;
461
	}
462
463
464
465
	/**
466
	 * thePosts
467
	 *
468
	 * @access public
469
	 * @param  \WP_Post[] $posts
470
	 * @return \WP_Post[]
471
	 */
472
	public function thePosts( $posts ) {
473
		$CPT_class = $this->cpt_details['class_name'];
474
		// loop thru posts
475
		if ( is_array( $posts ) && $this->model instanceof \EEM_CPT_Base ) {
476
			foreach ( $posts as $key => $post ) {
477
				if ( $post->post_type === $this->post_type ) {
478
					$post->{$CPT_class} = $this->model->instantiate_class_from_post_object( $post );
479
				}
480
			}
481
		}
482
		remove_filter( 'the_posts', array( $this, 'thePosts' ), 1 );
483
		return $posts;
484
	}
485
486
487
488
	/**
489
	 * @param $url
490
	 * @param $ID
491
	 * @return string
492
	 */
493
	public function getEditPostLink( $url, $ID ) {
494
		// need to make sure we only edit links if our cpt
495
		global $post;
496
		//notice if the cpt is registered with `show_ee_ui` set to false, we take that to mean that the WordPress core ui
497
		//for interacting with the CPT is desired and there is no EE UI for interacting with the CPT in the admin.
498
		if (
499
			! $post instanceof \WP_Post
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
500
			|| $post->post_type !== $this->post_type
501
			|| (
502
				isset( $this->cpt_details['args']['show_ee_ui'] )
503
				&& ! $this->cpt_details['args']['show_ee_ui']
504
			)
505
		) {
506
			return $url;
507
		}
508
		//k made it here so all is good.
509
		return wp_nonce_url(
510
			add_query_arg(
511
				array( 'page' => $this->post_type, 'post' => $ID, 'action' => 'edit' ),
512
				admin_url( 'admin.php' )
513
			),
514
			'edit',
515
			'edit_nonce'
516
		);
517
	}
518
519
520
521
	/**
522
	 * Execute any template filters.
523
	 * This method is only called if in main query.
524
	 *
525
	 * @return void
526
	 */
527
	public function addTemplateFilters() {
528
		// if requested cpt supports page_templates and it's the main query
529
		if ( ! empty( $this->cpt_details['args']['page_templates'] ) && $this->wp_query->is_main_query() ) {
530
			// then let's hook into the appropriate query_template hook
531
			add_filter( 'single_template', array( $this, 'singleCptTemplate' ) );
532
		}
533
	}
534
535
536
537
	/**
538
	 * Callback for single_template wp filter.
539
	 * This is used to load the set page_template for a single ee cpt if its set.  If "default" then we load the normal hierarchy.
540
	 *
541
	 * @access public
542
	 * @param string $current_template Existing default template path derived for this page call.
543
	 * @return string the path to the full template file.
544
	 */
545
	public function singleCptTemplate( $current_template ) {
546
		$object = get_queried_object();
547
		//does this called object HAVE a page template set that is something other than the default.
548
		$template = get_post_meta( $object->ID, '_wp_page_template', true );
549
		//exit early if default or not set or invalid path (accounts for theme changes)
550
		if (
551
			$template === 'default'
552
			|| empty( $template )
553
			|| ! is_readable( get_stylesheet_directory() . '/' . $template )
554
		) {
555
			return $current_template;
556
		}
557
		//made it here so we SHOULD be able to just locate the template and then return it.
558
		return locate_template( array( $template ) );
559
	}
560
561
562
}
563
// End of file CptQueryModifier.php
564
// Location: /CptQueryModifier.php