function persist()
{
$aLines = explode(LF, $this->getConfigAsString());
$iLines = count($aLines);
foreach (array_keys($this->aData) as $prop) {
$sPattern = '/\\s*define\\(\\s*["|\']' . $prop . '["|\']\\s*\\,\\s*(.*?)\\s*\\);\\s*/ix';
$sValue = $this->aData[$prop];
# We replace value by it's native PHP notation
switch ($this->aConstants[$prop]["type"]) {
case "string":
$sValue = var_export($sValue, true);
# Add quotes, and escape " and all string-termination chars
break;
case "integer":
$sValue = intval($sValue);
# Cast as integer
break;
case "boolean":
if (intval($sValue) === 1) {
# Note as a BOOLEAN PHP constant
$sValue = "TRUE";
} else {
$sValue = "FALSE";
}
break;
case "litteral":
$sValue = trim($sValue);
break;
default:
$sValue = "''";
break;
}
$mFound = false;
for ($k = $iLines - 1; $k >= 0; $k--) {
if (preg_match($sPattern, $aLines[$k])) {
# Found the last matching line
$mFound = $k;
break;
}
}
if ($mFound === false) {
# Adding line at the end of the file
$aLines[] = "\n" . "# " . $this->aConstants[$prop]["comment"] . "\ndefine(\"" . $prop . "\", " . $sValue . ");";
} else {
$aLines[$mFound] = "define(\"" . $prop . "\", " . $sValue . ");";
}
}
$sLines = implode("\n", $aLines);
$sSandboxedCode = str_replace(["<?php", "<?", "?>"], "", $sLines);
$sRand = (string) rand();
$sCode = "if(0) {" . $sSandboxedCode . "}; echo '" . $sRand . "';";
ob_start();
eval($sCode);
$sRes = ob_get_contents();
ob_end_clean();
if ($sRes !== $sRand) {
echo "<pre>" . htmlspecialchars($sLines) . "</pre>";
throw new \Exception("Parse error in new config file. Aborting, nothing has been changed.");
}
# We asserted that the syntax is OK;
# We now check that all the constants are present, and with the right value
$aNewConfig = $this->parseConfig($sLines);
$aWrittenConfig = $this->aData;
asort($aNewConfig);
asort($aWrittenConfig);
if ($aNewConfig != $aWrittenConfig) {
throw new \Exception("New config does not correspond to expected config. Aborting, nothing has been changed.");
}
file_put_contents($this->sConfigFilePath, $sLines);
}