diff --git a/classes/errors.php b/classes/errors.php index 31be558cf..aa626d017 100644 --- a/classes/errors.php +++ b/classes/errors.php @@ -14,4 +14,27 @@ class Errors { static function to_json(string $code, array $params = []): string { return json_encode(["error" => ["code" => $code, "params" => $params]]); } + + static function libxml_last_error() : string { + $error = libxml_get_last_error(); + $error_formatted = ""; + + if ($error) { + foreach (libxml_get_errors() as $error) { + if ($error->level == LIBXML_ERR_FATAL) { + // currently only the first error is reported + $error_formatted = self::format_libxml_error($error); + break; + } + } + } + + return UConverter::transcode($error_formatted, 'UTF-8', 'UTF-8'); + } + + static function format_libxml_error(LibXMLError $error) : string { + return sprintf("LibXML error %s at line %d (column %d): %s", + $error->code, $error->line, $error->column, + $error->message); + } } diff --git a/classes/feedparser.php b/classes/feedparser.php index 6ce69cc89..3ed0647d2 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -193,10 +193,9 @@ class FeedParser { } } + /** @deprecated use Errors::format_libxml_error() instead */ function format_error(LibXMLError $error) : string { - return sprintf("LibXML error %s at line %d (column %d): %s", - $error->code, $error->line, $error->column, - $error->message); + return Errors::format_libxml_error($error); } // libxml may have invalid unicode data in error messages diff --git a/classes/feeds.php b/classes/feeds.php index 65027cb9e..2c37d659a 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -254,6 +254,10 @@ class Feeds extends Handler_Protected { $line["buttons_left"] .= $button_doc->saveXML($button_doc->firstChild); } + } else if ($result) { + user_error(get_class($plugin) . + " plugin: content provided in HOOK_ARTICLE_LEFT_BUTTON is not valid XML: " . + Errors::libxml_last_error() . " $result", E_USER_WARNING); } }, $line); @@ -273,6 +277,10 @@ class Feeds extends Handler_Protected { $line["buttons"] .= $button_doc->saveXML($button_doc->firstChild); } + } else if ($result) { + user_error(get_class($plugin) . + " plugin: content provided in HOOK_ARTICLE_BUTTON is not valid XML: " . + Errors::libxml_last_error() . " $result", E_USER_WARNING); } }, $line); diff --git a/classes/plugin.php b/classes/plugin.php index 3bced3b04..39af6a9a1 100644 --- a/classes/plugin.php +++ b/classes/plugin.php @@ -98,7 +98,7 @@ abstract class Plugin { /* GLOBAL hooks are invoked in global context, only available to system plugins (loaded via .env for all users) */ - /** Adds buttons for article (on the right) - e.g. mail, share, add note. + /** Adds buttons for article (on the right) - e.g. mail, share, add note. Generated markup must be valid XML. * @param array $line * @return string * @see PluginHost::HOOK_ARTICLE_BUTTON @@ -307,7 +307,7 @@ abstract class Plugin { return []; } - /** Adds per-article buttons on the left side + /** Adds per-article buttons on the left side. Generated markup must be valid XML. * @param array $row * @return string * @see PluginHost::HOOK_ARTICLE_LEFT_BUTTON