Files
wp-multisite-waas/inc/helpers/class-wp-config.php
2025-02-07 19:02:33 -07:00

229 lines
6.0 KiB
PHP

<?php
/**
* Handles modifications to the wp-config.php file, if permissions allow.
*
* @package WP_Ultimo
* @subpackage Helper
* @since 2.0.0
*/
namespace WP_Ultimo\Helpers;
// Exit if accessed directly
defined('ABSPATH') || exit;
/**
* Handles modifications to the wp-config.php file, if permissions allow.
*
* @since 2.0.0
*/
class WP_Config {
use \WP_Ultimo\Traits\Singleton;
/**
* Inject the constant into the wp-config.php file.
*
* @since 2.0.0
*
* @param string $constant The name of the constant. e.g. WP_ULTIMO_CONSTANT.
* @param string|int $value The value of that constant.
* @return bool|\WP_Error
*/
public function inject_wp_config_constant($constant, $value) {
$config_path = $this->get_wp_config_path();
if ( ! is_writeable($config_path)) {
// translators: %s is the file name.
return new \WP_Error('not-writeable', sprintf(__('The file %s is not writable', 'wp-ultimo'), $config_path));
}
$config = file($config_path);
$line = $this->find_injected_line($config, $constant);
$content = str_pad(sprintf("define( '%s', '%s' );", $constant, $value), 50) . '// Automatically injected by WP Multisite WaaS;';
if ($line === false) {
// no defined, we just need to inject
$hook_line = $this->find_reference_hook_line($config);
if ($hook_line === false) {
return new \WP_Error('unknown-wpconfig', __("WP Multisite WaaS can't recognize your wp-config.php, please revert it to original state for further process.", 'wp-ultimo'));
}
$config = $this->inject_contents($config, $hook_line + 1, PHP_EOL . $content . PHP_EOL);
return file_put_contents($config_path, implode('', $config), LOCK_EX);
} else {
list($value, $line) = $line;
if ($value !== true) {
$config[ $line ] = $content . PHP_EOL;
return file_put_contents($config_path, implode('', $config), LOCK_EX);
}
}
return false;
}
/**
* Actually inserts the new lines into the array of wp-config.php lines.
*
* @since 2.0.0
*
* @param array $content_array Array containing the original lines of the file being edited.
* @param int $line Line number to inject the new content at.
* @param string $value Value to add to that specific line.
* @return array New array containing the lines of the modified file.
*/
public function inject_contents($content_array, $line, $value) {
if ( ! is_array($value)) {
$value = array($value);
}
array_splice($content_array, $line, 0, $value);
return $content_array;
}
/**
* Gets the correct path to the wp-config.php file.
*
* @since 2.0.0
* @return string
*/
public function get_wp_config_path() {
if (file_exists(ABSPATH . 'wp-config.php')) {
return (ABSPATH . 'wp-config.php');
} elseif (@file_exists(dirname(ABSPATH) . '/wp-config.php') && ! @file_exists(dirname(ABSPATH) . '/wp-settings.php')) {
return (dirname(ABSPATH) . '/wp-config.php');
} elseif (defined('WP_TESTS_MULTISITE') && constant('WP_TESTS_MULTISITE') === true) {
return '/tmp/wordpress-tests-lib/wp-tests-config.php';
}
}
/**
* Find reference line for injection.
*
* We need a hook point we can use as reference to inject our constants.
* For now, we are using the line defining the $table_prefix.
* e.g. $table_prefix = 'wp_';
* We retrieve that line via RegEx.
*
* @since 2.0.0
*
* @param array $config Array containing the lines of the config file, for searching.
* @return false|int Line number.
*/
public function find_reference_hook_line($config) {
global $wpdb;
/**
* We check for three patterns when trying to figure our
* where we can inject our constants:
*
* 1. We search for the $table_prefix variable definition;
* 2. We search for more complex $table_prefix definitions - the ones that
* use env variables, for example;
* 3. If that's not available, we look for the 'Happy Publishing' comment;
* 4. If that's also not available, we look for the beginning of the file.
*
* The key represents the pattern and the value the number of lines to add.
* A negative number of lines can be passed to write before the found line,
* instead of writing after it.
*/
$patterns = apply_filters(
'wu_wp_config_reference_hook_line_patterns',
array(
'/^\$table_prefix\s*=\s*[\'|\"]' . $wpdb->prefix . '[\'|\"]/' => 0,
'/^( ){0,}\$table_prefix\s*=.*[\'|\"]' . $wpdb->prefix . '[\'|\"]/' => 0,
'/(\/\* That\'s all, stop editing! Happy publishing\. \*\/)/' => -2,
'/<\?php/' => 0,
)
);
$line = 1;
foreach ($patterns as $pattern => $lines_to_add) {
foreach ($config as $k => $line) {
if (preg_match($pattern, (string) $line)) {
$line = $k + $lines_to_add;
break 2;
}
}
}
return $line;
}
/**
* Revert the injection of a constant in wp-config.php
*
* @since 2.0.0
*
* @param string $constant Constant name.
* @return mixed
*/
public function revert($constant) {
$config_path = $this->get_wp_config_path();
if ( ! is_writeable($config_path)) {
// translators: %s is the file name.
return new \WP_Error('not-writeable', sprintf(__('The file %s is not writable', 'wp-ultimo'), $config_path));
}
$config = file($config_path);
$line = $this->find_injected_line($config, $constant);
if ($line === false) {
return;
} else {
$value = $line[0];
$line = $line[1];
if ($value === 'true' || $value === '1') {
// value is true, we will remove this
unset($config[ $line ]);
// save it
return file_put_contents($config_path, implode('', $config), LOCK_EX);
}
}
}
/**
* Checks for the injected line inside of the wp-config.php file.
*
* @since 2.0.0
*
* @param array $config Array containing the lines of the config file, for searching.
* @param string $constant The constant name.
* @return mixed[]|bool
*/
public function find_injected_line($config, $constant) {
$pattern = "/^define\(\s*['|\"]" . $constant . "['|\"],(.*)\)/";
foreach ($config as $k => $line) {
if (preg_match($pattern, (string) $line, $matches)) {
return array(trim($matches[1]), $k);
}
}
return false;
}
}