Passed
Push — master ( 6f0a6d...90a9ca )
by
unknown
09:41
created

MonsterInsights_Popular_Posts_Ajax   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 87
dl 0
loc 244
rs 10
c 1
b 0
f 0
wmc 30

11 Methods

Rating   Name   Duplication   Size   Complexity  
A register_api_endpoints() 0 32 1
A get_taxonomy() 0 5 2
A get_themes_by_type() 0 25 6
A get_themes() 0 5 1
A get_taxonomy_terms() 0 21 4
A empty_cache() 0 19 3
A get_gutenberg_themes() 0 5 2
A get_theme_details() 0 5 1
B get_ajax_output() 0 21 7
A __construct() 0 13 1
A ajax_get_themes() 0 7 2
1
<?php
2
/**
3
 * Used to handle ajax requests specific to popular posts.
4
 *
5
 * @package MonsterInsights
6
 */
7
8
/**
9
 * Class MonsterInsights_Popular_Posts_Ajax
10
 */
11
class MonsterInsights_Popular_Posts_Ajax {
12
13
	/**
14
	 * MonsterInsights_Popular_Posts_Ajax constructor.
15
	 */
16
	public function __construct() {
17
18
		add_action( 'rest_api_init', array( $this, 'register_api_endpoints' ) );
19
20
		add_action( 'wp_ajax_monsterinsights_popular_posts_empty_cache', array( $this, 'empty_cache' ) );
21
22
		add_action( 'wp_ajax_monsterinsights_popular_posts_get_widget_output', array( $this, 'get_ajax_output' ) );
23
		add_action( 'wp_ajax_nopriv_monsterinsights_popular_posts_get_widget_output', array(
24
			$this,
25
			'get_ajax_output'
26
		) );
27
28
		add_action( 'wp_ajax_monsterinsights_get_popular_posts_themes', array( $this, 'ajax_get_themes' ) );
29
	}
30
31
	/**
32
	 * Register the wp-json API endpoints for the Gutenberg blocks.
33
	 */
34
	public function register_api_endpoints() {
35
36
		register_rest_route( 'monsterinsights/v1', '/popular-posts/themes/(?P<type>[a-zA-Z0-9-]+)', array(
37
			'methods'             => 'GET',
38
			'callback'            => array( $this, 'get_gutenberg_themes' ),
39
			'permission_callback' => function () {
40
				return current_user_can( 'edit_posts' );
41
			},
42
			'args'                => array(
43
				'type',
44
			),
45
		) );
46
47
		register_rest_route( 'monsterinsights/v1', '/terms/(?P<slug>[a-zA-Z0-9-_]+)', array(
48
			'methods'             => 'GET',
49
			'callback'            => array( $this, 'get_taxonomy_terms' ),
50
			'permission_callback' => function () {
51
				return current_user_can( 'edit_posts' );
52
			},
53
			'args'                => array(
54
				'slug',
55
			),
56
		) );
57
58
		register_rest_route( 'monsterinsights/v1', '/taxonomy/(?P<slug>[a-zA-Z0-9-_]+)', array(
59
			'methods'             => 'GET',
60
			'callback'            => array( $this, 'get_taxonomy' ),
61
			'permission_callback' => function () {
62
				return current_user_can( 'edit_posts' );
63
			},
64
			'args'                => array(
65
				'slug',
66
			),
67
		) );
68
	}
69
70
	/**
71
	 * Get the themes for Gutenberg (use the specific nonce).
72
	 */
73
	public function get_gutenberg_themes( $data ) {
74
75
		$type = ! empty( $data['type'] ) ? $data['type'] : 'inline';
76
77
		return $this->get_themes_by_type( $type );
78
79
	}
80
81
	/**
82
	 * Get the themes for a specific type using ajax.
83
	 */
84
	public function ajax_get_themes() {
85
86
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
87
88
		$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : 'inline';
89
90
		wp_send_json_success( $this->get_themes_by_type( $type, false ) );
91
92
	}
93
94
	/**
95
	 * Helper to get themes by type.
96
	 *
97
	 * @param string $type The widget type: inline/widget/products.
98
	 * @param bool   $styled Whether to style the selected theme or not.
99
	 *
100
	 * @return array
101
	 */
102
	public function get_themes_by_type( $type, $styled = true ) {
103
		$theme = '';
104
105
		if ( $styled ) {
106
			if ( 'inline' === $type ) {
107
				$theme = MonsterInsights_Popular_Posts_Inline()->theme;
0 ignored issues
show
Bug Best Practice introduced by
The property theme does not exist on MonsterInsights_Popular_Posts_Inline. Since you implemented __get, consider adding a @property annotation.
Loading history...
108
			}
109
110
			if ( 'widget' === $type ) {
111
				$theme = MonsterInsights_Popular_Posts_Widget()->theme;
0 ignored issues
show
Bug Best Practice introduced by
The property theme does not exist on MonsterInsights_Popular_Posts_Widget. Since you implemented __get, consider adding a @property annotation.
Loading history...
112
			}
113
		}
114
		$themes       = $this->get_themes( $type, $theme );
115
		$themes_array = $themes->themes;
116
117
		if ( isset( $themes_array[ $theme ] ) && $styled ) {
118
			$themes_array[ $theme ] = $themes->get_theme();
119
		}
120
121
		$response = array(
122
			'themes'   => $themes_array,
123
			'selected' => $theme,
124
		);
125
126
		return $response;
127
	}
128
129
	/**
130
	 * Get themes by type.
131
	 *
132
	 * @param string $type The widget type: inline/widget/products.
133
	 * @param string $theme The selected theme.
134
	 *
135
	 * @return MonsterInsights_Popular_Posts_Themes
136
	 */
137
	public function get_themes( $type, $theme ) {
138
139
		$themes_object = new MonsterInsights_Popular_Posts_Themes( $type, $theme );
140
141
		return $themes_object;
142
	}
143
144
	/**
145
	 * Get a specific theme details.
146
	 *
147
	 * @param string $type The widget type: inline/widget/products.
148
	 * @param string $theme The selected theme.
149
	 *
150
	 * @return array|mixed
151
	 */
152
	public function get_theme_details( $type, $theme ) {
153
154
		$themes = new MonsterInsights_Popular_Posts_Themes( $type, $theme );
155
156
		return $themes->get_theme();
157
158
	}
159
160
	/**
161
	 * Handler for loading taxonomy terms using a custom endpoint.
162
	 *
163
	 * @param array $data Data passed from the request.
164
	 *
165
	 * @return array
166
	 */
167
	public function get_taxonomy_terms( $data ) {
168
169
		$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
170
171
		$terms = get_terms( array(
172
			'taxonomy' => $slug,
173
		) );
174
175
		$return = array();
176
177
		if ( ! is_wp_error( $terms ) ) {
178
			foreach ( $terms as $term ) {
179
				$return[] = array(
180
					'id'     => $term->term_id,
181
					'name'   => $term->name,
182
					'parent' => $term->parent,
183
				);
184
			}
185
		}
186
187
		return $return;
188
189
	}
190
191
	/**
192
	 * Get details for a taxonomy so we can use it in the Gutenberg block.
193
	 *
194
	 * @param array $data Data passed from the request.
195
	 *
196
	 * @return false|WP_Taxonomy
197
	 */
198
	public function get_taxonomy( $data ) {
199
200
		$slug = ! empty( $data['slug'] ) ? $data['slug'] : 'category';
201
202
		return get_taxonomy( $slug );
203
204
	}
205
206
	/**
207
	 * Ajax handler to empty the Popular Posts cache for all instances.
208
	 */
209
	public function empty_cache() {
210
211
		check_ajax_referer( 'mi-admin-nonce', 'nonce' );
212
213
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
214
			return;
215
		}
216
217
		$types = array(
218
			'inline',
219
			'widget',
220
			'products',
221
		);
222
223
		foreach ( $types as $type ) {
224
			delete_option( 'monsterinsights_popular_posts_cache_' . $type );
225
		}
226
227
		wp_send_json_success();
228
229
	}
230
231
	/**
232
	 * Ajax handler to get the output for Popular Posts widgets from the JSON data on the frontend.
233
	 */
234
	public function get_ajax_output() {
235
236
		if ( empty( $_POST['data'] ) || ! is_array( $_POST['data'] ) ) {
237
			return;
238
		}
239
240
		$html         = array();
241
		$widgets_args = $_POST['data'];
242
243
		foreach ( $widgets_args as $args ) {
244
			$args = json_decode( sanitize_text_field( wp_unslash( $args ) ), true );
0 ignored issues
show
Bug introduced by
It seems like wp_unslash($args) can also be of type string[]; however, parameter $str of sanitize_text_field() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

244
			$args = json_decode( sanitize_text_field( /** @scrutinizer ignore-type */ wp_unslash( $args ) ), true );
Loading history...
245
			if ( ! empty( $args['type'] ) ) {
246
				$type            = ucfirst( $args['type'] );
247
				$widget_function = function_exists( 'MonsterInsights_Popular_Posts_' . $type ) ? call_user_func( 'MonsterInsights_Popular_Posts_' . $type ) : false;
248
				if ( $widget_function ) {
249
					$html[] = $widget_function->get_rendered_html( $args );
250
				}
251
			}
252
		}
253
254
		wp_send_json( $html );
255
	}
256
257
}
258
259
new MonsterInsights_Popular_Posts_Ajax();
260