From 6701504876d6c9242eb310b35f41d40d9785ab4e Mon Sep 17 00:00:00 2001 From: Barnaby Walters Date: Sun, 12 Jul 2015 15:09:26 +0100 Subject: [PATCH] Corrected handling of value and html keys of property-nested microformat structures Fixes #64. As per https://github.com/indieweb/php-mf2/issues/64, microformats nested under e-* properties dropped their html keys. When looking into fixing this, I found several other nested cases where nested mf structure value keys were being incorrectly assigned. This commit fixes the handling of microformats nested under p-, e- and u- properties, with associated tests. --- Mf2/Parser.php | 30 ++++++++++++++++++++----- tests/Mf2/CombinedMicroformatsTest.php | 31 +++++++++++++++++++++++++- tests/Mf2/ParserTest.php | 4 ++-- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/Mf2/Parser.php b/Mf2/Parser.php index a7e9ef6..b8a954f 100644 --- a/Mf2/Parser.php +++ b/Mf2/Parser.php @@ -153,12 +153,17 @@ function nestedMfPropertyNamesFromClass($class) { $class = str_replace(array(' ', ' ', "\n"), ' ', $class); foreach (explode(' ', $class) as $classname) { foreach ($prefixes as $prefix) { - $compare_classname = strtolower(' ' . $classname); - if (stristr($compare_classname, $prefix) && ($compare_classname != $prefix)) { - $propertyNames = array_merge($propertyNames, mfNamesFromClass($classname, ltrim($prefix))); + // Check if $classname is a valid property classname for $prefix. + if (mb_substr($classname, 0, mb_strlen($prefix)) == $prefix && $classname != $prefix) { + $propertyName = mb_substr($classname, mb_strlen($prefix)); + $propertyNames[$propertyName][] = $prefix; } } } + + foreach ($propertyNames as $property => $prefixes) { + $propertyNames[$property] = array_unique($prefixes); + } return $propertyNames; } @@ -663,7 +668,9 @@ public function parseH(\DOMElement $e) { // If result was already parsed, skip it if (null === $result) continue; - + + // In most cases, the value attribute of the nested microformat should be the p- parsed value of the elemnt. + // The only times this is different is when the microformat is nested under certain prefixes, which are handled below. $result['value'] = $this->parseP($subMF); // Does this µf have any property names other than h-*? @@ -671,8 +678,19 @@ public function parseH(\DOMElement $e) { if (!empty($properties)) { // Yes! It’s a nested property µf - foreach ($properties as $property) { - $return[$property][] = $result; + foreach ($properties as $property => $prefixes) { + // Note: handling microformat nesting under multiple conflicting prefixes is not currently specified by the mf2 parsing spec. + $prefixSpecificResult = $result; + if (in_array('p-', $prefixes)) { + $prefixSpecificResult['value'] = $prefixSpecificResult['properties']['name'][0]; + } elseif (in_array('e-', $prefixes)) { + $eParsedResult = $this->parseE($subMF); + $prefixSpecificResult['html'] = $eParsedResult['html']; + $prefixSpecificResult['value'] = $eParsedResult['value']; + } elseif (in_array('u-', $prefixes)) { + $prefixSpecificResult['value'] = $this->parseU($subMF); + } + $return[$property][] = $prefixSpecificResult; } } else { // No, it’s a child µf diff --git a/tests/Mf2/CombinedMicroformatsTest.php b/tests/Mf2/CombinedMicroformatsTest.php index a50f54d..de63fe1 100644 --- a/tests/Mf2/CombinedMicroformatsTest.php +++ b/tests/Mf2/CombinedMicroformatsTest.php @@ -45,7 +45,7 @@ public function testHEventLocationHCard() { "start": ["2012-06-30"], "end": ["2012-07-01"], "location": [{ - "value": "Geoloqi, 920 SW 3rd Ave. Suite 400, Portland, OR", + "value": "Geoloqi", "type": ["h-card"], "properties": { "name": ["Geoloqi"], @@ -220,4 +220,33 @@ public function testNestedMicroformatUnderMultipleProperties() { $this->assertCount(1, $mf['items'][0]['properties']['like-of']); $this->assertCount(1, $mf['items'][0]['properties']['in-reply-to']); } + + /** + * Test microformats nested under e-* property classnames retain html: key in structure + * + * @see https://github.com/indieweb/php-mf2/issues/64 + */ + public function testMicroformatsNestedUnderEPropertyClassnamesRetainHtmlKey() { + $input = '

Hello

'; + $mf = Mf2\parse($input); + + $this->assertEquals($mf['items'][0]['properties']['content'][0]['html'], '

Hello

'); + } + + /** + * Test microformats nested under u-* property classnames derive value: key from parsing as u-* + */ + public function testMicroformatsNestedUnderUPropertyClassnamesDeriveValueCorrectly() { + $input = '
This should not be the value
'; + $mf = Mf2\parse($input); + + $this->assertEquals($mf['items'][0]['properties']['url'][0]['value'], 'This should be the value'); + } + + public function testMicroformatsNestedUnderPPropertyClassnamesDeriveValueFromFirstPName() { + $input = '
This post was written by Zoe.
'; + $mf = Mf2\parse($input); + + $this->assertEquals($mf['items'][0]['properties']['author'][0]['value'], 'Zoe'); + } } diff --git a/tests/Mf2/ParserTest.php b/tests/Mf2/ParserTest.php index 094f5d8..54a229d 100644 --- a/tests/Mf2/ParserTest.php +++ b/tests/Mf2/ParserTest.php @@ -48,8 +48,8 @@ public function testMicroformatStripsPrefixFromPropertyClassname() { } public function testNestedMicroformatPropertyNameWorks() { - $expected = array('location', 'author'); - $test = 'someclass p-location someotherclass u-author'; + $expected = array('location' => array('p-'), 'author' => array('u-', 'p-')); + $test = 'someclass p-location someotherclass u-author p-author'; $actual = Mf2\nestedMfPropertyNamesFromClass($test); $this->assertEquals($expected, $actual);