diff --git a/Mf2/Parser.php b/Mf2/Parser.php index 3075ed0..64bc442 100644 --- a/Mf2/Parser.php +++ b/Mf2/Parser.php @@ -1250,16 +1250,15 @@ public function parseRelsAndAlternates() { // Iterate through all a, area and link elements with rel attributes foreach ($this->xpath->query('//a[@rel and @href] | //link[@rel and @href] | //area[@rel and @href]') as $hyperlink) { - if ($hyperlink->getAttribute('rel') == '') { + // Parse the set of rels for the current link + $linkRels = array_unique(array_filter(preg_split('/[\t\n\f\r ]/', $hyperlink->getAttribute('rel')))); + if (count($linkRels) === 0) { continue; } // Resolve the href $href = $this->resolveUrl($hyperlink->getAttribute('href')); - // Split up the rel into space-separated values - $linkRels = array_filter(explode(' ', $hyperlink->getAttribute('rel'))); - $rel_attributes = array(); if ($hyperlink->hasAttribute('media')) { @@ -1278,8 +1277,8 @@ public function parseRelsAndAlternates() { $rel_attributes['type'] = $hyperlink->getAttribute('type'); } - if ($hyperlink->nodeValue) { - $rel_attributes['text'] = $hyperlink->nodeValue; + if (strlen($hyperlink->textContent) > 0) { + $rel_attributes['text'] = $hyperlink->textContent; } if ($this->enableAlternates) { @@ -1296,16 +1295,34 @@ public function parseRelsAndAlternates() { } foreach ($linkRels as $rel) { - $rels[$rel][] = $href; + if (!array_key_exists($rel, $rels)) { + $rels[$rel] = array($href); + } elseif (!in_array($href, $rels[$rel])) { + $rels[$rel][] = $href; + } } - if (!in_array($href, $rel_urls)) { - $rel_urls[$href] = array_merge( - $rel_attributes, - array('rels' => $linkRels) - ); + if (!array_key_exists($href, $rel_urls)) { + $rel_urls[$href] = array('rels' => array()); } + // Add the attributes collected only if they were not already set + $rel_urls[$href] = array_merge( + $rel_attributes, + $rel_urls[$href] + ); + + // Merge current rels with those already set + $rel_urls[$href]['rels'] = array_merge( + $rel_urls[$href]['rels'], + $linkRels + ); + } + + // Alphabetically sort the rels arrays after removing duplicates + foreach ($rel_urls as $href => $object) { + $rel_urls[$href]['rels'] = array_unique($rel_urls[$href]['rels']); + sort($rel_urls[$href]['rels']); } if (empty($rels) and $this->jsonMode) { @@ -1314,8 +1331,8 @@ public function parseRelsAndAlternates() { if (empty($rel_urls) and $this->jsonMode) { $rel_urls = new stdClass(); - } - + } + return array($rels, $rel_urls, $alternates); } diff --git a/tests/Mf2/RelTest.php b/tests/Mf2/RelTest.php index 55c08f0..2d737a2 100644 --- a/tests/Mf2/RelTest.php +++ b/tests/Mf2/RelTest.php @@ -176,4 +176,47 @@ public function testRelURLs() { $this->assertArrayHasKey('rels', $output['rel-urls']['http://example.com/articles.atom']); } + /** + * @see https://github.com/microformats/microformats2-parsing/issues/29 + * @see https://github.com/microformats/microformats2-parsing/issues/30 + */ + public function testRelURLsRelsUniqueAndSorted() { + $input = ' +'; + $parser = new Parser($input); + $output = $parser->parse(); + $this->assertEquals($output['rel-urls']['#']['rels'], array('archived', 'bookmark', 'me')); + } + + public function testRelURLsInfoMergesCorrectly() { + $input = 'This nodeValue +Not this nodeValue'; + $parser = new Parser($input); + $output = $parser->parse(); + $this->assertEquals($output['rel-urls']['#']['hreflang'], 'en'); + $this->assertArrayNotHasKey('media', $output['rel-urls']['#']); + $this->assertArrayNotHasKey('title', $output['rel-urls']['#']); + $this->assertArrayNotHasKey('type', $output['rel-urls']['#']); + $this->assertEquals($output['rel-urls']['#']['text'], 'This nodeValue'); + } + + public function testRelURLsNoDuplicates() { + $input = ' + +'; + $parser = new Parser($input); + $output = $parser->parse(); + $this->assertEquals($output['rels']['a'], array('#a', '#b')); + } + + public function testRelURLsFalsyTextVSEmpty() { + $input = '0 +'; + $parser = new Parser($input); + $output = $parser->parse(); + $this->assertArrayHasKey('text', $output['rel-urls']['#a']); + $this->assertEquals($output['rel-urls']['#a']['text'], '0'); + $this->assertArrayNotHasKey('text', $output['rel-urls']['#b']); + } + }