Skip to content

Instantly share code, notes, and snippets.

@derak-kilgo
Last active October 29, 2021 14:16
Show Gist options
  • Save derak-kilgo/6ddae8760aed523338c42b78ab0fb651 to your computer and use it in GitHub Desktop.
Save derak-kilgo/6ddae8760aed523338c42b78ab0fb651 to your computer and use it in GitHub Desktop.
Extract database and other constants from a wp-config.php file without "including" it.
<?php
/**
* Extract key and value from all "define" constants in a wp-config.php file using built-in php tokenizer functions.
* Does not "include" the file so it won't pollute the current scope or cause side effects.
*
* NOTE: Works with constants defined as string, bool or number
* Method can extract values from statements like:
* define( 'DB_NAME', 'wordpress' );
* define('WP_DEBUG', true);
* define('SOMEINT', 1234567);
*
* Any defined using a function or magic var ( __FILE__ or __DIR__ ) will not decode properly.
* define( 'ABSPATH', dirname( __FILE__ ) . '/' );
* The value requires php to interpret it.
* You'll get NULL for these values.
*
* @param $pathToFile
* @return array
*/
function extractNamedConstants($pathToFile)
{
if(is_readable($pathToFile)){
$tokens = token_get_all(file_get_contents($pathToFile));
}else{
throw new InvalidArgumentException("Cannot read file. Check permissions.");
}
//useful for debugging @see http://php.net/manual/en/function.token-get-all.php
//foreach($tokens as &$token){
// if(is_array($token))
// $token[0] = token_name($token[0]) . ':' . $token[0];
//}
//print_r($tokens); die(__FILE__ . __LINE__);
//list of tokens by line#
$lineIndex = array();
//list of lines with "define" statements.
$defineIndex = array();
foreach ($tokens as $index => $attribs) {
//FYI: $attribs[0]= token_name(); $attribs[1]==value; $attribs[2]==line#
if (is_array($attribs)) {
$lineNum = $attribs[2];
//group tokens by line#. (make list if it doesn't exist)
if (!isset($lineIndex[$lineNum])) {
$lineIndex[$lineNum] = array();
}
$lineIndex[$lineNum][] = $index;
//remember a line# with a 'define' statement
if ($attribs[0] == T_STRING && strtolower($attribs[1]) == 'define') {
$defineIndex[] = $lineNum;
}
}
}
//loop again and consider only lines with 'define' statements
$data = [];
foreach ($defineIndex as $lineNum) {
$kvp = [];
//look on each line with a define for the key and value tokens. (Assumes one define statement per line)
foreach ($lineIndex[$lineNum] as $tokenIndex) {
//load token attributes
$attribs = $tokens[$tokenIndex];
//Look for string constant like define( 'DB_NAME', 'wordpress' );
if ($attribs[0] == T_CONSTANT_ENCAPSED_STRING) {
$kvp[] = trim($attribs[1], "'");
} elseif ($attribs[0] == T_STRING && !empty($kvp)) {
//Look for bool values like define('TEST',true);
//Check value for functions like: define( 'ABSPATH', dirname( __FILE__ ) . '/' );
if (function_exists($attribs[1]) && $tokens[$tokenIndex + 1] == '(') {
//this "define" is using a function. decoding requires parsing. Error out.
$kvp[] = NULL;
} else {
$kvp[] = $attribs[1];
}
} elseif ($attribs[0] == T_LNUMBER && !empty($kvp)) {
//Look for bool/number values like define('TEST',1);
$kvp[] = $attribs[1];
}
}
//store result. Assumes T_CONSTANT_ENCAPSED_STRING is encountered first on a line with one or more other elements after.
$data[$kvp[0]] = $kvp[1];
}
return $data;
}
/*
* Try it out!
*/
$data = extractNamedConstants(__DIR__ . '/wordpress/wp-config.php');
var_dump($data);
die();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment