From b4041091ab5eaae15d2996edc1897e351252c7e5 Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Wed, 23 Feb 2022 20:42:47 +0100 Subject: [PATCH] Fixed issue parsing elements with mixed valid and invalid mf2 classnames on Previously, an element with an invalid root classname such as would correctly not get parsed into a -type mf struct, but the h-12 would prevent the element from being parsed for valid classnames. This is now fixed. --- Mf2/Parser.php | 26 ++++++++++++++++---------- tests/Mf2/ParserTest.php | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Mf2/Parser.php b/Mf2/Parser.php index e8e6dda..68c911a 100644 --- a/Mf2/Parser.php +++ b/Mf2/Parser.php @@ -144,6 +144,15 @@ function mfNamesFromClass($class, $prefix='h-') { return $matches; } +/** + * Registered with the XPath object and used within XPaths for finding root elements. + * @param string $class + * @return bool + */ +function classHasMf2RootClassname($class) { + return count(mfNamesFromClass($class, 'h-')) > 0; +} + /** * Get Nested µf Property Name From Class * @@ -371,7 +380,10 @@ public function __construct($input, $url = null, $jsonMode = false) { @$doc->loadHTML(''); } + // Create an XPath object and allow some PHP functions to be used within XPath queries. $this->xpath = new DOMXPath($doc); + $this->xpath->registerNamespace('php', 'http://php.net/xpath'); + $this->xpath->registerPhpFunctions('\\Mf2\\classHasMf2RootClassname'); $baseurl = $url; foreach ($this->xpath->query('//base[@href]') as $base) { @@ -1164,7 +1176,7 @@ public function parseH(\DOMElement $e, $is_backcompat = false, $has_nested_mf = 'type' => $mfTypes, 'properties' => $return ); - + if(trim($e->getAttribute('id')) !== '') { $parsed['id'] = trim($e->getAttribute("id")); } @@ -1506,7 +1518,7 @@ public function parseFromId($id, $convertClassic=true) { public function getRootMF(DOMElement $context = null) { // start with mf2 root class name xpath $xpaths = array( - 'contains(concat(" ",normalize-space(@class)), " h-")' + '(php:function("\\Mf2\\classHasMf2RootClassname", normalize-space(@class)))' ); // add mf1 root class names @@ -1687,15 +1699,9 @@ public function addMfClasses(DOMElement $el, $classes) { */ public function hasRootMf2(\DOMElement $el) { $class = str_replace(array("\t", "\n"), ' ', $el->getAttribute('class')); - $classes = array_filter(explode(' ', $class)); - foreach ( $classes as $classname ) { - if ( strpos($classname, 'h-') === 0 ) { - return true; - } - } - - return false; + // Check for valid mf2 root classnames, not just any classname with a h- prefix. + return count(mfNamesFromClass($class, 'h-')) > 0; } /** diff --git a/tests/Mf2/ParserTest.php b/tests/Mf2/ParserTest.php index e0f96cc..3338026 100644 --- a/tests/Mf2/ParserTest.php +++ b/tests/Mf2/ParserTest.php @@ -860,5 +860,36 @@ public function testInvalidOrdinalDate() { $this->assertEquals('2016-12-31', Mf2\normalizeOrdinalDate('2016-366')); $this->assertEquals('', Mf2\normalizeOrdinalDate('2016-367')); } + + /** + * @see https://github.com/microformats/php-mf2/issues/230 + */ + public function testPropertyWithInvalidHPrefixedRootClassParsed() { + $input = << + Jon Doe + +EOF; + + $output = Mf2\parse($input); + $this->assertEquals(array('value' => '/image.jpg', 'alt' => 'Jon Doe'), $output['items'][0]['properties']['photo'][0]); + } + + public function testGetRootMfOnlyFindsValidElements() { + $input = << content + + + + + +EOF; + + $p = new Mf2\Parser($input); + $rootEls = $p->getRootMF(); + + $this->assertEquals(1, count($rootEls)); + $this->assertEquals('h-vendor123-name', $rootEls->item(0)->getAttribute('class')); + } }