Completed
Push — master ( 15aa29...17da96 )
by Claudio
18:39 queued 11s
created

includes/admin/class-wc-admin-addons.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Addons Page
4
 *
5
 * @author   WooThemes
6
 * @category Admin
7
 * @package  WooCommerce/Admin
8
 * @version  2.5.0
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
/**
16
 * WC_Admin_Addons Class.
17
 */
18
class WC_Admin_Addons {
19
20
	/**
21
	 * Get featured for the addons screen
22
	 *
23
	 * @return array of objects
24
	 */
25 View Code Duplication
	public static function get_featured() {
26
		if ( false === ( $featured = get_transient( 'wc_addons_featured' ) ) ) {
27
			$raw_featured = wp_safe_remote_get( 'https://d3t0oesq8995hv.cloudfront.net/add-ons/featured-v2.json', array( 'user-agent' => 'WooCommerce Addons Page' ) );
28
			if ( ! is_wp_error( $raw_featured ) ) {
29
				$featured = json_decode( wp_remote_retrieve_body( $raw_featured ) );
30
				if ( $featured ) {
31
					set_transient( 'wc_addons_featured', $featured, WEEK_IN_SECONDS );
32
				}
33
			}
34
		}
35
36
		if ( is_object( $featured ) ) {
37
			self::output_featured_sections( $featured->sections );
38
			return $featured;
39
		}
40
	}
41
42
	/**
43
	 * Build url parameter string
44
	 *
45
	 * @param  string $category
46
	 * @param  string $term
47
	 * @param  string $country
48
	 *
49
	 * @return string url parameter string
50
	 */
51
	public static function build_parameter_string( $category, $term, $country ) {
52
53
		$paramters = array(
54
			'category' => $category,
55
			'term'     => $term,
56
			'country'  => $country,
57
		);
58
59
		return '?' . http_build_query( $paramters );
60
	}
61
62
	/**
63
	 * Call API to get extensions
64
	 *
65
	 * @param  string $category
66
	 * @param  string $term
67
	 * @param  string $country
68
	 *
69
	 * @return array of extensions
70
	 */
71
	public static function get_extension_data( $category, $term, $country ) {
72
		$parameters     = self::build_parameter_string( $category, $term, $country );
73
		$raw_extensions = wp_remote_get(
0 ignored issues
show
wp_remote_get is highly discouraged, please use vip_safe_wp_remote_get() instead.
Loading history...
74
			'https://woocommerce.com/wp-json/wccom-extensions/1.0/search' . $parameters
75
		);
76
		if ( ! is_wp_error( $raw_extensions ) ) {
77
			$addons = json_decode( wp_remote_retrieve_body( $raw_extensions ) )->products;
78
		}
79
		return $addons;
80
	}
81
82
	/**
83
	 * Get sections for the addons screen
84
	 *
85
	 * @return array of objects
86
	 */
87 View Code Duplication
	public static function get_sections() {
88
		$addon_sections = get_transient( 'wc_addons_sections' );
89
		if ( false === ( $addon_sections ) ) {
90
			$raw_sections = wp_safe_remote_get(
91
				'https://woocommerce.com/wp-json/wccom-extensions/1.0/categories'
92
			);
93
			if ( ! is_wp_error( $raw_sections ) ) {
94
				$addon_sections = json_decode( wp_remote_retrieve_body( $raw_sections ) );
95
				if ( $addon_sections ) {
96
					set_transient( 'wc_addons_sections', $addon_sections, WEEK_IN_SECONDS );
97
				}
98
			}
99
		}
100
		return apply_filters( 'woocommerce_addons_sections', $addon_sections );
101
	}
102
103
	/**
104
	 * Get section for the addons screen.
105
	 *
106
	 * @param  string $section_id
107
	 *
108
	 * @return object|bool
109
	 */
110
	public static function get_section( $section_id ) {
111
		$sections = self::get_sections();
112
		if ( isset( $sections[ $section_id ] ) ) {
113
			return $sections[ $section_id ];
114
		}
115
		return false;
116
	}
117
118
	/**
119
	 * Get section content for the addons screen.
120
	 *
121
	 * @param  string $section_id
122
	 *
123
	 * @return array
124
	 */
125
	public static function get_section_data( $section_id ) {
126
		$section      = self::get_section( $section_id );
127
		$section_data = '';
128
129
		if ( ! empty( $section->endpoint ) ) {
130
			if ( false === ( $section_data = get_transient( 'wc_addons_section_' . $section_id ) ) ) {
131
				$raw_section = wp_safe_remote_get( esc_url_raw( $section->endpoint ), array( 'user-agent' => 'WooCommerce Addons Page' ) );
132
133
				if ( ! is_wp_error( $raw_section ) ) {
134
					$section_data = json_decode( wp_remote_retrieve_body( $raw_section ) );
135
136
					if ( ! empty( $section_data->products ) ) {
137
						set_transient( 'wc_addons_section_' . $section_id, $section_data, WEEK_IN_SECONDS );
138
					}
139
				}
140
			}
141
		}
142
143
		return apply_filters( 'woocommerce_addons_section_data', $section_data->products, $section_id );
144
	}
145
146
	/**
147
	 * Handles the outputting of a contextually aware Storefront link (points to child themes if Storefront is already active).
148
	 */
149
	public static function output_storefront_button() {
150
		$template   = get_option( 'template' );
151
		$stylesheet = get_option( 'stylesheet' );
152
153
		if ( 'storefront' === $template ) {
154
			if ( 'storefront' === $stylesheet ) {
155
				$url         = 'https://woocommerce.com/product-category/themes/storefront-child-theme-themes/';
156
				$text        = __( 'Need a fresh look? Try Storefront child themes', 'woocommerce' );
157
				$utm_content = 'nostorefrontchildtheme';
158
			} else {
159
				$url         = 'https://woocommerce.com/product-category/themes/storefront-child-theme-themes/';
160
				$text        = __( 'View more Storefront child themes', 'woocommerce' );
161
				$utm_content = 'hasstorefrontchildtheme';
162
			}
163
		} else {
164
			$url         = 'https://woocommerce.com/storefront/';
165
			$text        = __( 'Need a theme? Try Storefront', 'woocommerce' );
166
			$utm_content = 'nostorefront';
167
		}
168
169
		$url = add_query_arg(
170
			array(
171
				'utm_source'   => 'addons',
172
				'utm_medium'   => 'product',
173
				'utm_campaign' => 'woocommerceplugin',
174
				'utm_content'  => $utm_content,
175
			), $url
176
		);
177
178
		echo '<a href="' . esc_url( $url ) . '" class="add-new-h2">' . esc_html( $text ) . '</a>' . "\n";
179
	}
180
181
	/**
182
	 * Handles the outputting of a banner block.
183
	 *
184
	 * @param object $block
185
	 */
186 View Code Duplication
	public static function output_banner_block( $block ) {
187
		?>
188
		<div class="addons-banner-block">
189
			<h1><?php echo esc_html( $block->title ); ?></h1>
190
			<p><?php echo esc_html( $block->description ); ?></p>
191
			<div class="addons-banner-block-items">
192
				<?php foreach ( $block->items as $item ) : ?>
193
					<?php if ( self::show_extension( $item ) ) : ?>
194
						<div class="addons-banner-block-item">
195
							<div class="addons-banner-block-item-icon">
196
								<img class="addons-img" src="<?php echo esc_url( $item->image ); ?>" />
197
							</div>
198
							<div class="addons-banner-block-item-content">
199
								<h3><?php echo esc_html( $item->title ); ?></h3>
200
								<p><?php echo esc_html( $item->description ); ?></p>
201
								<?php
202
									self::output_button(
203
										$item->href,
204
										$item->button,
205
										'addons-button-solid',
206
										$item->plugin
207
									);
208
								?>
209
							</div>
210
						</div>
211
					<?php endif; ?>
212
				<?php endforeach; ?>
213
			</div>
214
		</div>
215
		<?php
216
	}
217
218
	/**
219
	 * Handles the outputting of a column.
220
	 *
221
	 * @param object $block
222
	 */
223
	public static function output_column( $block ) {
224
		if ( isset( $block->container ) && 'column_container_start' === $block->container ) {
225
			?>
226
			<div class="addons-column-section">
227
			<?php
228
		}
229
		if ( 'column_start' === $block->module ) {
230
			?>
231
			<div class="addons-column">
232
			<?php
233
		} else {
234
			?>
235
			</div>
236
			<?php
237
		}
238
		if ( isset( $block->container ) && 'column_container_end' === $block->container ) {
239
			?>
240
			</div>
241
			<?php
242
		}
243
	}
244
245
	/**
246
	 * Handles the outputting of a column block.
247
	 *
248
	 * @param object $block
249
	 */
250 View Code Duplication
	public static function output_column_block( $block ) {
251
		?>
252
		<div class="addons-column-block">
253
			<h1><?php echo esc_html( $block->title ); ?></h1>
254
			<p><?php echo esc_html( $block->description ); ?></p>
255
			<?php foreach ( $block->items as $item ) : ?>
256
				<?php if ( self::show_extension( $item ) ) : ?>
257
					<div class="addons-column-block-item">
258
						<div class="addons-column-block-item-icon">
259
							<img class="addons-img" src="<?php echo esc_url( $item->image ); ?>" />
260
						</div>
261
						<div class="addons-column-block-item-content">
262
							<h2><?php echo esc_html( $item->title ); ?></h2>
263
							<?php
264
								self::output_button(
265
									$item->href,
266
									$item->button,
267
									'addons-button-solid',
268
									$item->plugin
269
								);
270
							?>
271
							<p><?php echo esc_html( $item->description ); ?></p>
272
						</div>
273
					</div>
274
				<?php endif; ?>
275
			<?php endforeach; ?>
276
		</div>
277
278
		<?php
279
	}
280
281
	/**
282
	 * Handles the outputting of a small light block.
283
	 *
284
	 * @param object $block
285
	 */
286 View Code Duplication
	public static function output_small_light_block( $block ) {
287
		?>
288
		<div class="addons-small-light-block">
289
			<img class="addons-img" src="<?php echo esc_url( $block->image ); ?>" />
290
			<div class="addons-small-light-block-content">
291
				<h1><?php echo esc_html( $block->title ); ?></h1>
292
				<p><?php echo esc_html( $block->description ); ?></p>
293
				<div class="addons-small-light-block-buttons">
294
					<?php foreach ( $block->buttons as $button ) : ?>
295
						<?php
296
							self::output_button(
297
								$button->href,
298
								$button->text,
299
								'addons-button-solid'
300
							);
301
						?>
302
					<?php endforeach; ?>
303
				</div>
304
			</div>
305
		</div>
306
		<?php
307
	}
308
309
	/**
310
	 * Handles the outputting of a small dark block.
311
	 *
312
	 * @param object $block
313
	 */
314 View Code Duplication
	public static function output_small_dark_block( $block ) {
315
		?>
316
		<div class="addons-small-dark-block">
317
			<h1><?php echo esc_html( $block->title ); ?></h1>
318
			<p><?php echo esc_html( $block->description ); ?></p>
319
			<div class="addons-small-dark-items">
320
				<?php foreach ( $block->items as $item ) : ?>
321
					<div class="addons-small-dark-item">
322
						<?php if ( ! empty( $item->image ) ) : ?>
323
							<div class="addons-small-dark-item-icon">
324
								<img class="addons-img" src="<?php echo esc_url( $item->image ); ?>" />
325
							</div>
326
						<?php endif; ?>
327
						<?php
328
							self::output_button(
329
								$item->href,
330
								$item->button,
331
								'addons-button-outline-white'
332
							);
333
						?>
334
					</div>
335
				<?php endforeach; ?>
336
			</div>
337
		</div>
338
		<?php
339
	}
340
341
	/**
342
	 * Handles the outputting of the WooCommerce Services banner block.
343
	 *
344
	 * @param object $block
345
	 */
346
	public static function output_wcs_banner_block( $block = array() ) {
347
		$is_active = is_plugin_active( 'woocommerce-services/woocommerce-services.php' );
348
		$location  = wc_get_base_location();
349
350
		if (
351
			! in_array( $location['country'], array( 'US', 'CA' ), true ) ||
352
			$is_active ||
353
			! current_user_can( 'install_plugins' ) ||
354
			! current_user_can( 'activate_plugins' )
355
		) {
356
			return;
357
		}
358
359
		$button_url = wp_nonce_url(
360
			add_query_arg(
361
				array(
362
					'install-addon' => 'woocommerce-services',
363
				)
364
			),
365
			'install-addon_woocommerce-services'
366
		);
367
368
		$defaults = array(
369
			'image'       => WC()->plugin_url() . '/assets/images/wcs-extensions-banner-3x.png',
370
			'image_alt'   => __( 'WooCommerce Services', 'woocommerce' ),
371
			'title'       => __( 'Buy discounted shipping labels — then print them from your dashboard.', 'woocommerce' ),
372
			'description' => __( 'Integrate your store with USPS to buy discounted shipping labels, and print them directly from your WooCommerce dashboard. Powered by WooCommerce Services.', 'woocommerce' ),
373
			'button'      => __( 'Free - Install now', 'woocommerce' ),
374
			'href'        => $button_url,
375
			'logos'       => array(),
376
		);
377
378
		switch ( $location['country'] ) {
379
			case 'CA':
380
				$local_defaults = array(
381
					'image'       => WC()->plugin_url() . '/assets/images/wcs-truck-banner-3x.png',
382
					'title'       => __( 'Show Canada Post shipping rates', 'woocommerce' ),
383
					'description' => __( 'Display live rates from Canada Post at checkout to make shipping a breeze. Powered by WooCommerce Services.', 'woocommerce' ),
384
					'logos'       => array_merge(
385
						$defaults['logos'], array(
386
							array(
387
								'link' => WC()->plugin_url() . '/assets/images/wcs-canada-post-logo.jpg',
388
								'alt'  => 'Canada Post logo',
389
							),
390
						)
391
					),
392
				);
393
				break;
394
			case 'US':
395
				$local_defaults = array(
396
					'logos' => array_merge(
397
						$defaults['logos'], array(
398
							array(
399
								'link' => WC()->plugin_url() . '/assets/images/wcs-usps-logo.png',
400
								'alt'  => 'USPS logo',
401
							),
402
						)
403
					),
404
				);
405
				break;
406
			default:
407
				$local_defaults = array();
408
		}
409
410
		$block_data = array_merge( $defaults, $local_defaults, $block );
411
		?>
412
		<div class="addons-wcs-banner-block">
413
			<div class="addons-wcs-banner-block-image">
414
				<img
415
					class="addons-img"
416
					src="<?php echo esc_url( $block_data['image'] ); ?>"
417
					alt="<?php echo esc_attr( $block_data['image_alt'] ); ?>"
418
				/>
419
			</div>
420
			<div class="addons-wcs-banner-block-content">
421
				<h1><?php echo esc_html( $block_data['title'] ); ?></h1>
422
				<p><?php echo esc_html( $block_data['description'] ); ?></p>
423
				<ul>
424
					<?php foreach ( $block_data['logos'] as $logo ) : ?>
425
						<li>
426
							<img
427
								alt="<?php echo esc_url( $logo['alt'] ); ?>"
428
								class="wcs-service-logo"
429
								src="<?php echo esc_url( $logo['link'] ); ?>"
430
							>
431
						</li>
432
					<?php endforeach; ?>
433
				</ul>
434
				<?php
435
					self::output_button(
436
						$block_data['href'],
437
						$block_data['button'],
438
						'addons-button-outline-green'
439
					);
440
				?>
441
			</div>
442
		</div>
443
	<?php
444
	}
445
446
	/**
447
	 * Handles the outputting of featured sections
448
	 *
449
	 * @param array $sections
450
	 */
451
	public static function output_featured_sections( $sections ) {
452
		foreach ( $sections as $section ) {
453
			switch ( $section->module ) {
454
				case 'banner_block':
455
					self::output_banner_block( $section );
456
					break;
457
				case 'column_start':
458
					self::output_column( $section );
459
					break;
460
				case 'column_end':
461
					self::output_column( $section );
462
					break;
463
				case 'column_block':
464
					self::output_column_block( $section );
465
					break;
466
				case 'small_light_block':
467
					self::output_small_light_block( $section );
468
					break;
469
				case 'small_dark_block':
470
					self::output_small_dark_block( $section );
471
					break;
472
				case 'wcs_banner_block':
473
					self::output_wcs_banner_block( (array) $section );
474
					break;
475
			}
476
		}
477
	}
478
479
	/**
480
	 * Outputs a button.
481
	 *
482
	 * @param string $url
483
	 * @param string $text
484
	 * @param string $theme
485
	 * @param string $plugin
486
	 */
487
	public static function output_button( $url, $text, $theme, $plugin = '' ) {
488
		$theme = __( 'Free', 'woocommerce' ) === $text ? 'addons-button-outline-green' : $theme;
489
		$theme = is_plugin_active( $plugin ) ? 'addons-button-installed' : $theme;
490
		$text  = is_plugin_active( $plugin ) ? __( 'Installed', 'woocommerce' ) : $text;
491
		?>
492
		<a
493
			class="addons-button <?php echo esc_attr( $theme ); ?>"
494
			href="<?php echo esc_url( $url ); ?>">
495
			<?php echo esc_html( $text ); ?>
496
		</a>
497
		<?php
498
	}
499
500
501
	/**
502
	 * Handles output of the addons page in admin.
503
	 */
504
	public static function output() {
505
		if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) {
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_GET
Loading history...
506
			do_action( 'woocommerce_helper_output' );
507
			return;
508
		}
509
510
		if ( isset( $_GET['install-addon'] ) && 'woocommerce-services' === $_GET['install-addon'] ) {
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_GET
Loading history...
511
			self::install_woocommerce_services_addon();
512
		}
513
514
		$sections        = self::get_sections();
515
		$theme           = wp_get_theme();
516
		$current_section = isset( $_GET['section'] ) ? sanitize_text_field( $_GET['section'] ) : '_featured';
517
		$addons          = array();
518
519
		if ( '_featured' !== $current_section ) {
520
			$category = isset( $_GET['section'] ) ? $_GET['section'] : null;
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_GET
Loading history...
521
			$term     = isset( $_GET['search'] ) ? $_GET['search'] : null;
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_GET
Loading history...
522
			$country  = WC()->countries->get_base_country();
523
			$addons   = self::get_extension_data( $category, $term, $country );
524
		}
525
526
		/**
527
		 * Addon page view.
528
		 *
529
		 * @uses $addons
530
		 * @uses $sections
531
		 * @uses $theme
532
		 * @uses $current_section
533
		 */
534
		include_once dirname( __FILE__ ) . '/views/html-admin-page-addons.php';
535
	}
536
537
	/**
538
	 * Install WooCommerce Services from Extensions screens.
539
	 */
540
	public static function install_woocommerce_services_addon() {
541
		check_admin_referer( 'install-addon_woocommerce-services' );
542
543
		$services_plugin_id = 'woocommerce-services';
544
		$services_plugin    = array(
545
			'name'      => __( 'WooCommerce Services', 'woocommerce' ),
546
			'repo-slug' => 'woocommerce-services',
547
		);
548
549
		WC_Install::background_installer( $services_plugin_id, $services_plugin );
550
551
		wp_safe_redirect( remove_query_arg( array( 'install-addon', '_wpnonce' ) ) );
552
		exit;
553
	}
554
555
	/**
556
	 * Should an extension be shown on the featured page.
557
	 *
558
	 * @param object $item
559
	 * @return boolean
560
	 */
561
	public static function show_extension( $item ) {
562
		$location = WC()->countries->get_base_country();
563
		if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) {
564
			return false;
565
		}
566
567
		if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) {
568
			return false;
569
		}
570
571
		if ( is_plugin_active( $item->plugin ) ) {
572
			return false;
573
		}
574
575
		return true;
576
	}
577
}
578