Total Complexity | 124 |
Total Lines | 572 |
Duplicated Lines | 0 % |
Changes | 3 | ||
Bugs | 0 | Features | 0 |
Complex classes like MonsterInsights_Report 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.
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 MonsterInsights_Report, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class MonsterInsights_Report { |
||
20 | |||
21 | public $title; |
||
22 | public $class; |
||
23 | public $name; |
||
24 | public $version = '1.0.0'; |
||
25 | public $source = 'reports'; |
||
26 | public $start_date; |
||
27 | public $end_date; |
||
28 | |||
29 | /** |
||
30 | * We will use this value if we are not using the same value for report store and relay path. |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $api_path; |
||
35 | |||
36 | /** |
||
37 | * Primary class constructor. |
||
38 | * |
||
39 | * @access public |
||
40 | * @since 6.0.0 |
||
41 | */ |
||
42 | public function __construct() { |
||
43 | add_filter( 'monsterinsights_reports_abstract_get_data_pre_cache', array( $this, 'requirements' ), 10, 3 ); |
||
44 | } |
||
45 | |||
46 | // Let's get the HTML to output for a particular report. This is not the AJAX endpoint. Args can hold things (generally start/end date range) |
||
47 | protected function get_report_html( $args = array() ) { |
||
48 | /* Defined in the report class */ |
||
49 | // For ajax, args start, end, and data will be set with the data to use. Else call $this->get_data( array( 'default' => true ) ) |
||
50 | return ''; |
||
51 | } |
||
52 | |||
53 | public function additional_data() { |
||
54 | return array(); |
||
55 | } |
||
56 | |||
57 | public function requirements( $error = false, $args = array(), $name = '' ) { |
||
58 | return $error; |
||
59 | } |
||
60 | |||
61 | public function show_report( $args = array() ) { |
||
62 | |||
63 | if ( ! current_user_can( 'monsterinsights_view_dashboard' ) ) { |
||
64 | return monsterinsights_get_message( 'error', esc_html__( 'Oops! Access is denied. If you believe you should be able to view this report, please contact your website administrator to ensure you have the correct user role to view MonsterInsights reports.', 'google-analytics-for-wordpress' ) ); |
||
65 | } |
||
66 | |||
67 | if ( monsterinsights_get_option( 'dashboard_disabled', false ) ) { |
||
68 | if ( current_user_can( 'monsterinsights_save_settings' ) ) { |
||
69 | $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' ); |
||
70 | |||
71 | // Translators: Placeholders add a link to the settings panel. |
||
72 | return monsterinsights_get_message( 'error', sprintf( esc_html__( 'Please %1$senable the dashboard%2$s to see report data.', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' ) ); |
||
73 | } else { |
||
74 | $message = sprintf( |
||
75 | // Translators: Link tag starts with url and link tag ends. |
||
76 | esc_html__( 'Oops! The MonsterInsights dashboard has been disabled. Please check with your site administrator that your role is included in the MonsterInsights permissions settings. %1$sClick here for more information%2$s.', 'google-analytics-for-wordpress' ), |
||
77 | '<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'cannot-view-reports', 'https://www.monsterinsights.com/docs/how-to-allow-user-roles-to-access-the-monsterinsights-reports-and-settings/' ) . '">', |
||
78 | '</a>' |
||
79 | ); |
||
80 | |||
81 | return monsterinsights_get_message( 'error', $message ); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | if ( monsterinsights_is_pro_version() ) { |
||
86 | if ( ! MonsterInsights()->license->has_license() ) { |
||
87 | $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' ); |
||
88 | // Translators: Placeholders add a link to the settings panel, Support link tag starts with url and support link tag ends. |
||
89 | $message = sprintf( |
||
90 | esc_html__( 'Oops! We did not find an active MonsterInsights license. Please %1$scheck your license settings%2$s or %3$scontact our support team%4$s for help.', 'google-analytics-for-wordpress' ), |
||
91 | '<a href="' . $url . '">', |
||
92 | '</a>', |
||
93 | '<a target="_blank" href="' . monsterinsights_get_url( 'notice', 'no-active-license', 'https://www.monsterinsights.com/my-account/support/' ) . '">', |
||
94 | '</a>' |
||
95 | ); |
||
96 | |||
97 | return monsterinsights_get_message( 'error', $message ); |
||
98 | } else if ( MonsterInsights()->license->license_has_error() ) { |
||
99 | return monsterinsights_get_message( 'error', $this->get_license_error() ); |
||
100 | } |
||
101 | } |
||
102 | |||
103 | if ( ! ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() ) ) { |
||
104 | if ( current_user_can( 'monsterinsights_save_settings' ) ) { |
||
105 | $url = is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_settings' ) : admin_url( 'admin.php?page=monsterinsights_settings' ); |
||
106 | |||
107 | // Translators: Placeholders add a link to the settings panel. |
||
108 | return monsterinsights_get_message( 'error', sprintf( esc_html__( 'Oops! We did not find a properly authenticated analytics account. Please %1$sauthenticate with Google%2$s to allow MonsterInsights to show you reports.', 'google-analytics-for-wordpress' ), '<a href="' . $url . '">', '</a>' ) ); |
||
109 | } else { |
||
110 | return monsterinsights_get_message( 'error', esc_html__( 'Oops! It appears as though you do not have the right user permissions to authenticate. Please contact your website administrator to check your user roles.', 'google-analytics-for-wordpress' ) ); |
||
111 | } |
||
112 | } |
||
113 | |||
114 | if ( monsterinsights_is_pro_version() ) { |
||
115 | if ( ! MonsterInsights()->license->license_can( $this->level ) ) { |
||
116 | return $this->get_upsell_notice(); |
||
117 | } |
||
118 | } |
||
119 | |||
120 | $error = $this->requirements( false, array(), $this->name ); |
||
121 | |||
122 | if ( ! empty( $error ) ) { |
||
123 | return monsterinsights_get_message( 'error', $error ); |
||
124 | } |
||
125 | |||
126 | if ( ! empty( $args['error'] ) ) { |
||
127 | return monsterinsights_get_message( 'error', $args['error'] ); |
||
128 | } |
||
129 | |||
130 | if ( empty( $args['data'] ) || ! is_array( $args['data'] ) ) { |
||
131 | if ( monsterinsights_is_pro_version() ) { |
||
132 | return ''; |
||
133 | } else { |
||
134 | // Try to get default data. |
||
135 | $args = $this->get_data( array( 'default' => true ) ); |
||
136 | if ( empty( $args['data'] ) || is_array( $args['data'] ) ) { |
||
137 | return monsterinsights_get_message( 'error', __( 'No data found', 'google-analytics-for-wordpress' ) ); |
||
138 | } |
||
139 | |||
140 | if ( ! empty( $args['error'] ) ) { |
||
141 | return monsterinsights_get_message( 'error', $args['error'] ); |
||
142 | } |
||
143 | } |
||
144 | } |
||
145 | |||
146 | return $this->get_report_html( $args['data'] ); |
||
147 | } |
||
148 | |||
149 | // Deletes the report data from the cache |
||
150 | public function delete_cache( $where = 'site' ) { |
||
151 | |||
152 | if ( $where === 'site' || $where === 'both' ) { |
||
153 | delete_option( 'monsterinsights_report_data_' . $this->name ); |
||
154 | } |
||
155 | |||
156 | if ( $where === 'network' || $where === 'both' ) { |
||
157 | delete_option( 'monsterinsights_network_report_data_' . $this->name ); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | // Get report data |
||
162 | public function get_data( $args = array() ) { |
||
163 | |||
164 | if ( ! empty( $args['default'] ) ) { |
||
165 | $args['start'] = $this->default_start_date(); |
||
166 | $args['end'] = $this->default_end_date(); |
||
167 | } |
||
168 | |||
169 | $start = ! empty( $args['start'] ) && $this->is_valid_date( $args['start'] ) ? $args['start'] : ''; |
||
170 | $end = ! empty( $args['end'] ) && $this->is_valid_date( $args['end'] ) ? $args['end'] : ''; |
||
171 | |||
172 | $compare_start = null; |
||
173 | $compare_end = null; |
||
174 | |||
175 | if ( isset( $args['compare_start'] ) ) { |
||
176 | $compare_start = ! empty( $args['compare_start'] ) && $this->is_valid_date( $args['compare_start'] ) ? $args['compare_start'] : ''; |
||
177 | $compare_end = ! empty( $args['compare_end'] ) && $this->is_valid_date( $args['compare_end'] ) ? $args['compare_end'] : ''; |
||
178 | } |
||
179 | |||
180 | if ( monsterinsights_is_pro_version() && ! MonsterInsights()->license->license_can( $this->level ) ) { |
||
181 | return array( |
||
182 | 'success' => true, |
||
183 | 'upgrade' => true, |
||
184 | 'data' => array(), |
||
185 | ); |
||
186 | } |
||
187 | |||
188 | if ( ! $this->is_valid_date_range( $start, $end ) ) { |
||
189 | return array( |
||
190 | 'success' => false, |
||
191 | 'error' => __( 'Whoops! No data found for this date range', 'google-analytics-for-wordpress' ), |
||
192 | 'data' => array( |
||
193 | 'type' => 'INVALID_DATE_RANGE', |
||
194 | ), |
||
195 | ); |
||
196 | } |
||
197 | |||
198 | if ( ( $start !== $this->default_start_date() || $end !== $this->default_end_date() ) && ! monsterinsights_is_pro_version() ) { |
||
199 | // On lite version, the date range is blocked with upgrade to pro message and this conflicts with getting YIR report. |
||
200 | // $start = $this->default_start_date(); |
||
201 | // $end = $this->default_end_date(); |
||
202 | |||
203 | // return array( |
||
204 | // 'success' => false, |
||
205 | // 'error' => __( 'Please upgrade to MonsterInsights Pro to use custom date ranges.', 'google-analytics-for-wordpress' ), |
||
206 | // 'data' => array(), |
||
207 | // ); |
||
208 | } |
||
209 | |||
210 | $error = apply_filters( 'monsterinsights_reports_abstract_get_data_pre_cache', false, $args, $this->name ); |
||
211 | if ( $error ) { |
||
212 | return apply_filters( 'monsterinsights_reports_handle_error_message', array( |
||
213 | 'success' => false, |
||
214 | 'error' => $error, |
||
215 | 'data' => array(), |
||
216 | ) ); |
||
217 | } |
||
218 | |||
219 | // These values are going to use on child classes. |
||
220 | $this->start_date = $start; |
||
221 | $this->end_date = $end; |
||
222 | |||
223 | $check_cache = ( $start === $this->default_start_date() && $end === $this->default_end_date() ) || apply_filters( 'monsterinsights_report_use_cache', false, $this->name ); |
||
224 | $site_auth = MonsterInsights()->auth->get_viewname(); |
||
225 | $ms_auth = is_multisite() && MonsterInsights()->auth->get_network_viewname(); |
||
226 | |||
227 | if ( $compare_start && $compare_end ) { |
||
228 | $transient = 'monsterinsights_report_' . $this->name . '_' . $start . '_' . $end . '_to_' . $compare_start . '_' . $compare_end; |
||
229 | } else { |
||
230 | $transient = 'monsterinsights_report_' . $this->name . '_' . $start . '_' . $end; |
||
231 | } |
||
232 | |||
233 | $current_timestamp = current_time( 'U' ); |
||
234 | // Set to same time as MI cache. MI caches same day to 15 and others to 1 day, so there's no point pinging MI before then. |
||
235 | $expiration = apply_filters( 'monsterinsights_report_transient_expiration', |
||
236 | date( 'Y-m-d' ) === $end ? ( 15 * MINUTE_IN_SECONDS ) : ( strtotime( 'Tomorrow 12:05am', $current_timestamp ) - $current_timestamp ), |
||
237 | $this->name ); |
||
238 | |||
239 | // Default date range, check. |
||
240 | if ( $site_auth || $ms_auth ) { |
||
241 | // Single site or MS with auth at subsite |
||
242 | if ( $compare_start && $compare_end ) { |
||
243 | $option_name = $site_auth ? 'monsterinsights_report_data_compare_' . $this->name : 'monsterinsights_network_report_data_compare_' . $this->name; |
||
244 | } else { |
||
245 | $option_name = $site_auth ? 'monsterinsights_report_data_' . $this->name : 'monsterinsights_network_report_data_' . $this->name; |
||
246 | } |
||
247 | |||
248 | $p = $site_auth ? MonsterInsights()->auth->get_viewid() : MonsterInsights()->auth->get_network_viewid(); |
||
249 | |||
250 | $data = array(); |
||
251 | // If default date range then get cache data from option. |
||
252 | if ( $check_cache ) { |
||
253 | $data = ! $site_auth && $ms_auth ? get_site_option( $option_name, array() ) : get_option( $option_name, array() ); |
||
254 | } else { |
||
255 | $data = ! $site_auth && $ms_auth ? get_site_transient( $transient ) : get_transient( $transient ); |
||
256 | } |
||
257 | |||
258 | if ( ! empty( $data ) && |
||
259 | ! empty( $data['expires'] ) && |
||
260 | $data['expires'] >= time() && |
||
261 | ! empty( $data['data'] ) && |
||
262 | ! empty( $data['p'] ) && |
||
263 | $data['p'] === $p |
||
264 | ) { |
||
265 | return $this->prepare_report_data( array( |
||
266 | 'success' => true, |
||
267 | 'data' => $data['data'], |
||
268 | ) ); |
||
269 | } |
||
270 | |||
271 | // Nothing in cache, either not saved before, expired or mismatch. Let's grab from API |
||
272 | $api_options = array( 'start' => $start, 'end' => $end ); |
||
273 | |||
274 | if ( $compare_start && $compare_end ) { |
||
275 | $api_options['compare_start'] = $compare_start; |
||
276 | $api_options['compare_end'] = $compare_end; |
||
277 | } |
||
278 | |||
279 | if ( ! $site_auth && $ms_auth ) { |
||
280 | $api_options['network'] = true; |
||
281 | } |
||
282 | |||
283 | // Get the path of the relay. |
||
284 | $api_path = empty( $this->api_path ) ? $this->name : $this->api_path; |
||
285 | |||
286 | $api = new MonsterInsights_API_Request( 'analytics/reports/' . $api_path . '/', $api_options, 'GET' ); |
||
287 | |||
288 | // Use a report source indicator for requests. |
||
289 | if ( ! empty( $this->source ) ) { |
||
290 | $api->set_additional_data( array( |
||
291 | 'source' => $this->source, |
||
292 | ) ); |
||
293 | } |
||
294 | |||
295 | $additional_data = $this->additional_data(); |
||
296 | |||
297 | if ( ! empty( $additional_data ) ) { |
||
298 | $api->set_additional_data( $additional_data ); |
||
299 | } |
||
300 | |||
301 | $ret = $api->request(); |
||
302 | |||
303 | if ( is_wp_error( $ret ) ) { |
||
304 | return array( |
||
305 | 'success' => false, |
||
306 | 'error' => $ret->get_error_message(), |
||
307 | 'data' => array(), |
||
308 | ); |
||
309 | } else { |
||
310 | // Success |
||
311 | |||
312 | // Strip any HTML tags from API response |
||
313 | $ret['data'] = json_encode($ret['data']); |
||
314 | $ret['data'] = strip_tags($ret['data']); |
||
315 | $ret['data'] = json_decode($ret['data'], true); |
||
316 | |||
317 | $data = array( |
||
318 | 'expires' => time() + $expiration, |
||
319 | 'p' => $p, |
||
320 | 'data' => $ret['data'], |
||
321 | ); |
||
322 | |||
323 | if ( $check_cache ) { |
||
324 | ! $site_auth && $ms_auth ? update_site_option( $option_name, $data ) : update_option( $option_name, $data ); |
||
325 | } else { |
||
326 | ! $site_auth && $ms_auth ? set_site_transient( $transient, $data, $expiration ) : set_transient( $transient, $data, $expiration ); |
||
327 | } |
||
328 | |||
329 | return $this->prepare_report_data( array( |
||
330 | 'success' => true, |
||
331 | 'data' => $ret['data'], |
||
332 | ) ); |
||
333 | } |
||
334 | |||
335 | } else { |
||
336 | $url = admin_url( 'admin.php?page=monsterinsights-onboarding' ); |
||
337 | |||
338 | // Check for MS dashboard |
||
339 | if ( is_network_admin() ) { |
||
340 | $url = network_admin_url( 'admin.php?page=monsterinsights-onboarding' ); |
||
341 | } |
||
342 | |||
343 | return array( |
||
344 | 'success' => false, |
||
345 | 'error' => sprintf( |
||
346 | /* translators: Placeholders add a link to the Setup Wizard page. */ |
||
347 | __( 'You must be properly authenticated with MonsterInsights to use our reports. Please use our %1$ssetup wizard%2$s to get started.', 'google-analytics-for-wordpress' ), |
||
348 | '<a href=" ' . $url . ' ">', |
||
349 | '</a>' |
||
350 | ), |
||
351 | 'data' => array(), |
||
352 | ); |
||
353 | } |
||
354 | } |
||
355 | |||
356 | public function default_start_date() { |
||
357 | return date( 'Y-m-d', strtotime( '-30 days' ) ); |
||
358 | } |
||
359 | |||
360 | public function default_end_date() { |
||
361 | return date( 'Y-m-d', strtotime( '-1 day' ) ); |
||
362 | } |
||
363 | |||
364 | /** |
||
365 | * Default date for compare start. |
||
366 | * |
||
367 | * @return string |
||
368 | */ |
||
369 | public function default_compare_start_date() { |
||
370 | return date( 'Y-m-d', strtotime( '-60 days' ) ); |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Default date for compare end. |
||
375 | * |
||
376 | * @return string |
||
377 | */ |
||
378 | public function default_compare_end_date() { |
||
380 | } |
||
381 | |||
382 | // Checks to see if date range is valid. Should be 30-yesterday always for lite & any valid date range to today for Pro. |
||
383 | public function is_valid_date_range( $start, $end ) { |
||
384 | $now = current_datetime(); |
||
385 | $wp_timezone = wp_timezone_string(); |
||
386 | $start_date = DateTime::createFromFormat( 'Y-m-d', $start, new DateTimeZone( $wp_timezone ) ); |
||
387 | $end_date = DateTime::createFromFormat( 'Y-m-d', $end, new DateTimeZone( $wp_timezone ) ); |
||
388 | |||
389 | $ancient_date = DateTime::createFromFormat( 'Y-m-d', '2005-01-01', new DateTimeZone( $wp_timezone ) ); |
||
390 | |||
391 | if ( $start_date > $now || $end_date > $now || $start_date < $ancient_date || $end_date < $ancient_date ) { |
||
392 | return false; |
||
393 | } |
||
394 | |||
395 | // return false if the start date is after the end date |
||
396 | return ( $start > $end ) ? false : true; |
||
397 | } |
||
398 | |||
399 | // Is a valid date value |
||
400 | public function is_valid_date( $date = '' ) { |
||
401 | $d = MonsterInsightsDateTime::create_from_format( 'Y-m-d', $date ); |
||
402 | |||
403 | return $d && $d->format( 'Y-m-d' ) === $date; |
||
404 | } |
||
405 | |||
406 | /** |
||
407 | * Do not use the functions below this. They are unused and are just here so people |
||
408 | * with out of date MonsterInsights addons won't get fatal errors. |
||
409 | */ |
||
410 | protected function get_api_max_limit() { |
||
411 | return 300; |
||
412 | } |
||
413 | |||
414 | protected function get_date_range() { |
||
415 | return array(); |
||
416 | } |
||
417 | |||
418 | protected function get_ga_report_url( $v4_name, $data, $v4_extra_params = '', $v4_endpoint = 'explorer', $is_real_time = false ) { |
||
440 | ); |
||
441 | } |
||
442 | |||
443 | public function get_upsell_notice() { |
||
530 | } |
||
531 | |||
532 | function get_ga_report_range( $data = array() ) { |
||
533 | if ( empty( $data['reportcurrentrange'] ) || empty( $data['reportcurrentrange']['startDate'] ) || empty( $data['reportcurrentrange']['endDate'] ) ) { |
||
534 | return ''; |
||
535 | } else { |
||
536 | if ( ! empty( $data['reportprevrange'] ) && ! empty( $data['reportprevrange']['startDate'] ) && ! empty( $data['reportprevrange']['endDate'] ) ) { |
||
537 | return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) . '&_u.date10=' . str_replace( '-', '', $data['reportprevrange']['startDate'] ) . '&_u.date11=' . str_replace( '-', '', $data['reportprevrange']['endDate'] ) ); |
||
538 | } |
||
539 | |||
540 | return urlencode( '_u.date00=' . str_replace( '-', '', $data['reportcurrentrange']['startDate'] ) . '&_u.date01=' . str_replace( '-', '', $data['reportcurrentrange']['endDate'] ) ); |
||
541 | } |
||
542 | } |
||
543 | |||
544 | /** |
||
545 | * Grab the link to the addons page used in each report's error message. |
||
546 | * |
||
547 | * @return string |
||
548 | */ |
||
549 | public function get_addons_page_link() { |
||
550 | if ( monsterinsights_can_install_plugins() ) { |
||
551 | $addons_link = 'install_addon'; |
||
552 | } else { |
||
553 | $addons_link = esc_html__( 'Please ask your webmaster to enable this addon.', 'google-analytics-for-wordpress' ); |
||
554 | } |
||
555 | |||
556 | return $addons_link; |
||
557 | } |
||
558 | |||
559 | /** |
||
560 | * When called will add the footer link to be displayed in the error popup. |
||
561 | * |
||
562 | * @param array $data The data sent as error response to the ajax call. |
||
563 | * |
||
564 | * @return array |
||
565 | */ |
||
566 | public function add_error_addon_link( $data ) { |
||
567 | $data['data']['footer'] = $this->get_addons_page_link(); |
||
568 | |||
569 | return $data; |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Added to allow individual reports to alter data when outputting for Vue reports. |
||
574 | * |
||
575 | * @param $data |
||
576 | * |
||
577 | * @return mixed |
||
578 | */ |
||
579 | public function prepare_report_data( $data ) { |
||
580 | return $data; |
||
581 | } |
||
582 | |||
583 | /** |
||
584 | * Set a report source to be sent with the request. |
||
585 | * |
||
586 | * @param string $source The source where the report is called from, defaults to reports. |
||
587 | */ |
||
588 | public function set_report_source( $source ) { |
||
591 | } |
||
592 | } |
||
593 | } |
||
594 | |||
595 | if ( ! class_exists( 'MonsterInsightsDateTime' ) ) { |
||
596 | class MonsterInsightsDateTime extends DateTime { |
||
597 | public static function create_from_format( $format, $time, $timezone = null ) { |
||
598 | if ( ! $timezone ) { |
||
599 | $timezone = new DateTimeZone( date_default_timezone_get() ); |
||
600 | } |
||
601 | if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) { |
||
602 | return parent::createFromFormat( $format, $time, $timezone ); |
||
603 | } |
||
604 | |||
609 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.