Passed
Push — main ( 16d49b...d78e29 )
by TARIQ
111:03
created
brighty/wp-admin/includes/class-walker-category-checklist.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -17,122 +17,122 @@
 block discarded – undo
17 17
  * @see wp_terms_checklist()
18 18
  */
19 19
 class Walker_Category_Checklist extends Walker {
20
-	public $tree_type = 'category';
21
-	public $db_fields = array(
22
-		'parent' => 'parent',
23
-		'id'     => 'term_id',
24
-	); // TODO: Decouple this.
20
+    public $tree_type = 'category';
21
+    public $db_fields = array(
22
+        'parent' => 'parent',
23
+        'id'     => 'term_id',
24
+    ); // TODO: Decouple this.
25 25
 
26
-	/**
27
-	 * Starts the list before the elements are added.
28
-	 *
29
-	 * @see Walker:start_lvl()
30
-	 *
31
-	 * @since 2.5.1
32
-	 *
33
-	 * @param string $output Used to append additional content (passed by reference).
34
-	 * @param int    $depth  Depth of category. Used for tab indentation.
35
-	 * @param array  $args   An array of arguments. @see wp_terms_checklist()
36
-	 */
37
-	public function start_lvl( &$output, $depth = 0, $args = array() ) {
38
-		$indent  = str_repeat( "\t", $depth );
39
-		$output .= "$indent<ul class='children'>\n";
40
-	}
26
+    /**
27
+     * Starts the list before the elements are added.
28
+     *
29
+     * @see Walker:start_lvl()
30
+     *
31
+     * @since 2.5.1
32
+     *
33
+     * @param string $output Used to append additional content (passed by reference).
34
+     * @param int    $depth  Depth of category. Used for tab indentation.
35
+     * @param array  $args   An array of arguments. @see wp_terms_checklist()
36
+     */
37
+    public function start_lvl( &$output, $depth = 0, $args = array() ) {
38
+        $indent  = str_repeat( "\t", $depth );
39
+        $output .= "$indent<ul class='children'>\n";
40
+    }
41 41
 
42
-	/**
43
-	 * Ends the list of after the elements are added.
44
-	 *
45
-	 * @see Walker::end_lvl()
46
-	 *
47
-	 * @since 2.5.1
48
-	 *
49
-	 * @param string $output Used to append additional content (passed by reference).
50
-	 * @param int    $depth  Depth of category. Used for tab indentation.
51
-	 * @param array  $args   An array of arguments. @see wp_terms_checklist()
52
-	 */
53
-	public function end_lvl( &$output, $depth = 0, $args = array() ) {
54
-		$indent  = str_repeat( "\t", $depth );
55
-		$output .= "$indent</ul>\n";
56
-	}
42
+    /**
43
+     * Ends the list of after the elements are added.
44
+     *
45
+     * @see Walker::end_lvl()
46
+     *
47
+     * @since 2.5.1
48
+     *
49
+     * @param string $output Used to append additional content (passed by reference).
50
+     * @param int    $depth  Depth of category. Used for tab indentation.
51
+     * @param array  $args   An array of arguments. @see wp_terms_checklist()
52
+     */
53
+    public function end_lvl( &$output, $depth = 0, $args = array() ) {
54
+        $indent  = str_repeat( "\t", $depth );
55
+        $output .= "$indent</ul>\n";
56
+    }
57 57
 
58
-	/**
59
-	 * Start the element output.
60
-	 *
61
-	 * @see Walker::start_el()
62
-	 *
63
-	 * @since 2.5.1
64
-	 * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id`
65
-	 *              to match parent class for PHP 8 named parameter support.
66
-	 *
67
-	 * @param string  $output            Used to append additional content (passed by reference).
68
-	 * @param WP_Term $data_object       The current term object.
69
-	 * @param int     $depth             Depth of the term in reference to parents. Default 0.
70
-	 * @param array   $args              An array of arguments. @see wp_terms_checklist()
71
-	 * @param int     $current_object_id Optional. ID of the current term. Default 0.
72
-	 */
73
-	public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {
74
-		// Restores the more descriptive, specific name for use within this method.
75
-		$category = $data_object;
58
+    /**
59
+     * Start the element output.
60
+     *
61
+     * @see Walker::start_el()
62
+     *
63
+     * @since 2.5.1
64
+     * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id`
65
+     *              to match parent class for PHP 8 named parameter support.
66
+     *
67
+     * @param string  $output            Used to append additional content (passed by reference).
68
+     * @param WP_Term $data_object       The current term object.
69
+     * @param int     $depth             Depth of the term in reference to parents. Default 0.
70
+     * @param array   $args              An array of arguments. @see wp_terms_checklist()
71
+     * @param int     $current_object_id Optional. ID of the current term. Default 0.
72
+     */
73
+    public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {
74
+        // Restores the more descriptive, specific name for use within this method.
75
+        $category = $data_object;
76 76
 
77
-		if ( empty( $args['taxonomy'] ) ) {
78
-			$taxonomy = 'category';
79
-		} else {
80
-			$taxonomy = $args['taxonomy'];
81
-		}
77
+        if ( empty( $args['taxonomy'] ) ) {
78
+            $taxonomy = 'category';
79
+        } else {
80
+            $taxonomy = $args['taxonomy'];
81
+        }
82 82
 
83
-		if ( 'category' === $taxonomy ) {
84
-			$name = 'post_category';
85
-		} else {
86
-			$name = 'tax_input[' . $taxonomy . ']';
87
-		}
83
+        if ( 'category' === $taxonomy ) {
84
+            $name = 'post_category';
85
+        } else {
86
+            $name = 'tax_input[' . $taxonomy . ']';
87
+        }
88 88
 
89
-		$args['popular_cats'] = ! empty( $args['popular_cats'] ) ? array_map( 'intval', $args['popular_cats'] ) : array();
89
+        $args['popular_cats'] = ! empty( $args['popular_cats'] ) ? array_map( 'intval', $args['popular_cats'] ) : array();
90 90
 
91
-		$class = in_array( $category->term_id, $args['popular_cats'], true ) ? ' class="popular-category"' : '';
91
+        $class = in_array( $category->term_id, $args['popular_cats'], true ) ? ' class="popular-category"' : '';
92 92
 
93
-		$args['selected_cats'] = ! empty( $args['selected_cats'] ) ? array_map( 'intval', $args['selected_cats'] ) : array();
93
+        $args['selected_cats'] = ! empty( $args['selected_cats'] ) ? array_map( 'intval', $args['selected_cats'] ) : array();
94 94
 
95
-		if ( ! empty( $args['list_only'] ) ) {
96
-			$aria_checked = 'false';
97
-			$inner_class  = 'category';
95
+        if ( ! empty( $args['list_only'] ) ) {
96
+            $aria_checked = 'false';
97
+            $inner_class  = 'category';
98 98
 
99
-			if ( in_array( $category->term_id, $args['selected_cats'], true ) ) {
100
-				$inner_class .= ' selected';
101
-				$aria_checked = 'true';
102
-			}
99
+            if ( in_array( $category->term_id, $args['selected_cats'], true ) ) {
100
+                $inner_class .= ' selected';
101
+                $aria_checked = 'true';
102
+            }
103 103
 
104
-			$output .= "\n" . '<li' . $class . '>' .
105
-				'<div class="' . $inner_class . '" data-term-id=' . $category->term_id .
106
-				' tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '">' .
107
-				/** This filter is documented in wp-includes/category-template.php */
108
-				esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</div>';
109
-		} else {
110
-			$is_selected = in_array( $category->term_id, $args['selected_cats'], true );
111
-			$is_disabled = ! empty( $args['disabled'] );
104
+            $output .= "\n" . '<li' . $class . '>' .
105
+                '<div class="' . $inner_class . '" data-term-id=' . $category->term_id .
106
+                ' tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '">' .
107
+                /** This filter is documented in wp-includes/category-template.php */
108
+                esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</div>';
109
+        } else {
110
+            $is_selected = in_array( $category->term_id, $args['selected_cats'], true );
111
+            $is_disabled = ! empty( $args['disabled'] );
112 112
 
113
-			$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" .
114
-				'<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="in-' . $taxonomy . '-' . $category->term_id . '"' .
115
-				checked( $is_selected, true, false ) .
116
-				disabled( $is_disabled, true, false ) . ' /> ' .
117
-				/** This filter is documented in wp-includes/category-template.php */
118
-				esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</label>';
119
-		}
120
-	}
113
+            $output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" .
114
+                '<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="in-' . $taxonomy . '-' . $category->term_id . '"' .
115
+                checked( $is_selected, true, false ) .
116
+                disabled( $is_disabled, true, false ) . ' /> ' .
117
+                /** This filter is documented in wp-includes/category-template.php */
118
+                esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</label>';
119
+        }
120
+    }
121 121
 
122
-	/**
123
-	 * Ends the element output, if needed.
124
-	 *
125
-	 * @see Walker::end_el()
126
-	 *
127
-	 * @since 2.5.1
128
-	 * @since 5.9.0 Renamed `$category` to `$data_object` to match parent class for PHP 8 named parameter support.
129
-	 *
130
-	 * @param string  $output      Used to append additional content (passed by reference).
131
-	 * @param WP_Term $data_object The current term object.
132
-	 * @param int     $depth       Depth of the term in reference to parents. Default 0.
133
-	 * @param array   $args        An array of arguments. @see wp_terms_checklist()
134
-	 */
135
-	public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {
136
-		$output .= "</li>\n";
137
-	}
122
+    /**
123
+     * Ends the element output, if needed.
124
+     *
125
+     * @see Walker::end_el()
126
+     *
127
+     * @since 2.5.1
128
+     * @since 5.9.0 Renamed `$category` to `$data_object` to match parent class for PHP 8 named parameter support.
129
+     *
130
+     * @param string  $output      Used to append additional content (passed by reference).
131
+     * @param WP_Term $data_object The current term object.
132
+     * @param int     $depth       Depth of the term in reference to parents. Default 0.
133
+     * @param array   $args        An array of arguments. @see wp_terms_checklist()
134
+     */
135
+    public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {
136
+        $output .= "</li>\n";
137
+    }
138 138
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/theme-install.php 1 patch
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -7,47 +7,47 @@  discard block
 block discarded – undo
7 7
  */
8 8
 
9 9
 $themes_allowedtags = array(
10
-	'a'       => array(
11
-		'href'   => array(),
12
-		'title'  => array(),
13
-		'target' => array(),
14
-	),
15
-	'abbr'    => array( 'title' => array() ),
16
-	'acronym' => array( 'title' => array() ),
17
-	'code'    => array(),
18
-	'pre'     => array(),
19
-	'em'      => array(),
20
-	'strong'  => array(),
21
-	'div'     => array(),
22
-	'p'       => array(),
23
-	'ul'      => array(),
24
-	'ol'      => array(),
25
-	'li'      => array(),
26
-	'h1'      => array(),
27
-	'h2'      => array(),
28
-	'h3'      => array(),
29
-	'h4'      => array(),
30
-	'h5'      => array(),
31
-	'h6'      => array(),
32
-	'img'     => array(
33
-		'src'   => array(),
34
-		'class' => array(),
35
-		'alt'   => array(),
36
-	),
10
+    'a'       => array(
11
+        'href'   => array(),
12
+        'title'  => array(),
13
+        'target' => array(),
14
+    ),
15
+    'abbr'    => array( 'title' => array() ),
16
+    'acronym' => array( 'title' => array() ),
17
+    'code'    => array(),
18
+    'pre'     => array(),
19
+    'em'      => array(),
20
+    'strong'  => array(),
21
+    'div'     => array(),
22
+    'p'       => array(),
23
+    'ul'      => array(),
24
+    'ol'      => array(),
25
+    'li'      => array(),
26
+    'h1'      => array(),
27
+    'h2'      => array(),
28
+    'h3'      => array(),
29
+    'h4'      => array(),
30
+    'h5'      => array(),
31
+    'h6'      => array(),
32
+    'img'     => array(
33
+        'src'   => array(),
34
+        'class' => array(),
35
+        'alt'   => array(),
36
+    ),
37 37
 );
38 38
 
39 39
 $theme_field_defaults = array(
40
-	'description'  => true,
41
-	'sections'     => false,
42
-	'tested'       => true,
43
-	'requires'     => true,
44
-	'rating'       => true,
45
-	'downloaded'   => true,
46
-	'downloadlink' => true,
47
-	'last_updated' => true,
48
-	'homepage'     => true,
49
-	'tags'         => true,
50
-	'num_ratings'  => true,
40
+    'description'  => true,
41
+    'sections'     => false,
42
+    'tested'       => true,
43
+    'requires'     => true,
44
+    'rating'       => true,
45
+    'downloaded'   => true,
46
+    'downloadlink' => true,
47
+    'last_updated' => true,
48
+    'homepage'     => true,
49
+    'tags'         => true,
50
+    'num_ratings'  => true,
51 51
 );
52 52
 
53 53
 /**
@@ -60,25 +60,25 @@  discard block
 block discarded – undo
60 60
  * @return array
61 61
  */
62 62
 function install_themes_feature_list() {
63
-	_deprecated_function( __FUNCTION__, '3.1.0', 'get_theme_feature_list()' );
63
+    _deprecated_function( __FUNCTION__, '3.1.0', 'get_theme_feature_list()' );
64 64
 
65
-	$cache = get_transient( 'wporg_theme_feature_list' );
66
-	if ( ! $cache ) {
67
-		set_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS );
68
-	}
65
+    $cache = get_transient( 'wporg_theme_feature_list' );
66
+    if ( ! $cache ) {
67
+        set_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS );
68
+    }
69 69
 
70
-	if ( $cache ) {
71
-		return $cache;
72
-	}
70
+    if ( $cache ) {
71
+        return $cache;
72
+    }
73 73
 
74
-	$feature_list = themes_api( 'feature_list', array() );
75
-	if ( is_wp_error( $feature_list ) ) {
76
-		return array();
77
-	}
74
+    $feature_list = themes_api( 'feature_list', array() );
75
+    if ( is_wp_error( $feature_list ) ) {
76
+        return array();
77
+    }
78 78
 
79
-	set_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS );
79
+    set_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS );
80 80
 
81
-	return $feature_list;
81
+    return $feature_list;
82 82
 }
83 83
 
84 84
 /**
@@ -89,12 +89,12 @@  discard block
 block discarded – undo
89 89
  * @param bool $type_selector
90 90
  */
91 91
 function install_theme_search_form( $type_selector = true ) {
92
-	$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
93
-	$term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
94
-	if ( ! $type_selector ) {
95
-		echo '<p class="install-help">' . __( 'Search for themes by keyword.' ) . '</p>';
96
-	}
97
-	?>
92
+    $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
93
+    $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
94
+    if ( ! $type_selector ) {
95
+        echo '<p class="install-help">' . __( 'Search for themes by keyword.' ) . '</p>';
96
+    }
97
+    ?>
98 98
 <form id="search-themes" method="get">
99 99
 	<input type="hidden" name="tab" value="search" />
100 100
 	<?php if ( $type_selector ) : ?>
@@ -106,18 +106,18 @@  discard block
 block discarded – undo
106 106
 	</select>
107 107
 	<label class="screen-reader-text" for="s">
108 108
 		<?php
109
-		switch ( $type ) {
110
-			case 'term':
111
-				_e( 'Search by keyword' );
112
-				break;
113
-			case 'author':
114
-				_e( 'Search by author' );
115
-				break;
116
-			case 'tag':
117
-				_e( 'Search by tag' );
118
-				break;
119
-		}
120
-		?>
109
+        switch ( $type ) {
110
+            case 'term':
111
+                _e( 'Search by keyword' );
112
+                break;
113
+            case 'author':
114
+                _e( 'Search by author' );
115
+                break;
116
+            case 'tag':
117
+                _e( 'Search by tag' );
118
+                break;
119
+        }
120
+        ?>
121 121
 	</label>
122 122
 	<?php else : ?>
123 123
 	<label class="screen-reader-text" for="s"><?php _e( 'Search by keyword' ); ?></label>
@@ -134,26 +134,26 @@  discard block
 block discarded – undo
134 134
  * @since 2.8.0
135 135
  */
136 136
 function install_themes_dashboard() {
137
-	install_theme_search_form( false );
138
-	?>
137
+    install_theme_search_form( false );
138
+    ?>
139 139
 <h4><?php _e( 'Feature Filter' ); ?></h4>
140 140
 <p class="install-help"><?php _e( 'Find a theme based on specific features.' ); ?></p>
141 141
 
142 142
 <form method="get">
143 143
 	<input type="hidden" name="tab" value="search" />
144 144
 	<?php
145
-	$feature_list = get_theme_feature_list();
146
-	echo '<div class="feature-filter">';
145
+    $feature_list = get_theme_feature_list();
146
+    echo '<div class="feature-filter">';
147 147
 
148
-	foreach ( (array) $feature_list as $feature_name => $features ) {
149
-		$feature_name = esc_html( $feature_name );
150
-		echo '<div class="feature-name">' . $feature_name . '</div>';
148
+    foreach ( (array) $feature_list as $feature_name => $features ) {
149
+        $feature_name = esc_html( $feature_name );
150
+        echo '<div class="feature-name">' . $feature_name . '</div>';
151 151
 
152
-		echo '<ol class="feature-group">';
153
-		foreach ( $features as $feature => $feature_name ) {
154
-			$feature_name = esc_html( $feature_name );
155
-			$feature      = esc_attr( $feature );
156
-			?>
152
+        echo '<ol class="feature-group">';
153
+        foreach ( $features as $feature => $feature_name ) {
154
+            $feature_name = esc_html( $feature_name );
155
+            $feature      = esc_attr( $feature );
156
+            ?>
157 157
 
158 158
 <li>
159 159
 	<input type="checkbox" name="features[]" id="feature-id-<?php echo $feature; ?>" value="<?php echo $feature; ?>" />
@@ -164,8 +164,8 @@  discard block
 block discarded – undo
164 164
 </ol>
165 165
 <br class="clear" />
166 166
 		<?php
167
-	}
168
-	?>
167
+    }
168
+    ?>
169 169
 
170 170
 </div>
171 171
 <br class="clear" />
@@ -178,7 +178,7 @@  discard block
 block discarded – undo
178 178
  * @since 2.8.0
179 179
  */
180 180
 function install_themes_upload() {
181
-	?>
181
+    ?>
182 182
 <p class="install-help"><?php _e( 'If you have a theme in a .zip format, you may install or update it by uploading it here.' ); ?></p>
183 183
 <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo self_admin_url( 'update.php?action=upload-theme' ); ?>">
184 184
 	<?php wp_nonce_field( 'theme-upload' ); ?>
@@ -199,13 +199,13 @@  discard block
 block discarded – undo
199 199
  * @param object $theme
200 200
  */
201 201
 function display_theme( $theme ) {
202
-	_deprecated_function( __FUNCTION__, '3.4.0' );
203
-	global $wp_list_table;
204
-	if ( ! isset( $wp_list_table ) ) {
205
-		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
206
-	}
207
-	$wp_list_table->prepare_items();
208
-	$wp_list_table->single_row( $theme );
202
+    _deprecated_function( __FUNCTION__, '3.4.0' );
203
+    global $wp_list_table;
204
+    if ( ! isset( $wp_list_table ) ) {
205
+        $wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
206
+    }
207
+    $wp_list_table->prepare_items();
208
+    $wp_list_table->single_row( $theme );
209 209
 }
210 210
 
211 211
 /**
@@ -216,13 +216,13 @@  discard block
 block discarded – undo
216 216
  * @global WP_Theme_Install_List_Table $wp_list_table
217 217
  */
218 218
 function display_themes() {
219
-	global $wp_list_table;
219
+    global $wp_list_table;
220 220
 
221
-	if ( ! isset( $wp_list_table ) ) {
222
-		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
223
-	}
224
-	$wp_list_table->prepare_items();
225
-	$wp_list_table->display();
221
+    if ( ! isset( $wp_list_table ) ) {
222
+        $wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
223
+    }
224
+    $wp_list_table->prepare_items();
225
+    $wp_list_table->display();
226 226
 
227 227
 }
228 228
 
@@ -234,19 +234,19 @@  discard block
 block discarded – undo
234 234
  * @global WP_Theme_Install_List_Table $wp_list_table
235 235
  */
236 236
 function install_theme_information() {
237
-	global $wp_list_table;
237
+    global $wp_list_table;
238 238
 
239
-	$theme = themes_api( 'theme_information', array( 'slug' => wp_unslash( $_REQUEST['theme'] ) ) );
239
+    $theme = themes_api( 'theme_information', array( 'slug' => wp_unslash( $_REQUEST['theme'] ) ) );
240 240
 
241
-	if ( is_wp_error( $theme ) ) {
242
-		wp_die( $theme );
243
-	}
241
+    if ( is_wp_error( $theme ) ) {
242
+        wp_die( $theme );
243
+    }
244 244
 
245
-	iframe_header( __( 'Theme Installation' ) );
246
-	if ( ! isset( $wp_list_table ) ) {
247
-		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
248
-	}
249
-	$wp_list_table->theme_installer_single( $theme );
250
-	iframe_footer();
251
-	exit;
245
+    iframe_header( __( 'Theme Installation' ) );
246
+    if ( ! isset( $wp_list_table ) ) {
247
+        $wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
248
+    }
249
+    $wp_list_table->theme_installer_single( $theme );
250
+    iframe_footer();
251
+    exit;
252 252
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/class-ftp-sockets.php 1 patch
Indentation   +200 added lines, -200 removed lines patch added patch discarded remove patch
@@ -27,220 +27,220 @@
 block discarded – undo
27 27
  */
28 28
 class ftp_sockets extends ftp_base {
29 29
 
30
-	function __construct($verb=FALSE, $le=FALSE) {
31
-		parent::__construct(true, $verb, $le);
32
-	}
30
+    function __construct($verb=FALSE, $le=FALSE) {
31
+        parent::__construct(true, $verb, $le);
32
+    }
33 33
 
34 34
 // <!-- --------------------------------------------------------------------------------------- -->
35 35
 // <!--       Private functions                                                                 -->
36 36
 // <!-- --------------------------------------------------------------------------------------- -->
37 37
 
38
-	function _settimeout($sock) {
39
-		if(!@socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
40
-			$this->PushError('_connect','socket set receive timeout',socket_strerror(socket_last_error($sock)));
41
-			@socket_close($sock);
42
-			return FALSE;
43
-		}
44
-		if(!@socket_set_option($sock, SOL_SOCKET , SO_SNDTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
45
-			$this->PushError('_connect','socket set send timeout',socket_strerror(socket_last_error($sock)));
46
-			@socket_close($sock);
47
-			return FALSE;
48
-		}
49
-		return true;
50
-	}
38
+    function _settimeout($sock) {
39
+        if(!@socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
40
+            $this->PushError('_connect','socket set receive timeout',socket_strerror(socket_last_error($sock)));
41
+            @socket_close($sock);
42
+            return FALSE;
43
+        }
44
+        if(!@socket_set_option($sock, SOL_SOCKET , SO_SNDTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
45
+            $this->PushError('_connect','socket set send timeout',socket_strerror(socket_last_error($sock)));
46
+            @socket_close($sock);
47
+            return FALSE;
48
+        }
49
+        return true;
50
+    }
51 51
 
52
-	function _connect($host, $port) {
53
-		$this->SendMSG("Creating socket");
54
-		if(!($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
55
-			$this->PushError('_connect','socket create failed',socket_strerror(socket_last_error($sock)));
56
-			return FALSE;
57
-		}
58
-		if(!$this->_settimeout($sock)) return FALSE;
59
-		$this->SendMSG("Connecting to \"".$host.":".$port."\"");
60
-		if (!($res = @socket_connect($sock, $host, $port))) {
61
-			$this->PushError('_connect','socket connect failed',socket_strerror(socket_last_error($sock)));
62
-			@socket_close($sock);
63
-			return FALSE;
64
-		}
65
-		$this->_connected=true;
66
-		return $sock;
67
-	}
52
+    function _connect($host, $port) {
53
+        $this->SendMSG("Creating socket");
54
+        if(!($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
55
+            $this->PushError('_connect','socket create failed',socket_strerror(socket_last_error($sock)));
56
+            return FALSE;
57
+        }
58
+        if(!$this->_settimeout($sock)) return FALSE;
59
+        $this->SendMSG("Connecting to \"".$host.":".$port."\"");
60
+        if (!($res = @socket_connect($sock, $host, $port))) {
61
+            $this->PushError('_connect','socket connect failed',socket_strerror(socket_last_error($sock)));
62
+            @socket_close($sock);
63
+            return FALSE;
64
+        }
65
+        $this->_connected=true;
66
+        return $sock;
67
+    }
68 68
 
69
-	function _readmsg($fnction="_readmsg"){
70
-		if(!$this->_connected) {
71
-			$this->PushError($fnction,'Connect first');
72
-			return FALSE;
73
-		}
74
-		$result=true;
75
-		$this->_message="";
76
-		$this->_code=0;
77
-		$go=true;
78
-		do {
79
-			$tmp=@socket_read($this->_ftp_control_sock, 4096, PHP_BINARY_READ);
80
-			if($tmp===false) {
81
-				$go=$result=false;
82
-				$this->PushError($fnction,'Read failed', socket_strerror(socket_last_error($this->_ftp_control_sock)));
83
-			} else {
84
-				$this->_message.=$tmp;
85
-				$go = !preg_match("/^([0-9]{3})(-.+\\1)? [^".CRLF."]+".CRLF."$/Us", $this->_message, $regs);
86
-			}
87
-		} while($go);
88
-		if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF;
89
-		$this->_code=(int)$regs[1];
90
-		return $result;
91
-	}
69
+    function _readmsg($fnction="_readmsg"){
70
+        if(!$this->_connected) {
71
+            $this->PushError($fnction,'Connect first');
72
+            return FALSE;
73
+        }
74
+        $result=true;
75
+        $this->_message="";
76
+        $this->_code=0;
77
+        $go=true;
78
+        do {
79
+            $tmp=@socket_read($this->_ftp_control_sock, 4096, PHP_BINARY_READ);
80
+            if($tmp===false) {
81
+                $go=$result=false;
82
+                $this->PushError($fnction,'Read failed', socket_strerror(socket_last_error($this->_ftp_control_sock)));
83
+            } else {
84
+                $this->_message.=$tmp;
85
+                $go = !preg_match("/^([0-9]{3})(-.+\\1)? [^".CRLF."]+".CRLF."$/Us", $this->_message, $regs);
86
+            }
87
+        } while($go);
88
+        if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF;
89
+        $this->_code=(int)$regs[1];
90
+        return $result;
91
+    }
92 92
 
93
-	function _exec($cmd, $fnction="_exec") {
94
-		if(!$this->_ready) {
95
-			$this->PushError($fnction,'Connect first');
96
-			return FALSE;
97
-		}
98
-		if($this->LocalEcho) echo "PUT > ",$cmd,CRLF;
99
-		$status=@socket_write($this->_ftp_control_sock, $cmd.CRLF);
100
-		if($status===false) {
101
-			$this->PushError($fnction,'socket write failed', socket_strerror(socket_last_error($this->stream)));
102
-			return FALSE;
103
-		}
104
-		$this->_lastaction=time();
105
-		if(!$this->_readmsg($fnction)) return FALSE;
106
-		return TRUE;
107
-	}
93
+    function _exec($cmd, $fnction="_exec") {
94
+        if(!$this->_ready) {
95
+            $this->PushError($fnction,'Connect first');
96
+            return FALSE;
97
+        }
98
+        if($this->LocalEcho) echo "PUT > ",$cmd,CRLF;
99
+        $status=@socket_write($this->_ftp_control_sock, $cmd.CRLF);
100
+        if($status===false) {
101
+            $this->PushError($fnction,'socket write failed', socket_strerror(socket_last_error($this->stream)));
102
+            return FALSE;
103
+        }
104
+        $this->_lastaction=time();
105
+        if(!$this->_readmsg($fnction)) return FALSE;
106
+        return TRUE;
107
+    }
108 108
 
109
-	function _data_prepare($mode=FTP_ASCII) {
110
-		if(!$this->_settype($mode)) return FALSE;
111
-		$this->SendMSG("Creating data socket");
112
-		$this->_ftp_data_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
113
-		if ($this->_ftp_data_sock < 0) {
114
-			$this->PushError('_data_prepare','socket create failed',socket_strerror(socket_last_error($this->_ftp_data_sock)));
115
-			return FALSE;
116
-		}
117
-		if(!$this->_settimeout($this->_ftp_data_sock)) {
118
-			$this->_data_close();
119
-			return FALSE;
120
-		}
121
-		if($this->_passive) {
122
-			if(!$this->_exec("PASV", "pasv")) {
123
-				$this->_data_close();
124
-				return FALSE;
125
-			}
126
-			if(!$this->_checkCode()) {
127
-				$this->_data_close();
128
-				return FALSE;
129
-			}
130
-			$ip_port = explode(",", preg_replace("/^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*$/s", "\\1", $this->_message));
131
-			$this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3];
132
-			$this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]);
133
-			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
134
-			if(!@socket_connect($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
135
-				$this->PushError("_data_prepare","socket_connect", socket_strerror(socket_last_error($this->_ftp_data_sock)));
136
-				$this->_data_close();
137
-				return FALSE;
138
-			}
139
-			else $this->_ftp_temp_sock=$this->_ftp_data_sock;
140
-		} else {
141
-			if(!@socket_getsockname($this->_ftp_control_sock, $addr, $port)) {
142
-				$this->PushError("_data_prepare","cannot get control socket information", socket_strerror(socket_last_error($this->_ftp_control_sock)));
143
-				$this->_data_close();
144
-				return FALSE;
145
-			}
146
-			if(!@socket_bind($this->_ftp_data_sock,$addr)){
147
-				$this->PushError("_data_prepare","cannot bind data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
148
-				$this->_data_close();
149
-				return FALSE;
150
-			}
151
-			if(!@socket_listen($this->_ftp_data_sock)) {
152
-				$this->PushError("_data_prepare","cannot listen data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
153
-				$this->_data_close();
154
-				return FALSE;
155
-			}
156
-			if(!@socket_getsockname($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
157
-				$this->PushError("_data_prepare","cannot get data socket information", socket_strerror(socket_last_error($this->_ftp_data_sock)));
158
-				$this->_data_close();
159
-				return FALSE;
160
-			}
161
-			if(!$this->_exec('PORT '.str_replace('.',',',$this->_datahost.'.'.($this->_dataport>>8).'.'.($this->_dataport&0x00FF)), "_port")) {
162
-				$this->_data_close();
163
-				return FALSE;
164
-			}
165
-			if(!$this->_checkCode()) {
166
-				$this->_data_close();
167
-				return FALSE;
168
-			}
169
-		}
170
-		return TRUE;
171
-	}
109
+    function _data_prepare($mode=FTP_ASCII) {
110
+        if(!$this->_settype($mode)) return FALSE;
111
+        $this->SendMSG("Creating data socket");
112
+        $this->_ftp_data_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
113
+        if ($this->_ftp_data_sock < 0) {
114
+            $this->PushError('_data_prepare','socket create failed',socket_strerror(socket_last_error($this->_ftp_data_sock)));
115
+            return FALSE;
116
+        }
117
+        if(!$this->_settimeout($this->_ftp_data_sock)) {
118
+            $this->_data_close();
119
+            return FALSE;
120
+        }
121
+        if($this->_passive) {
122
+            if(!$this->_exec("PASV", "pasv")) {
123
+                $this->_data_close();
124
+                return FALSE;
125
+            }
126
+            if(!$this->_checkCode()) {
127
+                $this->_data_close();
128
+                return FALSE;
129
+            }
130
+            $ip_port = explode(",", preg_replace("/^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*$/s", "\\1", $this->_message));
131
+            $this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3];
132
+            $this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]);
133
+            $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
134
+            if(!@socket_connect($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
135
+                $this->PushError("_data_prepare","socket_connect", socket_strerror(socket_last_error($this->_ftp_data_sock)));
136
+                $this->_data_close();
137
+                return FALSE;
138
+            }
139
+            else $this->_ftp_temp_sock=$this->_ftp_data_sock;
140
+        } else {
141
+            if(!@socket_getsockname($this->_ftp_control_sock, $addr, $port)) {
142
+                $this->PushError("_data_prepare","cannot get control socket information", socket_strerror(socket_last_error($this->_ftp_control_sock)));
143
+                $this->_data_close();
144
+                return FALSE;
145
+            }
146
+            if(!@socket_bind($this->_ftp_data_sock,$addr)){
147
+                $this->PushError("_data_prepare","cannot bind data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
148
+                $this->_data_close();
149
+                return FALSE;
150
+            }
151
+            if(!@socket_listen($this->_ftp_data_sock)) {
152
+                $this->PushError("_data_prepare","cannot listen data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
153
+                $this->_data_close();
154
+                return FALSE;
155
+            }
156
+            if(!@socket_getsockname($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
157
+                $this->PushError("_data_prepare","cannot get data socket information", socket_strerror(socket_last_error($this->_ftp_data_sock)));
158
+                $this->_data_close();
159
+                return FALSE;
160
+            }
161
+            if(!$this->_exec('PORT '.str_replace('.',',',$this->_datahost.'.'.($this->_dataport>>8).'.'.($this->_dataport&0x00FF)), "_port")) {
162
+                $this->_data_close();
163
+                return FALSE;
164
+            }
165
+            if(!$this->_checkCode()) {
166
+                $this->_data_close();
167
+                return FALSE;
168
+            }
169
+        }
170
+        return TRUE;
171
+    }
172 172
 
173
-	function _data_read($mode=FTP_ASCII, $fp=NULL) {
174
-		$NewLine=$this->_eol_code[$this->OS_local];
175
-		if(is_resource($fp)) $out=0;
176
-		else $out="";
177
-		if(!$this->_passive) {
178
-			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
179
-			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
180
-			if($this->_ftp_temp_sock===FALSE) {
181
-				$this->PushError("_data_read","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
182
-				$this->_data_close();
183
-				return FALSE;
184
-			}
185
-		}
173
+    function _data_read($mode=FTP_ASCII, $fp=NULL) {
174
+        $NewLine=$this->_eol_code[$this->OS_local];
175
+        if(is_resource($fp)) $out=0;
176
+        else $out="";
177
+        if(!$this->_passive) {
178
+            $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
179
+            $this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
180
+            if($this->_ftp_temp_sock===FALSE) {
181
+                $this->PushError("_data_read","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
182
+                $this->_data_close();
183
+                return FALSE;
184
+            }
185
+        }
186 186
 
187
-		while(($block=@socket_read($this->_ftp_temp_sock, $this->_ftp_buff_size, PHP_BINARY_READ))!==false) {
188
-			if($block==="") break;
189
-			if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block);
190
-			if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block));
191
-			else $out.=$block;
192
-		}
193
-		return $out;
194
-	}
187
+        while(($block=@socket_read($this->_ftp_temp_sock, $this->_ftp_buff_size, PHP_BINARY_READ))!==false) {
188
+            if($block==="") break;
189
+            if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block);
190
+            if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block));
191
+            else $out.=$block;
192
+        }
193
+        return $out;
194
+    }
195 195
 
196
-	function _data_write($mode=FTP_ASCII, $fp=NULL) {
197
-		$NewLine=$this->_eol_code[$this->OS_local];
198
-		if(is_resource($fp)) $out=0;
199
-		else $out="";
200
-		if(!$this->_passive) {
201
-			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
202
-			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
203
-			if($this->_ftp_temp_sock===FALSE) {
204
-				$this->PushError("_data_write","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
205
-				$this->_data_close();
206
-				return false;
207
-			}
208
-		}
209
-		if(is_resource($fp)) {
210
-			while(!feof($fp)) {
211
-				$block=fread($fp, $this->_ftp_buff_size);
212
-				if(!$this->_data_write_block($mode, $block)) return false;
213
-			}
214
-		} elseif(!$this->_data_write_block($mode, $fp)) return false;
215
-		return true;
216
-	}
196
+    function _data_write($mode=FTP_ASCII, $fp=NULL) {
197
+        $NewLine=$this->_eol_code[$this->OS_local];
198
+        if(is_resource($fp)) $out=0;
199
+        else $out="";
200
+        if(!$this->_passive) {
201
+            $this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
202
+            $this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
203
+            if($this->_ftp_temp_sock===FALSE) {
204
+                $this->PushError("_data_write","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
205
+                $this->_data_close();
206
+                return false;
207
+            }
208
+        }
209
+        if(is_resource($fp)) {
210
+            while(!feof($fp)) {
211
+                $block=fread($fp, $this->_ftp_buff_size);
212
+                if(!$this->_data_write_block($mode, $block)) return false;
213
+            }
214
+        } elseif(!$this->_data_write_block($mode, $fp)) return false;
215
+        return true;
216
+    }
217 217
 
218
-	function _data_write_block($mode, $block) {
219
-		if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block);
220
-		do {
221
-			if(($t=@socket_write($this->_ftp_temp_sock, $block))===FALSE) {
222
-				$this->PushError("_data_write","socket_write", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
223
-				$this->_data_close();
224
-				return FALSE;
225
-			}
226
-			$block=substr($block, $t);
227
-		} while(!empty($block));
228
-		return true;
229
-	}
218
+    function _data_write_block($mode, $block) {
219
+        if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block);
220
+        do {
221
+            if(($t=@socket_write($this->_ftp_temp_sock, $block))===FALSE) {
222
+                $this->PushError("_data_write","socket_write", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
223
+                $this->_data_close();
224
+                return FALSE;
225
+            }
226
+            $block=substr($block, $t);
227
+        } while(!empty($block));
228
+        return true;
229
+    }
230 230
 
231
-	function _data_close() {
232
-		@socket_close($this->_ftp_temp_sock);
233
-		@socket_close($this->_ftp_data_sock);
234
-		$this->SendMSG("Disconnected data from remote host");
235
-		return TRUE;
236
-	}
231
+    function _data_close() {
232
+        @socket_close($this->_ftp_temp_sock);
233
+        @socket_close($this->_ftp_data_sock);
234
+        $this->SendMSG("Disconnected data from remote host");
235
+        return TRUE;
236
+    }
237 237
 
238
-	function _quit() {
239
-		if($this->_connected) {
240
-			@socket_close($this->_ftp_control_sock);
241
-			$this->_connected=false;
242
-			$this->SendMSG("Socket closed");
243
-		}
244
-	}
238
+    function _quit() {
239
+        if($this->_connected) {
240
+            @socket_close($this->_ftp_control_sock);
241
+            $this->_connected=false;
242
+            $this->SendMSG("Socket closed");
243
+        }
244
+    }
245 245
 }
246 246
 ?>
Please login to merge, or discard this patch.
brighty/wp-admin/includes/admin.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -8,12 +8,12 @@  discard block
 block discarded – undo
8 8
  */
9 9
 
10 10
 if ( ! defined( 'WP_ADMIN' ) ) {
11
-	/*
11
+    /*
12 12
 	 * This file is being included from a file other than wp-admin/admin.php, so
13 13
 	 * some setup was skipped. Make sure the admin message catalog is loaded since
14 14
 	 * load_default_textdomain() will not have done so in this context.
15 15
 	 */
16
-	load_textdomain( 'default', WP_LANG_DIR . '/admin-' . get_locale() . '.mo' );
16
+    load_textdomain( 'default', WP_LANG_DIR . '/admin-' . get_locale() . '.mo' );
17 17
 }
18 18
 
19 19
 /** WordPress Administration Hooks */
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
 
94 94
 /** WordPress Multisite support API */
95 95
 if ( is_multisite() ) {
96
-	require_once ABSPATH . 'wp-admin/includes/ms-admin-filters.php';
97
-	require_once ABSPATH . 'wp-admin/includes/ms.php';
98
-	require_once ABSPATH . 'wp-admin/includes/ms-deprecated.php';
96
+    require_once ABSPATH . 'wp-admin/includes/ms-admin-filters.php';
97
+    require_once ABSPATH . 'wp-admin/includes/ms.php';
98
+    require_once ABSPATH . 'wp-admin/includes/ms-deprecated.php';
99 99
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/class-wp-filesystem-ftpext.php 1 patch
Indentation   +764 added lines, -764 removed lines patch added patch discarded remove patch
@@ -15,768 +15,768 @@
 block discarded – undo
15 15
  */
16 16
 class WP_Filesystem_FTPext extends WP_Filesystem_Base {
17 17
 
18
-	/**
19
-	 * @since 2.5.0
20
-	 * @var resource
21
-	 */
22
-	public $link;
23
-
24
-	/**
25
-	 * Constructor.
26
-	 *
27
-	 * @since 2.5.0
28
-	 *
29
-	 * @param array $opt
30
-	 */
31
-	public function __construct( $opt = '' ) {
32
-		$this->method = 'ftpext';
33
-		$this->errors = new WP_Error();
34
-
35
-		// Check if possible to use ftp functions.
36
-		if ( ! extension_loaded( 'ftp' ) ) {
37
-			$this->errors->add( 'no_ftp_ext', __( 'The ftp PHP extension is not available' ) );
38
-			return;
39
-		}
40
-
41
-		// This class uses the timeout on a per-connection basis, others use it on a per-action basis.
42
-		if ( ! defined( 'FS_TIMEOUT' ) ) {
43
-			define( 'FS_TIMEOUT', 240 );
44
-		}
45
-
46
-		if ( empty( $opt['port'] ) ) {
47
-			$this->options['port'] = 21;
48
-		} else {
49
-			$this->options['port'] = $opt['port'];
50
-		}
51
-
52
-		if ( empty( $opt['hostname'] ) ) {
53
-			$this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
54
-		} else {
55
-			$this->options['hostname'] = $opt['hostname'];
56
-		}
57
-
58
-		// Check if the options provided are OK.
59
-		if ( empty( $opt['username'] ) ) {
60
-			$this->errors->add( 'empty_username', __( 'FTP username is required' ) );
61
-		} else {
62
-			$this->options['username'] = $opt['username'];
63
-		}
64
-
65
-		if ( empty( $opt['password'] ) ) {
66
-			$this->errors->add( 'empty_password', __( 'FTP password is required' ) );
67
-		} else {
68
-			$this->options['password'] = $opt['password'];
69
-		}
70
-
71
-		$this->options['ssl'] = false;
72
-
73
-		if ( isset( $opt['connection_type'] ) && 'ftps' === $opt['connection_type'] ) {
74
-			$this->options['ssl'] = true;
75
-		}
76
-	}
77
-
78
-	/**
79
-	 * Connects filesystem.
80
-	 *
81
-	 * @since 2.5.0
82
-	 *
83
-	 * @return bool True on success, false on failure.
84
-	 */
85
-	public function connect() {
86
-		if ( isset( $this->options['ssl'] ) && $this->options['ssl'] && function_exists( 'ftp_ssl_connect' ) ) {
87
-			$this->link = @ftp_ssl_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
88
-		} else {
89
-			$this->link = @ftp_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
90
-		}
91
-
92
-		if ( ! $this->link ) {
93
-			$this->errors->add(
94
-				'connect',
95
-				sprintf(
96
-					/* translators: %s: hostname:port */
97
-					__( 'Failed to connect to FTP Server %s' ),
98
-					$this->options['hostname'] . ':' . $this->options['port']
99
-				)
100
-			);
101
-
102
-			return false;
103
-		}
104
-
105
-		if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) {
106
-			$this->errors->add(
107
-				'auth',
108
-				sprintf(
109
-					/* translators: %s: Username. */
110
-					__( 'Username/Password incorrect for %s' ),
111
-					$this->options['username']
112
-				)
113
-			);
114
-
115
-			return false;
116
-		}
117
-
118
-		// Set the connection to use Passive FTP.
119
-		ftp_pasv( $this->link, true );
120
-
121
-		if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) {
122
-			@ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT );
123
-		}
124
-
125
-		return true;
126
-	}
127
-
128
-	/**
129
-	 * Reads entire file into a string.
130
-	 *
131
-	 * @since 2.5.0
132
-	 *
133
-	 * @param string $file Name of the file to read.
134
-	 * @return string|false Read data on success, false if no temporary file could be opened,
135
-	 *                      or if the file couldn't be retrieved.
136
-	 */
137
-	public function get_contents( $file ) {
138
-		$tempfile   = wp_tempnam( $file );
139
-		$temphandle = fopen( $tempfile, 'w+' );
140
-
141
-		if ( ! $temphandle ) {
142
-			unlink( $tempfile );
143
-			return false;
144
-		}
145
-
146
-		if ( ! ftp_fget( $this->link, $temphandle, $file, FTP_BINARY ) ) {
147
-			fclose( $temphandle );
148
-			unlink( $tempfile );
149
-			return false;
150
-		}
151
-
152
-		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
153
-		$contents = '';
154
-
155
-		while ( ! feof( $temphandle ) ) {
156
-			$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
157
-		}
158
-
159
-		fclose( $temphandle );
160
-		unlink( $tempfile );
161
-
162
-		return $contents;
163
-	}
164
-
165
-	/**
166
-	 * Reads entire file into an array.
167
-	 *
168
-	 * @since 2.5.0
169
-	 *
170
-	 * @param string $file Path to the file.
171
-	 * @return array|false File contents in an array on success, false on failure.
172
-	 */
173
-	public function get_contents_array( $file ) {
174
-		return explode( "\n", $this->get_contents( $file ) );
175
-	}
176
-
177
-	/**
178
-	 * Writes a string to a file.
179
-	 *
180
-	 * @since 2.5.0
181
-	 *
182
-	 * @param string    $file     Remote path to the file where to write the data.
183
-	 * @param string    $contents The data to write.
184
-	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
185
-	 *                            Default false.
186
-	 * @return bool True on success, false on failure.
187
-	 */
188
-	public function put_contents( $file, $contents, $mode = false ) {
189
-		$tempfile   = wp_tempnam( $file );
190
-		$temphandle = fopen( $tempfile, 'wb+' );
191
-
192
-		if ( ! $temphandle ) {
193
-			unlink( $tempfile );
194
-			return false;
195
-		}
196
-
197
-		mbstring_binary_safe_encoding();
198
-
199
-		$data_length   = strlen( $contents );
200
-		$bytes_written = fwrite( $temphandle, $contents );
201
-
202
-		reset_mbstring_encoding();
203
-
204
-		if ( $data_length !== $bytes_written ) {
205
-			fclose( $temphandle );
206
-			unlink( $tempfile );
207
-			return false;
208
-		}
209
-
210
-		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
211
-
212
-		$ret = ftp_fput( $this->link, $file, $temphandle, FTP_BINARY );
213
-
214
-		fclose( $temphandle );
215
-		unlink( $tempfile );
216
-
217
-		$this->chmod( $file, $mode );
218
-
219
-		return $ret;
220
-	}
221
-
222
-	/**
223
-	 * Gets the current working directory.
224
-	 *
225
-	 * @since 2.5.0
226
-	 *
227
-	 * @return string|false The current working directory on success, false on failure.
228
-	 */
229
-	public function cwd() {
230
-		$cwd = ftp_pwd( $this->link );
231
-
232
-		if ( $cwd ) {
233
-			$cwd = trailingslashit( $cwd );
234
-		}
235
-
236
-		return $cwd;
237
-	}
238
-
239
-	/**
240
-	 * Changes current directory.
241
-	 *
242
-	 * @since 2.5.0
243
-	 *
244
-	 * @param string $dir The new current directory.
245
-	 * @return bool True on success, false on failure.
246
-	 */
247
-	public function chdir( $dir ) {
248
-		return @ftp_chdir( $this->link, $dir );
249
-	}
250
-
251
-	/**
252
-	 * Changes filesystem permissions.
253
-	 *
254
-	 * @since 2.5.0
255
-	 *
256
-	 * @param string    $file      Path to the file.
257
-	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
258
-	 *                             0755 for directories. Default false.
259
-	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
260
-	 *                             Default false.
261
-	 * @return bool True on success, false on failure.
262
-	 */
263
-	public function chmod( $file, $mode = false, $recursive = false ) {
264
-		if ( ! $mode ) {
265
-			if ( $this->is_file( $file ) ) {
266
-				$mode = FS_CHMOD_FILE;
267
-			} elseif ( $this->is_dir( $file ) ) {
268
-				$mode = FS_CHMOD_DIR;
269
-			} else {
270
-				return false;
271
-			}
272
-		}
273
-
274
-		// chmod any sub-objects if recursive.
275
-		if ( $recursive && $this->is_dir( $file ) ) {
276
-			$filelist = $this->dirlist( $file );
277
-
278
-			foreach ( (array) $filelist as $filename => $filemeta ) {
279
-				$this->chmod( $file . '/' . $filename, $mode, $recursive );
280
-			}
281
-		}
282
-
283
-		// chmod the file or directory.
284
-		if ( ! function_exists( 'ftp_chmod' ) ) {
285
-			return (bool) ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) );
286
-		}
287
-
288
-		return (bool) ftp_chmod( $this->link, $mode, $file );
289
-	}
290
-
291
-	/**
292
-	 * Gets the file owner.
293
-	 *
294
-	 * @since 2.5.0
295
-	 *
296
-	 * @param string $file Path to the file.
297
-	 * @return string|false Username of the owner on success, false on failure.
298
-	 */
299
-	public function owner( $file ) {
300
-		$dir = $this->dirlist( $file );
301
-
302
-		return $dir[ $file ]['owner'];
303
-	}
304
-
305
-	/**
306
-	 * Gets the permissions of the specified file or filepath in their octal format.
307
-	 *
308
-	 * @since 2.5.0
309
-	 *
310
-	 * @param string $file Path to the file.
311
-	 * @return string Mode of the file (the last 3 digits).
312
-	 */
313
-	public function getchmod( $file ) {
314
-		$dir = $this->dirlist( $file );
315
-
316
-		return $dir[ $file ]['permsn'];
317
-	}
318
-
319
-	/**
320
-	 * Gets the file's group.
321
-	 *
322
-	 * @since 2.5.0
323
-	 *
324
-	 * @param string $file Path to the file.
325
-	 * @return string|false The group on success, false on failure.
326
-	 */
327
-	public function group( $file ) {
328
-		$dir = $this->dirlist( $file );
329
-
330
-		return $dir[ $file ]['group'];
331
-	}
332
-
333
-	/**
334
-	 * Copies a file.
335
-	 *
336
-	 * @since 2.5.0
337
-	 *
338
-	 * @param string    $source      Path to the source file.
339
-	 * @param string    $destination Path to the destination file.
340
-	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
341
-	 *                               Default false.
342
-	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
343
-	 *                               0755 for dirs. Default false.
344
-	 * @return bool True on success, false on failure.
345
-	 */
346
-	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
347
-		if ( ! $overwrite && $this->exists( $destination ) ) {
348
-			return false;
349
-		}
350
-
351
-		$content = $this->get_contents( $source );
352
-
353
-		if ( false === $content ) {
354
-			return false;
355
-		}
356
-
357
-		return $this->put_contents( $destination, $content, $mode );
358
-	}
359
-
360
-	/**
361
-	 * Moves a file.
362
-	 *
363
-	 * @since 2.5.0
364
-	 *
365
-	 * @param string $source      Path to the source file.
366
-	 * @param string $destination Path to the destination file.
367
-	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
368
-	 *                            Default false.
369
-	 * @return bool True on success, false on failure.
370
-	 */
371
-	public function move( $source, $destination, $overwrite = false ) {
372
-		return ftp_rename( $this->link, $source, $destination );
373
-	}
374
-
375
-	/**
376
-	 * Deletes a file or directory.
377
-	 *
378
-	 * @since 2.5.0
379
-	 *
380
-	 * @param string       $file      Path to the file or directory.
381
-	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
382
-	 *                                Default false.
383
-	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
384
-	 *                                Default false.
385
-	 * @return bool True on success, false on failure.
386
-	 */
387
-	public function delete( $file, $recursive = false, $type = false ) {
388
-		if ( empty( $file ) ) {
389
-			return false;
390
-		}
391
-
392
-		if ( 'f' === $type || $this->is_file( $file ) ) {
393
-			return ftp_delete( $this->link, $file );
394
-		}
395
-
396
-		if ( ! $recursive ) {
397
-			return ftp_rmdir( $this->link, $file );
398
-		}
399
-
400
-		$filelist = $this->dirlist( trailingslashit( $file ) );
401
-
402
-		if ( ! empty( $filelist ) ) {
403
-			foreach ( $filelist as $delete_file ) {
404
-				$this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] );
405
-			}
406
-		}
407
-
408
-		return ftp_rmdir( $this->link, $file );
409
-	}
410
-
411
-	/**
412
-	 * Checks if a file or directory exists.
413
-	 *
414
-	 * @since 2.5.0
415
-	 *
416
-	 * @param string $file Path to file or directory.
417
-	 * @return bool Whether $file exists or not.
418
-	 */
419
-	public function exists( $file ) {
420
-		$list = ftp_nlist( $this->link, $file );
421
-
422
-		if ( empty( $list ) && $this->is_dir( $file ) ) {
423
-			return true; // File is an empty directory.
424
-		}
425
-
426
-		return ! empty( $list ); // Empty list = no file, so invert.
427
-	}
428
-
429
-	/**
430
-	 * Checks if resource is a file.
431
-	 *
432
-	 * @since 2.5.0
433
-	 *
434
-	 * @param string $file File path.
435
-	 * @return bool Whether $file is a file.
436
-	 */
437
-	public function is_file( $file ) {
438
-		return $this->exists( $file ) && ! $this->is_dir( $file );
439
-	}
440
-
441
-	/**
442
-	 * Checks if resource is a directory.
443
-	 *
444
-	 * @since 2.5.0
445
-	 *
446
-	 * @param string $path Directory path.
447
-	 * @return bool Whether $path is a directory.
448
-	 */
449
-	public function is_dir( $path ) {
450
-		$cwd    = $this->cwd();
451
-		$result = @ftp_chdir( $this->link, trailingslashit( $path ) );
452
-
453
-		if ( $result && $path === $this->cwd() || $this->cwd() !== $cwd ) {
454
-			@ftp_chdir( $this->link, $cwd );
455
-			return true;
456
-		}
457
-
458
-		return false;
459
-	}
460
-
461
-	/**
462
-	 * Checks if a file is readable.
463
-	 *
464
-	 * @since 2.5.0
465
-	 *
466
-	 * @param string $file Path to file.
467
-	 * @return bool Whether $file is readable.
468
-	 */
469
-	public function is_readable( $file ) {
470
-		return true;
471
-	}
472
-
473
-	/**
474
-	 * Checks if a file or directory is writable.
475
-	 *
476
-	 * @since 2.5.0
477
-	 *
478
-	 * @param string $file Path to file or directory.
479
-	 * @return bool Whether $file is writable.
480
-	 */
481
-	public function is_writable( $file ) {
482
-		return true;
483
-	}
484
-
485
-	/**
486
-	 * Gets the file's last access time.
487
-	 *
488
-	 * @since 2.5.0
489
-	 *
490
-	 * @param string $file Path to file.
491
-	 * @return int|false Unix timestamp representing last access time, false on failure.
492
-	 */
493
-	public function atime( $file ) {
494
-		return false;
495
-	}
496
-
497
-	/**
498
-	 * Gets the file modification time.
499
-	 *
500
-	 * @since 2.5.0
501
-	 *
502
-	 * @param string $file Path to file.
503
-	 * @return int|false Unix timestamp representing modification time, false on failure.
504
-	 */
505
-	public function mtime( $file ) {
506
-		return ftp_mdtm( $this->link, $file );
507
-	}
508
-
509
-	/**
510
-	 * Gets the file size (in bytes).
511
-	 *
512
-	 * @since 2.5.0
513
-	 *
514
-	 * @param string $file Path to file.
515
-	 * @return int|false Size of the file in bytes on success, false on failure.
516
-	 */
517
-	public function size( $file ) {
518
-		return ftp_size( $this->link, $file );
519
-	}
520
-
521
-	/**
522
-	 * Sets the access and modification times of a file.
523
-	 *
524
-	 * Note: If $file doesn't exist, it will be created.
525
-	 *
526
-	 * @since 2.5.0
527
-	 *
528
-	 * @param string $file  Path to file.
529
-	 * @param int    $time  Optional. Modified time to set for file.
530
-	 *                      Default 0.
531
-	 * @param int    $atime Optional. Access time to set for file.
532
-	 *                      Default 0.
533
-	 * @return bool True on success, false on failure.
534
-	 */
535
-	public function touch( $file, $time = 0, $atime = 0 ) {
536
-		return false;
537
-	}
538
-
539
-	/**
540
-	 * Creates a directory.
541
-	 *
542
-	 * @since 2.5.0
543
-	 *
544
-	 * @param string           $path  Path for new directory.
545
-	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
546
-	 *                                Default false.
547
-	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
548
-	 *                                Default false.
549
-	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
550
-	 *                                Default false.
551
-	 * @return bool True on success, false on failure.
552
-	 */
553
-	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
554
-		$path = untrailingslashit( $path );
555
-
556
-		if ( empty( $path ) ) {
557
-			return false;
558
-		}
559
-
560
-		if ( ! ftp_mkdir( $this->link, $path ) ) {
561
-			return false;
562
-		}
563
-
564
-		$this->chmod( $path, $chmod );
565
-
566
-		return true;
567
-	}
568
-
569
-	/**
570
-	 * Deletes a directory.
571
-	 *
572
-	 * @since 2.5.0
573
-	 *
574
-	 * @param string $path      Path to directory.
575
-	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
576
-	 *                          Default false.
577
-	 * @return bool True on success, false on failure.
578
-	 */
579
-	public function rmdir( $path, $recursive = false ) {
580
-		return $this->delete( $path, $recursive );
581
-	}
582
-
583
-	/**
584
-	 * @param string $line
585
-	 * @return array
586
-	 */
587
-	public function parselisting( $line ) {
588
-		static $is_windows = null;
589
-
590
-		if ( is_null( $is_windows ) ) {
591
-			$is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false;
592
-		}
593
-
594
-		if ( $is_windows && preg_match( '/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer ) ) {
595
-			$b = array();
596
-
597
-			if ( $lucifer[3] < 70 ) {
598
-				$lucifer[3] += 2000;
599
-			} else {
600
-				$lucifer[3] += 1900; // 4-digit year fix.
601
-			}
602
-
603
-			$b['isdir'] = ( '<DIR>' === $lucifer[7] );
604
-
605
-			if ( $b['isdir'] ) {
606
-				$b['type'] = 'd';
607
-			} else {
608
-				$b['type'] = 'f';
609
-			}
610
-
611
-			$b['size']   = $lucifer[7];
612
-			$b['month']  = $lucifer[1];
613
-			$b['day']    = $lucifer[2];
614
-			$b['year']   = $lucifer[3];
615
-			$b['hour']   = $lucifer[4];
616
-			$b['minute'] = $lucifer[5];
617
-			$b['time']   = mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) === 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] );
618
-			$b['am/pm']  = $lucifer[6];
619
-			$b['name']   = $lucifer[8];
620
-		} elseif ( ! $is_windows ) {
621
-			$lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY );
622
-
623
-			if ( $lucifer ) {
624
-				// echo $line."\n";
625
-				$lcount = count( $lucifer );
626
-
627
-				if ( $lcount < 8 ) {
628
-					return '';
629
-				}
630
-
631
-				$b           = array();
632
-				$b['isdir']  = 'd' === $lucifer[0][0];
633
-				$b['islink'] = 'l' === $lucifer[0][0];
634
-
635
-				if ( $b['isdir'] ) {
636
-					$b['type'] = 'd';
637
-				} elseif ( $b['islink'] ) {
638
-					$b['type'] = 'l';
639
-				} else {
640
-					$b['type'] = 'f';
641
-				}
642
-
643
-				$b['perms']  = $lucifer[0];
644
-				$b['permsn'] = $this->getnumchmodfromh( $b['perms'] );
645
-				$b['number'] = $lucifer[1];
646
-				$b['owner']  = $lucifer[2];
647
-				$b['group']  = $lucifer[3];
648
-				$b['size']   = $lucifer[4];
649
-
650
-				if ( 8 === $lcount ) {
651
-					sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] );
652
-					sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] );
653
-
654
-					$b['time'] = mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] );
655
-					$b['name'] = $lucifer[7];
656
-				} else {
657
-					$b['month'] = $lucifer[5];
658
-					$b['day']   = $lucifer[6];
659
-
660
-					if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) {
661
-						$b['year']   = gmdate( 'Y' );
662
-						$b['hour']   = $l2[1];
663
-						$b['minute'] = $l2[2];
664
-					} else {
665
-						$b['year']   = $lucifer[7];
666
-						$b['hour']   = 0;
667
-						$b['minute'] = 0;
668
-					}
669
-
670
-					$b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) );
671
-					$b['name'] = $lucifer[8];
672
-				}
673
-			}
674
-		}
675
-
676
-		// Replace symlinks formatted as "source -> target" with just the source name.
677
-		if ( isset( $b['islink'] ) && $b['islink'] ) {
678
-			$b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] );
679
-		}
680
-
681
-		return $b;
682
-	}
683
-
684
-	/**
685
-	 * Gets details for files in a directory or a specific file.
686
-	 *
687
-	 * @since 2.5.0
688
-	 *
689
-	 * @param string $path           Path to directory or file.
690
-	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
691
-	 *                               Default true.
692
-	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
693
-	 *                               Default false.
694
-	 * @return array|false {
695
-	 *     Array of files. False if unable to list directory contents.
696
-	 *
697
-	 *     @type string $name        Name of the file or directory.
698
-	 *     @type string $perms       *nix representation of permissions.
699
-	 *     @type string $permsn      Octal representation of permissions.
700
-	 *     @type string $owner       Owner name or ID.
701
-	 *     @type int    $size        Size of file in bytes.
702
-	 *     @type int    $lastmodunix Last modified unix timestamp.
703
-	 *     @type mixed  $lastmod     Last modified month (3 letter) and day (without leading 0).
704
-	 *     @type int    $time        Last modified time.
705
-	 *     @type string $type        Type of resource. 'f' for file, 'd' for directory.
706
-	 *     @type mixed  $files       If a directory and `$recursive` is true, contains another array of files.
707
-	 * }
708
-	 */
709
-	public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
710
-		if ( $this->is_file( $path ) ) {
711
-			$limit_file = basename( $path );
712
-			$path       = dirname( $path ) . '/';
713
-		} else {
714
-			$limit_file = false;
715
-		}
716
-
717
-		$pwd = ftp_pwd( $this->link );
718
-
719
-		if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist.
720
-			return false;
721
-		}
722
-
723
-		$list = ftp_rawlist( $this->link, '-a', false );
724
-
725
-		@ftp_chdir( $this->link, $pwd );
726
-
727
-		if ( empty( $list ) ) { // Empty array = non-existent folder (real folder will show . at least).
728
-			return false;
729
-		}
730
-
731
-		$dirlist = array();
732
-
733
-		foreach ( $list as $k => $v ) {
734
-			$entry = $this->parselisting( $v );
735
-
736
-			if ( empty( $entry ) ) {
737
-				continue;
738
-			}
739
-
740
-			if ( '.' === $entry['name'] || '..' === $entry['name'] ) {
741
-				continue;
742
-			}
743
-
744
-			if ( ! $include_hidden && '.' === $entry['name'][0] ) {
745
-				continue;
746
-			}
747
-
748
-			if ( $limit_file && $entry['name'] !== $limit_file ) {
749
-				continue;
750
-			}
751
-
752
-			$dirlist[ $entry['name'] ] = $entry;
753
-		}
754
-
755
-		$ret = array();
756
-
757
-		foreach ( (array) $dirlist as $struc ) {
758
-			if ( 'd' === $struc['type'] ) {
759
-				if ( $recursive ) {
760
-					$struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
761
-				} else {
762
-					$struc['files'] = array();
763
-				}
764
-			}
765
-
766
-			$ret[ $struc['name'] ] = $struc;
767
-		}
768
-
769
-		return $ret;
770
-	}
771
-
772
-	/**
773
-	 * Destructor.
774
-	 *
775
-	 * @since 2.5.0
776
-	 */
777
-	public function __destruct() {
778
-		if ( $this->link ) {
779
-			ftp_close( $this->link );
780
-		}
781
-	}
18
+    /**
19
+     * @since 2.5.0
20
+     * @var resource
21
+     */
22
+    public $link;
23
+
24
+    /**
25
+     * Constructor.
26
+     *
27
+     * @since 2.5.0
28
+     *
29
+     * @param array $opt
30
+     */
31
+    public function __construct( $opt = '' ) {
32
+        $this->method = 'ftpext';
33
+        $this->errors = new WP_Error();
34
+
35
+        // Check if possible to use ftp functions.
36
+        if ( ! extension_loaded( 'ftp' ) ) {
37
+            $this->errors->add( 'no_ftp_ext', __( 'The ftp PHP extension is not available' ) );
38
+            return;
39
+        }
40
+
41
+        // This class uses the timeout on a per-connection basis, others use it on a per-action basis.
42
+        if ( ! defined( 'FS_TIMEOUT' ) ) {
43
+            define( 'FS_TIMEOUT', 240 );
44
+        }
45
+
46
+        if ( empty( $opt['port'] ) ) {
47
+            $this->options['port'] = 21;
48
+        } else {
49
+            $this->options['port'] = $opt['port'];
50
+        }
51
+
52
+        if ( empty( $opt['hostname'] ) ) {
53
+            $this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
54
+        } else {
55
+            $this->options['hostname'] = $opt['hostname'];
56
+        }
57
+
58
+        // Check if the options provided are OK.
59
+        if ( empty( $opt['username'] ) ) {
60
+            $this->errors->add( 'empty_username', __( 'FTP username is required' ) );
61
+        } else {
62
+            $this->options['username'] = $opt['username'];
63
+        }
64
+
65
+        if ( empty( $opt['password'] ) ) {
66
+            $this->errors->add( 'empty_password', __( 'FTP password is required' ) );
67
+        } else {
68
+            $this->options['password'] = $opt['password'];
69
+        }
70
+
71
+        $this->options['ssl'] = false;
72
+
73
+        if ( isset( $opt['connection_type'] ) && 'ftps' === $opt['connection_type'] ) {
74
+            $this->options['ssl'] = true;
75
+        }
76
+    }
77
+
78
+    /**
79
+     * Connects filesystem.
80
+     *
81
+     * @since 2.5.0
82
+     *
83
+     * @return bool True on success, false on failure.
84
+     */
85
+    public function connect() {
86
+        if ( isset( $this->options['ssl'] ) && $this->options['ssl'] && function_exists( 'ftp_ssl_connect' ) ) {
87
+            $this->link = @ftp_ssl_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
88
+        } else {
89
+            $this->link = @ftp_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
90
+        }
91
+
92
+        if ( ! $this->link ) {
93
+            $this->errors->add(
94
+                'connect',
95
+                sprintf(
96
+                    /* translators: %s: hostname:port */
97
+                    __( 'Failed to connect to FTP Server %s' ),
98
+                    $this->options['hostname'] . ':' . $this->options['port']
99
+                )
100
+            );
101
+
102
+            return false;
103
+        }
104
+
105
+        if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) {
106
+            $this->errors->add(
107
+                'auth',
108
+                sprintf(
109
+                    /* translators: %s: Username. */
110
+                    __( 'Username/Password incorrect for %s' ),
111
+                    $this->options['username']
112
+                )
113
+            );
114
+
115
+            return false;
116
+        }
117
+
118
+        // Set the connection to use Passive FTP.
119
+        ftp_pasv( $this->link, true );
120
+
121
+        if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) {
122
+            @ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT );
123
+        }
124
+
125
+        return true;
126
+    }
127
+
128
+    /**
129
+     * Reads entire file into a string.
130
+     *
131
+     * @since 2.5.0
132
+     *
133
+     * @param string $file Name of the file to read.
134
+     * @return string|false Read data on success, false if no temporary file could be opened,
135
+     *                      or if the file couldn't be retrieved.
136
+     */
137
+    public function get_contents( $file ) {
138
+        $tempfile   = wp_tempnam( $file );
139
+        $temphandle = fopen( $tempfile, 'w+' );
140
+
141
+        if ( ! $temphandle ) {
142
+            unlink( $tempfile );
143
+            return false;
144
+        }
145
+
146
+        if ( ! ftp_fget( $this->link, $temphandle, $file, FTP_BINARY ) ) {
147
+            fclose( $temphandle );
148
+            unlink( $tempfile );
149
+            return false;
150
+        }
151
+
152
+        fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
153
+        $contents = '';
154
+
155
+        while ( ! feof( $temphandle ) ) {
156
+            $contents .= fread( $temphandle, 8 * KB_IN_BYTES );
157
+        }
158
+
159
+        fclose( $temphandle );
160
+        unlink( $tempfile );
161
+
162
+        return $contents;
163
+    }
164
+
165
+    /**
166
+     * Reads entire file into an array.
167
+     *
168
+     * @since 2.5.0
169
+     *
170
+     * @param string $file Path to the file.
171
+     * @return array|false File contents in an array on success, false on failure.
172
+     */
173
+    public function get_contents_array( $file ) {
174
+        return explode( "\n", $this->get_contents( $file ) );
175
+    }
176
+
177
+    /**
178
+     * Writes a string to a file.
179
+     *
180
+     * @since 2.5.0
181
+     *
182
+     * @param string    $file     Remote path to the file where to write the data.
183
+     * @param string    $contents The data to write.
184
+     * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
185
+     *                            Default false.
186
+     * @return bool True on success, false on failure.
187
+     */
188
+    public function put_contents( $file, $contents, $mode = false ) {
189
+        $tempfile   = wp_tempnam( $file );
190
+        $temphandle = fopen( $tempfile, 'wb+' );
191
+
192
+        if ( ! $temphandle ) {
193
+            unlink( $tempfile );
194
+            return false;
195
+        }
196
+
197
+        mbstring_binary_safe_encoding();
198
+
199
+        $data_length   = strlen( $contents );
200
+        $bytes_written = fwrite( $temphandle, $contents );
201
+
202
+        reset_mbstring_encoding();
203
+
204
+        if ( $data_length !== $bytes_written ) {
205
+            fclose( $temphandle );
206
+            unlink( $tempfile );
207
+            return false;
208
+        }
209
+
210
+        fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
211
+
212
+        $ret = ftp_fput( $this->link, $file, $temphandle, FTP_BINARY );
213
+
214
+        fclose( $temphandle );
215
+        unlink( $tempfile );
216
+
217
+        $this->chmod( $file, $mode );
218
+
219
+        return $ret;
220
+    }
221
+
222
+    /**
223
+     * Gets the current working directory.
224
+     *
225
+     * @since 2.5.0
226
+     *
227
+     * @return string|false The current working directory on success, false on failure.
228
+     */
229
+    public function cwd() {
230
+        $cwd = ftp_pwd( $this->link );
231
+
232
+        if ( $cwd ) {
233
+            $cwd = trailingslashit( $cwd );
234
+        }
235
+
236
+        return $cwd;
237
+    }
238
+
239
+    /**
240
+     * Changes current directory.
241
+     *
242
+     * @since 2.5.0
243
+     *
244
+     * @param string $dir The new current directory.
245
+     * @return bool True on success, false on failure.
246
+     */
247
+    public function chdir( $dir ) {
248
+        return @ftp_chdir( $this->link, $dir );
249
+    }
250
+
251
+    /**
252
+     * Changes filesystem permissions.
253
+     *
254
+     * @since 2.5.0
255
+     *
256
+     * @param string    $file      Path to the file.
257
+     * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
258
+     *                             0755 for directories. Default false.
259
+     * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
260
+     *                             Default false.
261
+     * @return bool True on success, false on failure.
262
+     */
263
+    public function chmod( $file, $mode = false, $recursive = false ) {
264
+        if ( ! $mode ) {
265
+            if ( $this->is_file( $file ) ) {
266
+                $mode = FS_CHMOD_FILE;
267
+            } elseif ( $this->is_dir( $file ) ) {
268
+                $mode = FS_CHMOD_DIR;
269
+            } else {
270
+                return false;
271
+            }
272
+        }
273
+
274
+        // chmod any sub-objects if recursive.
275
+        if ( $recursive && $this->is_dir( $file ) ) {
276
+            $filelist = $this->dirlist( $file );
277
+
278
+            foreach ( (array) $filelist as $filename => $filemeta ) {
279
+                $this->chmod( $file . '/' . $filename, $mode, $recursive );
280
+            }
281
+        }
282
+
283
+        // chmod the file or directory.
284
+        if ( ! function_exists( 'ftp_chmod' ) ) {
285
+            return (bool) ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) );
286
+        }
287
+
288
+        return (bool) ftp_chmod( $this->link, $mode, $file );
289
+    }
290
+
291
+    /**
292
+     * Gets the file owner.
293
+     *
294
+     * @since 2.5.0
295
+     *
296
+     * @param string $file Path to the file.
297
+     * @return string|false Username of the owner on success, false on failure.
298
+     */
299
+    public function owner( $file ) {
300
+        $dir = $this->dirlist( $file );
301
+
302
+        return $dir[ $file ]['owner'];
303
+    }
304
+
305
+    /**
306
+     * Gets the permissions of the specified file or filepath in their octal format.
307
+     *
308
+     * @since 2.5.0
309
+     *
310
+     * @param string $file Path to the file.
311
+     * @return string Mode of the file (the last 3 digits).
312
+     */
313
+    public function getchmod( $file ) {
314
+        $dir = $this->dirlist( $file );
315
+
316
+        return $dir[ $file ]['permsn'];
317
+    }
318
+
319
+    /**
320
+     * Gets the file's group.
321
+     *
322
+     * @since 2.5.0
323
+     *
324
+     * @param string $file Path to the file.
325
+     * @return string|false The group on success, false on failure.
326
+     */
327
+    public function group( $file ) {
328
+        $dir = $this->dirlist( $file );
329
+
330
+        return $dir[ $file ]['group'];
331
+    }
332
+
333
+    /**
334
+     * Copies a file.
335
+     *
336
+     * @since 2.5.0
337
+     *
338
+     * @param string    $source      Path to the source file.
339
+     * @param string    $destination Path to the destination file.
340
+     * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
341
+     *                               Default false.
342
+     * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
343
+     *                               0755 for dirs. Default false.
344
+     * @return bool True on success, false on failure.
345
+     */
346
+    public function copy( $source, $destination, $overwrite = false, $mode = false ) {
347
+        if ( ! $overwrite && $this->exists( $destination ) ) {
348
+            return false;
349
+        }
350
+
351
+        $content = $this->get_contents( $source );
352
+
353
+        if ( false === $content ) {
354
+            return false;
355
+        }
356
+
357
+        return $this->put_contents( $destination, $content, $mode );
358
+    }
359
+
360
+    /**
361
+     * Moves a file.
362
+     *
363
+     * @since 2.5.0
364
+     *
365
+     * @param string $source      Path to the source file.
366
+     * @param string $destination Path to the destination file.
367
+     * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
368
+     *                            Default false.
369
+     * @return bool True on success, false on failure.
370
+     */
371
+    public function move( $source, $destination, $overwrite = false ) {
372
+        return ftp_rename( $this->link, $source, $destination );
373
+    }
374
+
375
+    /**
376
+     * Deletes a file or directory.
377
+     *
378
+     * @since 2.5.0
379
+     *
380
+     * @param string       $file      Path to the file or directory.
381
+     * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
382
+     *                                Default false.
383
+     * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
384
+     *                                Default false.
385
+     * @return bool True on success, false on failure.
386
+     */
387
+    public function delete( $file, $recursive = false, $type = false ) {
388
+        if ( empty( $file ) ) {
389
+            return false;
390
+        }
391
+
392
+        if ( 'f' === $type || $this->is_file( $file ) ) {
393
+            return ftp_delete( $this->link, $file );
394
+        }
395
+
396
+        if ( ! $recursive ) {
397
+            return ftp_rmdir( $this->link, $file );
398
+        }
399
+
400
+        $filelist = $this->dirlist( trailingslashit( $file ) );
401
+
402
+        if ( ! empty( $filelist ) ) {
403
+            foreach ( $filelist as $delete_file ) {
404
+                $this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] );
405
+            }
406
+        }
407
+
408
+        return ftp_rmdir( $this->link, $file );
409
+    }
410
+
411
+    /**
412
+     * Checks if a file or directory exists.
413
+     *
414
+     * @since 2.5.0
415
+     *
416
+     * @param string $file Path to file or directory.
417
+     * @return bool Whether $file exists or not.
418
+     */
419
+    public function exists( $file ) {
420
+        $list = ftp_nlist( $this->link, $file );
421
+
422
+        if ( empty( $list ) && $this->is_dir( $file ) ) {
423
+            return true; // File is an empty directory.
424
+        }
425
+
426
+        return ! empty( $list ); // Empty list = no file, so invert.
427
+    }
428
+
429
+    /**
430
+     * Checks if resource is a file.
431
+     *
432
+     * @since 2.5.0
433
+     *
434
+     * @param string $file File path.
435
+     * @return bool Whether $file is a file.
436
+     */
437
+    public function is_file( $file ) {
438
+        return $this->exists( $file ) && ! $this->is_dir( $file );
439
+    }
440
+
441
+    /**
442
+     * Checks if resource is a directory.
443
+     *
444
+     * @since 2.5.0
445
+     *
446
+     * @param string $path Directory path.
447
+     * @return bool Whether $path is a directory.
448
+     */
449
+    public function is_dir( $path ) {
450
+        $cwd    = $this->cwd();
451
+        $result = @ftp_chdir( $this->link, trailingslashit( $path ) );
452
+
453
+        if ( $result && $path === $this->cwd() || $this->cwd() !== $cwd ) {
454
+            @ftp_chdir( $this->link, $cwd );
455
+            return true;
456
+        }
457
+
458
+        return false;
459
+    }
460
+
461
+    /**
462
+     * Checks if a file is readable.
463
+     *
464
+     * @since 2.5.0
465
+     *
466
+     * @param string $file Path to file.
467
+     * @return bool Whether $file is readable.
468
+     */
469
+    public function is_readable( $file ) {
470
+        return true;
471
+    }
472
+
473
+    /**
474
+     * Checks if a file or directory is writable.
475
+     *
476
+     * @since 2.5.0
477
+     *
478
+     * @param string $file Path to file or directory.
479
+     * @return bool Whether $file is writable.
480
+     */
481
+    public function is_writable( $file ) {
482
+        return true;
483
+    }
484
+
485
+    /**
486
+     * Gets the file's last access time.
487
+     *
488
+     * @since 2.5.0
489
+     *
490
+     * @param string $file Path to file.
491
+     * @return int|false Unix timestamp representing last access time, false on failure.
492
+     */
493
+    public function atime( $file ) {
494
+        return false;
495
+    }
496
+
497
+    /**
498
+     * Gets the file modification time.
499
+     *
500
+     * @since 2.5.0
501
+     *
502
+     * @param string $file Path to file.
503
+     * @return int|false Unix timestamp representing modification time, false on failure.
504
+     */
505
+    public function mtime( $file ) {
506
+        return ftp_mdtm( $this->link, $file );
507
+    }
508
+
509
+    /**
510
+     * Gets the file size (in bytes).
511
+     *
512
+     * @since 2.5.0
513
+     *
514
+     * @param string $file Path to file.
515
+     * @return int|false Size of the file in bytes on success, false on failure.
516
+     */
517
+    public function size( $file ) {
518
+        return ftp_size( $this->link, $file );
519
+    }
520
+
521
+    /**
522
+     * Sets the access and modification times of a file.
523
+     *
524
+     * Note: If $file doesn't exist, it will be created.
525
+     *
526
+     * @since 2.5.0
527
+     *
528
+     * @param string $file  Path to file.
529
+     * @param int    $time  Optional. Modified time to set for file.
530
+     *                      Default 0.
531
+     * @param int    $atime Optional. Access time to set for file.
532
+     *                      Default 0.
533
+     * @return bool True on success, false on failure.
534
+     */
535
+    public function touch( $file, $time = 0, $atime = 0 ) {
536
+        return false;
537
+    }
538
+
539
+    /**
540
+     * Creates a directory.
541
+     *
542
+     * @since 2.5.0
543
+     *
544
+     * @param string           $path  Path for new directory.
545
+     * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
546
+     *                                Default false.
547
+     * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
548
+     *                                Default false.
549
+     * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
550
+     *                                Default false.
551
+     * @return bool True on success, false on failure.
552
+     */
553
+    public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
554
+        $path = untrailingslashit( $path );
555
+
556
+        if ( empty( $path ) ) {
557
+            return false;
558
+        }
559
+
560
+        if ( ! ftp_mkdir( $this->link, $path ) ) {
561
+            return false;
562
+        }
563
+
564
+        $this->chmod( $path, $chmod );
565
+
566
+        return true;
567
+    }
568
+
569
+    /**
570
+     * Deletes a directory.
571
+     *
572
+     * @since 2.5.0
573
+     *
574
+     * @param string $path      Path to directory.
575
+     * @param bool   $recursive Optional. Whether to recursively remove files/directories.
576
+     *                          Default false.
577
+     * @return bool True on success, false on failure.
578
+     */
579
+    public function rmdir( $path, $recursive = false ) {
580
+        return $this->delete( $path, $recursive );
581
+    }
582
+
583
+    /**
584
+     * @param string $line
585
+     * @return array
586
+     */
587
+    public function parselisting( $line ) {
588
+        static $is_windows = null;
589
+
590
+        if ( is_null( $is_windows ) ) {
591
+            $is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false;
592
+        }
593
+
594
+        if ( $is_windows && preg_match( '/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer ) ) {
595
+            $b = array();
596
+
597
+            if ( $lucifer[3] < 70 ) {
598
+                $lucifer[3] += 2000;
599
+            } else {
600
+                $lucifer[3] += 1900; // 4-digit year fix.
601
+            }
602
+
603
+            $b['isdir'] = ( '<DIR>' === $lucifer[7] );
604
+
605
+            if ( $b['isdir'] ) {
606
+                $b['type'] = 'd';
607
+            } else {
608
+                $b['type'] = 'f';
609
+            }
610
+
611
+            $b['size']   = $lucifer[7];
612
+            $b['month']  = $lucifer[1];
613
+            $b['day']    = $lucifer[2];
614
+            $b['year']   = $lucifer[3];
615
+            $b['hour']   = $lucifer[4];
616
+            $b['minute'] = $lucifer[5];
617
+            $b['time']   = mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) === 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] );
618
+            $b['am/pm']  = $lucifer[6];
619
+            $b['name']   = $lucifer[8];
620
+        } elseif ( ! $is_windows ) {
621
+            $lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY );
622
+
623
+            if ( $lucifer ) {
624
+                // echo $line."\n";
625
+                $lcount = count( $lucifer );
626
+
627
+                if ( $lcount < 8 ) {
628
+                    return '';
629
+                }
630
+
631
+                $b           = array();
632
+                $b['isdir']  = 'd' === $lucifer[0][0];
633
+                $b['islink'] = 'l' === $lucifer[0][0];
634
+
635
+                if ( $b['isdir'] ) {
636
+                    $b['type'] = 'd';
637
+                } elseif ( $b['islink'] ) {
638
+                    $b['type'] = 'l';
639
+                } else {
640
+                    $b['type'] = 'f';
641
+                }
642
+
643
+                $b['perms']  = $lucifer[0];
644
+                $b['permsn'] = $this->getnumchmodfromh( $b['perms'] );
645
+                $b['number'] = $lucifer[1];
646
+                $b['owner']  = $lucifer[2];
647
+                $b['group']  = $lucifer[3];
648
+                $b['size']   = $lucifer[4];
649
+
650
+                if ( 8 === $lcount ) {
651
+                    sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] );
652
+                    sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] );
653
+
654
+                    $b['time'] = mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] );
655
+                    $b['name'] = $lucifer[7];
656
+                } else {
657
+                    $b['month'] = $lucifer[5];
658
+                    $b['day']   = $lucifer[6];
659
+
660
+                    if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) {
661
+                        $b['year']   = gmdate( 'Y' );
662
+                        $b['hour']   = $l2[1];
663
+                        $b['minute'] = $l2[2];
664
+                    } else {
665
+                        $b['year']   = $lucifer[7];
666
+                        $b['hour']   = 0;
667
+                        $b['minute'] = 0;
668
+                    }
669
+
670
+                    $b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) );
671
+                    $b['name'] = $lucifer[8];
672
+                }
673
+            }
674
+        }
675
+
676
+        // Replace symlinks formatted as "source -> target" with just the source name.
677
+        if ( isset( $b['islink'] ) && $b['islink'] ) {
678
+            $b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] );
679
+        }
680
+
681
+        return $b;
682
+    }
683
+
684
+    /**
685
+     * Gets details for files in a directory or a specific file.
686
+     *
687
+     * @since 2.5.0
688
+     *
689
+     * @param string $path           Path to directory or file.
690
+     * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
691
+     *                               Default true.
692
+     * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
693
+     *                               Default false.
694
+     * @return array|false {
695
+     *     Array of files. False if unable to list directory contents.
696
+     *
697
+     *     @type string $name        Name of the file or directory.
698
+     *     @type string $perms       *nix representation of permissions.
699
+     *     @type string $permsn      Octal representation of permissions.
700
+     *     @type string $owner       Owner name or ID.
701
+     *     @type int    $size        Size of file in bytes.
702
+     *     @type int    $lastmodunix Last modified unix timestamp.
703
+     *     @type mixed  $lastmod     Last modified month (3 letter) and day (without leading 0).
704
+     *     @type int    $time        Last modified time.
705
+     *     @type string $type        Type of resource. 'f' for file, 'd' for directory.
706
+     *     @type mixed  $files       If a directory and `$recursive` is true, contains another array of files.
707
+     * }
708
+     */
709
+    public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
710
+        if ( $this->is_file( $path ) ) {
711
+            $limit_file = basename( $path );
712
+            $path       = dirname( $path ) . '/';
713
+        } else {
714
+            $limit_file = false;
715
+        }
716
+
717
+        $pwd = ftp_pwd( $this->link );
718
+
719
+        if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist.
720
+            return false;
721
+        }
722
+
723
+        $list = ftp_rawlist( $this->link, '-a', false );
724
+
725
+        @ftp_chdir( $this->link, $pwd );
726
+
727
+        if ( empty( $list ) ) { // Empty array = non-existent folder (real folder will show . at least).
728
+            return false;
729
+        }
730
+
731
+        $dirlist = array();
732
+
733
+        foreach ( $list as $k => $v ) {
734
+            $entry = $this->parselisting( $v );
735
+
736
+            if ( empty( $entry ) ) {
737
+                continue;
738
+            }
739
+
740
+            if ( '.' === $entry['name'] || '..' === $entry['name'] ) {
741
+                continue;
742
+            }
743
+
744
+            if ( ! $include_hidden && '.' === $entry['name'][0] ) {
745
+                continue;
746
+            }
747
+
748
+            if ( $limit_file && $entry['name'] !== $limit_file ) {
749
+                continue;
750
+            }
751
+
752
+            $dirlist[ $entry['name'] ] = $entry;
753
+        }
754
+
755
+        $ret = array();
756
+
757
+        foreach ( (array) $dirlist as $struc ) {
758
+            if ( 'd' === $struc['type'] ) {
759
+                if ( $recursive ) {
760
+                    $struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive );
761
+                } else {
762
+                    $struc['files'] = array();
763
+                }
764
+            }
765
+
766
+            $ret[ $struc['name'] ] = $struc;
767
+        }
768
+
769
+        return $ret;
770
+    }
771
+
772
+    /**
773
+     * Destructor.
774
+     *
775
+     * @since 2.5.0
776
+     */
777
+    public function __destruct() {
778
+        if ( $this->link ) {
779
+            ftp_close( $this->link );
780
+        }
781
+    }
782 782
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/image-edit.php 1 patch
Indentation   +683 added lines, -683 removed lines patch added patch discarded remove patch
@@ -16,43 +16,43 @@  discard block
 block discarded – undo
16 16
  *                              Default false.
17 17
  */
18 18
 function wp_image_editor( $post_id, $msg = false ) {
19
-	$nonce     = wp_create_nonce( "image_editor-$post_id" );
20
-	$meta      = wp_get_attachment_metadata( $post_id );
21
-	$thumb     = image_get_intermediate_size( $post_id, 'thumbnail' );
22
-	$sub_sizes = isset( $meta['sizes'] ) && is_array( $meta['sizes'] );
23
-	$note      = '';
24
-
25
-	if ( isset( $meta['width'], $meta['height'] ) ) {
26
-		$big = max( $meta['width'], $meta['height'] );
27
-	} else {
28
-		die( __( 'Image data does not exist. Please re-upload the image.' ) );
29
-	}
30
-
31
-	$sizer = $big > 400 ? 400 / $big : 1;
32
-
33
-	$backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
34
-	$can_restore  = false;
35
-	if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
36
-		$can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
37
-	}
38
-
39
-	if ( $msg ) {
40
-		if ( isset( $msg->error ) ) {
41
-			$note = "<div class='notice notice-error' tabindex='-1' role='alert'><p>$msg->error</p></div>";
42
-		} elseif ( isset( $msg->msg ) ) {
43
-			$note = "<div class='notice notice-success' tabindex='-1' role='alert'><p>$msg->msg</p></div>";
44
-		}
45
-	}
46
-	$edit_custom_sizes = false;
47
-	/**
48
-	 * Filters whether custom sizes are available options for image editing.
49
-	 *
50
-	 * @since 6.0.0
51
-	 *
52
-	 * @param bool|string[] $edit_custom_sizes True if custom sizes can be edited or array of custom size names.
53
-	 */
54
-	$edit_custom_sizes = apply_filters( 'edit_custom_thumbnail_sizes', $edit_custom_sizes );
55
-	?>
19
+    $nonce     = wp_create_nonce( "image_editor-$post_id" );
20
+    $meta      = wp_get_attachment_metadata( $post_id );
21
+    $thumb     = image_get_intermediate_size( $post_id, 'thumbnail' );
22
+    $sub_sizes = isset( $meta['sizes'] ) && is_array( $meta['sizes'] );
23
+    $note      = '';
24
+
25
+    if ( isset( $meta['width'], $meta['height'] ) ) {
26
+        $big = max( $meta['width'], $meta['height'] );
27
+    } else {
28
+        die( __( 'Image data does not exist. Please re-upload the image.' ) );
29
+    }
30
+
31
+    $sizer = $big > 400 ? 400 / $big : 1;
32
+
33
+    $backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
34
+    $can_restore  = false;
35
+    if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
36
+        $can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
37
+    }
38
+
39
+    if ( $msg ) {
40
+        if ( isset( $msg->error ) ) {
41
+            $note = "<div class='notice notice-error' tabindex='-1' role='alert'><p>$msg->error</p></div>";
42
+        } elseif ( isset( $msg->msg ) ) {
43
+            $note = "<div class='notice notice-success' tabindex='-1' role='alert'><p>$msg->msg</p></div>";
44
+        }
45
+    }
46
+    $edit_custom_sizes = false;
47
+    /**
48
+     * Filters whether custom sizes are available options for image editing.
49
+     *
50
+     * @since 6.0.0
51
+     *
52
+     * @param bool|string[] $edit_custom_sizes True if custom sizes can be edited or array of custom size names.
53
+     */
54
+    $edit_custom_sizes = apply_filters( 'edit_custom_thumbnail_sizes', $edit_custom_sizes );
55
+    ?>
56 56
 	<div class="imgedit-wrap wp-clearfix">
57 57
 	<div id="imgedit-panel-<?php echo $post_id; ?>">
58 58
 
@@ -62,21 +62,21 @@  discard block
 block discarded – undo
62 62
 			<button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this )" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
63 63
 			<?php
64 64
 
65
-			// On some setups GD library does not provide imagerotate() - Ticket #11536.
66
-			if ( wp_image_editor_supports(
67
-				array(
68
-					'mime_type' => get_post_mime_type( $post_id ),
69
-					'methods'   => array( 'rotate' ),
70
-				)
71
-			) ) {
72
-				$note_no_rotate = '';
73
-				?>
65
+            // On some setups GD library does not provide imagerotate() - Ticket #11536.
66
+            if ( wp_image_editor_supports(
67
+                array(
68
+                    'mime_type' => get_post_mime_type( $post_id ),
69
+                    'methods'   => array( 'rotate' ),
70
+                )
71
+            ) ) {
72
+                $note_no_rotate = '';
73
+                ?>
74 74
 				<button type="button" class="imgedit-rleft button" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate left' ); ?></button>
75 75
 				<button type="button" class="imgedit-rright button" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)"><?php esc_html_e( 'Rotate right' ); ?></button>
76 76
 				<?php
77
-			} else {
78
-				$note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
79
-				?>
77
+            } else {
78
+                $note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
79
+                ?>
80 80
 				<button type="button" class="imgedit-rleft button disabled" disabled></button>
81 81
 				<button type="button" class="imgedit-rright button disabled" disabled></button>
82 82
 			<?php } ?>
@@ -119,12 +119,12 @@  discard block
 block discarded – undo
119 119
 		<?php if ( isset( $meta['width'], $meta['height'] ) ) : ?>
120 120
 		<p>
121 121
 			<?php
122
-			printf(
123
-				/* translators: %s: Image width and height in pixels. */
124
-				__( 'Original dimensions %s' ),
125
-				'<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
126
-			);
127
-			?>
122
+            printf(
123
+                /* translators: %s: Image width and height in pixels. */
124
+                __( 'Original dimensions %s' ),
125
+                '<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
126
+            );
127
+            ?>
128 128
 		</p>
129 129
 		<?php endif; ?>
130 130
 		<div class="imgedit-submit">
@@ -154,12 +154,12 @@  discard block
 block discarded – undo
154 154
 		<div class="imgedit-help imgedit-restore">
155 155
 		<p>
156 156
 			<?php
157
-			_e( 'Discard any changes and restore the original image.' );
157
+            _e( 'Discard any changes and restore the original image.' );
158 158
 
159
-			if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
160
-				echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
161
-			}
162
-			?>
159
+            if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
160
+                echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
161
+            }
162
+            ?>
163 163
 		</p>
164 164
 		<div class="imgedit-submit">
165 165
 		<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
@@ -211,9 +211,9 @@  discard block
 block discarded – undo
211 211
 	</div>
212 212
 
213 213
 	<?php
214
-	if ( $thumb && $sub_sizes ) {
215
-		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
216
-		?>
214
+    if ( $thumb && $sub_sizes ) {
215
+        $thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
216
+        ?>
217 217
 
218 218
 	<div class="imgedit-group imgedit-applyto">
219 219
 	<div class="imgedit-group-top">
@@ -248,25 +248,25 @@  discard block
 block discarded – undo
248 248
 			<label for="imgedit-target-nothumb"><?php _e( 'All sizes except thumbnail' ); ?></label>
249 249
 		</span>
250 250
 		<?php
251
-		if ( $edit_custom_sizes ) {
252
-			if ( ! is_array( $edit_custom_sizes ) ) {
253
-				$edit_custom_sizes = get_intermediate_image_sizes();
254
-			}
255
-			foreach ( array_unique( $edit_custom_sizes ) as $key => $size ) {
256
-				if ( array_key_exists( $size, $meta['sizes'] ) ) {
257
-					if ( 'thumbnail' === $size ) {
258
-						continue;
259
-					}
260
-					?>
251
+        if ( $edit_custom_sizes ) {
252
+            if ( ! is_array( $edit_custom_sizes ) ) {
253
+                $edit_custom_sizes = get_intermediate_image_sizes();
254
+            }
255
+            foreach ( array_unique( $edit_custom_sizes ) as $key => $size ) {
256
+                if ( array_key_exists( $size, $meta['sizes'] ) ) {
257
+                    if ( 'thumbnail' === $size ) {
258
+                        continue;
259
+                    }
260
+                    ?>
261 261
 					<span class="imgedit-label">
262 262
 						<input type="radio" id="imgedit-target-custom<?php echo esc_attr( $key ); ?>" name="imgedit-target-<?php echo $post_id; ?>" value="<?php echo esc_attr( $size ); ?>" />
263 263
 						<label for="imgedit-target-custom<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $size ); ?></label>
264 264
 					</span>
265 265
 					<?php
266
-				}
267
-			}
268
-		}
269
-		?>
266
+                }
267
+            }
268
+        }
269
+        ?>
270 270
 	</fieldset>
271 271
 	</div>
272 272
 	</div>
@@ -293,58 +293,58 @@  discard block
 block discarded – undo
293 293
  * @return bool True on success, false on failure.
294 294
  */
295 295
 function wp_stream_image( $image, $mime_type, $attachment_id ) {
296
-	if ( $image instanceof WP_Image_Editor ) {
297
-
298
-		/**
299
-		 * Filters the WP_Image_Editor instance for the image to be streamed to the browser.
300
-		 *
301
-		 * @since 3.5.0
302
-		 *
303
-		 * @param WP_Image_Editor $image         The image editor instance.
304
-		 * @param int             $attachment_id The attachment post ID.
305
-		 */
306
-		$image = apply_filters( 'image_editor_save_pre', $image, $attachment_id );
307
-
308
-		if ( is_wp_error( $image->stream( $mime_type ) ) ) {
309
-			return false;
310
-		}
311
-
312
-		return true;
313
-	} else {
314
-		/* translators: 1: $image, 2: WP_Image_Editor */
315
-		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
316
-
317
-		/**
318
-		 * Filters the GD image resource to be streamed to the browser.
319
-		 *
320
-		 * @since 2.9.0
321
-		 * @deprecated 3.5.0 Use {@see 'image_editor_save_pre'} instead.
322
-		 *
323
-		 * @param resource|GdImage $image         Image resource to be streamed.
324
-		 * @param int              $attachment_id The attachment post ID.
325
-		 */
326
-		$image = apply_filters_deprecated( 'image_save_pre', array( $image, $attachment_id ), '3.5.0', 'image_editor_save_pre' );
327
-
328
-		switch ( $mime_type ) {
329
-			case 'image/jpeg':
330
-				header( 'Content-Type: image/jpeg' );
331
-				return imagejpeg( $image, null, 90 );
332
-			case 'image/png':
333
-				header( 'Content-Type: image/png' );
334
-				return imagepng( $image );
335
-			case 'image/gif':
336
-				header( 'Content-Type: image/gif' );
337
-				return imagegif( $image );
338
-			case 'image/webp':
339
-				if ( function_exists( 'imagewebp' ) ) {
340
-					header( 'Content-Type: image/webp' );
341
-					return imagewebp( $image, null, 90 );
342
-				}
343
-				return false;
344
-			default:
345
-				return false;
346
-		}
347
-	}
296
+    if ( $image instanceof WP_Image_Editor ) {
297
+
298
+        /**
299
+         * Filters the WP_Image_Editor instance for the image to be streamed to the browser.
300
+         *
301
+         * @since 3.5.0
302
+         *
303
+         * @param WP_Image_Editor $image         The image editor instance.
304
+         * @param int             $attachment_id The attachment post ID.
305
+         */
306
+        $image = apply_filters( 'image_editor_save_pre', $image, $attachment_id );
307
+
308
+        if ( is_wp_error( $image->stream( $mime_type ) ) ) {
309
+            return false;
310
+        }
311
+
312
+        return true;
313
+    } else {
314
+        /* translators: 1: $image, 2: WP_Image_Editor */
315
+        _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
316
+
317
+        /**
318
+         * Filters the GD image resource to be streamed to the browser.
319
+         *
320
+         * @since 2.9.0
321
+         * @deprecated 3.5.0 Use {@see 'image_editor_save_pre'} instead.
322
+         *
323
+         * @param resource|GdImage $image         Image resource to be streamed.
324
+         * @param int              $attachment_id The attachment post ID.
325
+         */
326
+        $image = apply_filters_deprecated( 'image_save_pre', array( $image, $attachment_id ), '3.5.0', 'image_editor_save_pre' );
327
+
328
+        switch ( $mime_type ) {
329
+            case 'image/jpeg':
330
+                header( 'Content-Type: image/jpeg' );
331
+                return imagejpeg( $image, null, 90 );
332
+            case 'image/png':
333
+                header( 'Content-Type: image/png' );
334
+                return imagepng( $image );
335
+            case 'image/gif':
336
+                header( 'Content-Type: image/gif' );
337
+                return imagegif( $image );
338
+            case 'image/webp':
339
+                if ( function_exists( 'imagewebp' ) ) {
340
+                    header( 'Content-Type: image/webp' );
341
+                    return imagewebp( $image, null, 90 );
342
+                }
343
+                return false;
344
+            default:
345
+                return false;
346
+        }
347
+    }
348 348
 }
349 349
 
350 350
 /**
@@ -359,82 +359,82 @@  discard block
 block discarded – undo
359 359
  * @return bool True on success, false on failure.
360 360
  */
361 361
 function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
362
-	if ( $image instanceof WP_Image_Editor ) {
363
-
364
-		/** This filter is documented in wp-admin/includes/image-edit.php */
365
-		$image = apply_filters( 'image_editor_save_pre', $image, $post_id );
366
-
367
-		/**
368
-		 * Filters whether to skip saving the image file.
369
-		 *
370
-		 * Returning a non-null value will short-circuit the save method,
371
-		 * returning that value instead.
372
-		 *
373
-		 * @since 3.5.0
374
-		 *
375
-		 * @param bool|null       $override  Value to return instead of saving. Default null.
376
-		 * @param string          $filename  Name of the file to be saved.
377
-		 * @param WP_Image_Editor $image     The image editor instance.
378
-		 * @param string          $mime_type The mime type of the image.
379
-		 * @param int             $post_id   Attachment post ID.
380
-		 */
381
-		$saved = apply_filters( 'wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id );
382
-
383
-		if ( null !== $saved ) {
384
-			return $saved;
385
-		}
386
-
387
-		return $image->save( $filename, $mime_type );
388
-	} else {
389
-		/* translators: 1: $image, 2: WP_Image_Editor */
390
-		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
391
-
392
-		/** This filter is documented in wp-admin/includes/image-edit.php */
393
-		$image = apply_filters_deprecated( 'image_save_pre', array( $image, $post_id ), '3.5.0', 'image_editor_save_pre' );
394
-
395
-		/**
396
-		 * Filters whether to skip saving the image file.
397
-		 *
398
-		 * Returning a non-null value will short-circuit the save method,
399
-		 * returning that value instead.
400
-		 *
401
-		 * @since 2.9.0
402
-		 * @deprecated 3.5.0 Use {@see 'wp_save_image_editor_file'} instead.
403
-		 *
404
-		 * @param bool|null        $override  Value to return instead of saving. Default null.
405
-		 * @param string           $filename  Name of the file to be saved.
406
-		 * @param resource|GdImage $image     Image resource or GdImage instance.
407
-		 * @param string           $mime_type The mime type of the image.
408
-		 * @param int              $post_id   Attachment post ID.
409
-		 */
410
-		$saved = apply_filters_deprecated(
411
-			'wp_save_image_file',
412
-			array( null, $filename, $image, $mime_type, $post_id ),
413
-			'3.5.0',
414
-			'wp_save_image_editor_file'
415
-		);
416
-
417
-		if ( null !== $saved ) {
418
-			return $saved;
419
-		}
420
-
421
-		switch ( $mime_type ) {
422
-			case 'image/jpeg':
423
-				/** This filter is documented in wp-includes/class-wp-image-editor.php */
424
-				return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
425
-			case 'image/png':
426
-				return imagepng( $image, $filename );
427
-			case 'image/gif':
428
-				return imagegif( $image, $filename );
429
-			case 'image/webp':
430
-				if ( function_exists( 'imagewebp' ) ) {
431
-					return imagewebp( $image, $filename );
432
-				}
433
-				return false;
434
-			default:
435
-				return false;
436
-		}
437
-	}
362
+    if ( $image instanceof WP_Image_Editor ) {
363
+
364
+        /** This filter is documented in wp-admin/includes/image-edit.php */
365
+        $image = apply_filters( 'image_editor_save_pre', $image, $post_id );
366
+
367
+        /**
368
+         * Filters whether to skip saving the image file.
369
+         *
370
+         * Returning a non-null value will short-circuit the save method,
371
+         * returning that value instead.
372
+         *
373
+         * @since 3.5.0
374
+         *
375
+         * @param bool|null       $override  Value to return instead of saving. Default null.
376
+         * @param string          $filename  Name of the file to be saved.
377
+         * @param WP_Image_Editor $image     The image editor instance.
378
+         * @param string          $mime_type The mime type of the image.
379
+         * @param int             $post_id   Attachment post ID.
380
+         */
381
+        $saved = apply_filters( 'wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id );
382
+
383
+        if ( null !== $saved ) {
384
+            return $saved;
385
+        }
386
+
387
+        return $image->save( $filename, $mime_type );
388
+    } else {
389
+        /* translators: 1: $image, 2: WP_Image_Editor */
390
+        _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
391
+
392
+        /** This filter is documented in wp-admin/includes/image-edit.php */
393
+        $image = apply_filters_deprecated( 'image_save_pre', array( $image, $post_id ), '3.5.0', 'image_editor_save_pre' );
394
+
395
+        /**
396
+         * Filters whether to skip saving the image file.
397
+         *
398
+         * Returning a non-null value will short-circuit the save method,
399
+         * returning that value instead.
400
+         *
401
+         * @since 2.9.0
402
+         * @deprecated 3.5.0 Use {@see 'wp_save_image_editor_file'} instead.
403
+         *
404
+         * @param bool|null        $override  Value to return instead of saving. Default null.
405
+         * @param string           $filename  Name of the file to be saved.
406
+         * @param resource|GdImage $image     Image resource or GdImage instance.
407
+         * @param string           $mime_type The mime type of the image.
408
+         * @param int              $post_id   Attachment post ID.
409
+         */
410
+        $saved = apply_filters_deprecated(
411
+            'wp_save_image_file',
412
+            array( null, $filename, $image, $mime_type, $post_id ),
413
+            '3.5.0',
414
+            'wp_save_image_editor_file'
415
+        );
416
+
417
+        if ( null !== $saved ) {
418
+            return $saved;
419
+        }
420
+
421
+        switch ( $mime_type ) {
422
+            case 'image/jpeg':
423
+                /** This filter is documented in wp-includes/class-wp-image-editor.php */
424
+                return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
425
+            case 'image/png':
426
+                return imagepng( $image, $filename );
427
+            case 'image/gif':
428
+                return imagegif( $image, $filename );
429
+            case 'image/webp':
430
+                if ( function_exists( 'imagewebp' ) ) {
431
+                    return imagewebp( $image, $filename );
432
+                }
433
+                return false;
434
+            default:
435
+                return false;
436
+        }
437
+    }
438 438
 }
439 439
 
440 440
 /**
@@ -448,8 +448,8 @@  discard block
 block discarded – undo
448 448
  * @return float|int Image preview ratio.
449 449
  */
450 450
 function _image_get_preview_ratio( $w, $h ) {
451
-	$max = max( $w, $h );
452
-	return $max > 400 ? ( 400 / $max ) : 1;
451
+    $max = max( $w, $h );
452
+    return $max > 400 ? ( 400 / $max ) : 1;
453 453
 }
454 454
 
455 455
 /**
@@ -465,18 +465,18 @@  discard block
 block discarded – undo
465 465
  * @return resource|GdImage|false GD image resource or GdImage instance, false otherwise.
466 466
  */
467 467
 function _rotate_image_resource( $img, $angle ) {
468
-	_deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::rotate()' );
468
+    _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::rotate()' );
469 469
 
470
-	if ( function_exists( 'imagerotate' ) ) {
471
-		$rotated = imagerotate( $img, $angle, 0 );
470
+    if ( function_exists( 'imagerotate' ) ) {
471
+        $rotated = imagerotate( $img, $angle, 0 );
472 472
 
473
-		if ( is_gd_image( $rotated ) ) {
474
-			imagedestroy( $img );
475
-			$img = $rotated;
476
-		}
477
-	}
473
+        if ( is_gd_image( $rotated ) ) {
474
+            imagedestroy( $img );
475
+            $img = $rotated;
476
+        }
477
+    }
478 478
 
479
-	return $img;
479
+    return $img;
480 480
 }
481 481
 
482 482
 /**
@@ -493,25 +493,25 @@  discard block
 block discarded – undo
493 493
  * @return resource|GdImage (maybe) flipped image resource or GdImage instance.
494 494
  */
495 495
 function _flip_image_resource( $img, $horz, $vert ) {
496
-	_deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::flip()' );
496
+    _deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::flip()' );
497 497
 
498
-	$w   = imagesx( $img );
499
-	$h   = imagesy( $img );
500
-	$dst = wp_imagecreatetruecolor( $w, $h );
498
+    $w   = imagesx( $img );
499
+    $h   = imagesy( $img );
500
+    $dst = wp_imagecreatetruecolor( $w, $h );
501 501
 
502
-	if ( is_gd_image( $dst ) ) {
503
-		$sx = $vert ? ( $w - 1 ) : 0;
504
-		$sy = $horz ? ( $h - 1 ) : 0;
505
-		$sw = $vert ? -$w : $w;
506
-		$sh = $horz ? -$h : $h;
502
+    if ( is_gd_image( $dst ) ) {
503
+        $sx = $vert ? ( $w - 1 ) : 0;
504
+        $sy = $horz ? ( $h - 1 ) : 0;
505
+        $sw = $vert ? -$w : $w;
506
+        $sh = $horz ? -$h : $h;
507 507
 
508
-		if ( imagecopyresampled( $dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
509
-			imagedestroy( $img );
510
-			$img = $dst;
511
-		}
512
-	}
508
+        if ( imagecopyresampled( $dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
509
+            imagedestroy( $img );
510
+            $img = $dst;
511
+        }
512
+    }
513 513
 
514
-	return $img;
514
+    return $img;
515 515
 }
516 516
 
517 517
 /**
@@ -528,16 +528,16 @@  discard block
 block discarded – undo
528 528
  * @return resource|GdImage (maybe) cropped image resource or GdImage instance.
529 529
  */
530 530
 function _crop_image_resource( $img, $x, $y, $w, $h ) {
531
-	$dst = wp_imagecreatetruecolor( $w, $h );
531
+    $dst = wp_imagecreatetruecolor( $w, $h );
532 532
 
533
-	if ( is_gd_image( $dst ) ) {
534
-		if ( imagecopy( $dst, $img, 0, 0, $x, $y, $w, $h ) ) {
535
-			imagedestroy( $img );
536
-			$img = $dst;
537
-		}
538
-	}
533
+    if ( is_gd_image( $dst ) ) {
534
+        if ( imagecopy( $dst, $img, 0, 0, $x, $y, $w, $h ) ) {
535
+            imagedestroy( $img );
536
+            $img = $dst;
537
+        }
538
+    }
539 539
 
540
-	return $img;
540
+    return $img;
541 541
 }
542 542
 
543 543
 /**
@@ -550,123 +550,123 @@  discard block
 block discarded – undo
550 550
  * @return WP_Image_Editor WP_Image_Editor instance with changes applied.
551 551
  */
552 552
 function image_edit_apply_changes( $image, $changes ) {
553
-	if ( is_gd_image( $image ) ) {
554
-		/* translators: 1: $image, 2: WP_Image_Editor */
555
-		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
556
-	}
557
-
558
-	if ( ! is_array( $changes ) ) {
559
-		return $image;
560
-	}
561
-
562
-	// Expand change operations.
563
-	foreach ( $changes as $key => $obj ) {
564
-		if ( isset( $obj->r ) ) {
565
-			$obj->type  = 'rotate';
566
-			$obj->angle = $obj->r;
567
-			unset( $obj->r );
568
-		} elseif ( isset( $obj->f ) ) {
569
-			$obj->type = 'flip';
570
-			$obj->axis = $obj->f;
571
-			unset( $obj->f );
572
-		} elseif ( isset( $obj->c ) ) {
573
-			$obj->type = 'crop';
574
-			$obj->sel  = $obj->c;
575
-			unset( $obj->c );
576
-		}
577
-		$changes[ $key ] = $obj;
578
-	}
579
-
580
-	// Combine operations.
581
-	if ( count( $changes ) > 1 ) {
582
-		$filtered = array( $changes[0] );
583
-		for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
584
-			$combined = false;
585
-			if ( $filtered[ $i ]->type == $changes[ $j ]->type ) {
586
-				switch ( $filtered[ $i ]->type ) {
587
-					case 'rotate':
588
-						$filtered[ $i ]->angle += $changes[ $j ]->angle;
589
-						$combined               = true;
590
-						break;
591
-					case 'flip':
592
-						$filtered[ $i ]->axis ^= $changes[ $j ]->axis;
593
-						$combined              = true;
594
-						break;
595
-				}
596
-			}
597
-			if ( ! $combined ) {
598
-				$filtered[ ++$i ] = $changes[ $j ];
599
-			}
600
-		}
601
-		$changes = $filtered;
602
-		unset( $filtered );
603
-	}
604
-
605
-	// Image resource before applying the changes.
606
-	if ( $image instanceof WP_Image_Editor ) {
607
-
608
-		/**
609
-		 * Filters the WP_Image_Editor instance before applying changes to the image.
610
-		 *
611
-		 * @since 3.5.0
612
-		 *
613
-		 * @param WP_Image_Editor $image   WP_Image_Editor instance.
614
-		 * @param array           $changes Array of change operations.
615
-		 */
616
-		$image = apply_filters( 'wp_image_editor_before_change', $image, $changes );
617
-	} elseif ( is_gd_image( $image ) ) {
618
-
619
-		/**
620
-		 * Filters the GD image resource before applying changes to the image.
621
-		 *
622
-		 * @since 2.9.0
623
-		 * @deprecated 3.5.0 Use {@see 'wp_image_editor_before_change'} instead.
624
-		 *
625
-		 * @param resource|GdImage $image   GD image resource or GdImage instance.
626
-		 * @param array            $changes Array of change operations.
627
-		 */
628
-		$image = apply_filters_deprecated( 'image_edit_before_change', array( $image, $changes ), '3.5.0', 'wp_image_editor_before_change' );
629
-	}
630
-
631
-	foreach ( $changes as $operation ) {
632
-		switch ( $operation->type ) {
633
-			case 'rotate':
634
-				if ( 0 != $operation->angle ) {
635
-					if ( $image instanceof WP_Image_Editor ) {
636
-						$image->rotate( $operation->angle );
637
-					} else {
638
-						$image = _rotate_image_resource( $image, $operation->angle );
639
-					}
640
-				}
641
-				break;
642
-			case 'flip':
643
-				if ( 0 != $operation->axis ) {
644
-					if ( $image instanceof WP_Image_Editor ) {
645
-						$image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
646
-					} else {
647
-						$image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
648
-					}
649
-				}
650
-				break;
651
-			case 'crop':
652
-				$sel = $operation->sel;
653
-
654
-				if ( $image instanceof WP_Image_Editor ) {
655
-					$size = $image->get_size();
656
-					$w    = $size['width'];
657
-					$h    = $size['height'];
658
-
659
-					$scale = 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
660
-					$image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
661
-				} else {
662
-					$scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // Discard preview scaling.
663
-					$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
664
-				}
665
-				break;
666
-		}
667
-	}
668
-
669
-	return $image;
553
+    if ( is_gd_image( $image ) ) {
554
+        /* translators: 1: $image, 2: WP_Image_Editor */
555
+        _deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
556
+    }
557
+
558
+    if ( ! is_array( $changes ) ) {
559
+        return $image;
560
+    }
561
+
562
+    // Expand change operations.
563
+    foreach ( $changes as $key => $obj ) {
564
+        if ( isset( $obj->r ) ) {
565
+            $obj->type  = 'rotate';
566
+            $obj->angle = $obj->r;
567
+            unset( $obj->r );
568
+        } elseif ( isset( $obj->f ) ) {
569
+            $obj->type = 'flip';
570
+            $obj->axis = $obj->f;
571
+            unset( $obj->f );
572
+        } elseif ( isset( $obj->c ) ) {
573
+            $obj->type = 'crop';
574
+            $obj->sel  = $obj->c;
575
+            unset( $obj->c );
576
+        }
577
+        $changes[ $key ] = $obj;
578
+    }
579
+
580
+    // Combine operations.
581
+    if ( count( $changes ) > 1 ) {
582
+        $filtered = array( $changes[0] );
583
+        for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
584
+            $combined = false;
585
+            if ( $filtered[ $i ]->type == $changes[ $j ]->type ) {
586
+                switch ( $filtered[ $i ]->type ) {
587
+                    case 'rotate':
588
+                        $filtered[ $i ]->angle += $changes[ $j ]->angle;
589
+                        $combined               = true;
590
+                        break;
591
+                    case 'flip':
592
+                        $filtered[ $i ]->axis ^= $changes[ $j ]->axis;
593
+                        $combined              = true;
594
+                        break;
595
+                }
596
+            }
597
+            if ( ! $combined ) {
598
+                $filtered[ ++$i ] = $changes[ $j ];
599
+            }
600
+        }
601
+        $changes = $filtered;
602
+        unset( $filtered );
603
+    }
604
+
605
+    // Image resource before applying the changes.
606
+    if ( $image instanceof WP_Image_Editor ) {
607
+
608
+        /**
609
+         * Filters the WP_Image_Editor instance before applying changes to the image.
610
+         *
611
+         * @since 3.5.0
612
+         *
613
+         * @param WP_Image_Editor $image   WP_Image_Editor instance.
614
+         * @param array           $changes Array of change operations.
615
+         */
616
+        $image = apply_filters( 'wp_image_editor_before_change', $image, $changes );
617
+    } elseif ( is_gd_image( $image ) ) {
618
+
619
+        /**
620
+         * Filters the GD image resource before applying changes to the image.
621
+         *
622
+         * @since 2.9.0
623
+         * @deprecated 3.5.0 Use {@see 'wp_image_editor_before_change'} instead.
624
+         *
625
+         * @param resource|GdImage $image   GD image resource or GdImage instance.
626
+         * @param array            $changes Array of change operations.
627
+         */
628
+        $image = apply_filters_deprecated( 'image_edit_before_change', array( $image, $changes ), '3.5.0', 'wp_image_editor_before_change' );
629
+    }
630
+
631
+    foreach ( $changes as $operation ) {
632
+        switch ( $operation->type ) {
633
+            case 'rotate':
634
+                if ( 0 != $operation->angle ) {
635
+                    if ( $image instanceof WP_Image_Editor ) {
636
+                        $image->rotate( $operation->angle );
637
+                    } else {
638
+                        $image = _rotate_image_resource( $image, $operation->angle );
639
+                    }
640
+                }
641
+                break;
642
+            case 'flip':
643
+                if ( 0 != $operation->axis ) {
644
+                    if ( $image instanceof WP_Image_Editor ) {
645
+                        $image->flip( ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
646
+                    } else {
647
+                        $image = _flip_image_resource( $image, ( $operation->axis & 1 ) != 0, ( $operation->axis & 2 ) != 0 );
648
+                    }
649
+                }
650
+                break;
651
+            case 'crop':
652
+                $sel = $operation->sel;
653
+
654
+                if ( $image instanceof WP_Image_Editor ) {
655
+                    $size = $image->get_size();
656
+                    $w    = $size['width'];
657
+                    $h    = $size['height'];
658
+
659
+                    $scale = 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
660
+                    $image->crop( $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
661
+                } else {
662
+                    $scale = 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // Discard preview scaling.
663
+                    $image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
664
+                }
665
+                break;
666
+        }
667
+    }
668
+
669
+    return $image;
670 670
 }
671 671
 
672 672
 
@@ -680,35 +680,35 @@  discard block
 block discarded – undo
680 680
  * @return bool True on success, false on failure.
681 681
  */
682 682
 function stream_preview_image( $post_id ) {
683
-	$post = get_post( $post_id );
683
+    $post = get_post( $post_id );
684 684
 
685
-	wp_raise_memory_limit( 'admin' );
685
+    wp_raise_memory_limit( 'admin' );
686 686
 
687
-	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
687
+    $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );
688 688
 
689
-	if ( is_wp_error( $img ) ) {
690
-		return false;
691
-	}
689
+    if ( is_wp_error( $img ) ) {
690
+        return false;
691
+    }
692 692
 
693
-	$changes = ! empty( $_REQUEST['history'] ) ? json_decode( wp_unslash( $_REQUEST['history'] ) ) : null;
694
-	if ( $changes ) {
695
-		$img = image_edit_apply_changes( $img, $changes );
696
-	}
693
+    $changes = ! empty( $_REQUEST['history'] ) ? json_decode( wp_unslash( $_REQUEST['history'] ) ) : null;
694
+    if ( $changes ) {
695
+        $img = image_edit_apply_changes( $img, $changes );
696
+    }
697 697
 
698
-	// Scale the image.
699
-	$size = $img->get_size();
700
-	$w    = $size['width'];
701
-	$h    = $size['height'];
698
+    // Scale the image.
699
+    $size = $img->get_size();
700
+    $w    = $size['width'];
701
+    $h    = $size['height'];
702 702
 
703
-	$ratio = _image_get_preview_ratio( $w, $h );
704
-	$w2    = max( 1, $w * $ratio );
705
-	$h2    = max( 1, $h * $ratio );
703
+    $ratio = _image_get_preview_ratio( $w, $h );
704
+    $w2    = max( 1, $w * $ratio );
705
+    $h2    = max( 1, $h * $ratio );
706 706
 
707
-	if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) {
708
-		return false;
709
-	}
707
+    if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) {
708
+        return false;
709
+    }
710 710
 
711
-	return wp_stream_image( $img, $post->post_mime_type, $post_id );
711
+    return wp_stream_image( $img, $post->post_mime_type, $post_id );
712 712
 }
713 713
 
714 714
 /**
@@ -720,85 +720,85 @@  discard block
 block discarded – undo
720 720
  * @return stdClass Image restoration message object.
721 721
  */
722 722
 function wp_restore_image( $post_id ) {
723
-	$meta             = wp_get_attachment_metadata( $post_id );
724
-	$file             = get_attached_file( $post_id );
725
-	$backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
726
-	$old_backup_sizes = $backup_sizes;
727
-	$restored         = false;
728
-	$msg              = new stdClass;
729
-
730
-	if ( ! is_array( $backup_sizes ) ) {
731
-		$msg->error = __( 'Cannot load image metadata.' );
732
-		return $msg;
733
-	}
734
-
735
-	$parts         = pathinfo( $file );
736
-	$suffix        = time() . rand( 100, 999 );
737
-	$default_sizes = get_intermediate_image_sizes();
738
-
739
-	if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
740
-		$data = $backup_sizes['full-orig'];
741
-
742
-		if ( $parts['basename'] != $data['file'] ) {
743
-			if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
744
-
745
-				// Delete only if it's an edited image.
746
-				if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
747
-					wp_delete_file( $file );
748
-				}
749
-			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
750
-				$backup_sizes[ "full-$suffix" ] = array(
751
-					'width'  => $meta['width'],
752
-					'height' => $meta['height'],
753
-					'file'   => $parts['basename'],
754
-				);
755
-			}
756
-		}
757
-
758
-		$restored_file = path_join( $parts['dirname'], $data['file'] );
759
-		$restored      = update_attached_file( $post_id, $restored_file );
760
-
761
-		$meta['file']   = _wp_relative_upload_path( $restored_file );
762
-		$meta['width']  = $data['width'];
763
-		$meta['height'] = $data['height'];
764
-	}
765
-
766
-	foreach ( $default_sizes as $default_size ) {
767
-		if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
768
-			$data = $backup_sizes[ "$default_size-orig" ];
769
-			if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] != $data['file'] ) {
770
-				if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
771
-
772
-					// Delete only if it's an edited image.
773
-					if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
774
-						$delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
775
-						wp_delete_file( $delete_file );
776
-					}
777
-				} else {
778
-					$backup_sizes[ "$default_size-{$suffix}" ] = $meta['sizes'][ $default_size ];
779
-				}
780
-			}
781
-
782
-			$meta['sizes'][ $default_size ] = $data;
783
-		} else {
784
-			unset( $meta['sizes'][ $default_size ] );
785
-		}
786
-	}
787
-
788
-	if ( ! wp_update_attachment_metadata( $post_id, $meta ) ||
789
-		( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) ) ) {
790
-
791
-		$msg->error = __( 'Cannot save image metadata.' );
792
-		return $msg;
793
-	}
794
-
795
-	if ( ! $restored ) {
796
-		$msg->error = __( 'Image metadata is inconsistent.' );
797
-	} else {
798
-		$msg->msg = __( 'Image restored successfully.' );
799
-	}
800
-
801
-	return $msg;
723
+    $meta             = wp_get_attachment_metadata( $post_id );
724
+    $file             = get_attached_file( $post_id );
725
+    $backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
726
+    $old_backup_sizes = $backup_sizes;
727
+    $restored         = false;
728
+    $msg              = new stdClass;
729
+
730
+    if ( ! is_array( $backup_sizes ) ) {
731
+        $msg->error = __( 'Cannot load image metadata.' );
732
+        return $msg;
733
+    }
734
+
735
+    $parts         = pathinfo( $file );
736
+    $suffix        = time() . rand( 100, 999 );
737
+    $default_sizes = get_intermediate_image_sizes();
738
+
739
+    if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
740
+        $data = $backup_sizes['full-orig'];
741
+
742
+        if ( $parts['basename'] != $data['file'] ) {
743
+            if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
744
+
745
+                // Delete only if it's an edited image.
746
+                if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
747
+                    wp_delete_file( $file );
748
+                }
749
+            } elseif ( isset( $meta['width'], $meta['height'] ) ) {
750
+                $backup_sizes[ "full-$suffix" ] = array(
751
+                    'width'  => $meta['width'],
752
+                    'height' => $meta['height'],
753
+                    'file'   => $parts['basename'],
754
+                );
755
+            }
756
+        }
757
+
758
+        $restored_file = path_join( $parts['dirname'], $data['file'] );
759
+        $restored      = update_attached_file( $post_id, $restored_file );
760
+
761
+        $meta['file']   = _wp_relative_upload_path( $restored_file );
762
+        $meta['width']  = $data['width'];
763
+        $meta['height'] = $data['height'];
764
+    }
765
+
766
+    foreach ( $default_sizes as $default_size ) {
767
+        if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
768
+            $data = $backup_sizes[ "$default_size-orig" ];
769
+            if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] != $data['file'] ) {
770
+                if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
771
+
772
+                    // Delete only if it's an edited image.
773
+                    if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
774
+                        $delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
775
+                        wp_delete_file( $delete_file );
776
+                    }
777
+                } else {
778
+                    $backup_sizes[ "$default_size-{$suffix}" ] = $meta['sizes'][ $default_size ];
779
+                }
780
+            }
781
+
782
+            $meta['sizes'][ $default_size ] = $data;
783
+        } else {
784
+            unset( $meta['sizes'][ $default_size ] );
785
+        }
786
+    }
787
+
788
+    if ( ! wp_update_attachment_metadata( $post_id, $meta ) ||
789
+        ( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) ) ) {
790
+
791
+        $msg->error = __( 'Cannot save image metadata.' );
792
+        return $msg;
793
+    }
794
+
795
+    if ( ! $restored ) {
796
+        $msg->error = __( 'Image metadata is inconsistent.' );
797
+    } else {
798
+        $msg->msg = __( 'Image restored successfully.' );
799
+    }
800
+
801
+    return $msg;
802 802
 }
803 803
 
804 804
 /**
@@ -811,236 +811,236 @@  discard block
 block discarded – undo
811 811
  * @return stdClass
812 812
  */
813 813
 function wp_save_image( $post_id ) {
814
-	$_wp_additional_image_sizes = wp_get_additional_image_sizes();
815
-
816
-	$return  = new stdClass;
817
-	$success = false;
818
-	$delete  = false;
819
-	$scaled  = false;
820
-	$nocrop  = false;
821
-	$post    = get_post( $post_id );
822
-
823
-	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
824
-	if ( is_wp_error( $img ) ) {
825
-		$return->error = esc_js( __( 'Unable to create new image.' ) );
826
-		return $return;
827
-	}
828
-
829
-	$fwidth  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
830
-	$fheight = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
831
-	$target  = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
832
-	$scale   = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
833
-
834
-	if ( $scale && $fwidth > 0 && $fheight > 0 ) {
835
-		$size = $img->get_size();
836
-		$sX   = $size['width'];
837
-		$sY   = $size['height'];
838
-
839
-		// Check if it has roughly the same w / h ratio.
840
-		$diff = round( $sX / $sY, 2 ) - round( $fwidth / $fheight, 2 );
841
-		if ( -0.1 < $diff && $diff < 0.1 ) {
842
-			// Scale the full size image.
843
-			if ( $img->resize( $fwidth, $fheight ) ) {
844
-				$scaled = true;
845
-			}
846
-		}
847
-
848
-		if ( ! $scaled ) {
849
-			$return->error = esc_js( __( 'Error while saving the scaled image. Please reload the page and try again.' ) );
850
-			return $return;
851
-		}
852
-	} elseif ( ! empty( $_REQUEST['history'] ) ) {
853
-		$changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
854
-		if ( $changes ) {
855
-			$img = image_edit_apply_changes( $img, $changes );
856
-		}
857
-	} else {
858
-		$return->error = esc_js( __( 'Nothing to save, the image has not changed.' ) );
859
-		return $return;
860
-	}
861
-
862
-	$meta         = wp_get_attachment_metadata( $post_id );
863
-	$backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
864
-
865
-	if ( ! is_array( $meta ) ) {
866
-		$return->error = esc_js( __( 'Image data does not exist. Please re-upload the image.' ) );
867
-		return $return;
868
-	}
869
-
870
-	if ( ! is_array( $backup_sizes ) ) {
871
-		$backup_sizes = array();
872
-	}
873
-
874
-	// Generate new filename.
875
-	$path = get_attached_file( $post_id );
876
-
877
-	$basename = pathinfo( $path, PATHINFO_BASENAME );
878
-	$dirname  = pathinfo( $path, PATHINFO_DIRNAME );
879
-	$ext      = pathinfo( $path, PATHINFO_EXTENSION );
880
-	$filename = pathinfo( $path, PATHINFO_FILENAME );
881
-	$suffix   = time() . rand( 100, 999 );
882
-
883
-	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE &&
884
-		isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] != $basename ) {
885
-
886
-		if ( 'thumbnail' === $target ) {
887
-			$new_path = "{$dirname}/{$filename}-temp.{$ext}";
888
-		} else {
889
-			$new_path = $path;
890
-		}
891
-	} else {
892
-		while ( true ) {
893
-			$filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
894
-			$filename    .= "-e{$suffix}";
895
-			$new_filename = "{$filename}.{$ext}";
896
-			$new_path     = "{$dirname}/$new_filename";
897
-			if ( file_exists( $new_path ) ) {
898
-				$suffix++;
899
-			} else {
900
-				break;
901
-			}
902
-		}
903
-	}
904
-
905
-	// Save the full-size file, also needed to create sub-sizes.
906
-	if ( ! wp_save_image_file( $new_path, $img, $post->post_mime_type, $post_id ) ) {
907
-		$return->error = esc_js( __( 'Unable to save the image.' ) );
908
-		return $return;
909
-	}
910
-
911
-	if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
912
-		$tag = false;
913
-		if ( isset( $backup_sizes['full-orig'] ) ) {
914
-			if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] !== $basename ) {
915
-				$tag = "full-$suffix";
916
-			}
917
-		} else {
918
-			$tag = 'full-orig';
919
-		}
920
-
921
-		if ( $tag ) {
922
-			$backup_sizes[ $tag ] = array(
923
-				'width'  => $meta['width'],
924
-				'height' => $meta['height'],
925
-				'file'   => $basename,
926
-			);
927
-		}
928
-		$success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
929
-
930
-		$meta['file'] = _wp_relative_upload_path( $new_path );
931
-
932
-		$size           = $img->get_size();
933
-		$meta['width']  = $size['width'];
934
-		$meta['height'] = $size['height'];
935
-
936
-		if ( $success ) {
937
-			$sizes = get_intermediate_image_sizes();
938
-			if ( 'nothumb' === $target || 'all' === $target ) {
939
-				if ( 'nothumb' === $target ) {
940
-					$sizes = array_diff( $sizes, array( 'thumbnail' ) );
941
-				}
942
-			} elseif ( 'thumbnail' !== $target ) {
943
-				$sizes = array_diff( $sizes, array( $target ) );
944
-			}
945
-		}
946
-
947
-		$return->fw = $meta['width'];
948
-		$return->fh = $meta['height'];
949
-	} elseif ( 'thumbnail' === $target ) {
950
-		$sizes   = array( 'thumbnail' );
951
-		$success = true;
952
-		$delete  = true;
953
-		$nocrop  = true;
954
-	} else {
955
-		$sizes   = array( $target );
956
-		$success = true;
957
-		$delete  = true;
958
-		$nocrop  = $_wp_additional_image_sizes[ $size ]['crop'];
959
-	}
960
-
961
-	/*
814
+    $_wp_additional_image_sizes = wp_get_additional_image_sizes();
815
+
816
+    $return  = new stdClass;
817
+    $success = false;
818
+    $delete  = false;
819
+    $scaled  = false;
820
+    $nocrop  = false;
821
+    $post    = get_post( $post_id );
822
+
823
+    $img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );
824
+    if ( is_wp_error( $img ) ) {
825
+        $return->error = esc_js( __( 'Unable to create new image.' ) );
826
+        return $return;
827
+    }
828
+
829
+    $fwidth  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
830
+    $fheight = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
831
+    $target  = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
832
+    $scale   = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
833
+
834
+    if ( $scale && $fwidth > 0 && $fheight > 0 ) {
835
+        $size = $img->get_size();
836
+        $sX   = $size['width'];
837
+        $sY   = $size['height'];
838
+
839
+        // Check if it has roughly the same w / h ratio.
840
+        $diff = round( $sX / $sY, 2 ) - round( $fwidth / $fheight, 2 );
841
+        if ( -0.1 < $diff && $diff < 0.1 ) {
842
+            // Scale the full size image.
843
+            if ( $img->resize( $fwidth, $fheight ) ) {
844
+                $scaled = true;
845
+            }
846
+        }
847
+
848
+        if ( ! $scaled ) {
849
+            $return->error = esc_js( __( 'Error while saving the scaled image. Please reload the page and try again.' ) );
850
+            return $return;
851
+        }
852
+    } elseif ( ! empty( $_REQUEST['history'] ) ) {
853
+        $changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
854
+        if ( $changes ) {
855
+            $img = image_edit_apply_changes( $img, $changes );
856
+        }
857
+    } else {
858
+        $return->error = esc_js( __( 'Nothing to save, the image has not changed.' ) );
859
+        return $return;
860
+    }
861
+
862
+    $meta         = wp_get_attachment_metadata( $post_id );
863
+    $backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
864
+
865
+    if ( ! is_array( $meta ) ) {
866
+        $return->error = esc_js( __( 'Image data does not exist. Please re-upload the image.' ) );
867
+        return $return;
868
+    }
869
+
870
+    if ( ! is_array( $backup_sizes ) ) {
871
+        $backup_sizes = array();
872
+    }
873
+
874
+    // Generate new filename.
875
+    $path = get_attached_file( $post_id );
876
+
877
+    $basename = pathinfo( $path, PATHINFO_BASENAME );
878
+    $dirname  = pathinfo( $path, PATHINFO_DIRNAME );
879
+    $ext      = pathinfo( $path, PATHINFO_EXTENSION );
880
+    $filename = pathinfo( $path, PATHINFO_FILENAME );
881
+    $suffix   = time() . rand( 100, 999 );
882
+
883
+    if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE &&
884
+        isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] != $basename ) {
885
+
886
+        if ( 'thumbnail' === $target ) {
887
+            $new_path = "{$dirname}/{$filename}-temp.{$ext}";
888
+        } else {
889
+            $new_path = $path;
890
+        }
891
+    } else {
892
+        while ( true ) {
893
+            $filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
894
+            $filename    .= "-e{$suffix}";
895
+            $new_filename = "{$filename}.{$ext}";
896
+            $new_path     = "{$dirname}/$new_filename";
897
+            if ( file_exists( $new_path ) ) {
898
+                $suffix++;
899
+            } else {
900
+                break;
901
+            }
902
+        }
903
+    }
904
+
905
+    // Save the full-size file, also needed to create sub-sizes.
906
+    if ( ! wp_save_image_file( $new_path, $img, $post->post_mime_type, $post_id ) ) {
907
+        $return->error = esc_js( __( 'Unable to save the image.' ) );
908
+        return $return;
909
+    }
910
+
911
+    if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
912
+        $tag = false;
913
+        if ( isset( $backup_sizes['full-orig'] ) ) {
914
+            if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes['full-orig']['file'] !== $basename ) {
915
+                $tag = "full-$suffix";
916
+            }
917
+        } else {
918
+            $tag = 'full-orig';
919
+        }
920
+
921
+        if ( $tag ) {
922
+            $backup_sizes[ $tag ] = array(
923
+                'width'  => $meta['width'],
924
+                'height' => $meta['height'],
925
+                'file'   => $basename,
926
+            );
927
+        }
928
+        $success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );
929
+
930
+        $meta['file'] = _wp_relative_upload_path( $new_path );
931
+
932
+        $size           = $img->get_size();
933
+        $meta['width']  = $size['width'];
934
+        $meta['height'] = $size['height'];
935
+
936
+        if ( $success ) {
937
+            $sizes = get_intermediate_image_sizes();
938
+            if ( 'nothumb' === $target || 'all' === $target ) {
939
+                if ( 'nothumb' === $target ) {
940
+                    $sizes = array_diff( $sizes, array( 'thumbnail' ) );
941
+                }
942
+            } elseif ( 'thumbnail' !== $target ) {
943
+                $sizes = array_diff( $sizes, array( $target ) );
944
+            }
945
+        }
946
+
947
+        $return->fw = $meta['width'];
948
+        $return->fh = $meta['height'];
949
+    } elseif ( 'thumbnail' === $target ) {
950
+        $sizes   = array( 'thumbnail' );
951
+        $success = true;
952
+        $delete  = true;
953
+        $nocrop  = true;
954
+    } else {
955
+        $sizes   = array( $target );
956
+        $success = true;
957
+        $delete  = true;
958
+        $nocrop  = $_wp_additional_image_sizes[ $size ]['crop'];
959
+    }
960
+
961
+    /*
962 962
 	 * We need to remove any existing resized image files because
963 963
 	 * a new crop or rotate could generate different sizes (and hence, filenames),
964 964
 	 * keeping the new resized images from overwriting the existing image files.
965 965
 	 * https://core.trac.wordpress.org/ticket/32171
966 966
 	 */
967
-	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
968
-		foreach ( $meta['sizes'] as $size ) {
969
-			if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
970
-				$delete_file = path_join( $dirname, $size['file'] );
971
-				wp_delete_file( $delete_file );
972
-			}
973
-		}
974
-	}
975
-
976
-	if ( isset( $sizes ) ) {
977
-		$_sizes = array();
978
-
979
-		foreach ( $sizes as $size ) {
980
-			$tag = false;
981
-			if ( isset( $meta['sizes'][ $size ] ) ) {
982
-				if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
983
-					if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes[ "$size-orig" ]['file'] != $meta['sizes'][ $size ]['file'] ) {
984
-						$tag = "$size-$suffix";
985
-					}
986
-				} else {
987
-					$tag = "$size-orig";
988
-				}
989
-
990
-				if ( $tag ) {
991
-					$backup_sizes[ $tag ] = $meta['sizes'][ $size ];
992
-				}
993
-			}
994
-
995
-			if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
996
-				$width  = (int) $_wp_additional_image_sizes[ $size ]['width'];
997
-				$height = (int) $_wp_additional_image_sizes[ $size ]['height'];
998
-				$crop   = ( $nocrop ) ? false : $_wp_additional_image_sizes[ $size ]['crop'];
999
-			} else {
1000
-				$height = get_option( "{$size}_size_h" );
1001
-				$width  = get_option( "{$size}_size_w" );
1002
-				$crop   = ( $nocrop ) ? false : get_option( "{$size}_crop" );
1003
-			}
1004
-
1005
-			$_sizes[ $size ] = array(
1006
-				'width'  => $width,
1007
-				'height' => $height,
1008
-				'crop'   => $crop,
1009
-			);
1010
-		}
1011
-
1012
-		$meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
1013
-	}
1014
-
1015
-	unset( $img );
1016
-
1017
-	if ( $success ) {
1018
-		wp_update_attachment_metadata( $post_id, $meta );
1019
-		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );
1020
-
1021
-		if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
1022
-			// Check if it's an image edit from attachment edit screen.
1023
-			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
1024
-				$thumb_url         = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
1025
-				$return->thumbnail = $thumb_url[0];
1026
-			} else {
1027
-				$file_url = wp_get_attachment_url( $post_id );
1028
-				if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
1029
-					$thumb             = $meta['sizes']['thumbnail'];
1030
-					$return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
1031
-				} else {
1032
-					$return->thumbnail = "$file_url?w=128&h=128";
1033
-				}
1034
-			}
1035
-		}
1036
-	} else {
1037
-		$delete = true;
1038
-	}
1039
-
1040
-	if ( $delete ) {
1041
-		wp_delete_file( $new_path );
1042
-	}
1043
-
1044
-	$return->msg = esc_js( __( 'Image saved' ) );
1045
-	return $return;
967
+    if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
968
+        foreach ( $meta['sizes'] as $size ) {
969
+            if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
970
+                $delete_file = path_join( $dirname, $size['file'] );
971
+                wp_delete_file( $delete_file );
972
+            }
973
+        }
974
+    }
975
+
976
+    if ( isset( $sizes ) ) {
977
+        $_sizes = array();
978
+
979
+        foreach ( $sizes as $size ) {
980
+            $tag = false;
981
+            if ( isset( $meta['sizes'][ $size ] ) ) {
982
+                if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
983
+                    if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) && $backup_sizes[ "$size-orig" ]['file'] != $meta['sizes'][ $size ]['file'] ) {
984
+                        $tag = "$size-$suffix";
985
+                    }
986
+                } else {
987
+                    $tag = "$size-orig";
988
+                }
989
+
990
+                if ( $tag ) {
991
+                    $backup_sizes[ $tag ] = $meta['sizes'][ $size ];
992
+                }
993
+            }
994
+
995
+            if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
996
+                $width  = (int) $_wp_additional_image_sizes[ $size ]['width'];
997
+                $height = (int) $_wp_additional_image_sizes[ $size ]['height'];
998
+                $crop   = ( $nocrop ) ? false : $_wp_additional_image_sizes[ $size ]['crop'];
999
+            } else {
1000
+                $height = get_option( "{$size}_size_h" );
1001
+                $width  = get_option( "{$size}_size_w" );
1002
+                $crop   = ( $nocrop ) ? false : get_option( "{$size}_crop" );
1003
+            }
1004
+
1005
+            $_sizes[ $size ] = array(
1006
+                'width'  => $width,
1007
+                'height' => $height,
1008
+                'crop'   => $crop,
1009
+            );
1010
+        }
1011
+
1012
+        $meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
1013
+    }
1014
+
1015
+    unset( $img );
1016
+
1017
+    if ( $success ) {
1018
+        wp_update_attachment_metadata( $post_id, $meta );
1019
+        update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );
1020
+
1021
+        if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
1022
+            // Check if it's an image edit from attachment edit screen.
1023
+            if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
1024
+                $thumb_url         = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );
1025
+                $return->thumbnail = $thumb_url[0];
1026
+            } else {
1027
+                $file_url = wp_get_attachment_url( $post_id );
1028
+                if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
1029
+                    $thumb             = $meta['sizes']['thumbnail'];
1030
+                    $return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
1031
+                } else {
1032
+                    $return->thumbnail = "$file_url?w=128&h=128";
1033
+                }
1034
+            }
1035
+        }
1036
+    } else {
1037
+        $delete = true;
1038
+    }
1039
+
1040
+    if ( $delete ) {
1041
+        wp_delete_file( $new_path );
1042
+    }
1043
+
1044
+    $return->msg = esc_js( __( 'Image saved' ) );
1045
+    return $return;
1046 1046
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/class-bulk-plugin-upgrader-skin.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -16,63 +16,63 @@
 block discarded – undo
16 16
  * @see Bulk_Upgrader_Skin
17 17
  */
18 18
 class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin {
19
-	public $plugin_info = array(); // Plugin_Upgrader::bulk_upgrade() will fill this in.
19
+    public $plugin_info = array(); // Plugin_Upgrader::bulk_upgrade() will fill this in.
20 20
 
21
-	public function add_strings() {
22
-		parent::add_strings();
23
-		/* translators: 1: Plugin name, 2: Number of the plugin, 3: Total number of plugins being updated. */
24
-		$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)' );
25
-	}
21
+    public function add_strings() {
22
+        parent::add_strings();
23
+        /* translators: 1: Plugin name, 2: Number of the plugin, 3: Total number of plugins being updated. */
24
+        $this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)' );
25
+    }
26 26
 
27
-	/**
28
-	 * @param string $title
29
-	 */
30
-	public function before( $title = '' ) {
31
-		parent::before( $this->plugin_info['Title'] );
32
-	}
27
+    /**
28
+     * @param string $title
29
+     */
30
+    public function before( $title = '' ) {
31
+        parent::before( $this->plugin_info['Title'] );
32
+    }
33 33
 
34
-	/**
35
-	 * @param string $title
36
-	 */
37
-	public function after( $title = '' ) {
38
-		parent::after( $this->plugin_info['Title'] );
39
-		$this->decrement_update_count( 'plugin' );
40
-	}
34
+    /**
35
+     * @param string $title
36
+     */
37
+    public function after( $title = '' ) {
38
+        parent::after( $this->plugin_info['Title'] );
39
+        $this->decrement_update_count( 'plugin' );
40
+    }
41 41
 
42
-	/**
43
-	 */
44
-	public function bulk_footer() {
45
-		parent::bulk_footer();
42
+    /**
43
+     */
44
+    public function bulk_footer() {
45
+        parent::bulk_footer();
46 46
 
47
-		$update_actions = array(
48
-			'plugins_page' => sprintf(
49
-				'<a href="%s" target="_parent">%s</a>',
50
-				self_admin_url( 'plugins.php' ),
51
-				__( 'Go to Plugins page' )
52
-			),
53
-			'updates_page' => sprintf(
54
-				'<a href="%s" target="_parent">%s</a>',
55
-				self_admin_url( 'update-core.php' ),
56
-				__( 'Go to WordPress Updates page' )
57
-			),
58
-		);
47
+        $update_actions = array(
48
+            'plugins_page' => sprintf(
49
+                '<a href="%s" target="_parent">%s</a>',
50
+                self_admin_url( 'plugins.php' ),
51
+                __( 'Go to Plugins page' )
52
+            ),
53
+            'updates_page' => sprintf(
54
+                '<a href="%s" target="_parent">%s</a>',
55
+                self_admin_url( 'update-core.php' ),
56
+                __( 'Go to WordPress Updates page' )
57
+            ),
58
+        );
59 59
 
60
-		if ( ! current_user_can( 'activate_plugins' ) ) {
61
-			unset( $update_actions['plugins_page'] );
62
-		}
60
+        if ( ! current_user_can( 'activate_plugins' ) ) {
61
+            unset( $update_actions['plugins_page'] );
62
+        }
63 63
 
64
-		/**
65
-		 * Filters the list of action links available following bulk plugin updates.
66
-		 *
67
-		 * @since 3.0.0
68
-		 *
69
-		 * @param string[] $update_actions Array of plugin action links.
70
-		 * @param array    $plugin_info    Array of information for the last-updated plugin.
71
-		 */
72
-		$update_actions = apply_filters( 'update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
64
+        /**
65
+         * Filters the list of action links available following bulk plugin updates.
66
+         *
67
+         * @since 3.0.0
68
+         *
69
+         * @param string[] $update_actions Array of plugin action links.
70
+         * @param array    $plugin_info    Array of information for the last-updated plugin.
71
+         */
72
+        $update_actions = apply_filters( 'update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );
73 73
 
74
-		if ( ! empty( $update_actions ) ) {
75
-			$this->feedback( implode( ' | ', (array) $update_actions ) );
76
-		}
77
-	}
74
+        if ( ! empty( $update_actions ) ) {
75
+            $this->feedback( implode( ' | ', (array) $update_actions ) );
76
+        }
77
+    }
78 78
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/class-wp-site-health-auto-updates.php 1 patch
Indentation   +445 added lines, -445 removed lines patch added patch discarded remove patch
@@ -8,449 +8,449 @@
 block discarded – undo
8 8
  */
9 9
 
10 10
 class WP_Site_Health_Auto_Updates {
11
-	/**
12
-	 * WP_Site_Health_Auto_Updates constructor.
13
-	 *
14
-	 * @since 5.2.0
15
-	 */
16
-	public function __construct() {
17
-		require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
18
-	}
19
-
20
-
21
-	/**
22
-	 * Run tests to determine if auto-updates can run.
23
-	 *
24
-	 * @since 5.2.0
25
-	 *
26
-	 * @return array The test results.
27
-	 */
28
-	public function run_tests() {
29
-		$tests = array(
30
-			$this->test_constants( 'WP_AUTO_UPDATE_CORE', array( true, 'beta', 'rc', 'development', 'branch-development', 'minor' ) ),
31
-			$this->test_wp_version_check_attached(),
32
-			$this->test_filters_automatic_updater_disabled(),
33
-			$this->test_wp_automatic_updates_disabled(),
34
-			$this->test_if_failed_update(),
35
-			$this->test_vcs_abspath(),
36
-			$this->test_check_wp_filesystem_method(),
37
-			$this->test_all_files_writable(),
38
-			$this->test_accepts_dev_updates(),
39
-			$this->test_accepts_minor_updates(),
40
-		);
41
-
42
-		$tests = array_filter( $tests );
43
-		$tests = array_map(
44
-			static function( $test ) {
45
-				$test = (object) $test;
46
-
47
-				if ( empty( $test->severity ) ) {
48
-					$test->severity = 'warning';
49
-				}
50
-
51
-				return $test;
52
-			},
53
-			$tests
54
-		);
55
-
56
-		return $tests;
57
-	}
58
-
59
-	/**
60
-	 * Test if auto-updates related constants are set correctly.
61
-	 *
62
-	 * @since 5.2.0
63
-	 * @since 5.5.1 The `$value` parameter can accept an array.
64
-	 *
65
-	 * @param string $constant         The name of the constant to check.
66
-	 * @param bool|string|array $value The value that the constant should be, if set,
67
-	 *                                 or an array of acceptable values.
68
-	 * @return array The test results.
69
-	 */
70
-	public function test_constants( $constant, $value ) {
71
-		$acceptable_values = (array) $value;
72
-
73
-		if ( defined( $constant ) && ! in_array( constant( $constant ), $acceptable_values, true ) ) {
74
-			return array(
75
-				'description' => sprintf(
76
-					/* translators: %s: Name of the constant used. */
77
-					__( 'The %s constant is defined and enabled.' ),
78
-					"<code>$constant</code>"
79
-				),
80
-				'severity'    => 'fail',
81
-			);
82
-		}
83
-	}
84
-
85
-	/**
86
-	 * Check if updates are intercepted by a filter.
87
-	 *
88
-	 * @since 5.2.0
89
-	 *
90
-	 * @return array The test results.
91
-	 */
92
-	public function test_wp_version_check_attached() {
93
-		if ( ( ! is_multisite() || is_main_site() && is_network_admin() )
94
-			&& ! has_filter( 'wp_version_check', 'wp_version_check' )
95
-		) {
96
-			return array(
97
-				'description' => sprintf(
98
-					/* translators: %s: Name of the filter used. */
99
-					__( 'A plugin has prevented updates by disabling %s.' ),
100
-					'<code>wp_version_check()</code>'
101
-				),
102
-				'severity'    => 'fail',
103
-			);
104
-		}
105
-	}
106
-
107
-	/**
108
-	 * Check if automatic updates are disabled by a filter.
109
-	 *
110
-	 * @since 5.2.0
111
-	 *
112
-	 * @return array The test results.
113
-	 */
114
-	public function test_filters_automatic_updater_disabled() {
115
-		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
116
-		if ( apply_filters( 'automatic_updater_disabled', false ) ) {
117
-			return array(
118
-				'description' => sprintf(
119
-					/* translators: %s: Name of the filter used. */
120
-					__( 'The %s filter is enabled.' ),
121
-					'<code>automatic_updater_disabled</code>'
122
-				),
123
-				'severity'    => 'fail',
124
-			);
125
-		}
126
-	}
127
-
128
-	/**
129
-	 * Check if automatic updates are disabled.
130
-	 *
131
-	 * @since 5.3.0
132
-	 *
133
-	 * @return array|false The test results. False if auto-updates are enabled.
134
-	 */
135
-	public function test_wp_automatic_updates_disabled() {
136
-		if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
137
-			require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
138
-		}
139
-
140
-		$auto_updates = new WP_Automatic_Updater();
141
-
142
-		if ( ! $auto_updates->is_disabled() ) {
143
-			return false;
144
-		}
145
-
146
-		return array(
147
-			'description' => __( 'All automatic updates are disabled.' ),
148
-			'severity'    => 'fail',
149
-		);
150
-	}
151
-
152
-	/**
153
-	 * Check if automatic updates have tried to run, but failed, previously.
154
-	 *
155
-	 * @since 5.2.0
156
-	 *
157
-	 * @return array|false The test results. False if the auto-updates failed.
158
-	 */
159
-	public function test_if_failed_update() {
160
-		$failed = get_site_option( 'auto_core_update_failed' );
161
-
162
-		if ( ! $failed ) {
163
-			return false;
164
-		}
165
-
166
-		if ( ! empty( $failed['critical'] ) ) {
167
-			$description  = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.' );
168
-			$description .= ' ' . __( 'You would have received an email because of this.' );
169
-			$description .= ' ' . __( "When you've been able to update using the \"Update now\" button on Dashboard > Updates, we'll clear this error for future update attempts." );
170
-			$description .= ' ' . sprintf(
171
-				/* translators: %s: Code of error shown. */
172
-				__( 'The error code was %s.' ),
173
-				'<code>' . $failed['error_code'] . '</code>'
174
-			);
175
-			return array(
176
-				'description' => $description,
177
-				'severity'    => 'warning',
178
-			);
179
-		}
180
-
181
-		$description = __( 'A previous automatic background update could not occur.' );
182
-		if ( empty( $failed['retry'] ) ) {
183
-			$description .= ' ' . __( 'You would have received an email because of this.' );
184
-		}
185
-
186
-		$description .= ' ' . __( "We'll try again with the next release." );
187
-		$description .= ' ' . sprintf(
188
-			/* translators: %s: Code of error shown. */
189
-			__( 'The error code was %s.' ),
190
-			'<code>' . $failed['error_code'] . '</code>'
191
-		);
192
-		return array(
193
-			'description' => $description,
194
-			'severity'    => 'warning',
195
-		);
196
-	}
197
-
198
-	/**
199
-	 * Check if WordPress is controlled by a VCS (Git, Subversion etc).
200
-	 *
201
-	 * @since 5.2.0
202
-	 *
203
-	 * @return array The test results.
204
-	 */
205
-	public function test_vcs_abspath() {
206
-		$context_dirs = array( ABSPATH );
207
-		$vcs_dirs     = array( '.svn', '.git', '.hg', '.bzr' );
208
-		$check_dirs   = array();
209
-
210
-		foreach ( $context_dirs as $context_dir ) {
211
-			// Walk up from $context_dir to the root.
212
-			do {
213
-				$check_dirs[] = $context_dir;
214
-
215
-				// Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
216
-				if ( dirname( $context_dir ) === $context_dir ) {
217
-					break;
218
-				}
219
-
220
-				// Continue one level at a time.
221
-			} while ( $context_dir = dirname( $context_dir ) );
222
-		}
223
-
224
-		$check_dirs = array_unique( $check_dirs );
225
-
226
-		// Search all directories we've found for evidence of version control.
227
-		foreach ( $vcs_dirs as $vcs_dir ) {
228
-			foreach ( $check_dirs as $check_dir ) {
229
-				// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition,Squiz.PHP.DisallowMultipleAssignments
230
-				if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) {
231
-					break 2;
232
-				}
233
-			}
234
-		}
235
-
236
-		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
237
-		if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, ABSPATH ) ) {
238
-			return array(
239
-				'description' => sprintf(
240
-					/* translators: 1: Folder name. 2: Version control directory. 3: Filter name. */
241
-					__( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.' ),
242
-					'<code>' . $check_dir . '</code>',
243
-					"<code>$vcs_dir</code>",
244
-					'<code>automatic_updates_is_vcs_checkout</code>'
245
-				),
246
-				'severity'    => 'info',
247
-			);
248
-		}
249
-
250
-		if ( $checkout ) {
251
-			return array(
252
-				'description' => sprintf(
253
-					/* translators: 1: Folder name. 2: Version control directory. */
254
-					__( 'The folder %1$s was detected as being under version control (%2$s).' ),
255
-					'<code>' . $check_dir . '</code>',
256
-					"<code>$vcs_dir</code>"
257
-				),
258
-				'severity'    => 'warning',
259
-			);
260
-		}
261
-
262
-		return array(
263
-			'description' => __( 'No version control systems were detected.' ),
264
-			'severity'    => 'pass',
265
-		);
266
-	}
267
-
268
-	/**
269
-	 * Check if we can access files without providing credentials.
270
-	 *
271
-	 * @since 5.2.0
272
-	 *
273
-	 * @return array The test results.
274
-	 */
275
-	public function test_check_wp_filesystem_method() {
276
-		// Make sure the `request_filesystem_credentials()` function is available during our REST API call.
277
-		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
278
-			require_once ABSPATH . '/wp-admin/includes/file.php';
279
-		}
280
-
281
-		$skin    = new Automatic_Upgrader_Skin;
282
-		$success = $skin->request_filesystem_credentials( false, ABSPATH );
283
-
284
-		if ( ! $success ) {
285
-			$description  = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.' );
286
-			$description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)' );
287
-
288
-			return array(
289
-				'description' => $description,
290
-				'severity'    => 'fail',
291
-			);
292
-		}
293
-
294
-		return array(
295
-			'description' => __( 'Your installation of WordPress does not require FTP credentials to perform updates.' ),
296
-			'severity'    => 'pass',
297
-		);
298
-	}
299
-
300
-	/**
301
-	 * Check if core files are writable by the web user/group.
302
-	 *
303
-	 * @since 5.2.0
304
-	 *
305
-	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
306
-	 *
307
-	 * @return array|false The test results. False if they're not writeable.
308
-	 */
309
-	public function test_all_files_writable() {
310
-		global $wp_filesystem;
311
-
312
-		require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
313
-
314
-		$skin    = new Automatic_Upgrader_Skin;
315
-		$success = $skin->request_filesystem_credentials( false, ABSPATH );
316
-
317
-		if ( ! $success ) {
318
-			return false;
319
-		}
320
-
321
-		WP_Filesystem();
322
-
323
-		if ( 'direct' !== $wp_filesystem->method ) {
324
-			return false;
325
-		}
326
-
327
-		// Make sure the `get_core_checksums()` function is available during our REST API call.
328
-		if ( ! function_exists( 'get_core_checksums' ) ) {
329
-			require_once ABSPATH . '/wp-admin/includes/update.php';
330
-		}
331
-
332
-		$checksums = get_core_checksums( $wp_version, 'en_US' );
333
-		$dev       = ( false !== strpos( $wp_version, '-' ) );
334
-		// Get the last stable version's files and test against that.
335
-		if ( ! $checksums && $dev ) {
336
-			$checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
337
-		}
338
-
339
-		// There aren't always checksums for development releases, so just skip the test if we still can't find any.
340
-		if ( ! $checksums && $dev ) {
341
-			return false;
342
-		}
343
-
344
-		if ( ! $checksums ) {
345
-			$description = sprintf(
346
-				/* translators: %s: WordPress version. */
347
-				__( "Couldn't retrieve a list of the checksums for WordPress %s." ),
348
-				$wp_version
349
-			);
350
-			$description .= ' ' . __( 'This could mean that connections are failing to WordPress.org.' );
351
-			return array(
352
-				'description' => $description,
353
-				'severity'    => 'warning',
354
-			);
355
-		}
356
-
357
-		$unwritable_files = array();
358
-		foreach ( array_keys( $checksums ) as $file ) {
359
-			if ( 'wp-content' === substr( $file, 0, 10 ) ) {
360
-				continue;
361
-			}
362
-			if ( ! file_exists( ABSPATH . $file ) ) {
363
-				continue;
364
-			}
365
-			if ( ! is_writable( ABSPATH . $file ) ) {
366
-				$unwritable_files[] = $file;
367
-			}
368
-		}
369
-
370
-		if ( $unwritable_files ) {
371
-			if ( count( $unwritable_files ) > 20 ) {
372
-				$unwritable_files   = array_slice( $unwritable_files, 0, 20 );
373
-				$unwritable_files[] = '...';
374
-			}
375
-			return array(
376
-				'description' => __( 'Some files are not writable by WordPress:' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
377
-				'severity'    => 'fail',
378
-			);
379
-		} else {
380
-			return array(
381
-				'description' => __( 'All of your WordPress files are writable.' ),
382
-				'severity'    => 'pass',
383
-			);
384
-		}
385
-	}
386
-
387
-	/**
388
-	 * Check if the install is using a development branch and can use nightly packages.
389
-	 *
390
-	 * @since 5.2.0
391
-	 *
392
-	 * @return array|false The test results. False if it isn't a development version.
393
-	 */
394
-	public function test_accepts_dev_updates() {
395
-		require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
396
-		// Only for dev versions.
397
-		if ( false === strpos( $wp_version, '-' ) ) {
398
-			return false;
399
-		}
400
-
401
-		if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
402
-			return array(
403
-				'description' => sprintf(
404
-					/* translators: %s: Name of the constant used. */
405
-					__( 'WordPress development updates are blocked by the %s constant.' ),
406
-					'<code>WP_AUTO_UPDATE_CORE</code>'
407
-				),
408
-				'severity'    => 'fail',
409
-			);
410
-		}
411
-
412
-		/** This filter is documented in wp-admin/includes/class-core-upgrader.php */
413
-		if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
414
-			return array(
415
-				'description' => sprintf(
416
-					/* translators: %s: Name of the filter used. */
417
-					__( 'WordPress development updates are blocked by the %s filter.' ),
418
-					'<code>allow_dev_auto_core_updates</code>'
419
-				),
420
-				'severity'    => 'fail',
421
-			);
422
-		}
423
-	}
424
-
425
-	/**
426
-	 * Check if the site supports automatic minor updates.
427
-	 *
428
-	 * @since 5.2.0
429
-	 *
430
-	 * @return array The test results.
431
-	 */
432
-	public function test_accepts_minor_updates() {
433
-		if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
434
-			return array(
435
-				'description' => sprintf(
436
-					/* translators: %s: Name of the constant used. */
437
-					__( 'WordPress security and maintenance releases are blocked by %s.' ),
438
-					"<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
439
-				),
440
-				'severity'    => 'fail',
441
-			);
442
-		}
443
-
444
-		/** This filter is documented in wp-admin/includes/class-core-upgrader.php */
445
-		if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
446
-			return array(
447
-				'description' => sprintf(
448
-					/* translators: %s: Name of the filter used. */
449
-					__( 'WordPress security and maintenance releases are blocked by the %s filter.' ),
450
-					'<code>allow_minor_auto_core_updates</code>'
451
-				),
452
-				'severity'    => 'fail',
453
-			);
454
-		}
455
-	}
11
+    /**
12
+     * WP_Site_Health_Auto_Updates constructor.
13
+     *
14
+     * @since 5.2.0
15
+     */
16
+    public function __construct() {
17
+        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
18
+    }
19
+
20
+
21
+    /**
22
+     * Run tests to determine if auto-updates can run.
23
+     *
24
+     * @since 5.2.0
25
+     *
26
+     * @return array The test results.
27
+     */
28
+    public function run_tests() {
29
+        $tests = array(
30
+            $this->test_constants( 'WP_AUTO_UPDATE_CORE', array( true, 'beta', 'rc', 'development', 'branch-development', 'minor' ) ),
31
+            $this->test_wp_version_check_attached(),
32
+            $this->test_filters_automatic_updater_disabled(),
33
+            $this->test_wp_automatic_updates_disabled(),
34
+            $this->test_if_failed_update(),
35
+            $this->test_vcs_abspath(),
36
+            $this->test_check_wp_filesystem_method(),
37
+            $this->test_all_files_writable(),
38
+            $this->test_accepts_dev_updates(),
39
+            $this->test_accepts_minor_updates(),
40
+        );
41
+
42
+        $tests = array_filter( $tests );
43
+        $tests = array_map(
44
+            static function( $test ) {
45
+                $test = (object) $test;
46
+
47
+                if ( empty( $test->severity ) ) {
48
+                    $test->severity = 'warning';
49
+                }
50
+
51
+                return $test;
52
+            },
53
+            $tests
54
+        );
55
+
56
+        return $tests;
57
+    }
58
+
59
+    /**
60
+     * Test if auto-updates related constants are set correctly.
61
+     *
62
+     * @since 5.2.0
63
+     * @since 5.5.1 The `$value` parameter can accept an array.
64
+     *
65
+     * @param string $constant         The name of the constant to check.
66
+     * @param bool|string|array $value The value that the constant should be, if set,
67
+     *                                 or an array of acceptable values.
68
+     * @return array The test results.
69
+     */
70
+    public function test_constants( $constant, $value ) {
71
+        $acceptable_values = (array) $value;
72
+
73
+        if ( defined( $constant ) && ! in_array( constant( $constant ), $acceptable_values, true ) ) {
74
+            return array(
75
+                'description' => sprintf(
76
+                    /* translators: %s: Name of the constant used. */
77
+                    __( 'The %s constant is defined and enabled.' ),
78
+                    "<code>$constant</code>"
79
+                ),
80
+                'severity'    => 'fail',
81
+            );
82
+        }
83
+    }
84
+
85
+    /**
86
+     * Check if updates are intercepted by a filter.
87
+     *
88
+     * @since 5.2.0
89
+     *
90
+     * @return array The test results.
91
+     */
92
+    public function test_wp_version_check_attached() {
93
+        if ( ( ! is_multisite() || is_main_site() && is_network_admin() )
94
+            && ! has_filter( 'wp_version_check', 'wp_version_check' )
95
+        ) {
96
+            return array(
97
+                'description' => sprintf(
98
+                    /* translators: %s: Name of the filter used. */
99
+                    __( 'A plugin has prevented updates by disabling %s.' ),
100
+                    '<code>wp_version_check()</code>'
101
+                ),
102
+                'severity'    => 'fail',
103
+            );
104
+        }
105
+    }
106
+
107
+    /**
108
+     * Check if automatic updates are disabled by a filter.
109
+     *
110
+     * @since 5.2.0
111
+     *
112
+     * @return array The test results.
113
+     */
114
+    public function test_filters_automatic_updater_disabled() {
115
+        /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
116
+        if ( apply_filters( 'automatic_updater_disabled', false ) ) {
117
+            return array(
118
+                'description' => sprintf(
119
+                    /* translators: %s: Name of the filter used. */
120
+                    __( 'The %s filter is enabled.' ),
121
+                    '<code>automatic_updater_disabled</code>'
122
+                ),
123
+                'severity'    => 'fail',
124
+            );
125
+        }
126
+    }
127
+
128
+    /**
129
+     * Check if automatic updates are disabled.
130
+     *
131
+     * @since 5.3.0
132
+     *
133
+     * @return array|false The test results. False if auto-updates are enabled.
134
+     */
135
+    public function test_wp_automatic_updates_disabled() {
136
+        if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
137
+            require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
138
+        }
139
+
140
+        $auto_updates = new WP_Automatic_Updater();
141
+
142
+        if ( ! $auto_updates->is_disabled() ) {
143
+            return false;
144
+        }
145
+
146
+        return array(
147
+            'description' => __( 'All automatic updates are disabled.' ),
148
+            'severity'    => 'fail',
149
+        );
150
+    }
151
+
152
+    /**
153
+     * Check if automatic updates have tried to run, but failed, previously.
154
+     *
155
+     * @since 5.2.0
156
+     *
157
+     * @return array|false The test results. False if the auto-updates failed.
158
+     */
159
+    public function test_if_failed_update() {
160
+        $failed = get_site_option( 'auto_core_update_failed' );
161
+
162
+        if ( ! $failed ) {
163
+            return false;
164
+        }
165
+
166
+        if ( ! empty( $failed['critical'] ) ) {
167
+            $description  = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.' );
168
+            $description .= ' ' . __( 'You would have received an email because of this.' );
169
+            $description .= ' ' . __( "When you've been able to update using the \"Update now\" button on Dashboard > Updates, we'll clear this error for future update attempts." );
170
+            $description .= ' ' . sprintf(
171
+                /* translators: %s: Code of error shown. */
172
+                __( 'The error code was %s.' ),
173
+                '<code>' . $failed['error_code'] . '</code>'
174
+            );
175
+            return array(
176
+                'description' => $description,
177
+                'severity'    => 'warning',
178
+            );
179
+        }
180
+
181
+        $description = __( 'A previous automatic background update could not occur.' );
182
+        if ( empty( $failed['retry'] ) ) {
183
+            $description .= ' ' . __( 'You would have received an email because of this.' );
184
+        }
185
+
186
+        $description .= ' ' . __( "We'll try again with the next release." );
187
+        $description .= ' ' . sprintf(
188
+            /* translators: %s: Code of error shown. */
189
+            __( 'The error code was %s.' ),
190
+            '<code>' . $failed['error_code'] . '</code>'
191
+        );
192
+        return array(
193
+            'description' => $description,
194
+            'severity'    => 'warning',
195
+        );
196
+    }
197
+
198
+    /**
199
+     * Check if WordPress is controlled by a VCS (Git, Subversion etc).
200
+     *
201
+     * @since 5.2.0
202
+     *
203
+     * @return array The test results.
204
+     */
205
+    public function test_vcs_abspath() {
206
+        $context_dirs = array( ABSPATH );
207
+        $vcs_dirs     = array( '.svn', '.git', '.hg', '.bzr' );
208
+        $check_dirs   = array();
209
+
210
+        foreach ( $context_dirs as $context_dir ) {
211
+            // Walk up from $context_dir to the root.
212
+            do {
213
+                $check_dirs[] = $context_dir;
214
+
215
+                // Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
216
+                if ( dirname( $context_dir ) === $context_dir ) {
217
+                    break;
218
+                }
219
+
220
+                // Continue one level at a time.
221
+            } while ( $context_dir = dirname( $context_dir ) );
222
+        }
223
+
224
+        $check_dirs = array_unique( $check_dirs );
225
+
226
+        // Search all directories we've found for evidence of version control.
227
+        foreach ( $vcs_dirs as $vcs_dir ) {
228
+            foreach ( $check_dirs as $check_dir ) {
229
+                // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition,Squiz.PHP.DisallowMultipleAssignments
230
+                if ( $checkout = @is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" ) ) {
231
+                    break 2;
232
+                }
233
+            }
234
+        }
235
+
236
+        /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
237
+        if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, ABSPATH ) ) {
238
+            return array(
239
+                'description' => sprintf(
240
+                    /* translators: 1: Folder name. 2: Version control directory. 3: Filter name. */
241
+                    __( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.' ),
242
+                    '<code>' . $check_dir . '</code>',
243
+                    "<code>$vcs_dir</code>",
244
+                    '<code>automatic_updates_is_vcs_checkout</code>'
245
+                ),
246
+                'severity'    => 'info',
247
+            );
248
+        }
249
+
250
+        if ( $checkout ) {
251
+            return array(
252
+                'description' => sprintf(
253
+                    /* translators: 1: Folder name. 2: Version control directory. */
254
+                    __( 'The folder %1$s was detected as being under version control (%2$s).' ),
255
+                    '<code>' . $check_dir . '</code>',
256
+                    "<code>$vcs_dir</code>"
257
+                ),
258
+                'severity'    => 'warning',
259
+            );
260
+        }
261
+
262
+        return array(
263
+            'description' => __( 'No version control systems were detected.' ),
264
+            'severity'    => 'pass',
265
+        );
266
+    }
267
+
268
+    /**
269
+     * Check if we can access files without providing credentials.
270
+     *
271
+     * @since 5.2.0
272
+     *
273
+     * @return array The test results.
274
+     */
275
+    public function test_check_wp_filesystem_method() {
276
+        // Make sure the `request_filesystem_credentials()` function is available during our REST API call.
277
+        if ( ! function_exists( 'request_filesystem_credentials' ) ) {
278
+            require_once ABSPATH . '/wp-admin/includes/file.php';
279
+        }
280
+
281
+        $skin    = new Automatic_Upgrader_Skin;
282
+        $success = $skin->request_filesystem_credentials( false, ABSPATH );
283
+
284
+        if ( ! $success ) {
285
+            $description  = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.' );
286
+            $description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)' );
287
+
288
+            return array(
289
+                'description' => $description,
290
+                'severity'    => 'fail',
291
+            );
292
+        }
293
+
294
+        return array(
295
+            'description' => __( 'Your installation of WordPress does not require FTP credentials to perform updates.' ),
296
+            'severity'    => 'pass',
297
+        );
298
+    }
299
+
300
+    /**
301
+     * Check if core files are writable by the web user/group.
302
+     *
303
+     * @since 5.2.0
304
+     *
305
+     * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
306
+     *
307
+     * @return array|false The test results. False if they're not writeable.
308
+     */
309
+    public function test_all_files_writable() {
310
+        global $wp_filesystem;
311
+
312
+        require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
313
+
314
+        $skin    = new Automatic_Upgrader_Skin;
315
+        $success = $skin->request_filesystem_credentials( false, ABSPATH );
316
+
317
+        if ( ! $success ) {
318
+            return false;
319
+        }
320
+
321
+        WP_Filesystem();
322
+
323
+        if ( 'direct' !== $wp_filesystem->method ) {
324
+            return false;
325
+        }
326
+
327
+        // Make sure the `get_core_checksums()` function is available during our REST API call.
328
+        if ( ! function_exists( 'get_core_checksums' ) ) {
329
+            require_once ABSPATH . '/wp-admin/includes/update.php';
330
+        }
331
+
332
+        $checksums = get_core_checksums( $wp_version, 'en_US' );
333
+        $dev       = ( false !== strpos( $wp_version, '-' ) );
334
+        // Get the last stable version's files and test against that.
335
+        if ( ! $checksums && $dev ) {
336
+            $checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
337
+        }
338
+
339
+        // There aren't always checksums for development releases, so just skip the test if we still can't find any.
340
+        if ( ! $checksums && $dev ) {
341
+            return false;
342
+        }
343
+
344
+        if ( ! $checksums ) {
345
+            $description = sprintf(
346
+                /* translators: %s: WordPress version. */
347
+                __( "Couldn't retrieve a list of the checksums for WordPress %s." ),
348
+                $wp_version
349
+            );
350
+            $description .= ' ' . __( 'This could mean that connections are failing to WordPress.org.' );
351
+            return array(
352
+                'description' => $description,
353
+                'severity'    => 'warning',
354
+            );
355
+        }
356
+
357
+        $unwritable_files = array();
358
+        foreach ( array_keys( $checksums ) as $file ) {
359
+            if ( 'wp-content' === substr( $file, 0, 10 ) ) {
360
+                continue;
361
+            }
362
+            if ( ! file_exists( ABSPATH . $file ) ) {
363
+                continue;
364
+            }
365
+            if ( ! is_writable( ABSPATH . $file ) ) {
366
+                $unwritable_files[] = $file;
367
+            }
368
+        }
369
+
370
+        if ( $unwritable_files ) {
371
+            if ( count( $unwritable_files ) > 20 ) {
372
+                $unwritable_files   = array_slice( $unwritable_files, 0, 20 );
373
+                $unwritable_files[] = '...';
374
+            }
375
+            return array(
376
+                'description' => __( 'Some files are not writable by WordPress:' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
377
+                'severity'    => 'fail',
378
+            );
379
+        } else {
380
+            return array(
381
+                'description' => __( 'All of your WordPress files are writable.' ),
382
+                'severity'    => 'pass',
383
+            );
384
+        }
385
+    }
386
+
387
+    /**
388
+     * Check if the install is using a development branch and can use nightly packages.
389
+     *
390
+     * @since 5.2.0
391
+     *
392
+     * @return array|false The test results. False if it isn't a development version.
393
+     */
394
+    public function test_accepts_dev_updates() {
395
+        require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
396
+        // Only for dev versions.
397
+        if ( false === strpos( $wp_version, '-' ) ) {
398
+            return false;
399
+        }
400
+
401
+        if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
402
+            return array(
403
+                'description' => sprintf(
404
+                    /* translators: %s: Name of the constant used. */
405
+                    __( 'WordPress development updates are blocked by the %s constant.' ),
406
+                    '<code>WP_AUTO_UPDATE_CORE</code>'
407
+                ),
408
+                'severity'    => 'fail',
409
+            );
410
+        }
411
+
412
+        /** This filter is documented in wp-admin/includes/class-core-upgrader.php */
413
+        if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
414
+            return array(
415
+                'description' => sprintf(
416
+                    /* translators: %s: Name of the filter used. */
417
+                    __( 'WordPress development updates are blocked by the %s filter.' ),
418
+                    '<code>allow_dev_auto_core_updates</code>'
419
+                ),
420
+                'severity'    => 'fail',
421
+            );
422
+        }
423
+    }
424
+
425
+    /**
426
+     * Check if the site supports automatic minor updates.
427
+     *
428
+     * @since 5.2.0
429
+     *
430
+     * @return array The test results.
431
+     */
432
+    public function test_accepts_minor_updates() {
433
+        if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
434
+            return array(
435
+                'description' => sprintf(
436
+                    /* translators: %s: Name of the constant used. */
437
+                    __( 'WordPress security and maintenance releases are blocked by %s.' ),
438
+                    "<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
439
+                ),
440
+                'severity'    => 'fail',
441
+            );
442
+        }
443
+
444
+        /** This filter is documented in wp-admin/includes/class-core-upgrader.php */
445
+        if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
446
+            return array(
447
+                'description' => sprintf(
448
+                    /* translators: %s: Name of the filter used. */
449
+                    __( 'WordPress security and maintenance releases are blocked by the %s filter.' ),
450
+                    '<code>allow_minor_auto_core_updates</code>'
451
+                ),
452
+                'severity'    => 'fail',
453
+            );
454
+        }
455
+    }
456 456
 }
Please login to merge, or discard this patch.
brighty/wp-admin/includes/class-wp-plugin-install-list-table.php 1 patch
Indentation   +717 added lines, -717 removed lines patch added patch discarded remove patch
@@ -17,391 +17,391 @@  discard block
 block discarded – undo
17 17
  */
18 18
 class WP_Plugin_Install_List_Table extends WP_List_Table {
19 19
 
20
-	public $order   = 'ASC';
21
-	public $orderby = null;
22
-	public $groups  = array();
23
-
24
-	private $error;
25
-
26
-	/**
27
-	 * @return bool
28
-	 */
29
-	public function ajax_user_can() {
30
-		return current_user_can( 'install_plugins' );
31
-	}
32
-
33
-	/**
34
-	 * Return the list of known plugins.
35
-	 *
36
-	 * Uses the transient data from the updates API to determine the known
37
-	 * installed plugins.
38
-	 *
39
-	 * @since 4.9.0
40
-	 * @access protected
41
-	 *
42
-	 * @return array
43
-	 */
44
-	protected function get_installed_plugins() {
45
-		$plugins = array();
46
-
47
-		$plugin_info = get_site_transient( 'update_plugins' );
48
-		if ( isset( $plugin_info->no_update ) ) {
49
-			foreach ( $plugin_info->no_update as $plugin ) {
50
-				if ( isset( $plugin->slug ) ) {
51
-					$plugin->upgrade          = false;
52
-					$plugins[ $plugin->slug ] = $plugin;
53
-				}
54
-			}
55
-		}
56
-
57
-		if ( isset( $plugin_info->response ) ) {
58
-			foreach ( $plugin_info->response as $plugin ) {
59
-				if ( isset( $plugin->slug ) ) {
60
-					$plugin->upgrade          = true;
61
-					$plugins[ $plugin->slug ] = $plugin;
62
-				}
63
-			}
64
-		}
65
-
66
-		return $plugins;
67
-	}
68
-
69
-	/**
70
-	 * Return a list of slugs of installed plugins, if known.
71
-	 *
72
-	 * Uses the transient data from the updates API to determine the slugs of
73
-	 * known installed plugins. This might be better elsewhere, perhaps even
74
-	 * within get_plugins().
75
-	 *
76
-	 * @since 4.0.0
77
-	 *
78
-	 * @return array
79
-	 */
80
-	protected function get_installed_plugin_slugs() {
81
-		return array_keys( $this->get_installed_plugins() );
82
-	}
83
-
84
-	/**
85
-	 * @global array  $tabs
86
-	 * @global string $tab
87
-	 * @global int    $paged
88
-	 * @global string $type
89
-	 * @global string $term
90
-	 */
91
-	public function prepare_items() {
92
-		include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
93
-
94
-		global $tabs, $tab, $paged, $type, $term;
95
-
96
-		wp_reset_vars( array( 'tab' ) );
97
-
98
-		$paged = $this->get_pagenum();
99
-
100
-		$per_page = 36;
101
-
102
-		// These are the tabs which are shown on the page.
103
-		$tabs = array();
104
-
105
-		if ( 'search' === $tab ) {
106
-			$tabs['search'] = __( 'Search Results' );
107
-		}
108
-
109
-		if ( 'beta' === $tab || false !== strpos( get_bloginfo( 'version' ), '-' ) ) {
110
-			$tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
111
-		}
112
-
113
-		$tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
114
-		$tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
115
-		$tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
116
-		$tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );
117
-
118
-		if ( current_user_can( 'upload_plugins' ) ) {
119
-			// No longer a real tab. Here for filter compatibility.
120
-			// Gets skipped in get_views().
121
-			$tabs['upload'] = __( 'Upload Plugin' );
122
-		}
123
-
124
-		$nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.
125
-
126
-		/**
127
-		 * Filters the tabs shown on the Add Plugins screen.
128
-		 *
129
-		 * @since 2.7.0
130
-		 *
131
-		 * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include
132
-		 *                       'featured', 'popular', 'recommended', 'favorites', and 'upload'.
133
-		 */
134
-		$tabs = apply_filters( 'install_plugins_tabs', $tabs );
135
-
136
-		/**
137
-		 * Filters tabs not associated with a menu item on the Add Plugins screen.
138
-		 *
139
-		 * @since 2.7.0
140
-		 *
141
-		 * @param string[] $nonmenu_tabs The tabs that don't have a menu item on the Add Plugins screen.
142
-		 */
143
-		$nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs );
144
-
145
-		// If a non-valid menu tab has been selected, And it's not a non-menu action.
146
-		if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
147
-			$tab = key( $tabs );
148
-		}
149
-
150
-		$installed_plugins = $this->get_installed_plugins();
151
-
152
-		$args = array(
153
-			'page'     => $paged,
154
-			'per_page' => $per_page,
155
-			// Send the locale to the API so it can provide context-sensitive results.
156
-			'locale'   => get_user_locale(),
157
-		);
158
-
159
-		switch ( $tab ) {
160
-			case 'search':
161
-				$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
162
-				$term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
163
-
164
-				switch ( $type ) {
165
-					case 'tag':
166
-						$args['tag'] = sanitize_title_with_dashes( $term );
167
-						break;
168
-					case 'term':
169
-						$args['search'] = $term;
170
-						break;
171
-					case 'author':
172
-						$args['author'] = $term;
173
-						break;
174
-				}
175
-
176
-				break;
177
-
178
-			case 'featured':
179
-			case 'popular':
180
-			case 'new':
181
-			case 'beta':
182
-				$args['browse'] = $tab;
183
-				break;
184
-			case 'recommended':
185
-				$args['browse'] = $tab;
186
-				// Include the list of installed plugins so we can get relevant results.
187
-				$args['installed_plugins'] = array_keys( $installed_plugins );
188
-				break;
189
-
190
-			case 'favorites':
191
-				$action = 'save_wporg_username_' . get_current_user_id();
192
-				if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), $action ) ) {
193
-					$user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' );
194
-
195
-					// If the save url parameter is passed with a falsey value, don't save the favorite user.
196
-					if ( ! isset( $_GET['save'] ) || $_GET['save'] ) {
197
-						update_user_meta( get_current_user_id(), 'wporg_favorites', $user );
198
-					}
199
-				} else {
200
-					$user = get_user_option( 'wporg_favorites' );
201
-				}
202
-				if ( $user ) {
203
-					$args['user'] = $user;
204
-				} else {
205
-					$args = false;
206
-				}
207
-
208
-				add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 );
209
-				break;
210
-
211
-			default:
212
-				$args = false;
213
-				break;
214
-		}
215
-
216
-		/**
217
-		 * Filters API request arguments for each Add Plugins screen tab.
218
-		 *
219
-		 * The dynamic portion of the hook name, `$tab`, refers to the plugin install tabs.
220
-		 *
221
-		 * Possible hook names include:
222
-		 *
223
-		 *  - `install_plugins_table_api_args_favorites`
224
-		 *  - `install_plugins_table_api_args_featured`
225
-		 *  - `install_plugins_table_api_args_popular`
226
-		 *  - `install_plugins_table_api_args_recommended`
227
-		 *  - `install_plugins_table_api_args_upload`
228
-		 *  - `install_plugins_table_api_args_search`
229
-		 *  - `install_plugins_table_api_args_beta`
230
-		 *
231
-		 * @since 3.7.0
232
-		 *
233
-		 * @param array|false $args Plugin install API arguments.
234
-		 */
235
-		$args = apply_filters( "install_plugins_table_api_args_{$tab}", $args );
236
-
237
-		if ( ! $args ) {
238
-			return;
239
-		}
240
-
241
-		$api = plugins_api( 'query_plugins', $args );
242
-
243
-		if ( is_wp_error( $api ) ) {
244
-			$this->error = $api;
245
-			return;
246
-		}
247
-
248
-		$this->items = $api->plugins;
249
-
250
-		if ( $this->orderby ) {
251
-			uasort( $this->items, array( $this, 'order_callback' ) );
252
-		}
253
-
254
-		$this->set_pagination_args(
255
-			array(
256
-				'total_items' => $api->info['results'],
257
-				'per_page'    => $args['per_page'],
258
-			)
259
-		);
260
-
261
-		if ( isset( $api->info['groups'] ) ) {
262
-			$this->groups = $api->info['groups'];
263
-		}
264
-
265
-		if ( $installed_plugins ) {
266
-			$js_plugins = array_fill_keys(
267
-				array( 'all', 'search', 'active', 'inactive', 'recently_activated', 'mustuse', 'dropins' ),
268
-				array()
269
-			);
270
-
271
-			$js_plugins['all'] = array_values( wp_list_pluck( $installed_plugins, 'plugin' ) );
272
-			$upgrade_plugins   = wp_filter_object_list( $installed_plugins, array( 'upgrade' => true ), 'and', 'plugin' );
273
-
274
-			if ( $upgrade_plugins ) {
275
-				$js_plugins['upgrade'] = array_values( $upgrade_plugins );
276
-			}
277
-
278
-			wp_localize_script(
279
-				'updates',
280
-				'_wpUpdatesItemCounts',
281
-				array(
282
-					'plugins' => $js_plugins,
283
-					'totals'  => wp_get_update_data(),
284
-				)
285
-			);
286
-		}
287
-	}
288
-
289
-	/**
290
-	 */
291
-	public function no_items() {
292
-		if ( isset( $this->error ) ) { ?>
20
+    public $order   = 'ASC';
21
+    public $orderby = null;
22
+    public $groups  = array();
23
+
24
+    private $error;
25
+
26
+    /**
27
+     * @return bool
28
+     */
29
+    public function ajax_user_can() {
30
+        return current_user_can( 'install_plugins' );
31
+    }
32
+
33
+    /**
34
+     * Return the list of known plugins.
35
+     *
36
+     * Uses the transient data from the updates API to determine the known
37
+     * installed plugins.
38
+     *
39
+     * @since 4.9.0
40
+     * @access protected
41
+     *
42
+     * @return array
43
+     */
44
+    protected function get_installed_plugins() {
45
+        $plugins = array();
46
+
47
+        $plugin_info = get_site_transient( 'update_plugins' );
48
+        if ( isset( $plugin_info->no_update ) ) {
49
+            foreach ( $plugin_info->no_update as $plugin ) {
50
+                if ( isset( $plugin->slug ) ) {
51
+                    $plugin->upgrade          = false;
52
+                    $plugins[ $plugin->slug ] = $plugin;
53
+                }
54
+            }
55
+        }
56
+
57
+        if ( isset( $plugin_info->response ) ) {
58
+            foreach ( $plugin_info->response as $plugin ) {
59
+                if ( isset( $plugin->slug ) ) {
60
+                    $plugin->upgrade          = true;
61
+                    $plugins[ $plugin->slug ] = $plugin;
62
+                }
63
+            }
64
+        }
65
+
66
+        return $plugins;
67
+    }
68
+
69
+    /**
70
+     * Return a list of slugs of installed plugins, if known.
71
+     *
72
+     * Uses the transient data from the updates API to determine the slugs of
73
+     * known installed plugins. This might be better elsewhere, perhaps even
74
+     * within get_plugins().
75
+     *
76
+     * @since 4.0.0
77
+     *
78
+     * @return array
79
+     */
80
+    protected function get_installed_plugin_slugs() {
81
+        return array_keys( $this->get_installed_plugins() );
82
+    }
83
+
84
+    /**
85
+     * @global array  $tabs
86
+     * @global string $tab
87
+     * @global int    $paged
88
+     * @global string $type
89
+     * @global string $term
90
+     */
91
+    public function prepare_items() {
92
+        include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
93
+
94
+        global $tabs, $tab, $paged, $type, $term;
95
+
96
+        wp_reset_vars( array( 'tab' ) );
97
+
98
+        $paged = $this->get_pagenum();
99
+
100
+        $per_page = 36;
101
+
102
+        // These are the tabs which are shown on the page.
103
+        $tabs = array();
104
+
105
+        if ( 'search' === $tab ) {
106
+            $tabs['search'] = __( 'Search Results' );
107
+        }
108
+
109
+        if ( 'beta' === $tab || false !== strpos( get_bloginfo( 'version' ), '-' ) ) {
110
+            $tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
111
+        }
112
+
113
+        $tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
114
+        $tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
115
+        $tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
116
+        $tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );
117
+
118
+        if ( current_user_can( 'upload_plugins' ) ) {
119
+            // No longer a real tab. Here for filter compatibility.
120
+            // Gets skipped in get_views().
121
+            $tabs['upload'] = __( 'Upload Plugin' );
122
+        }
123
+
124
+        $nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.
125
+
126
+        /**
127
+         * Filters the tabs shown on the Add Plugins screen.
128
+         *
129
+         * @since 2.7.0
130
+         *
131
+         * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include
132
+         *                       'featured', 'popular', 'recommended', 'favorites', and 'upload'.
133
+         */
134
+        $tabs = apply_filters( 'install_plugins_tabs', $tabs );
135
+
136
+        /**
137
+         * Filters tabs not associated with a menu item on the Add Plugins screen.
138
+         *
139
+         * @since 2.7.0
140
+         *
141
+         * @param string[] $nonmenu_tabs The tabs that don't have a menu item on the Add Plugins screen.
142
+         */
143
+        $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs );
144
+
145
+        // If a non-valid menu tab has been selected, And it's not a non-menu action.
146
+        if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
147
+            $tab = key( $tabs );
148
+        }
149
+
150
+        $installed_plugins = $this->get_installed_plugins();
151
+
152
+        $args = array(
153
+            'page'     => $paged,
154
+            'per_page' => $per_page,
155
+            // Send the locale to the API so it can provide context-sensitive results.
156
+            'locale'   => get_user_locale(),
157
+        );
158
+
159
+        switch ( $tab ) {
160
+            case 'search':
161
+                $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
162
+                $term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
163
+
164
+                switch ( $type ) {
165
+                    case 'tag':
166
+                        $args['tag'] = sanitize_title_with_dashes( $term );
167
+                        break;
168
+                    case 'term':
169
+                        $args['search'] = $term;
170
+                        break;
171
+                    case 'author':
172
+                        $args['author'] = $term;
173
+                        break;
174
+                }
175
+
176
+                break;
177
+
178
+            case 'featured':
179
+            case 'popular':
180
+            case 'new':
181
+            case 'beta':
182
+                $args['browse'] = $tab;
183
+                break;
184
+            case 'recommended':
185
+                $args['browse'] = $tab;
186
+                // Include the list of installed plugins so we can get relevant results.
187
+                $args['installed_plugins'] = array_keys( $installed_plugins );
188
+                break;
189
+
190
+            case 'favorites':
191
+                $action = 'save_wporg_username_' . get_current_user_id();
192
+                if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), $action ) ) {
193
+                    $user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' );
194
+
195
+                    // If the save url parameter is passed with a falsey value, don't save the favorite user.
196
+                    if ( ! isset( $_GET['save'] ) || $_GET['save'] ) {
197
+                        update_user_meta( get_current_user_id(), 'wporg_favorites', $user );
198
+                    }
199
+                } else {
200
+                    $user = get_user_option( 'wporg_favorites' );
201
+                }
202
+                if ( $user ) {
203
+                    $args['user'] = $user;
204
+                } else {
205
+                    $args = false;
206
+                }
207
+
208
+                add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 );
209
+                break;
210
+
211
+            default:
212
+                $args = false;
213
+                break;
214
+        }
215
+
216
+        /**
217
+         * Filters API request arguments for each Add Plugins screen tab.
218
+         *
219
+         * The dynamic portion of the hook name, `$tab`, refers to the plugin install tabs.
220
+         *
221
+         * Possible hook names include:
222
+         *
223
+         *  - `install_plugins_table_api_args_favorites`
224
+         *  - `install_plugins_table_api_args_featured`
225
+         *  - `install_plugins_table_api_args_popular`
226
+         *  - `install_plugins_table_api_args_recommended`
227
+         *  - `install_plugins_table_api_args_upload`
228
+         *  - `install_plugins_table_api_args_search`
229
+         *  - `install_plugins_table_api_args_beta`
230
+         *
231
+         * @since 3.7.0
232
+         *
233
+         * @param array|false $args Plugin install API arguments.
234
+         */
235
+        $args = apply_filters( "install_plugins_table_api_args_{$tab}", $args );
236
+
237
+        if ( ! $args ) {
238
+            return;
239
+        }
240
+
241
+        $api = plugins_api( 'query_plugins', $args );
242
+
243
+        if ( is_wp_error( $api ) ) {
244
+            $this->error = $api;
245
+            return;
246
+        }
247
+
248
+        $this->items = $api->plugins;
249
+
250
+        if ( $this->orderby ) {
251
+            uasort( $this->items, array( $this, 'order_callback' ) );
252
+        }
253
+
254
+        $this->set_pagination_args(
255
+            array(
256
+                'total_items' => $api->info['results'],
257
+                'per_page'    => $args['per_page'],
258
+            )
259
+        );
260
+
261
+        if ( isset( $api->info['groups'] ) ) {
262
+            $this->groups = $api->info['groups'];
263
+        }
264
+
265
+        if ( $installed_plugins ) {
266
+            $js_plugins = array_fill_keys(
267
+                array( 'all', 'search', 'active', 'inactive', 'recently_activated', 'mustuse', 'dropins' ),
268
+                array()
269
+            );
270
+
271
+            $js_plugins['all'] = array_values( wp_list_pluck( $installed_plugins, 'plugin' ) );
272
+            $upgrade_plugins   = wp_filter_object_list( $installed_plugins, array( 'upgrade' => true ), 'and', 'plugin' );
273
+
274
+            if ( $upgrade_plugins ) {
275
+                $js_plugins['upgrade'] = array_values( $upgrade_plugins );
276
+            }
277
+
278
+            wp_localize_script(
279
+                'updates',
280
+                '_wpUpdatesItemCounts',
281
+                array(
282
+                    'plugins' => $js_plugins,
283
+                    'totals'  => wp_get_update_data(),
284
+                )
285
+            );
286
+        }
287
+    }
288
+
289
+    /**
290
+     */
291
+    public function no_items() {
292
+        if ( isset( $this->error ) ) { ?>
293 293
 			<div class="inline error"><p><?php echo $this->error->get_error_message(); ?></p>
294 294
 				<p class="hide-if-no-js"><button class="button try-again"><?php _e( 'Try Again' ); ?></button></p>
295 295
 			</div>
296 296
 		<?php } else { ?>
297 297
 			<div class="no-plugin-results"><?php _e( 'No plugins found. Try a different search.' ); ?></div>
298 298
 			<?php
299
-		}
300
-	}
301
-
302
-	/**
303
-	 * @global array $tabs
304
-	 * @global string $tab
305
-	 *
306
-	 * @return array
307
-	 */
308
-	protected function get_views() {
309
-		global $tabs, $tab;
310
-
311
-		$display_tabs = array();
312
-		foreach ( (array) $tabs as $action => $text ) {
313
-			$current_link_attributes                     = ( $action === $tab ) ? ' class="current" aria-current="page"' : '';
314
-			$href                                        = self_admin_url( 'plugin-install.php?tab=' . $action );
315
-			$display_tabs[ 'plugin-install-' . $action ] = "<a href='$href'$current_link_attributes>$text</a>";
316
-		}
317
-		// No longer a real tab.
318
-		unset( $display_tabs['plugin-install-upload'] );
319
-
320
-		return $display_tabs;
321
-	}
322
-
323
-	/**
324
-	 * Override parent views so we can use the filter bar display.
325
-	 */
326
-	public function views() {
327
-		$views = $this->get_views();
328
-
329
-		/** This filter is documented in wp-admin/inclues/class-wp-list-table.php */
330
-		$views = apply_filters( "views_{$this->screen->id}", $views );
331
-
332
-		$this->screen->render_screen_reader_content( 'heading_views' );
333
-		?>
299
+        }
300
+    }
301
+
302
+    /**
303
+     * @global array $tabs
304
+     * @global string $tab
305
+     *
306
+     * @return array
307
+     */
308
+    protected function get_views() {
309
+        global $tabs, $tab;
310
+
311
+        $display_tabs = array();
312
+        foreach ( (array) $tabs as $action => $text ) {
313
+            $current_link_attributes                     = ( $action === $tab ) ? ' class="current" aria-current="page"' : '';
314
+            $href                                        = self_admin_url( 'plugin-install.php?tab=' . $action );
315
+            $display_tabs[ 'plugin-install-' . $action ] = "<a href='$href'$current_link_attributes>$text</a>";
316
+        }
317
+        // No longer a real tab.
318
+        unset( $display_tabs['plugin-install-upload'] );
319
+
320
+        return $display_tabs;
321
+    }
322
+
323
+    /**
324
+     * Override parent views so we can use the filter bar display.
325
+     */
326
+    public function views() {
327
+        $views = $this->get_views();
328
+
329
+        /** This filter is documented in wp-admin/inclues/class-wp-list-table.php */
330
+        $views = apply_filters( "views_{$this->screen->id}", $views );
331
+
332
+        $this->screen->render_screen_reader_content( 'heading_views' );
333
+        ?>
334 334
 <div class="wp-filter">
335 335
 	<ul class="filter-links">
336 336
 		<?php
337
-		if ( ! empty( $views ) ) {
338
-			foreach ( $views as $class => $view ) {
339
-				$views[ $class ] = "\t<li class='$class'>$view";
340
-			}
341
-			echo implode( " </li>\n", $views ) . "</li>\n";
342
-		}
343
-		?>
337
+        if ( ! empty( $views ) ) {
338
+            foreach ( $views as $class => $view ) {
339
+                $views[ $class ] = "\t<li class='$class'>$view";
340
+            }
341
+            echo implode( " </li>\n", $views ) . "</li>\n";
342
+        }
343
+        ?>
344 344
 	</ul>
345 345
 
346 346
 		<?php install_search_form(); ?>
347 347
 </div>
348 348
 		<?php
349
-	}
349
+    }
350 350
 
351
-	/**
352
-	 * Displays the plugin install table.
353
-	 *
354
-	 * Overrides the parent display() method to provide a different container.
355
-	 *
356
-	 * @since 4.0.0
357
-	 */
358
-	public function display() {
359
-		$singular = $this->_args['singular'];
351
+    /**
352
+     * Displays the plugin install table.
353
+     *
354
+     * Overrides the parent display() method to provide a different container.
355
+     *
356
+     * @since 4.0.0
357
+     */
358
+    public function display() {
359
+        $singular = $this->_args['singular'];
360 360
 
361
-		$data_attr = '';
361
+        $data_attr = '';
362 362
 
363
-		if ( $singular ) {
364
-			$data_attr = " data-wp-lists='list:$singular'";
365
-		}
363
+        if ( $singular ) {
364
+            $data_attr = " data-wp-lists='list:$singular'";
365
+        }
366 366
 
367
-		$this->display_tablenav( 'top' );
367
+        $this->display_tablenav( 'top' );
368 368
 
369
-		?>
369
+        ?>
370 370
 <div class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
371 371
 		<?php
372
-		$this->screen->render_screen_reader_content( 'heading_list' );
373
-		?>
372
+        $this->screen->render_screen_reader_content( 'heading_list' );
373
+        ?>
374 374
 	<div id="the-list"<?php echo $data_attr; ?>>
375 375
 		<?php $this->display_rows_or_placeholder(); ?>
376 376
 	</div>
377 377
 </div>
378 378
 		<?php
379
-		$this->display_tablenav( 'bottom' );
380
-	}
381
-
382
-	/**
383
-	 * @global string $tab
384
-	 *
385
-	 * @param string $which
386
-	 */
387
-	protected function display_tablenav( $which ) {
388
-		if ( 'featured' === $GLOBALS['tab'] ) {
389
-			return;
390
-		}
391
-
392
-		if ( 'top' === $which ) {
393
-			wp_referer_field();
394
-			?>
379
+        $this->display_tablenav( 'bottom' );
380
+    }
381
+
382
+    /**
383
+     * @global string $tab
384
+     *
385
+     * @param string $which
386
+     */
387
+    protected function display_tablenav( $which ) {
388
+        if ( 'featured' === $GLOBALS['tab'] ) {
389
+            return;
390
+        }
391
+
392
+        if ( 'top' === $which ) {
393
+            wp_referer_field();
394
+            ?>
395 395
 			<div class="tablenav top">
396 396
 				<div class="alignleft actions">
397 397
 					<?php
398
-					/**
399
-					 * Fires before the Plugin Install table header pagination is displayed.
400
-					 *
401
-					 * @since 2.7.0
402
-					 */
403
-					do_action( 'install_plugins_table_header' );
404
-					?>
398
+                    /**
399
+                     * Fires before the Plugin Install table header pagination is displayed.
400
+                     *
401
+                     * @since 2.7.0
402
+                     */
403
+                    do_action( 'install_plugins_table_header' );
404
+                    ?>
405 405
 				</div>
406 406
 				<?php $this->pagination( $which ); ?>
407 407
 				<br class="clear" />
@@ -412,325 +412,325 @@  discard block
 block discarded – undo
412 412
 				<br class="clear" />
413 413
 			</div>
414 414
 			<?php
415
-		}
416
-	}
417
-
418
-	/**
419
-	 * @return array
420
-	 */
421
-	protected function get_table_classes() {
422
-		return array( 'widefat', $this->_args['plural'] );
423
-	}
424
-
425
-	/**
426
-	 * @return array
427
-	 */
428
-	public function get_columns() {
429
-		return array();
430
-	}
431
-
432
-	/**
433
-	 * @param object $plugin_a
434
-	 * @param object $plugin_b
435
-	 * @return int
436
-	 */
437
-	private function order_callback( $plugin_a, $plugin_b ) {
438
-		$orderby = $this->orderby;
439
-		if ( ! isset( $plugin_a->$orderby, $plugin_b->$orderby ) ) {
440
-			return 0;
441
-		}
442
-
443
-		$a = $plugin_a->$orderby;
444
-		$b = $plugin_b->$orderby;
445
-
446
-		if ( $a === $b ) {
447
-			return 0;
448
-		}
449
-
450
-		if ( 'DESC' === $this->order ) {
451
-			return ( $a < $b ) ? 1 : -1;
452
-		} else {
453
-			return ( $a < $b ) ? -1 : 1;
454
-		}
455
-	}
456
-
457
-	public function display_rows() {
458
-		$plugins_allowedtags = array(
459
-			'a'       => array(
460
-				'href'   => array(),
461
-				'title'  => array(),
462
-				'target' => array(),
463
-			),
464
-			'abbr'    => array( 'title' => array() ),
465
-			'acronym' => array( 'title' => array() ),
466
-			'code'    => array(),
467
-			'pre'     => array(),
468
-			'em'      => array(),
469
-			'strong'  => array(),
470
-			'ul'      => array(),
471
-			'ol'      => array(),
472
-			'li'      => array(),
473
-			'p'       => array(),
474
-			'br'      => array(),
475
-		);
476
-
477
-		$plugins_group_titles = array(
478
-			'Performance' => _x( 'Performance', 'Plugin installer group title' ),
479
-			'Social'      => _x( 'Social', 'Plugin installer group title' ),
480
-			'Tools'       => _x( 'Tools', 'Plugin installer group title' ),
481
-		);
482
-
483
-		$group = null;
484
-
485
-		foreach ( (array) $this->items as $plugin ) {
486
-			if ( is_object( $plugin ) ) {
487
-				$plugin = (array) $plugin;
488
-			}
489
-
490
-			// Display the group heading if there is one.
491
-			if ( isset( $plugin['group'] ) && $plugin['group'] !== $group ) {
492
-				if ( isset( $this->groups[ $plugin['group'] ] ) ) {
493
-					$group_name = $this->groups[ $plugin['group'] ];
494
-					if ( isset( $plugins_group_titles[ $group_name ] ) ) {
495
-						$group_name = $plugins_group_titles[ $group_name ];
496
-					}
497
-				} else {
498
-					$group_name = $plugin['group'];
499
-				}
500
-
501
-				// Starting a new group, close off the divs of the last one.
502
-				if ( ! empty( $group ) ) {
503
-					echo '</div></div>';
504
-				}
505
-
506
-				echo '<div class="plugin-group"><h3>' . esc_html( $group_name ) . '</h3>';
507
-				// Needs an extra wrapping div for nth-child selectors to work.
508
-				echo '<div class="plugin-items">';
509
-
510
-				$group = $plugin['group'];
511
-			}
512
-
513
-			$title = wp_kses( $plugin['name'], $plugins_allowedtags );
514
-
515
-			// Remove any HTML from the description.
516
-			$description = strip_tags( $plugin['short_description'] );
517
-
518
-			/**
519
-			 * Filters the plugin card description on the Add Plugins screen.
520
-			 *
521
-			 * @since 6.0.0
522
-			 *
523
-			 * @param string $description Plugin card description.
524
-			 * @param array  $plugin      An array of plugin data. See {@see plugins_api()}
525
-			 *                            for the list of possible values.
526
-			 */
527
-			$description = apply_filters( 'plugin_install_description', $description, $plugin );
528
-
529
-			$version = wp_kses( $plugin['version'], $plugins_allowedtags );
530
-
531
-			$name = strip_tags( $title . ' ' . $version );
532
-
533
-			$author = wp_kses( $plugin['author'], $plugins_allowedtags );
534
-			if ( ! empty( $author ) ) {
535
-				/* translators: %s: Plugin author. */
536
-				$author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>';
537
-			}
538
-
539
-			$requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null;
540
-			$requires_wp  = isset( $plugin['requires'] ) ? $plugin['requires'] : null;
541
-
542
-			$compatible_php = is_php_version_compatible( $requires_php );
543
-			$compatible_wp  = is_wp_version_compatible( $requires_wp );
544
-			$tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
545
-
546
-			$action_links = array();
547
-
548
-			if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) {
549
-				$status = install_plugin_install_status( $plugin );
550
-
551
-				switch ( $status['status'] ) {
552
-					case 'install':
553
-						if ( $status['url'] ) {
554
-							if ( $compatible_php && $compatible_wp ) {
555
-								$action_links[] = sprintf(
556
-									'<a class="install-now button" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
557
-									esc_attr( $plugin['slug'] ),
558
-									esc_url( $status['url'] ),
559
-									/* translators: %s: Plugin name and version. */
560
-									esc_attr( sprintf( _x( 'Install %s now', 'plugin' ), $name ) ),
561
-									esc_attr( $name ),
562
-									__( 'Install Now' )
563
-								);
564
-							} else {
565
-								$action_links[] = sprintf(
566
-									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
567
-									_x( 'Cannot Install', 'plugin' )
568
-								);
569
-							}
570
-						}
571
-						break;
572
-
573
-					case 'update_available':
574
-						if ( $status['url'] ) {
575
-							if ( $compatible_php && $compatible_wp ) {
576
-								$action_links[] = sprintf(
577
-									'<a class="update-now button aria-button-if-js" data-plugin="%s" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
578
-									esc_attr( $status['file'] ),
579
-									esc_attr( $plugin['slug'] ),
580
-									esc_url( $status['url'] ),
581
-									/* translators: %s: Plugin name and version. */
582
-									esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $name ) ),
583
-									esc_attr( $name ),
584
-									__( 'Update Now' )
585
-								);
586
-							} else {
587
-								$action_links[] = sprintf(
588
-									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
589
-									_x( 'Cannot Update', 'plugin' )
590
-								);
591
-							}
592
-						}
593
-						break;
594
-
595
-					case 'latest_installed':
596
-					case 'newer_installed':
597
-						if ( is_plugin_active( $status['file'] ) ) {
598
-							$action_links[] = sprintf(
599
-								'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
600
-								_x( 'Active', 'plugin' )
601
-							);
602
-						} elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
603
-							if ( $compatible_php && $compatible_wp ) {
604
-								$button_text = __( 'Activate' );
605
-								/* translators: %s: Plugin name. */
606
-								$button_label = _x( 'Activate %s', 'plugin' );
607
-								$activate_url = add_query_arg(
608
-									array(
609
-										'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ),
610
-										'action'   => 'activate',
611
-										'plugin'   => $status['file'],
612
-									),
613
-									network_admin_url( 'plugins.php' )
614
-								);
615
-
616
-								if ( is_network_admin() ) {
617
-									$button_text = __( 'Network Activate' );
618
-									/* translators: %s: Plugin name. */
619
-									$button_label = _x( 'Network Activate %s', 'plugin' );
620
-									$activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url );
621
-								}
622
-
623
-								$action_links[] = sprintf(
624
-									'<a href="%1$s" class="button activate-now" aria-label="%2$s">%3$s</a>',
625
-									esc_url( $activate_url ),
626
-									esc_attr( sprintf( $button_label, $plugin['name'] ) ),
627
-									$button_text
628
-								);
629
-							} else {
630
-								$action_links[] = sprintf(
631
-									'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
632
-									_x( 'Cannot Activate', 'plugin' )
633
-								);
634
-							}
635
-						} else {
636
-							$action_links[] = sprintf(
637
-								'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
638
-								_x( 'Installed', 'plugin' )
639
-							);
640
-						}
641
-						break;
642
-				}
643
-			}
644
-
645
-			$details_link = self_admin_url(
646
-				'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
647
-				'&amp;TB_iframe=true&amp;width=600&amp;height=550'
648
-			);
649
-
650
-			$action_links[] = sprintf(
651
-				'<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
652
-				esc_url( $details_link ),
653
-				/* translators: %s: Plugin name and version. */
654
-				esc_attr( sprintf( __( 'More information about %s' ), $name ) ),
655
-				esc_attr( $name ),
656
-				__( 'More Details' )
657
-			);
658
-
659
-			if ( ! empty( $plugin['icons']['svg'] ) ) {
660
-				$plugin_icon_url = $plugin['icons']['svg'];
661
-			} elseif ( ! empty( $plugin['icons']['2x'] ) ) {
662
-				$plugin_icon_url = $plugin['icons']['2x'];
663
-			} elseif ( ! empty( $plugin['icons']['1x'] ) ) {
664
-				$plugin_icon_url = $plugin['icons']['1x'];
665
-			} else {
666
-				$plugin_icon_url = $plugin['icons']['default'];
667
-			}
668
-
669
-			/**
670
-			 * Filters the install action links for a plugin.
671
-			 *
672
-			 * @since 2.7.0
673
-			 *
674
-			 * @param string[] $action_links An array of plugin action links.
675
-			 *                               Defaults are links to Details and Install Now.
676
-			 * @param array    $plugin       An array of plugin data. See {@see plugins_api()}
677
-			 *                               for the list of possible values.
678
-			 */
679
-			$action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin );
680
-
681
-			$last_updated_timestamp = strtotime( $plugin['last_updated'] );
682
-			?>
415
+        }
416
+    }
417
+
418
+    /**
419
+     * @return array
420
+     */
421
+    protected function get_table_classes() {
422
+        return array( 'widefat', $this->_args['plural'] );
423
+    }
424
+
425
+    /**
426
+     * @return array
427
+     */
428
+    public function get_columns() {
429
+        return array();
430
+    }
431
+
432
+    /**
433
+     * @param object $plugin_a
434
+     * @param object $plugin_b
435
+     * @return int
436
+     */
437
+    private function order_callback( $plugin_a, $plugin_b ) {
438
+        $orderby = $this->orderby;
439
+        if ( ! isset( $plugin_a->$orderby, $plugin_b->$orderby ) ) {
440
+            return 0;
441
+        }
442
+
443
+        $a = $plugin_a->$orderby;
444
+        $b = $plugin_b->$orderby;
445
+
446
+        if ( $a === $b ) {
447
+            return 0;
448
+        }
449
+
450
+        if ( 'DESC' === $this->order ) {
451
+            return ( $a < $b ) ? 1 : -1;
452
+        } else {
453
+            return ( $a < $b ) ? -1 : 1;
454
+        }
455
+    }
456
+
457
+    public function display_rows() {
458
+        $plugins_allowedtags = array(
459
+            'a'       => array(
460
+                'href'   => array(),
461
+                'title'  => array(),
462
+                'target' => array(),
463
+            ),
464
+            'abbr'    => array( 'title' => array() ),
465
+            'acronym' => array( 'title' => array() ),
466
+            'code'    => array(),
467
+            'pre'     => array(),
468
+            'em'      => array(),
469
+            'strong'  => array(),
470
+            'ul'      => array(),
471
+            'ol'      => array(),
472
+            'li'      => array(),
473
+            'p'       => array(),
474
+            'br'      => array(),
475
+        );
476
+
477
+        $plugins_group_titles = array(
478
+            'Performance' => _x( 'Performance', 'Plugin installer group title' ),
479
+            'Social'      => _x( 'Social', 'Plugin installer group title' ),
480
+            'Tools'       => _x( 'Tools', 'Plugin installer group title' ),
481
+        );
482
+
483
+        $group = null;
484
+
485
+        foreach ( (array) $this->items as $plugin ) {
486
+            if ( is_object( $plugin ) ) {
487
+                $plugin = (array) $plugin;
488
+            }
489
+
490
+            // Display the group heading if there is one.
491
+            if ( isset( $plugin['group'] ) && $plugin['group'] !== $group ) {
492
+                if ( isset( $this->groups[ $plugin['group'] ] ) ) {
493
+                    $group_name = $this->groups[ $plugin['group'] ];
494
+                    if ( isset( $plugins_group_titles[ $group_name ] ) ) {
495
+                        $group_name = $plugins_group_titles[ $group_name ];
496
+                    }
497
+                } else {
498
+                    $group_name = $plugin['group'];
499
+                }
500
+
501
+                // Starting a new group, close off the divs of the last one.
502
+                if ( ! empty( $group ) ) {
503
+                    echo '</div></div>';
504
+                }
505
+
506
+                echo '<div class="plugin-group"><h3>' . esc_html( $group_name ) . '</h3>';
507
+                // Needs an extra wrapping div for nth-child selectors to work.
508
+                echo '<div class="plugin-items">';
509
+
510
+                $group = $plugin['group'];
511
+            }
512
+
513
+            $title = wp_kses( $plugin['name'], $plugins_allowedtags );
514
+
515
+            // Remove any HTML from the description.
516
+            $description = strip_tags( $plugin['short_description'] );
517
+
518
+            /**
519
+             * Filters the plugin card description on the Add Plugins screen.
520
+             *
521
+             * @since 6.0.0
522
+             *
523
+             * @param string $description Plugin card description.
524
+             * @param array  $plugin      An array of plugin data. See {@see plugins_api()}
525
+             *                            for the list of possible values.
526
+             */
527
+            $description = apply_filters( 'plugin_install_description', $description, $plugin );
528
+
529
+            $version = wp_kses( $plugin['version'], $plugins_allowedtags );
530
+
531
+            $name = strip_tags( $title . ' ' . $version );
532
+
533
+            $author = wp_kses( $plugin['author'], $plugins_allowedtags );
534
+            if ( ! empty( $author ) ) {
535
+                /* translators: %s: Plugin author. */
536
+                $author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>';
537
+            }
538
+
539
+            $requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null;
540
+            $requires_wp  = isset( $plugin['requires'] ) ? $plugin['requires'] : null;
541
+
542
+            $compatible_php = is_php_version_compatible( $requires_php );
543
+            $compatible_wp  = is_wp_version_compatible( $requires_wp );
544
+            $tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );
545
+
546
+            $action_links = array();
547
+
548
+            if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) {
549
+                $status = install_plugin_install_status( $plugin );
550
+
551
+                switch ( $status['status'] ) {
552
+                    case 'install':
553
+                        if ( $status['url'] ) {
554
+                            if ( $compatible_php && $compatible_wp ) {
555
+                                $action_links[] = sprintf(
556
+                                    '<a class="install-now button" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
557
+                                    esc_attr( $plugin['slug'] ),
558
+                                    esc_url( $status['url'] ),
559
+                                    /* translators: %s: Plugin name and version. */
560
+                                    esc_attr( sprintf( _x( 'Install %s now', 'plugin' ), $name ) ),
561
+                                    esc_attr( $name ),
562
+                                    __( 'Install Now' )
563
+                                );
564
+                            } else {
565
+                                $action_links[] = sprintf(
566
+                                    '<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
567
+                                    _x( 'Cannot Install', 'plugin' )
568
+                                );
569
+                            }
570
+                        }
571
+                        break;
572
+
573
+                    case 'update_available':
574
+                        if ( $status['url'] ) {
575
+                            if ( $compatible_php && $compatible_wp ) {
576
+                                $action_links[] = sprintf(
577
+                                    '<a class="update-now button aria-button-if-js" data-plugin="%s" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>',
578
+                                    esc_attr( $status['file'] ),
579
+                                    esc_attr( $plugin['slug'] ),
580
+                                    esc_url( $status['url'] ),
581
+                                    /* translators: %s: Plugin name and version. */
582
+                                    esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $name ) ),
583
+                                    esc_attr( $name ),
584
+                                    __( 'Update Now' )
585
+                                );
586
+                            } else {
587
+                                $action_links[] = sprintf(
588
+                                    '<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
589
+                                    _x( 'Cannot Update', 'plugin' )
590
+                                );
591
+                            }
592
+                        }
593
+                        break;
594
+
595
+                    case 'latest_installed':
596
+                    case 'newer_installed':
597
+                        if ( is_plugin_active( $status['file'] ) ) {
598
+                            $action_links[] = sprintf(
599
+                                '<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
600
+                                _x( 'Active', 'plugin' )
601
+                            );
602
+                        } elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
603
+                            if ( $compatible_php && $compatible_wp ) {
604
+                                $button_text = __( 'Activate' );
605
+                                /* translators: %s: Plugin name. */
606
+                                $button_label = _x( 'Activate %s', 'plugin' );
607
+                                $activate_url = add_query_arg(
608
+                                    array(
609
+                                        '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ),
610
+                                        'action'   => 'activate',
611
+                                        'plugin'   => $status['file'],
612
+                                    ),
613
+                                    network_admin_url( 'plugins.php' )
614
+                                );
615
+
616
+                                if ( is_network_admin() ) {
617
+                                    $button_text = __( 'Network Activate' );
618
+                                    /* translators: %s: Plugin name. */
619
+                                    $button_label = _x( 'Network Activate %s', 'plugin' );
620
+                                    $activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url );
621
+                                }
622
+
623
+                                $action_links[] = sprintf(
624
+                                    '<a href="%1$s" class="button activate-now" aria-label="%2$s">%3$s</a>',
625
+                                    esc_url( $activate_url ),
626
+                                    esc_attr( sprintf( $button_label, $plugin['name'] ) ),
627
+                                    $button_text
628
+                                );
629
+                            } else {
630
+                                $action_links[] = sprintf(
631
+                                    '<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
632
+                                    _x( 'Cannot Activate', 'plugin' )
633
+                                );
634
+                            }
635
+                        } else {
636
+                            $action_links[] = sprintf(
637
+                                '<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
638
+                                _x( 'Installed', 'plugin' )
639
+                            );
640
+                        }
641
+                        break;
642
+                }
643
+            }
644
+
645
+            $details_link = self_admin_url(
646
+                'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
647
+                '&amp;TB_iframe=true&amp;width=600&amp;height=550'
648
+            );
649
+
650
+            $action_links[] = sprintf(
651
+                '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
652
+                esc_url( $details_link ),
653
+                /* translators: %s: Plugin name and version. */
654
+                esc_attr( sprintf( __( 'More information about %s' ), $name ) ),
655
+                esc_attr( $name ),
656
+                __( 'More Details' )
657
+            );
658
+
659
+            if ( ! empty( $plugin['icons']['svg'] ) ) {
660
+                $plugin_icon_url = $plugin['icons']['svg'];
661
+            } elseif ( ! empty( $plugin['icons']['2x'] ) ) {
662
+                $plugin_icon_url = $plugin['icons']['2x'];
663
+            } elseif ( ! empty( $plugin['icons']['1x'] ) ) {
664
+                $plugin_icon_url = $plugin['icons']['1x'];
665
+            } else {
666
+                $plugin_icon_url = $plugin['icons']['default'];
667
+            }
668
+
669
+            /**
670
+             * Filters the install action links for a plugin.
671
+             *
672
+             * @since 2.7.0
673
+             *
674
+             * @param string[] $action_links An array of plugin action links.
675
+             *                               Defaults are links to Details and Install Now.
676
+             * @param array    $plugin       An array of plugin data. See {@see plugins_api()}
677
+             *                               for the list of possible values.
678
+             */
679
+            $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin );
680
+
681
+            $last_updated_timestamp = strtotime( $plugin['last_updated'] );
682
+            ?>
683 683
 		<div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
684 684
 			<?php
685
-			if ( ! $compatible_php || ! $compatible_wp ) {
686
-				echo '<div class="notice inline notice-error notice-alt"><p>';
687
-				if ( ! $compatible_php && ! $compatible_wp ) {
688
-					_e( 'This plugin does not work with your versions of WordPress and PHP.' );
689
-					if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
690
-						printf(
691
-							/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
692
-							' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
693
-							self_admin_url( 'update-core.php' ),
694
-							esc_url( wp_get_update_php_url() )
695
-						);
696
-						wp_update_php_annotation( '</p><p><em>', '</em>' );
697
-					} elseif ( current_user_can( 'update_core' ) ) {
698
-						printf(
699
-							/* translators: %s: URL to WordPress Updates screen. */
700
-							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
701
-							self_admin_url( 'update-core.php' )
702
-						);
703
-					} elseif ( current_user_can( 'update_php' ) ) {
704
-						printf(
705
-							/* translators: %s: URL to Update PHP page. */
706
-							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
707
-							esc_url( wp_get_update_php_url() )
708
-						);
709
-						wp_update_php_annotation( '</p><p><em>', '</em>' );
710
-					}
711
-				} elseif ( ! $compatible_wp ) {
712
-					_e( 'This plugin does not work with your version of WordPress.' );
713
-					if ( current_user_can( 'update_core' ) ) {
714
-						printf(
715
-							/* translators: %s: URL to WordPress Updates screen. */
716
-							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
717
-							self_admin_url( 'update-core.php' )
718
-						);
719
-					}
720
-				} elseif ( ! $compatible_php ) {
721
-					_e( 'This plugin does not work with your version of PHP.' );
722
-					if ( current_user_can( 'update_php' ) ) {
723
-						printf(
724
-							/* translators: %s: URL to Update PHP page. */
725
-							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
726
-							esc_url( wp_get_update_php_url() )
727
-						);
728
-						wp_update_php_annotation( '</p><p><em>', '</em>' );
729
-					}
730
-				}
731
-				echo '</p></div>';
732
-			}
733
-			?>
685
+            if ( ! $compatible_php || ! $compatible_wp ) {
686
+                echo '<div class="notice inline notice-error notice-alt"><p>';
687
+                if ( ! $compatible_php && ! $compatible_wp ) {
688
+                    _e( 'This plugin does not work with your versions of WordPress and PHP.' );
689
+                    if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
690
+                        printf(
691
+                            /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
692
+                            ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
693
+                            self_admin_url( 'update-core.php' ),
694
+                            esc_url( wp_get_update_php_url() )
695
+                        );
696
+                        wp_update_php_annotation( '</p><p><em>', '</em>' );
697
+                    } elseif ( current_user_can( 'update_core' ) ) {
698
+                        printf(
699
+                            /* translators: %s: URL to WordPress Updates screen. */
700
+                            ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
701
+                            self_admin_url( 'update-core.php' )
702
+                        );
703
+                    } elseif ( current_user_can( 'update_php' ) ) {
704
+                        printf(
705
+                            /* translators: %s: URL to Update PHP page. */
706
+                            ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
707
+                            esc_url( wp_get_update_php_url() )
708
+                        );
709
+                        wp_update_php_annotation( '</p><p><em>', '</em>' );
710
+                    }
711
+                } elseif ( ! $compatible_wp ) {
712
+                    _e( 'This plugin does not work with your version of WordPress.' );
713
+                    if ( current_user_can( 'update_core' ) ) {
714
+                        printf(
715
+                            /* translators: %s: URL to WordPress Updates screen. */
716
+                            ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
717
+                            self_admin_url( 'update-core.php' )
718
+                        );
719
+                    }
720
+                } elseif ( ! $compatible_php ) {
721
+                    _e( 'This plugin does not work with your version of PHP.' );
722
+                    if ( current_user_can( 'update_php' ) ) {
723
+                        printf(
724
+                            /* translators: %s: URL to Update PHP page. */
725
+                            ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
726
+                            esc_url( wp_get_update_php_url() )
727
+                        );
728
+                        wp_update_php_annotation( '</p><p><em>', '</em>' );
729
+                    }
730
+                }
731
+                echo '</p></div>';
732
+            }
733
+            ?>
734 734
 			<div class="plugin-card-top">
735 735
 				<div class="name column-name">
736 736
 					<h3>
@@ -742,10 +742,10 @@  discard block
 block discarded – undo
742 742
 				</div>
743 743
 				<div class="action-links">
744 744
 					<?php
745
-					if ( $action_links ) {
746
-						echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>';
747
-					}
748
-					?>
745
+                    if ( $action_links ) {
746
+                        echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>';
747
+                    }
748
+                    ?>
749 749
 				</div>
750 750
 				<div class="desc column-description">
751 751
 					<p><?php echo $description; ?></p>
@@ -755,60 +755,60 @@  discard block
 block discarded – undo
755 755
 			<div class="plugin-card-bottom">
756 756
 				<div class="vers column-rating">
757 757
 					<?php
758
-					wp_star_rating(
759
-						array(
760
-							'rating' => $plugin['rating'],
761
-							'type'   => 'percent',
762
-							'number' => $plugin['num_ratings'],
763
-						)
764
-					);
765
-					?>
758
+                    wp_star_rating(
759
+                        array(
760
+                            'rating' => $plugin['rating'],
761
+                            'type'   => 'percent',
762
+                            'number' => $plugin['num_ratings'],
763
+                        )
764
+                    );
765
+                    ?>
766 766
 					<span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span>
767 767
 				</div>
768 768
 				<div class="column-updated">
769 769
 					<strong><?php _e( 'Last Updated:' ); ?></strong>
770 770
 					<?php
771
-						/* translators: %s: Human-readable time difference. */
772
-						printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) );
773
-					?>
771
+                        /* translators: %s: Human-readable time difference. */
772
+                        printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) );
773
+                    ?>
774 774
 				</div>
775 775
 				<div class="column-downloaded">
776 776
 					<?php
777
-					if ( $plugin['active_installs'] >= 1000000 ) {
778
-						$active_installs_millions = floor( $plugin['active_installs'] / 1000000 );
779
-						$active_installs_text     = sprintf(
780
-							/* translators: %s: Number of millions. */
781
-							_nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
782
-							number_format_i18n( $active_installs_millions )
783
-						);
784
-					} elseif ( 0 === $plugin['active_installs'] ) {
785
-						$active_installs_text = _x( 'Less Than 10', 'Active plugin installations' );
786
-					} else {
787
-						$active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+';
788
-					}
789
-					/* translators: %s: Number of installations. */
790
-					printf( __( '%s Active Installations' ), $active_installs_text );
791
-					?>
777
+                    if ( $plugin['active_installs'] >= 1000000 ) {
778
+                        $active_installs_millions = floor( $plugin['active_installs'] / 1000000 );
779
+                        $active_installs_text     = sprintf(
780
+                            /* translators: %s: Number of millions. */
781
+                            _nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
782
+                            number_format_i18n( $active_installs_millions )
783
+                        );
784
+                    } elseif ( 0 === $plugin['active_installs'] ) {
785
+                        $active_installs_text = _x( 'Less Than 10', 'Active plugin installations' );
786
+                    } else {
787
+                        $active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+';
788
+                    }
789
+                    /* translators: %s: Number of installations. */
790
+                    printf( __( '%s Active Installations' ), $active_installs_text );
791
+                    ?>
792 792
 				</div>
793 793
 				<div class="column-compatibility">
794 794
 					<?php
795
-					if ( ! $tested_wp ) {
796
-						echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>';
797
-					} elseif ( ! $compatible_wp ) {
798
-						echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>';
799
-					} else {
800
-						echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>';
801
-					}
802
-					?>
795
+                    if ( ! $tested_wp ) {
796
+                        echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>';
797
+                    } elseif ( ! $compatible_wp ) {
798
+                        echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>';
799
+                    } else {
800
+                        echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>';
801
+                    }
802
+                    ?>
803 803
 				</div>
804 804
 			</div>
805 805
 		</div>
806 806
 			<?php
807
-		}
807
+        }
808 808
 
809
-		// Close off the group divs of the last one.
810
-		if ( ! empty( $group ) ) {
811
-			echo '</div></div>';
812
-		}
813
-	}
809
+        // Close off the group divs of the last one.
810
+        if ( ! empty( $group ) ) {
811
+            echo '</div></div>';
812
+        }
813
+    }
814 814
 }
Please login to merge, or discard this patch.