- added type-hints
- added some documentation
- marked some generic methods to be moved to Util\Strings class instead
This commit is contained in:
Roland Häder 2022-06-20 23:49:29 +02:00
parent fbae0b8bcf
commit b6fa022a73
No known key found for this signature in database
GPG Key ID: C82EDE5DDFA0BA77
1 changed files with 70 additions and 45 deletions

View File

@ -21,6 +21,9 @@
namespace Friendica\Util; namespace Friendica\Util;
use DOMDocument;
use DOMElement;
use DOMNode;
use DOMXPath; use DOMXPath;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\System; use Friendica\Core\System;
@ -39,22 +42,21 @@ class XML
* @param bool $remove_header Should the XML header be removed or not? * @param bool $remove_header Should the XML header be removed or not?
* @param array $namespaces List of namespaces * @param array $namespaces List of namespaces
* @param bool $root interally used parameter. Mustn't be used from outside. * @param bool $root interally used parameter. Mustn't be used from outside.
* * @return void
* @return string The created XML
*/ */
public static function fromArray($array, &$xml, $remove_header = false, $namespaces = [], $root = true) public static function fromArray(array $array, &$xml, bool $remove_header = false, array $namespaces = [], bool $root = true)
{ {
if ($root) { if ($root) {
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
foreach ($namespaces as $nskey => $nsvalue) { foreach ($namespaces as $nskey => $nsvalue) {
$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"'; $key .= ' xmlns' . ($nskey == '' ? '' : ':') . $nskey . '="' . $nsvalue . '"';
} }
if (is_array($value)) { if (is_array($value)) {
$root = new SimpleXMLElement("<".$key."/>"); $root = new SimpleXMLElement('<' . $key . '/>');
self::fromArray($value, $root, $remove_header, $namespaces, false); self::fromArray($value, $root, $remove_header, $namespaces, false);
} else { } else {
$root = new SimpleXMLElement("<".$key.">".self::escape($value)."</".$key.">"); $root = new SimpleXMLElement('<' . $key . '>'.self::escape($value).'</' . $key . '>');
} }
$dom = dom_import_simplexml($root)->ownerDocument; $dom = dom_import_simplexml($root)->ownerDocument;
@ -88,11 +90,11 @@ class XML
continue; continue;
} }
$element_parts = explode(":", $key); $element_parts = explode(':', $key);
if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) { if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) {
$namespace = $namespaces[$element_parts[0]]; $namespace = $namespaces[$element_parts[0]];
} elseif (isset($namespaces[""])) { } elseif (isset($namespaces[''])) {
$namespace = $namespaces[""]; $namespace = $namespaces[''];
} else { } else {
$namespace = null; $namespace = null;
} }
@ -102,13 +104,13 @@ class XML
$key = $element_parts[1]; $key = $element_parts[1];
} }
if (substr($key, 0, 11) == "@attributes") { if (substr($key, 0, 11) == '@attributes') {
if (!isset($element) || !is_array($value)) { if (!isset($element) || !is_array($value)) {
continue; continue;
} }
foreach ($value as $attr_key => $attr_value) { foreach ($value as $attr_key => $attr_value) {
$element_parts = explode(":", $attr_key); $element_parts = explode(':', $attr_key);
if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) { if ((count($element_parts) > 1) && isset($namespaces[$element_parts[0]])) {
$namespace = $namespaces[$element_parts[0]]; $namespace = $namespaces[$element_parts[0]];
} else { } else {
@ -138,7 +140,7 @@ class XML
* @param string $elementname Name of the XML element of the target * @param string $elementname Name of the XML element of the target
* @return void * @return void
*/ */
public static function copy(&$source, &$target, $elementname) public static function copy(&$source, &$target, string $elementname)
{ {
if (count($source->children()) == 0) { if (count($source->children()) == 0) {
$target->addChild($elementname, self::escape($source)); $target->addChild($elementname, self::escape($source));
@ -153,14 +155,14 @@ class XML
/** /**
* Create an XML element * Create an XML element
* *
* @param \DOMDocument $doc XML root * @param DOMDocument $doc XML root
* @param string $element XML element name * @param string $element XML element name
* @param string $value XML value * @param string $value XML value
* @param array $attributes array containing the attributes * @param array $attributes array containing the attributes
* *
* @return \DOMElement XML element object * @return \DOMElement XML element object
*/ */
public static function createElement(\DOMDocument $doc, $element, $value = "", $attributes = []) public static function createElement(DOMDocument $doc, string $element, string $value = '', array $attributes = []): DOMElement
{ {
$element = $doc->createElement($element, self::escape($value)); $element = $doc->createElement($element, self::escape($value));
@ -175,14 +177,14 @@ class XML
/** /**
* Create an XML and append it to the parent object * Create an XML and append it to the parent object
* *
* @param \DOMDocument $doc XML root * @param DOMDocument $doc XML root
* @param object $parent parent object * @param object $parent parent object
* @param string $element XML element name * @param string $element XML element name
* @param string $value XML value * @param string $value XML value
* @param array $attributes array containing the attributes * @param array $attributes array containing the attributes
* @return void * @return void
*/ */
public static function addElement(\DOMDocument $doc, $parent, $element, $value = "", $attributes = []) public static function addElement(DOMDocument $doc, $parent, string $element, string $value = '', array $attributes = [])
{ {
$element = self::createElement($doc, $element, $value, $attributes); $element = self::createElement($doc, $element, $value, $attributes);
$parent->appendChild($element); $parent->appendChild($element);
@ -198,7 +200,7 @@ class XML
* *
* @return array | string The array from the xml element or the string * @return array | string The array from the xml element or the string
*/ */
public static function elementToArray($xml_element, &$recursion_depth = 0) public static function elementToArray($xml_element, int &$recursion_depth = 0)
{ {
// If we're getting too deep, bail out // If we're getting too deep, bail out
if ($recursion_depth > 512) { if ($recursion_depth > 512) {
@ -217,7 +219,7 @@ class XML
if (is_array($xml_element)) { if (is_array($xml_element)) {
$result_array = []; $result_array = [];
if (count($xml_element) <= 0) { if (count($xml_element) <= 0) {
return (trim(strval($xml_element_copy))); return trim(strval($xml_element_copy));
} }
foreach ($xml_element as $key => $value) { foreach ($xml_element as $key => $value) {
@ -233,9 +235,9 @@ class XML
]; ];
} }
return ($result_array); return $result_array;
} else { } else {
return (trim(strval($xml_element))); return trim(strval($xml_element));
} }
} }
@ -261,7 +263,7 @@ class XML
* @return array The parsed XML in an array form. Use print_r() to see the resulting array structure. * @return array The parsed XML in an array form. Use print_r() to see the resulting array structure.
* @throws \Exception * @throws \Exception
*/ */
public static function toArray($contents, $namespaces = true, $get_attributes = 1, $priority = 'attribute') public static function toArray(string $contents, bool $namespaces = true, int $get_attributes = 1, string $priority = 'attribute'): array
{ {
if (!$contents) { if (!$contents) {
return []; return [];
@ -300,7 +302,7 @@ class XML
Logger::debug('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message); Logger::debug('libxml: parse: ' . $err->code . " at " . $err->line . ":" . $err->column . " : " . $err->message);
} }
libxml_clear_errors(); libxml_clear_errors();
return; return [];
} }
//Initializations //Initializations
@ -414,20 +416,20 @@ class XML
} }
} }
return($xml_array); return $xml_array;
} }
/** /**
* Delete a node in a XML object * Delete a node in a XML object
* *
* @param \DOMDocument $doc XML document * @param DOMDocument $doc XML document
* @param string $node Node name * @param string $node Node name
* @return void * @return void
*/ */
public static function deleteNode(\DOMDocument $doc, $node) public static function deleteNode(DOMDocument $doc, string $node)
{ {
$xpath = new DOMXPath($doc); $xpath = new DOMXPath($doc);
$list = $xpath->query("//".$node); $list = $xpath->query('//' . $node);
foreach ($list as $child) { foreach ($list as $child) {
$child->parentNode->removeChild($child); $child->parentNode->removeChild($child);
} }
@ -436,9 +438,9 @@ class XML
/** /**
* Parse XML string * Parse XML string
* *
* @param string $s * @param string $s XML string to parse into object
* @param boolean $suppress_log * @param boolean $suppress_log Whether to supressing logging
* @return Object * @return SimpleXMLElement|bool SimpleXMLElement or false on failure
*/ */
public static function parseString(string $s, bool $suppress_log = false) public static function parseString(string $s, bool $suppress_log = false)
{ {
@ -458,7 +460,15 @@ class XML
return $x; return $x;
} }
public static function getFirstNodeValue(DOMXPath $xpath, $element, $context = null) /**
* Gets first node value
*
* @param DOMXPath $xpath XPath object
* @param string $element Element name
* @param DOMNode $context Context object or NULL
* @return string XML node value or empty string on failure
*/
public static function getFirstNodeValue(DOMXPath $xpath, string $element, DOMNode $context = null)
{ {
$result = @$xpath->evaluate($element, $context); $result = @$xpath->evaluate($element, $context);
if (!is_object($result)) { if (!is_object($result)) {
@ -473,7 +483,15 @@ class XML
return $first_item->nodeValue; return $first_item->nodeValue;
} }
public static function getFirstAttributes(DOMXPath $xpath, $element, $context = null) /**
* Gets first attributes
*
* @param DOMXPath $xpath XPath object
* @param string $element Element name
* @param DOMNode $context Context object or NULL
* @return ???|bool First element's attributes field or false on failure
*/
public static function getFirstAttributes(DOMXPath $xpath, string $element, DOMNode $context = null)
{ {
$result = @$xpath->query($element, $context); $result = @$xpath->query($element, $context);
if (!is_object($result)) { if (!is_object($result)) {
@ -488,9 +506,17 @@ class XML
return $first_item->attributes; return $first_item->attributes;
} }
public static function getFirstValue($xpath, $search, $context) /**
* Gets first node's value
*
* @param DOMXPath $xpath XPath object
* @param string $element Element name
* @param DOMNode $context Context object or NULL
* @return string First value or empty string on failure
*/
public static function getFirstValue(DOMXPath $xpath, string $element, DOMNode $context = null): string
{ {
$result = @$xpath->query($search, $context); $result = @$xpath->query($element, $context);
if (!is_object($result)) { if (!is_object($result)) {
return ''; return '';
} }
@ -508,32 +534,31 @@ class XML
* *
* @param string $str * @param string $str
* @return string Escaped text. * @return string Escaped text.
* @todo Move this generic method to Util\Strings and also rewrite all other findingd
*/ */
public static function escape($str) public static function escape(string $str): string
{ {
$buffer = htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); return trim(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));
$buffer = trim($buffer);
return $buffer;
} }
/** /**
* undo an escape * Undo an escape
* *
* @param string $s xml escaped text * @param string $s xml escaped text
* @return string unescaped text * @return string unescaped text
* @todo Move this generic method to Util\Strings and also rewrite all other findingd
*/ */
public static function unescape($s) public static function unescape(string $s): string
{ {
$ret = htmlspecialchars_decode($s, ENT_QUOTES); return htmlspecialchars_decode($s, ENT_QUOTES);
return $ret;
} }
/** /**
* apply escape() to all values of array $val, recursively * Apply escape() to all values of array $val, recursively
* *
* @param array $val * @param array|bool|string $val Value of type bool, array or string
* @return array|string * @return array|string Returns array if array provided or string in other cases
* @todo Move this generic method to Util\Strings
*/ */
public static function arrayEscape($val) public static function arrayEscape($val)
{ {