Vérifier la validité des fichiers de configuration XML de Magento
Magento ·Pour rappel, Magento s'appuie sur des fichiers XML pour configurer ses modules (entre autre). Le soucis avec l’utilisation qu'en fait Magento, c'est qu'il ne vérifie pas l'intégrité des fichiers XML.
En effet, si vous faite une faute de frappe, qu'une balise est mal fermé ou tout être erreur dans la structure XML de votre fichier de configuration, Magento levera une erreur (ou plutôt un warning) du type :
Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 19: parser error : expected '>' in magento\lib\Varien\Simplexml\Config.php on line 510
Notes :
- ce message est loggué dans
system.log
(si les logs sont activés) - dans le cas où le
DeveloperMode
n'est pas activée, l'erreur sera silencieuse
Vous me direz, ça n'est pas bloquant : un coup d'oeil dans le fichier exception.log
pour déterminer l'origine du problème et l'affaire est réglée ! Sauf que non, ce type d'erreur n'est pas "protégée" par un try/catch...
De ce fait, mise à part le fait de savoir qu'un fichier XML de configuration est en cause, vous n'êtes pas très avancé.
L'idée, pour se simplifier, est de connaitre le nom (où plutôt le chemin) du fichier en cause et la ligne qui pose problème.
Pour cela, je vous propose un overlap de classe Varien
en charge des fichiers de configuration XML : Varien_Simplexml_Config
. Le code est simple et mériterait d'être retravaillé, mais il fonctionne bien en l'état.
app/code/local/Varien/Simplexml/Config.php
:
class Varien_Simplexml_Config {
[...]
/**
* Imports XML file
*
* @param string $filePath
* @return boolean
*/
public function loadFile($filePath)
{
if (!is_readable($filePath)) {
//throw new Exception('Can not read xml file '.$filePath);
return false;
}
$fileData = file_get_contents($filePath);
$fileData = $this->processFileData($fileData);
/**
* Custom code: $filePath added
*/
// original
//return $this->loadString($fileData, $this->_elementClass);
// new
return $this->loadString($fileData, $this->_elementClass, $filePath);
}
/**
* Imports XML string
*
* @param string $string
* @return boolean
*/
public function loadString($string)
{
if (is_string($string)) {
/**
* Custom code: dealing with config file XML errors
*/
libxml_use_internal_errors(true);
$xmlcheck = simplexml_load_string($string);
if (!is_object($xmlcheck)) {
$argslist = func_get_args();
$filePath = $argslist[2];
foreach(libxml_get_errors() as $error) {
$error = array(
'message' => trim($error->message),
'code' => 'Code: ' . $error->code,
'file' => 'File: ' . ($error->file != '' ? $error->file : $filePath),
'line' => 'Line: ' . $error->line,
'column' => 'Column: ' . $error->column,
);
}
libxml_clear_errors();
// log
Mage::log("\n" . implode("\n", $error), Zend_Log::ERR, 'exception_config.log');
// throw in developer mode
if (Mage::getIsDeveloperMode()) {
Mage::printException(new Exception(implode("\n", $error)), 'CONFIG FILE ERROR');
}
}
// /Custom code
$xml = simplexml_load_string($string, $this->_elementClass);
if ($xml instanceof Varien_Simplexml_Element) {
$this->_xml = $xml;
return true;
}
} else {
Mage::logException(new Exception('"$string" parameter for simplexml_load_string is not a string'));
}
return false;
}
[...]
}
Le principe est très simple : je me contente d'utiliser l'outillage founi par PHP et libxml via libxml_use_internal_errors()
:
- j'active le gestionnaire d'erreur de la librairie
- je contrôle le fichier XML chargé dont je connais le chemin via
$filePath
- en cas d'erreurs, je les compile dans un tableau
- j'enregistre ces erreurs (message, code, fichier, ligne et colonne) dans un fichers de log dédié
- si le
DeveloperMode
est activée, je lève une exception bien violente
Voilà, c'est tout simple et le résultat est tout de même plus explicite :
CONFIG FILE ERROR
expected '>'
Code: 73
File: magento\app\code\local\ArnaudLigny\MonModule\etc\config.xml
Line: 20
Column: 1
Il semblerait que j'ai mal fermé une balise à la ligne 20 du fichier de configuration de MonModule
! :-)
Encore une fois j'insiste sur le fait qu'il s'agit d'un overlap simple et perfectible (et surtout bourrin). Si vous avez des idées d'amélioration, n'hésitez pas ! :-)
Pour aller plus loin dans la validation des fichiers XML de Magento, il serait nécessaire de valider leur schéma via une DTD (via l'option LIBXML_DTDVALID
de l'objet SimpleXMLElement
), mais le chantier s'annonce long et pénible...