diff --git a/Mf2/Parser.php b/Mf2/Parser.php index 3717c58..83c3389 100644 --- a/Mf2/Parser.php +++ b/Mf2/Parser.php @@ -951,25 +951,13 @@ public function parseH(\DOMElement $e) { // Check for u-photo if (!array_key_exists('photo', $return)) { - // Look for img @src - try { - if ($e->tagName == 'img') - throw new Exception($e->getAttribute('src')); - // Look for nested img @src - foreach ($this->xpath->query('./img[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) { - if ($em->getAttribute('src') != '') - throw new Exception($em->getAttribute('src')); - } + $photo = $this->parseImpliedPhoto($e); - // Look for double nested img @src - foreach ($this->xpath->query('./*[count(preceding-sibling::*)+count(following-sibling::*)=0]/img[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) { - if ($em->getAttribute('src') != '') - throw new Exception($em->getAttribute('src')); - } - } catch (Exception $exc) { - $return['photo'][] = $this->resolveUrl($exc->getMessage()); + if ($photo !== false) { + $return['photo'][] = $this->resolveUrl($photo); } + } // Check for u-url @@ -1023,6 +1011,50 @@ public function parseH(\DOMElement $e) { return $parsed; } + /** + * @see http://microformats.org/wiki/microformats2-parsing#parsing_for_implied_properties + */ + public function parseImpliedPhoto(\DOMElement $e) { + + if ($e->tagName == 'img') { + return $e->getAttribute('src'); + } + + if ($e->tagName == 'object' && $e->hasAttribute('data')) { + return $e->getAttribute('data'); + } + + $xpaths = array( + './img', + './object', + './*[count(preceding-sibling::*)+count(following-sibling::*)=0]/img', + './*[count(preceding-sibling::*)+count(following-sibling::*)=0]/object', + ); + + foreach ($xpaths as $path) { + $els = $this->xpath->query($path, $e); + + if ($els->length == 1) { + $el = $els->item(0); + $hClasses = mfNamesFromElement($el, 'h-'); + + // no nested h- + if (empty($hClasses)) { + + if ($el->tagName == 'img') { + return $el->getAttribute('src'); + } else if ($el->tagName == 'object' && $el->getAttribute('data') != '') { + return $el->getAttribute('data'); + } + + } // no nested h- + } + } + + // no implied photo + return false; + } + /** * Parse Rels and Alternatives * diff --git a/tests/Mf2/ParseImpliedTest.php b/tests/Mf2/ParseImpliedTest.php index 56d7004..416aced 100644 --- a/tests/Mf2/ParseImpliedTest.php +++ b/tests/Mf2/ParseImpliedTest.php @@ -81,6 +81,8 @@ public function testParsesImpliedUPhotoFromDoublyNestedImgSrc() { $this->assertEquals('http://example.com/img.png', $output['items'][0]['properties']['photo'][0]); } + /* + * see testImpliedPhotoFromNestedObject() and testImpliedPhotoFromNestedObject() public function testIgnoresImgIfNotOnlyChild() { $input = '

Moar text

'; $parser = new Parser($input); @@ -88,7 +90,7 @@ public function testIgnoresImgIfNotOnlyChild() { $this->assertArrayNotHasKey('photo', $output['items'][0]['properties']); } - + public function testIgnoresDoublyNestedImgIfNotOnlyDoublyNestedChild() { $input = '

Moar text

'; $parser = new Parser($input); @@ -96,7 +98,7 @@ public function testIgnoresDoublyNestedImgIfNotOnlyDoublyNestedChild() { $this->assertArrayNotHasKey('photo', $output['items'][0]['properties']); } - + */ public function testParsesImpliedUUrlFromAHref() { $input = 'Some Name'; @@ -182,4 +184,73 @@ public function testParsesImpliedNameFromAbbrTitle() { $result = Mf2\parse($input); $this->assertEquals('Barnaby Walters', $result['items'][0]['properties']['name'][0]); } + + public function testImpliedPhotoFromObject() { + $input = 'John Doe'; + $result = Mf2\parse($input); + + $this->assertArrayHasKey('photo', $result['items'][0]['properties']); + $this->assertEquals('http://example/photo1.jpg', $result['items'][0]['properties']['photo'][0]); + } + + /** + * Correcting previous test testIgnoresImgIfNotOnlyChild() + * This *should* return the photo since h-x>img[src]:only-of-type:not[.h-*] + * @see https://indiewebcamp.com/User:Tantek.com + */ + public function testImpliedPhotoFromNestedImg() { + $input = 'Tantek Çelik'; + $result = Mf2\parse($input); + + $this->assertArrayHasKey('photo', $result['items'][0]['properties']); + $this->assertEquals('https://pbs.twimg.com/profile_images/423350922408767488/nlA_m2WH.jpeg', $result['items'][0]['properties']['photo'][0]); + } + + public function testIgnoredPhotoIfMultipleImg() { + $input = '
'; + $result = Mf2\parse($input); + + $this->assertArrayNotHasKey('photo', $result['items'][0]['properties']); + } + + /** + * Correcting previous test testIgnoresDoublyNestedImgIfNotOnlyDoublyNestedChild() + * This *should* return the photo since .h-x>object[data]:only-of-type:not[.h-*] + */ + public function testImpliedPhotoFromNestedObject() { + $input = '
John Doe

Moar text

'; + $result = Mf2\parse($input); + + $this->assertArrayHasKey('photo', $result['items'][0]['properties']); + $this->assertEquals('http://example/photo3.jpg', $result['items'][0]['properties']['photo'][0]); + } + + public function testIgnoredPhotoIfMultipleObject() { + $input = '
John Doe
'; + $result = Mf2\parse($input); + + $this->assertArrayNotHasKey('photo', $result['items'][0]['properties']); + } + + public function testIgnoredPhotoIfNestedImgH() { + $input = '
'; + $result = Mf2\parse($input); + + $this->assertArrayNotHasKey('photo', $result['items'][0]['properties']); + } + + public function testIgnoredPhotoIfNestedImgHasHClass() { + $input = '
John Doe
'; + $result = Mf2\parse($input); + + $this->assertArrayNotHasKey('photo', $result['items'][0]['properties']); + } + + public function testIgnoredPhotoIfNestedObjectHasHClass() { + $input = '
John Doe
'; + $result = Mf2\parse($input); + + $this->assertArrayNotHasKey('photo', $result['items'][0]['properties']); + } + }