Classic Editor Addon - Version 2.6.1

Version Description

  • March 5, 2020
  • update WP Dependency Installer to 3.0.0
Download this release

Release Info

Developer senlin
Plugin Icon wp plugin Classic Editor Addon
Version 2.6.1
Comparing to
See all releases

Code changes from version 2.6.0 to 2.6.1

classic-editor-addon.php CHANGED
@@ -4,10 +4,10 @@
4
  * Description: This free "Classic Editor Addon" plugin makes sure that the new block editor cannot be accidentally activated and blocks the calls to additional styles from the `<head>` (frontend). See README for details.
5
 
6
  * Author: <a href="https://so-wp.com">Pieter Bos</a>, <a href="https://gschoppe.com">Greg Schoppe</a>
7
- * Version: 2.6.0
8
 
9
  * Requires at least: 4.9
10
- * Tested up to: 5.3
11
 
12
  * License: GPL-3.0+
13
  * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
4
  * Description: This free "Classic Editor Addon" plugin makes sure that the new block editor cannot be accidentally activated and blocks the calls to additional styles from the `&lt;head&gt;` (frontend). See README for details.
5
 
6
  * Author: <a href="https://so-wp.com">Pieter Bos</a>, <a href="https://gschoppe.com">Greg Schoppe</a>
7
+ * Version: 2.6.1
8
 
9
  * Requires at least: 4.9
10
+ * Tested up to: 5.3.2
11
 
12
  * License: GPL-3.0+
13
  * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: senlin, gschoppe
3
  Tags: gutenberg, block editor, classic editor, addon, wordpress 5.0, woocommerce
4
  Requires at least: 4.9
5
  Requires PHP: 5.6
6
- Tested up to: 5.3
7
- Stable tag: 2.6.0
8
  License: GPL-3.0+
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
10
 
@@ -17,7 +17,7 @@ This free "Classic Editor Addon" plugin makes sure that the new block editor can
17
  The free Classic Editor Addon plugin is targeted at everyone who is not yet ready for the new editing experience that has been introduced in WordPress 5.0. Install it now on sites and the UX remains the same as you are used to!
18
 
19
  <strong>What's New:</strong>
20
- Compatible with WP 5.3, fixes reported issues.
21
 
22
  Please pay attention that the minimum PHP version to use our plugin is <strong>5.6</strong>.
23
 
@@ -27,7 +27,7 @@ Since version 0.0.4 of the "Classic Editor" plugin, it finally set the default s
27
 
28
  Also, if we look at developers protecting the sites of their clients with the Classic Editor, they certainly don't want their clients to accidentally turn off the Classic Editor as the new block editor adds a lot of undesirable comments, tags and what not to the content.
29
 
30
- Sites running WooCommerce get another style added to the `<head>` section of the site. With the Classic Editor Addon installed that call is obviously redundant. With version 2.5.0 we introduce a condition that checks for WooCommerce and if active it removes that call. Win!
31
 
32
  Therefore we highly recommend installing this "Classic Editor Addon" plugin, which will automatically install the “Classic Editor” plugin and remove its settings.
33
 
@@ -63,6 +63,11 @@ Please open an issue on [Github](https://github.com/senlin/classic-editor-addon/
63
 
64
  == Changelog ==
65
 
 
 
 
 
 
66
  = 2.6.0 =
67
 
68
  * November 14, 2019
3
  Tags: gutenberg, block editor, classic editor, addon, wordpress 5.0, woocommerce
4
  Requires at least: 4.9
5
  Requires PHP: 5.6
6
+ Tested up to: 5.4
7
+ Stable tag: 2.6.1
8
  License: GPL-3.0+
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.txt
10
 
17
  The free Classic Editor Addon plugin is targeted at everyone who is not yet ready for the new editing experience that has been introduced in WordPress 5.0. Install it now on sites and the UX remains the same as you are used to!
18
 
19
  <strong>What's New:</strong>
20
+ Update WP Dependency Installer
21
 
22
  Please pay attention that the minimum PHP version to use our plugin is <strong>5.6</strong>.
23
 
27
 
28
  Also, if we look at developers protecting the sites of their clients with the Classic Editor, they certainly don't want their clients to accidentally turn off the Classic Editor as the new block editor adds a lot of undesirable comments, tags and what not to the content.
29
 
30
+ Sites running WooCommerce get another style added to the <code><head></code> section of the site. With the Classic Editor Addon installed that call is obviously redundant. With version 2.5.0 we introduce a condition that checks for WooCommerce and if active it removes that call. Win!
31
 
32
  Therefore we highly recommend installing this "Classic Editor Addon" plugin, which will automatically install the “Classic Editor” plugin and remove its settings.
33
 
63
 
64
  == Changelog ==
65
 
66
+ = 2.6.1 =
67
+
68
+ * March 5, 2020
69
+ * update WP Dependency Installer to 3.0.0
70
+
71
  = 2.6.0 =
72
 
73
  * November 14, 2019
vendor/afragen/wp-dependency-installer/wp-dependency-installer.php CHANGED
@@ -1,5 +1,4 @@
1
  <?php
2
-
3
  /**
4
  * WP Dependency Installer
5
  *
@@ -8,7 +7,7 @@
8
  * It can install a plugin from w.org, GitHub, Bitbucket, GitLab, Gitea or direct URL.
9
  *
10
  * @package WP_Dependency_Installer
11
- * @author Andy Fragen, Matt Gibbs
12
  * @license MIT
13
  * @link https://github.com/afragen/wp-dependency-installer
14
  */
@@ -21,124 +20,175 @@ if ( ! defined( 'WPINC' ) ) {
21
  }
22
 
23
  if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
24
-
25
  /**
26
  * Class WP_Dependency_Installer
27
  */
28
  class WP_Dependency_Installer {
29
-
30
  /**
31
  * Holds the JSON file contents.
32
  *
33
  * @var array $config
34
  */
35
- protected $config = array();
36
 
37
  /**
38
  * Holds the current dependency's slug.
39
  *
40
  * @var string $current_slug
41
  */
42
- protected $current_slug;
 
 
 
 
 
 
 
43
 
44
  /**
45
  * Holds the calling plugin/theme slug.
46
  *
47
  * @var string $source
48
  */
49
- protected $source;
50
 
51
  /**
52
  * Holds names of installed dependencies for admin notices.
53
  *
54
  * @var array $notices
55
  */
56
- protected $notices = array();
57
 
58
  /**
59
- * Singleton.
 
 
60
  */
61
- public static function instance() {
62
  static $instance = null;
63
  if ( null === $instance ) {
64
  $instance = new self();
65
  }
 
 
66
 
67
  return $instance;
68
  }
69
 
 
 
 
 
 
 
 
 
70
  /**
71
  * Load hooks.
72
  *
73
  * @return void
74
  */
75
  public function load_hooks() {
76
- add_action( 'admin_init', array( $this, 'admin_init' ) );
77
- add_action( 'admin_footer', array( $this, 'admin_footer' ) );
78
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
79
- add_action( 'network_admin_notices', array( $this, 'admin_notices' ) );
80
- add_action( 'wp_ajax_dependency_installer', array( $this, 'ajax_router' ) );
 
81
 
82
  // Initialize Persist admin Notices Dismissal dependency.
83
- add_action( 'admin_init', array( 'PAnD', 'init' ) );
84
  }
85
 
86
  /**
87
- * Register wp-dependencies.json
 
 
 
 
88
  *
89
- * @param string $plugin_path Path to plugin or theme calling the framework.
90
  */
91
- public function run( $plugin_path ) {
92
- if ( file_exists( $plugin_path . '/wp-dependencies.json' ) ) {
93
- $config = file_get_contents( $plugin_path . '/wp-dependencies.json' );
94
- if ( empty( $config ) ||
95
- null === ( $config = json_decode( $config, true ) )
96
- ) {
97
- return;
98
- }
99
- $this->source = basename( $plugin_path );
100
  $this->load_hooks();
101
- $this->register( $config );
102
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
104
 
105
  /**
106
  * Register dependencies (supports multiple instances).
107
  *
108
- * @param array $config JSON config as string.
 
 
 
109
  */
110
- public function register( $config ) {
 
111
  foreach ( $config as $dependency ) {
112
- $dependency['source'] = $this->source;
113
- $slug = $dependency['slug'];
114
- if ( ! isset( $this->config[ $slug ] ) || ! $dependency['optional'] ) {
 
 
 
 
 
 
 
115
  $this->config[ $slug ] = $dependency;
116
  }
117
  }
 
 
118
  }
119
 
120
  /**
121
  * Process the registered dependencies.
122
  */
123
- public function apply_config() {
124
  foreach ( $this->config as $dependency ) {
125
  $download_link = null;
126
  $base = null;
127
  $uri = $dependency['uri'];
128
  $slug = $dependency['slug'];
129
- $api = parse_url( $uri, PHP_URL_HOST );
130
- $scheme = parse_url( $uri, PHP_URL_SCHEME );
131
- $scheme = ! empty( $scheme ) ? $scheme . '://' : 'https://';
132
- $path = parse_url( $uri, PHP_URL_PATH );
 
 
 
133
  $owner_repo = str_replace( '.git', '', trim( $path, '/' ) );
134
 
135
  switch ( $dependency['host'] ) {
136
  case 'github':
137
  $base = null === $api || 'github.com' === $api ? 'api.github.com' : $api;
138
  $download_link = "{$scheme}{$base}/repos/{$owner_repo}/zipball/{$dependency['branch']}";
139
- if ( ! empty( $dependency['token'] ) ) {
140
- $download_link = add_query_arg( 'access_token', $dependency['token'], $download_link );
141
- }
142
  break;
143
  case 'bitbucket':
144
  $base = null === $api || 'bitbucket.org' === $api ? 'bitbucket.org' : $api;
@@ -149,15 +199,9 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
149
  $project_id = rawurlencode( $owner_repo );
150
  $download_link = "{$scheme}{$base}/api/v4/projects/{$project_id}/repository/archive.zip";
151
  $download_link = add_query_arg( 'sha', $dependency['branch'], $download_link );
152
- if ( ! empty( $dependency['token'] ) ) {
153
- $download_link = add_query_arg( 'private_token', $dependency['token'], $download_link );
154
- }
155
  break;
156
  case 'gitea':
157
- $download_link = "{$scheme}{$api}/repos/{$owner_repo}/archive/{$dependency['branch']}.zip";
158
- if ( ! empty( $dependency['token'] ) ) {
159
- $download_link = add_query_arg( 'access_token', $dependency['token'], $download_link );
160
- }
161
  break;
162
  case 'wordpress': // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
163
  $download_link = $this->get_dot_org_latest_download( basename( $owner_repo ) );
@@ -175,16 +219,23 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
175
  * @param string $download_link Download link.
176
  * @param array $dependency Dependency configuration.
177
  */
178
- $download_link = apply_filters( 'wp_dependency_download_link', $download_link, $dependency );
179
 
180
- $this->config[ $slug ]['download_link'] = $download_link;
 
 
 
 
 
 
 
181
  }
182
  }
183
 
184
  /**
185
  * Get lastest download link from WordPress API.
186
  *
187
- * @param string $slug Plugin slug.
188
  * @return string $download_link
189
  */
190
  private function get_dot_org_latest_download( $slug ) {
@@ -193,10 +244,10 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
193
  if ( ! $download_link ) {
194
  $url = 'https://api.wordpress.org/plugins/info/1.1/';
195
  $url = add_query_arg(
196
- array(
197
  'action' => 'plugin_information',
198
  rawurlencode( 'request[slug]' ) => $slug,
199
- ),
200
  $url
201
  );
202
  $response = wp_remote_get( $url );
@@ -220,40 +271,37 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
220
 
221
  // Generate admin notices.
222
  foreach ( $this->config as $slug => $dependency ) {
223
- $is_optional = ! ( isset( $dependency['optional'] ) && false === $dependency['optional'] );
224
 
225
- if ( ! $is_optional ) {
226
- $this->hide_plugin_action_links( $slug );
227
  }
228
 
229
- if ( is_plugin_active( $slug ) ) {
230
- continue;
231
- }
232
-
233
- if ( $this->is_installed( $slug ) ) {
234
- if ( $is_optional ) {
235
- $this->notices[] = array(
236
- 'action' => 'activate',
237
- 'slug' => $slug,
238
- /* translators: %s: Plugin name */
239
- 'text' => sprintf( esc_html__( 'Please activate the %s plugin.' ), $dependency['name'] ),
240
- 'source' => $dependency['source'],
241
- );
242
-
243
- } else {
244
  $this->notices[] = $this->activate( $slug );
 
 
245
  }
246
- } elseif ( $is_optional ) {
247
- $this->notices[] = array(
248
- 'action' => 'install',
249
- 'slug' => $slug,
250
- /* translators: %s: Plugin name */
251
- 'text' => sprintf( esc_html__( 'The %s plugin is required.' ), $dependency['name'] ),
252
- 'source' => $dependency['source'],
253
- );
254
  } else {
255
- $this->notices[] = $this->install( $slug );
 
 
 
 
256
  }
 
 
 
 
 
 
 
 
 
 
257
  }
258
  }
259
 
@@ -297,7 +345,7 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
297
  public function ajax_router() {
298
  $method = isset( $_POST['method'] ) ? $_POST['method'] : '';
299
  $slug = isset( $_POST['slug'] ) ? $_POST['slug'] : '';
300
- $whitelist = array( 'install', 'activate', 'dismiss' );
301
 
302
  if ( in_array( $method, $whitelist, true ) ) {
303
  $response = $this->$method( $slug );
@@ -306,6 +354,32 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
306
  wp_die();
307
  }
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  /**
310
  * Is dependency installed?
311
  *
@@ -319,6 +393,17 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
319
  return isset( $plugins[ $slug ] );
320
  }
321
 
 
 
 
 
 
 
 
 
 
 
 
322
  /**
323
  * Install and activate dependency.
324
  *
@@ -332,54 +417,73 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
332
  }
333
 
334
  $this->current_slug = $slug;
335
- add_filter( 'upgrader_source_selection', array( $this, 'upgrader_source_selection' ), 10, 2 );
336
 
337
  $skin = new WPDI_Plugin_Installer_Skin(
338
- array(
339
  'type' => 'plugin',
340
  'nonce' => wp_nonce_url( $this->config[ $slug ]['download_link'] ),
341
- )
342
  );
343
  $upgrader = new Plugin_Upgrader( $skin );
344
  $result = $upgrader->install( $this->config[ $slug ]['download_link'] );
345
 
346
  if ( is_wp_error( $result ) ) {
347
- return array(
348
  'status' => 'error',
349
  'message' => $result->get_error_message(),
350
- );
351
  }
352
 
353
  if ( null === $result ) {
354
- return array(
355
  'status' => 'error',
356
  'message' => esc_html__( 'Plugin download failed' ),
357
- );
358
  }
359
 
360
  wp_cache_flush();
361
- if ( ! $this->config[ $slug ]['optional'] ) {
362
  $this->activate( $slug );
363
 
364
- return array(
365
  'status' => 'updated',
366
  'slug' => $slug,
367
  /* translators: %s: Plugin name */
368
  'message' => sprintf( esc_html__( '%s has been installed and activated.' ), $this->config[ $slug ]['name'] ),
369
  'source' => $this->config[ $slug ]['source'],
370
- );
371
-
372
  }
373
- if ( 'error' === $result['status'] ) {
 
374
  return $result;
375
  }
376
 
377
- return array(
378
  'status' => 'updated',
379
  /* translators: %s: Plugin name */
380
  'message' => sprintf( esc_html__( '%s has been installed.' ), $this->config[ $slug ]['name'] ),
381
  'source' => $this->config[ $slug ]['source'],
382
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  }
384
 
385
  /**
@@ -390,23 +494,41 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
390
  * @return array Message.
391
  */
392
  public function activate( $slug ) {
393
-
394
  // network activate only if on network admin pages.
395
  $result = is_network_admin() ? activate_plugin( $slug, null, true ) : activate_plugin( $slug );
396
 
397
  if ( is_wp_error( $result ) ) {
398
- return array(
399
  'status' => 'error',
400
  'message' => $result->get_error_message(),
401
- );
402
  }
403
 
404
- return array(
405
  'status' => 'updated',
406
  /* translators: %s: Plugin name */
407
  'message' => sprintf( esc_html__( '%s has been activated.' ), $this->config[ $slug ]['name'] ),
408
  'source' => $this->config[ $slug ]['source'],
409
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  }
411
 
412
  /**
@@ -415,28 +537,62 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
415
  * @return array Empty Message.
416
  */
417
  public function dismiss() {
418
- return array(
419
  'status' => 'updated',
420
  'message' => '',
421
- );
422
  }
423
 
424
  /**
425
  * Correctly rename dependency for activation.
426
  *
427
- * @param string $source
428
- * @param string $remote_source
429
  *
430
  * @return string $new_source
431
  */
432
  public function upgrader_source_selection( $source, $remote_source ) {
433
- global $wp_filesystem;
434
  $new_source = trailingslashit( $remote_source ) . dirname( $this->current_slug );
435
- $wp_filesystem->move( $source, $new_source );
436
 
437
  return trailingslashit( $new_source );
438
  }
439
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  /**
441
  * Display admin notices / action links.
442
  *
@@ -446,82 +602,161 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
446
  if ( ! current_user_can( 'update_plugins' ) ) {
447
  return false;
448
  }
449
- $message = null;
450
  foreach ( $this->notices as $notice ) {
451
- $status = empty( $notice['status'] ) ? 'updated' : $notice['status'];
452
-
453
- if ( ! empty( $notice['action'] ) ) {
454
- $action = esc_attr( $notice['action'] );
455
- $message = esc_html( $notice['text'] );
456
- $message .= ' <a href="javascript:;" class="wpdi-button" data-action="' . $action . '" data-slug="' . $notice['slug'] . '">' . ucfirst( $action ) . ' Now &raquo;</a>';
457
- }
458
- if ( ! empty( $notice['status'] ) ) {
 
459
  $message = esc_html( $notice['message'] );
460
  }
461
 
462
- /**
463
- * Filters the dismissal timeout.
464
- *
465
- * @since 1.4.1
466
- *
467
- * @param string|int '7' Default dismissal in days.
468
- * @param string $notice['source'] Plugin slug of calling plugin.
469
- * @return string|int Dismissal timeout in days.
470
- */
471
- $timeout = '-' . apply_filters( 'wp_dependency_timeout', '7', $notice['source'] );
472
- $dismissible = isset( $notice['slug'] )
473
- ? 'dependency-installer-' . dirname( $notice['slug'] ) . $timeout
474
- : null;
475
- if ( class_exists( '\PAnd' ) && ! \PAnD::is_admin_notice_active( $dismissible ) ) {
476
- continue;
 
 
 
 
 
 
 
 
 
477
  }
478
- ?>
479
- <div data-dismissible="<?php echo $dismissible; ?>" class="<?php echo $status; ?> notice is-dismissible dependency-installer">
480
- <p><?php echo '<strong>[' . esc_html__( 'Dependency' ) . ']</strong> ' . $message; ?></p>
481
- </div>
482
- <?php
483
  }
484
  }
485
 
486
  /**
487
- * Hide links from plugin row.
488
  *
489
- * @param $plugin_file
490
  */
491
- public function hide_plugin_action_links( $plugin_file ) {
492
- add_filter( 'network_admin_plugin_action_links_' . $plugin_file, array( $this, 'unset_action_links' ) );
493
- add_filter( 'plugin_action_links_' . $plugin_file, array( $this, 'unset_action_links' ) );
494
- add_action(
495
- 'after_plugin_row_' . $plugin_file,
496
- function( $plugin_file ) {
497
- print( '<script>jQuery(".inactive[data-plugin=\'' . $plugin_file . '\']").attr("class", "active");</script>' );
498
- print( '<script>jQuery(".active[data-plugin=\'' . $plugin_file . '\'] .check-column input").remove();</script>' );
499
- }
500
- );
501
  }
502
 
503
  /**
504
- * Unset plugin action links so mandatory plugins can't be modified.
505
  *
506
- * @param $actions
 
507
  *
508
  * @return mixed
509
  */
510
- public function unset_action_links( $actions ) {
511
- if ( isset( $actions['edit'] ) ) {
512
- unset( $actions['edit'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  }
514
- if ( isset( $actions['delete'] ) ) {
515
- unset( $actions['delete'] );
 
 
 
 
 
 
 
 
 
516
  }
517
- if ( isset( $actions['deactivate'] ) ) {
518
- unset( $actions['deactivate'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
  }
 
 
 
 
520
 
521
- /* translators: %s: opening and closing span tags */
522
- $actions = array_merge( array( 'required-plugin' => sprintf( esc_html__( '%1$sPlugin dependency%2$s' ), '<span class="network_active">', '</span>' ) ), $actions );
 
 
 
 
 
 
 
 
 
 
523
 
524
- return $actions;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
  }
526
 
527
  /**
@@ -529,10 +764,59 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
529
  *
530
  * @since 1.4.11
531
  *
532
- * @return array The configuration.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  */
534
- public function get_config() {
535
- return $this->config;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  }
537
  }
538
 
@@ -542,10 +826,16 @@ if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
542
  * Class WPDI_Plugin_Installer_Skin
543
  */
544
  class WPDI_Plugin_Installer_Skin extends Plugin_Installer_Skin {
545
- public function header() {}
546
- public function footer() {}
547
- public function error( $errors ) {}
548
- public function feedback( $string, ...$args ) {}
549
- }
 
 
 
550
 
 
 
 
551
  }
1
  <?php
 
2
  /**
3
  * WP Dependency Installer
4
  *
7
  * It can install a plugin from w.org, GitHub, Bitbucket, GitLab, Gitea or direct URL.
8
  *
9
  * @package WP_Dependency_Installer
10
+ * @author Andy Fragen, Matt Gibbs, Raruto
11
  * @license MIT
12
  * @link https://github.com/afragen/wp-dependency-installer
13
  */
20
  }
21
 
22
  if ( ! class_exists( 'WP_Dependency_Installer' ) ) {
 
23
  /**
24
  * Class WP_Dependency_Installer
25
  */
26
  class WP_Dependency_Installer {
 
27
  /**
28
  * Holds the JSON file contents.
29
  *
30
  * @var array $config
31
  */
32
+ private $config;
33
 
34
  /**
35
  * Holds the current dependency's slug.
36
  *
37
  * @var string $current_slug
38
  */
39
+ private $current_slug;
40
+
41
+ /**
42
+ * Holds the calling plugin/theme file path.
43
+ *
44
+ * @var string $source
45
+ */
46
+ private static $caller;
47
 
48
  /**
49
  * Holds the calling plugin/theme slug.
50
  *
51
  * @var string $source
52
  */
53
+ private static $source;
54
 
55
  /**
56
  * Holds names of installed dependencies for admin notices.
57
  *
58
  * @var array $notices
59
  */
60
+ private $notices;
61
 
62
  /**
63
+ * Factory.
64
+ *
65
+ * @param string $caller File path to calling plugin/theme.
66
  */
67
+ public static function instance( $caller = false ) {
68
  static $instance = null;
69
  if ( null === $instance ) {
70
  $instance = new self();
71
  }
72
+ self::$caller = $caller;
73
+ self::$source = ! $caller ? false : basename( $caller );
74
 
75
  return $instance;
76
  }
77
 
78
+ /**
79
+ * Private constructor.
80
+ */
81
+ private function __construct() {
82
+ $this->config = [];
83
+ $this->notices = [];
84
+ }
85
+
86
  /**
87
  * Load hooks.
88
  *
89
  * @return void
90
  */
91
  public function load_hooks() {
92
+ add_action( 'admin_init', [ $this, 'admin_init' ] );
93
+ add_action( 'admin_footer', [ $this, 'admin_footer' ] );
94
+ add_action( 'admin_notices', [ $this, 'admin_notices' ] );
95
+ add_action( 'network_admin_notices', [ $this, 'admin_notices' ] );
96
+ add_action( 'wp_ajax_dependency_installer', [ $this, 'ajax_router' ] );
97
+ add_filter( 'http_request_args', [ $this, 'add_basic_auth_headers' ], 15, 2 );
98
 
99
  // Initialize Persist admin Notices Dismissal dependency.
100
+ add_action( 'admin_init', [ 'PAnD', 'init' ] );
101
  }
102
 
103
  /**
104
+ * Let's get going.
105
+ * First load data from wp-dependencies.json if present.
106
+ * Then load hooks needed to run.
107
+ *
108
+ * @param string $caller Path to plugin or theme calling the framework.
109
  *
110
+ * @return self
111
  */
112
+ public function run( $caller = false ) {
113
+ $caller = ! $caller ? self::$caller : $caller;
114
+ $config = $this->json_file_decode( $caller . '/wp-dependencies.json' );
115
+ if ( ! empty( $config ) ) {
116
+ $this->register( $config, $caller );
117
+ }
118
+ if ( ! empty( $this->config ) ) {
 
 
119
  $this->load_hooks();
 
120
  }
121
+
122
+ return $this;
123
+ }
124
+
125
+ /**
126
+ * Decode JSON config data from a file.
127
+ *
128
+ * @param string $json_path File path to JSON config file.
129
+ *
130
+ * @return bool|array $config
131
+ */
132
+ public function json_file_decode( $json_path ) {
133
+ $config = [];
134
+ if ( file_exists( $json_path ) ) {
135
+ $config = file_get_contents( $json_path );
136
+ $config = json_decode( $config, true );
137
+ }
138
+
139
+ return $config;
140
  }
141
 
142
  /**
143
  * Register dependencies (supports multiple instances).
144
  *
145
+ * @param array $config JSON config as array.
146
+ * @param string $caller Path to plugin or theme calling the framework.
147
+ *
148
+ * @return self
149
  */
150
+ public function register( $config, $caller = false ) {
151
+ $source = ! self::$source ? basename( $caller ) : self::$source;
152
  foreach ( $config as $dependency ) {
153
+ // Save a reference of current dependent plugin.
154
+ $dependency['source'] = $source;
155
+ $dependency['sources'][] = $source;
156
+ $slug = $dependency['slug'];
157
+ // Keep a reference of all dependent plugins.
158
+ if ( isset( $this->config[ $slug ] ) ) {
159
+ $dependency['sources'] = array_merge( $this->config[ $slug ]['sources'], $dependency['sources'] );
160
+ }
161
+ // Update config.
162
+ if ( ! isset( $this->config[ $slug ] ) || $this->is_required( $dependency ) ) {
163
  $this->config[ $slug ] = $dependency;
164
  }
165
  }
166
+
167
+ return $this;
168
  }
169
 
170
  /**
171
  * Process the registered dependencies.
172
  */
173
+ private function apply_config() {
174
  foreach ( $this->config as $dependency ) {
175
  $download_link = null;
176
  $base = null;
177
  $uri = $dependency['uri'];
178
  $slug = $dependency['slug'];
179
+ $uri_args = parse_url( $uri ); // phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url
180
+ $port = isset( $uri_args['port'] ) ? $uri_args['port'] : null;
181
+ $api = isset( $uri_args['host'] ) ? $uri_args['host'] : null;
182
+ $api = ! $port ? $api : "$api:$port";
183
+ $scheme = isset( $uri_args['scheme'] ) ? $uri_args['scheme'] : null;
184
+ $scheme = null !== $scheme ? $scheme . '://' : 'https://';
185
+ $path = isset( $uri_args['path'] ) ? $uri_args['path'] : null;
186
  $owner_repo = str_replace( '.git', '', trim( $path, '/' ) );
187
 
188
  switch ( $dependency['host'] ) {
189
  case 'github':
190
  $base = null === $api || 'github.com' === $api ? 'api.github.com' : $api;
191
  $download_link = "{$scheme}{$base}/repos/{$owner_repo}/zipball/{$dependency['branch']}";
 
 
 
192
  break;
193
  case 'bitbucket':
194
  $base = null === $api || 'bitbucket.org' === $api ? 'bitbucket.org' : $api;
199
  $project_id = rawurlencode( $owner_repo );
200
  $download_link = "{$scheme}{$base}/api/v4/projects/{$project_id}/repository/archive.zip";
201
  $download_link = add_query_arg( 'sha', $dependency['branch'], $download_link );
 
 
 
202
  break;
203
  case 'gitea':
204
+ $download_link = "{$scheme}{$api}/api/v1/repos/{$owner_repo}/archive/{$dependency['branch']}.zip";
 
 
 
205
  break;
206
  case 'wordpress': // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
207
  $download_link = $this->get_dot_org_latest_download( basename( $owner_repo ) );
219
  * @param string $download_link Download link.
220
  * @param array $dependency Dependency configuration.
221
  */
222
+ $dependency['download_link'] = apply_filters( 'wp_dependency_download_link', $download_link, $dependency );
223
 
224
+ /**
225
+ * Allow filtering of individual dependency config.
226
+ *
227
+ * @since 3.0.0
228
+ *
229
+ * @param array $dependency Dependency configuration.
230
+ */
231
+ $this->config[ $slug ] = apply_filters( 'wp_dependency_config', $dependency );
232
  }
233
  }
234
 
235
  /**
236
  * Get lastest download link from WordPress API.
237
  *
238
+ * @param string $slug Plugin slug.
239
  * @return string $download_link
240
  */
241
  private function get_dot_org_latest_download( $slug ) {
244
  if ( ! $download_link ) {
245
  $url = 'https://api.wordpress.org/plugins/info/1.1/';
246
  $url = add_query_arg(
247
+ [
248
  'action' => 'plugin_information',
249
  rawurlencode( 'request[slug]' ) => $slug,
250
+ ],
251
  $url
252
  );
253
  $response = wp_remote_get( $url );
271
 
272
  // Generate admin notices.
273
  foreach ( $this->config as $slug => $dependency ) {
274
+ $is_required = $this->is_required( $dependency );
275
 
276
+ if ( $is_required ) {
277
+ $this->modify_plugin_row( $slug );
278
  }
279
 
280
+ if ( $this->is_active( $slug ) ) {
281
+ // Do nothing.
282
+ } elseif ( $this->is_installed( $slug ) ) {
283
+ if ( $is_required ) {
 
 
 
 
 
 
 
 
 
 
 
284
  $this->notices[] = $this->activate( $slug );
285
+ } else {
286
+ $this->notices[] = $this->activate_notice( $slug );
287
  }
 
 
 
 
 
 
 
 
288
  } else {
289
+ if ( $is_required ) {
290
+ $this->notices[] = $this->install( $slug );
291
+ } else {
292
+ $this->notices[] = $this->install_notice( $slug );
293
+ }
294
  }
295
+
296
+ /**
297
+ * Allow filtering of admin notices.
298
+ *
299
+ * @since 3.0.0
300
+ *
301
+ * @param array $notices admin notices.
302
+ * @param string $slug plugin slug.
303
+ */
304
+ $this->notices = apply_filters( 'wp_dependency_notices', $this->notices, $slug );
305
  }
306
  }
307
 
345
  public function ajax_router() {
346
  $method = isset( $_POST['method'] ) ? $_POST['method'] : '';
347
  $slug = isset( $_POST['slug'] ) ? $_POST['slug'] : '';
348
+ $whitelist = [ 'install', 'activate', 'dismiss' ];
349
 
350
  if ( in_array( $method, $whitelist, true ) ) {
351
  $response = $this->$method( $slug );
354
  wp_die();
355
  }
356
 
357
+ /**
358
+ * Check if a dependency is currently required.
359
+ *
360
+ * @param string|array $plugin Plugin dependency slug or config.
361
+ *
362
+ * @return boolean True if required. Default: False
363
+ */
364
+ public function is_required( &$plugin ) {
365
+ if ( empty( $this->config ) ) {
366
+ return false;
367
+ }
368
+ if ( is_string( $plugin ) && isset( $this->config[ $plugin ] ) ) {
369
+ $dependency = &$this->config[ $plugin ];
370
+ } else {
371
+ $dependency = &$plugin;
372
+ }
373
+ if ( isset( $dependency['required'] ) ) {
374
+ return true === $dependency['required'] || 'true' === $dependency['required'];
375
+ }
376
+ if ( isset( $dependency['optional'] ) ) {
377
+ return false === $dependency['optional'] || 'false' === $dependency['optional'];
378
+ }
379
+
380
+ return false;
381
+ }
382
+
383
  /**
384
  * Is dependency installed?
385
  *
393
  return isset( $plugins[ $slug ] );
394
  }
395
 
396
+ /**
397
+ * Is dependency active?
398
+ *
399
+ * @param string $slug Plugin slug.
400
+ *
401
+ * @return boolean
402
+ */
403
+ public function is_active( $slug ) {
404
+ return is_plugin_active( $slug );
405
+ }
406
+
407
  /**
408
  * Install and activate dependency.
409
  *
417
  }
418
 
419
  $this->current_slug = $slug;
420
+ add_filter( 'upgrader_source_selection', [ $this, 'upgrader_source_selection' ], 10, 2 );
421
 
422
  $skin = new WPDI_Plugin_Installer_Skin(
423
+ [
424
  'type' => 'plugin',
425
  'nonce' => wp_nonce_url( $this->config[ $slug ]['download_link'] ),
426
+ ]
427
  );
428
  $upgrader = new Plugin_Upgrader( $skin );
429
  $result = $upgrader->install( $this->config[ $slug ]['download_link'] );
430
 
431
  if ( is_wp_error( $result ) ) {
432
+ return [
433
  'status' => 'error',
434
  'message' => $result->get_error_message(),
435
+ ];
436
  }
437
 
438
  if ( null === $result ) {
439
+ return [
440
  'status' => 'error',
441
  'message' => esc_html__( 'Plugin download failed' ),
442
+ ];
443
  }
444
 
445
  wp_cache_flush();
446
+ if ( $this->is_required( $slug ) ) {
447
  $this->activate( $slug );
448
 
449
+ return [
450
  'status' => 'updated',
451
  'slug' => $slug,
452
  /* translators: %s: Plugin name */
453
  'message' => sprintf( esc_html__( '%s has been installed and activated.' ), $this->config[ $slug ]['name'] ),
454
  'source' => $this->config[ $slug ]['source'],
455
+ ];
 
456
  }
457
+
458
+ if ( true !== $result && 'error' === $result['status'] ) {
459
  return $result;
460
  }
461
 
462
+ return [
463
  'status' => 'updated',
464
  /* translators: %s: Plugin name */
465
  'message' => sprintf( esc_html__( '%s has been installed.' ), $this->config[ $slug ]['name'] ),
466
  'source' => $this->config[ $slug ]['source'],
467
+ ];
468
+ }
469
+
470
+ /**
471
+ * Get install plugin notice.
472
+ *
473
+ * @param string $slug Plugin slug.
474
+ *
475
+ * @return array Admin notice.
476
+ */
477
+ public function install_notice( $slug ) {
478
+ $dependency = $this->config[ $slug ];
479
+
480
+ return [
481
+ 'action' => 'install',
482
+ 'slug' => $slug,
483
+ /* translators: %s: Plugin name */
484
+ 'message' => sprintf( esc_html__( 'The %s plugin is recommended.' ), $dependency['name'] ),
485
+ 'source' => $dependency['source'],
486
+ ];
487
  }
488
 
489
  /**
494
  * @return array Message.
495
  */
496
  public function activate( $slug ) {
 
497
  // network activate only if on network admin pages.
498
  $result = is_network_admin() ? activate_plugin( $slug, null, true ) : activate_plugin( $slug );
499
 
500
  if ( is_wp_error( $result ) ) {
501
+ return [
502
  'status' => 'error',
503
  'message' => $result->get_error_message(),
504
+ ];
505
  }
506
 
507
+ return [
508
  'status' => 'updated',
509
  /* translators: %s: Plugin name */
510
  'message' => sprintf( esc_html__( '%s has been activated.' ), $this->config[ $slug ]['name'] ),
511
  'source' => $this->config[ $slug ]['source'],
512
+ ];
513
+ }
514
+
515
+ /**
516
+ * Get activate plugin notice.
517
+ *
518
+ * @param string $slug Plugin slug.
519
+ *
520
+ * @return array Admin notice.
521
+ */
522
+ public function activate_notice( $slug ) {
523
+ $dependency = $this->config[ $slug ];
524
+
525
+ return [
526
+ 'action' => 'activate',
527
+ 'slug' => $slug,
528
+ /* translators: %s: Plugin name */
529
+ 'message' => sprintf( esc_html__( 'Please activate the %s plugin.' ), $dependency['name'] ),
530
+ 'source' => $dependency['source'],
531
+ ];
532
  }
533
 
534
  /**
537
  * @return array Empty Message.
538
  */
539
  public function dismiss() {
540
+ return [
541
  'status' => 'updated',
542
  'message' => '',
543
+ ];
544
  }
545
 
546
  /**
547
  * Correctly rename dependency for activation.
548
  *
549
+ * @param string $source Path fo $source.
550
+ * @param string $remote_source Path of $remote_source.
551
  *
552
  * @return string $new_source
553
  */
554
  public function upgrader_source_selection( $source, $remote_source ) {
 
555
  $new_source = trailingslashit( $remote_source ) . dirname( $this->current_slug );
556
+ $this->move( $source, $new_source );
557
 
558
  return trailingslashit( $new_source );
559
  }
560
 
561
+ /**
562
+ * Rename or recursive file copy and delete.
563
+ *
564
+ * This is more versatile than `$wp_filesystem->move()`.
565
+ * It moves/renames directories as well as files.
566
+ * Fix for https://github.com/afragen/github-updater/issues/826,
567
+ * strange failure of `rename()`.
568
+ *
569
+ * @param string $source File path of source.
570
+ * @param string $destination File path of destination.
571
+ *
572
+ * @return bool|void
573
+ */
574
+ private function move( $source, $destination ) {
575
+ if ( @rename( $source, $destination ) ) {
576
+ return true;
577
+ }
578
+ $dir = opendir( $source );
579
+ mkdir( $destination );
580
+ $source = untrailingslashit( $source );
581
+ // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
582
+ while ( false !== ( $file = readdir( $dir ) ) ) {
583
+ if ( ( '.' !== $file ) && ( '..' !== $file ) && "$source/$file" !== $destination ) {
584
+ if ( is_dir( "$source/$file" ) ) {
585
+ $this->move( "$source/$file", "$destination/$file" );
586
+ } else {
587
+ copy( "$source/$file", "$destination/$file" );
588
+ unlink( "$source/$file" );
589
+ }
590
+ }
591
+ }
592
+ @rmdir( $source );
593
+ closedir( $dir );
594
+ }
595
+
596
  /**
597
  * Display admin notices / action links.
598
  *
602
  if ( ! current_user_can( 'update_plugins' ) ) {
603
  return false;
604
  }
 
605
  foreach ( $this->notices as $notice ) {
606
+ $status = isset( $notice['status'] ) ? $notice['status'] : 'updated';
607
+ $source = isset( $notice['source'] ) ? $notice['source'] : __( 'Dependency' );
608
+ $class = esc_attr( $status ) . ' notice is-dismissible dependency-installer';
609
+ $label = esc_html( $this->get_dismiss_label( $source ) );
610
+ $message = '';
611
+ $action = '';
612
+ $dismissible = '';
613
+
614
+ if ( isset( $notice['message'] ) ) {
615
  $message = esc_html( $notice['message'] );
616
  }
617
 
618
+ if ( isset( $notice['action'] ) ) {
619
+ $action = sprintf(
620
+ ' <a href="javascript:;" class="wpdi-button" data-action="%1$s" data-slug="%2$s">%3$s Now &raquo;</a> ',
621
+ esc_attr( $notice['action'] ),
622
+ esc_attr( $notice['slug'] ),
623
+ esc_html( ucfirst( $notice['action'] ) )
624
+ );
625
+ }
626
+ if ( isset( $notice['slug'] ) ) {
627
+ /**
628
+ * Filters the dismissal timeout.
629
+ *
630
+ * @since 1.4.1
631
+ *
632
+ * @param string|int '7' Default dismissal in days.
633
+ * @param string $notice['source'] Plugin slug of calling plugin.
634
+ * @return string|int Dismissal timeout in days.
635
+ */
636
+ $timeout = apply_filters( 'wp_dependency_timeout', '7', $source );
637
+ $dependency = dirname( $notice['slug'] );
638
+ $dismissible = empty( $timeout ) ? '' : sprintf( 'dependency-installer-%1$s-%2$s', esc_attr( $dependency ), esc_attr( $timeout ) );
639
+ }
640
+ if ( class_exists( '\PAnD' ) && \PAnD::is_admin_notice_active( $dismissible ) ) {
641
+ printf( '<div class="%1$s" data-dismissible="%2$s"><p><strong>[%3$s]</strong> %4$s%5$s</p></div>', $class, $dismissible, $label, $message, $action );
642
  }
 
 
 
 
 
643
  }
644
  }
645
 
646
  /**
647
+ * Make modifications to plugin row.
648
  *
649
+ * @param string $plugin_file Plugin file.
650
  */
651
+ private function modify_plugin_row( $plugin_file ) {
652
+ add_filter( 'network_admin_plugin_action_links_' . $plugin_file, [ $this, 'unset_action_links' ], 10, 2 );
653
+ add_filter( 'plugin_action_links_' . $plugin_file, [ $this, 'unset_action_links' ], 10, 2 );
654
+ add_action( 'after_plugin_row_' . $plugin_file, [ $this, 'modify_plugin_row_elements' ] );
 
 
 
 
 
 
655
  }
656
 
657
  /**
658
+ * Unset plugin action links so required plugins can't be removed or deactivated.
659
  *
660
+ * @param array $actions Action links.
661
+ * @param string $plugin_file Plugin file.
662
  *
663
  * @return mixed
664
  */
665
+ public function unset_action_links( $actions, $plugin_file ) {
666
+ /**
667
+ * Allow to remove required plugin action links.
668
+ *
669
+ * @since 3.0.0
670
+ *
671
+ * @param bool $unset remove default action links.
672
+ */
673
+ if ( apply_filters( 'wp_dependency_unset_action_links', true ) ) {
674
+ if ( isset( $actions['delete'] ) ) {
675
+ unset( $actions['delete'] );
676
+ }
677
+
678
+ if ( isset( $actions['deactivate'] ) ) {
679
+ unset( $actions['deactivate'] );
680
+ }
681
  }
682
+
683
+ /**
684
+ * Allow to display of requied plugin label.
685
+ *
686
+ * @since 3.0.0
687
+ *
688
+ * @param bool $display show required plugin label.
689
+ */
690
+ if ( apply_filters( 'wp_dependency_required_label', true ) ) {
691
+ /* translators: %s: opening and closing span tags */
692
+ $actions = array_merge( [ 'required-plugin' => sprintf( esc_html__( '%1$sRequired Plugin%2$s' ), '<span class="network_active" style="font-variant-caps: small-caps;">', '</span>' ) ], $actions );
693
  }
694
+
695
+ return $actions;
696
+ }
697
+
698
+ /**
699
+ * Modify the plugin row elements.
700
+ *
701
+ * @param string $plugin_file Plugin file.
702
+ *
703
+ * @return void
704
+ */
705
+ public function modify_plugin_row_elements( $plugin_file ) {
706
+ print '<script>';
707
+ /**
708
+ * Allow to display additional row meta info of required plugin.
709
+ *
710
+ * @since 3.0.0
711
+ *
712
+ * @param bool $display show plugin row meta.
713
+ */
714
+ if ( apply_filters( 'wp_dependency_required_row_meta', true ) ) {
715
+ print 'jQuery("tr[data-plugin=\'' . $plugin_file . '\'] .plugin-version-author-uri").append("<br><br><strong>' . esc_html__( 'Required by:' ) . '</strong> ' . $this->get_dependency_sources( $plugin_file ) . '");';
716
  }
717
+ print 'jQuery(".inactive[data-plugin=\'' . $plugin_file . '\']").attr("class", "active");';
718
+ print 'jQuery(".active[data-plugin=\'' . $plugin_file . '\'] .check-column input").remove();';
719
+ print '</script>';
720
+ }
721
 
722
+ /**
723
+ * Get formatted string of dependent plugins.
724
+ *
725
+ * @param string $plugin_file Plugin file.
726
+ *
727
+ * @return string $dependents
728
+ */
729
+ private function get_dependency_sources( $plugin_file ) {
730
+ // Remove empty values from $sources.
731
+ $sources = array_filter( $this->config[ $plugin_file ]['sources'] );
732
+ $sources = array_map( [ $this, 'get_dismiss_label' ], $sources );
733
+ $sources = implode( ', ', $sources );
734
 
735
+ return $sources;
736
+ }
737
+
738
+ /**
739
+ * Get formatted source string for text usage.
740
+ *
741
+ * @param string $source plugin source.
742
+ *
743
+ * @return string friendly plugin name.
744
+ */
745
+ private function get_dismiss_label( $source ) {
746
+ $label = str_replace( '-', ' ', $source );
747
+ $label = ucwords( $label );
748
+ $label = str_ireplace( 'wp ', 'WP ', $label );
749
+
750
+ /**
751
+ * Filters the dismissal notice label
752
+ *
753
+ * @since 3.0.0
754
+ *
755
+ * @param string $label Default dismissal notice string.
756
+ * @param string $source Plugin slug of calling plugin.
757
+ * @return string Dismissal notice string.
758
+ */
759
+ return apply_filters( 'wp_dependency_dismiss_label', $label, $source );
760
  }
761
 
762
  /**
764
  *
765
  * @since 1.4.11
766
  *
767
+ * @param string $slug Plugin slug.
768
+ * @param string $key Dependency key.
769
+ *
770
+ * @return mixed|array The configuration.
771
+ */
772
+ public function get_config( $slug = '', $key = '' ) {
773
+ if ( empty( $slug ) && empty( $key ) ) {
774
+ return $this->config;
775
+ } elseif ( empty( $key ) ) {
776
+ return isset( $this->config[ $slug ] ) ? $this->config[ $slug ] : null;
777
+ } else {
778
+ return isset( $this->config[ $slug ][ $key ] ) ? $this->config[ $slug ][ $key ] : null;
779
+ }
780
+ }
781
+
782
+ /**
783
+ * Add Basic Auth headers for authentication.
784
+ *
785
+ * @param array $args HTTP header args.
786
+ * @param string $url URL.
787
+ *
788
+ * @return array $args
789
  */
790
+ public function add_basic_auth_headers( $args, $url ) {
791
+ if ( null === $this->current_slug ) {
792
+ return $args;
793
+ }
794
+ $package = $this->config[ $this->current_slug ];
795
+ $host = $package['host'];
796
+ $token = empty( $package['token'] ) ? false : $package['token'];
797
+
798
+ if ( $token && $url === $package['download_link'] ) {
799
+ if ( 'bitbucket' === $host ) {
800
+ // Bitbucket token must be in the form of 'username:password'.
801
+ // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
802
+ $args['headers']['Authorization'] = 'Basic ' . base64_encode( $token );
803
+ }
804
+ if ( 'github' === $host || 'gitea' === $host ) {
805
+ $args['headers']['Authorization'] = 'token ' . $token;
806
+ }
807
+ if ( 'gitlab' === $host ) {
808
+ $args['headers']['Authorization'] = 'Bearer ' . $token;
809
+ }
810
+ }
811
+
812
+ // dot org should not have auth header.
813
+ // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
814
+ if ( 'wordpress' === $host ) {
815
+ unset( $args['headers']['Authorization'] );
816
+ }
817
+ remove_filter( 'http_request_args', [ $this, 'add_basic_auth_headers' ] );
818
+
819
+ return $args;
820
  }
821
  }
822
 
826
  * Class WPDI_Plugin_Installer_Skin
827
  */
828
  class WPDI_Plugin_Installer_Skin extends Plugin_Installer_Skin {
829
+ public function header() {
830
+ }
831
+
832
+ public function footer() {
833
+ }
834
+
835
+ public function error( $errors ) {
836
+ }
837
 
838
+ public function feedback( $string, ...$args ) {
839
+ }
840
+ }
841
  }