Passed
Pull Request — master (#2)
by Der Mundschenk
02:26
created

WP_Requirements::check_multibyte_support()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 4
c 2
b 0
f 0
nc 4
nop 0
dl 0
loc 5
rs 10
1
<?php
2
/**
3
 *  This file is part of mundschenk-at/check-wp-requirements.
4
 *
5
 *  Copyright 2014-2019 Peter Putzer.
6
 *  Copyright 2009-2011 KINGdesk, LLC.
7
 *
8
 *  This program is free software; you can redistribute it and/or
9
 *  modify it under the terms of the GNU General Public License
10
 *  as published by the Free Software Foundation; either version 2
11
 *  of the License, or (at your option) any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
 *
22
 *  ***
23
 *
24
 *  @package mundschenk-at/check-wp-requirements
25
 *  @license http://www.gnu.org/licenses/gpl-2.0.html
26
 */
27
28
namespace Mundschenk;
29
30
/**
31
 * This class checks if the required runtime environment is available.
32
 *
33
 * Included checks:
34
 *    - PHP version
35
 *    - mb_string extension
36
 *    - UTF-8 encoding
37
 *
38
 * Note: All code must be executable on PHP 5.2.
39
 */
40
class WP_Requirements {
41
42
	/**
43
	 * The minimum requirements for running the plugins. Must contain:
44
	 *  - 'php'
45
	 *  - 'multibyte'
46
	 *  - 'utf-8'
47
	 *
48
	 * @var array A hash containing the version requirements for the plugin.
49
	 */
50
	private $install_requirements;
51
52
	/**
53
	 * The user-visible name of the plugin.
54
	 *
55
	 * @todo Should the plugin name be translated?
56
	 * @var string
57
	 */
58
	private $plugin_name;
59
60
	/**
61
	 * The full path to the main plugin file.
62
	 *
63
	 * @var string
64
	 */
65
	private $plugin_file;
66
67
	/**
68
	 * The textdomain used for loading plugin translations.
69
	 *
70
	 * @var string
71
	 */
72
	private $textdomain;
73
74
	/**
75
	 * The base directory of the Check_WP_Requirements component (i.e. the equivalent of __DIR__).
76
	 *
77
	 * @var string
78
	 */
79
	private $base_dir;
80
81
	/**
82
	 * Sets up a new Mundschenk\WP_Requirements object.
83
	 *
84
	 * @param string $name         The plugin name.
85
	 * @param string $plugin_path  The full path to the main plugin file.
86
	 * @param string $textdomain   The text domain used for i18n.
87
	 * @param array  $requirements The requirements to check against.
88
	 */
89
	public function __construct( $name, $plugin_path, $textdomain, $requirements ) {
90
		$this->plugin_name = $name;
91
		$this->plugin_file = $plugin_path;
92
		$this->textdomain  = $textdomain;
93
		$this->base_dir    = \dirname( __FILE__ );
94
95
		$this->install_requirements = \wp_parse_args( $requirements, [
96
			'php'       => '5.2.0',
97
			'multibyte' => false,
98
			'utf-8'     => false,
99
		] );
100
	}
101
102
	/**
103
	 * Checks if all runtime requirements for the plugin are met.
104
	 *
105
	 * @return bool
106
	 */
107
	public function check() {
108
		$requirements_met = true;
109
110
		foreach ( $this->get_requirements() as $requirement ) {
111
			if ( ! empty( $this->install_requirements[ $requirement['enable_key'] ] ) && ! \call_user_func( $requirement['check'] ) ) {
112
				$notice           = $requirement['notice'];
113
				$requirements_met = false;
114
				break;
115
			}
116
		}
117
118
		if ( ! $requirements_met && ! empty( $notice ) && \is_admin() ) {
119
			// Load text domain to ensure translated admin notices.
120
			\load_plugin_textdomain( $this->textdomain );
121
122
			// Add admin notice.
123
			\add_action( 'admin_notices', $notice );
124
		}
125
126
		return $requirements_met;
127
	}
128
129
130
	/**
131
	 * Retrieves an array of requirement specifications.
132
	 *
133
	 * @return array {
134
	 *         An array of requirements checks.
135
	 *
136
	 *   @type string   $enable_key An index in the $install_requirements array to switch the check on and off.
137
	 *   @type callable $check      A function returning true if the check was successful, false otherwise.
138
	 *   @type callable $notice     A function displaying an appropriate error notice.
139
	 * }
140
	 */
141
	protected function get_requirements() {
142
		return [
143
			[
144
				'enable_key' => 'php',
145
				'check'      => [ $this, 'check_php_support' ],
146
				'notice'     => [ $this, 'admin_notices_php_version_incompatible' ],
147
			],
148
			[
149
				'enable_key' => 'multibyte',
150
				'check'      => [ $this, 'check_multibyte_support' ],
151
				'notice'     => [ $this, 'admin_notices_mbstring_incompatible' ],
152
			],
153
			[
154
				'enable_key' => 'utf-8',
155
				'check'      => [ $this, 'check_utf8_support' ],
156
				'notice'     => [ $this, 'admin_notices_charset_incompatible' ],
157
			],
158
		];
159
	}
160
161
	/**
162
	 * Deactivates the plugin.
163
	 */
164
	public function deactivate_plugin() {
165
		\deactivate_plugins( \plugin_basename( $this->plugin_file ) );
166
	}
167
168
	/**
169
	 * Checks if the PHP version in use is at least equal to the required version.
170
	 *
171
	 * @return bool
172
	 */
173
	protected function check_php_support() {
174
		return \version_compare( \PHP_VERSION, $this->install_requirements['php'], '>=' );
175
	}
176
177
	/**
178
	 * Checks if multibyte functions are supported.
179
	 *
180
	 * @return bool
181
	 */
182
	protected function check_multibyte_support() {
183
		return \function_exists( 'mb_strlen' )
184
			&& \function_exists( 'mb_strtolower' )
185
			&& \function_exists( 'mb_substr' )
186
			&& \function_exists( 'mb_detect_encoding' );
187
	}
188
189
	/**
190
	 * Checks if the blog charset is set to UTF-8.
191
	 *
192
	 * @return bool
193
	 */
194
	protected function check_utf8_support() {
195
		return 'utf-8' === \strtolower( \get_bloginfo( 'charset' ) );
196
	}
197
198
	/**
199
	 * Print 'PHP version incompatible' admin notice
200
	 */
201
	public function admin_notices_php_version_incompatible() {
202
		$this->display_error_notice(
203
			/* translators: 1: plugin name 2: target PHP version number 3: actual PHP version number */
204
			\__( 'The activated plugin %1$s requires PHP %2$s or later. Your server is running PHP %3$s. Please deactivate this plugin, or upgrade your server\'s installation of PHP.', $this->textdomain ),
205
			"<strong>{$this->plugin_name}</strong>",
206
			$this->install_requirements['php'],
207
			\PHP_VERSION
208
		);
209
	}
210
211
	/**
212
	 * Prints 'mbstring extension missing' admin notice
213
	 */
214
	public function admin_notices_mbstring_incompatible() {
215
		$this->display_error_notice(
216
			/* translators: 1: plugin name 2: mbstring documentation URL */
217
			\__( 'The activated plugin %1$s requires the mbstring PHP extension to be enabled on your server. Please deactivate this plugin, or <a href="%2$s">enable the extension</a>.', $this->textdomain ),
218
			"<strong>{$this->plugin_name}</strong>",
219
			/* translators: URL with mbstring PHP extension installation instructions */
220
			\__( 'http://www.php.net/manual/en/mbstring.installation.php', $this->textdomain )
221
		);
222
	}
223
224
	/**
225
	 * Prints 'Charset incompatible' admin notice
226
	 */
227
	public function admin_notices_charset_incompatible() {
228
		$this->display_error_notice(
229
			/* translators: 1: plugin name 2: current character encoding 3: options URL */
230
			\__( 'The activated plugin %1$s requires your blog use the UTF-8 character encoding. You have set your blogs encoding to %2$s. Please deactivate this plugin, or <a href="%3$s">change your character encoding to UTF-8</a>.', $this->textdomain ),
231
			"<strong>{$this->plugin_name}</strong>",
232
			\get_bloginfo( 'charset' ),
233
			'/wp-admin/options-reading.php'
234
		);
235
	}
236
237
	/**
238
	 * Shows an error message in the admin area.
239
	 *
240
	 * @param string $format ... An `sprintf` format string, followd by an unspecified number of optional parameters.
241
	 */
242
	protected function display_error_notice( $format ) {
243
		if ( \func_num_args() < 1 || empty( $format ) ) {
244
			return; // abort.
245
		}
246
247
		$args    = \func_get_args();
248
		$format  = \array_shift( $args );
249
		$message = \vsprintf( $format, $args );
250
251
		require "{$this->base_dir}/partials/requirements-error-notice.php";
252
	}
253
}
254