@@ -280,6 +280,9 @@ class Parser {
280280 /** @var boolean Whether to include experimental language parsing in the result */
281281 public $ lang = false ;
282282
283+ /** @var bool Whether to include alternates object (dropped from spec in favor of rel-urls) */
284+ public $ enableAlternates = false ;
285+
283286 /**
284287 * Elements upgraded to mf2 during backcompat
285288 * @var SplObjectStorage
@@ -846,6 +849,10 @@ public function parseH(\DOMElement $e, $is_backcompat = false) {
846849 // Get current µf name
847850 $ mfTypes = mfNamesFromElement ($ e , 'h- ' );
848851
852+ if (!$ mfTypes ) {
853+ return null ;
854+ }
855+
849856 // Initalise var to store the representation in
850857 $ return = array ();
851858 $ children = array ();
@@ -1050,6 +1057,7 @@ public function parseH(\DOMElement $e, $is_backcompat = false) {
10501057
10511058 // Check for u-url
10521059 if (!array_key_exists ('url ' , $ return ) && !$ is_backcompat ) {
1060+ $ url = null ;
10531061 // Look for img @src
10541062 if ($ e ->tagName == 'a ' or $ e ->tagName == 'area ' ) {
10551063 $ url = $ e ->getAttribute ('href ' );
@@ -1073,7 +1081,7 @@ public function parseH(\DOMElement $e, $is_backcompat = false) {
10731081 }
10741082 }
10751083
1076- if (!empty ($ url )) {
1084+ if (!is_null ($ url )) {
10771085 $ return ['url ' ][] = $ this ->resolveUrl ($ url );
10781086 }
10791087 }
@@ -1153,62 +1161,89 @@ public function parseImpliedPhoto(\DOMElement $e) {
11531161 }
11541162
11551163 /**
1156- * Parse Rels and Alternatives
1164+ * Parse rels and alternates
11571165 *
1158- * Returns [$rels, $alternatives]. If the $rels value is to be empty, i.e. there are no links on the page
1159- * with a rel value *not* containing `alternate`, then the type of $rels depends on $this->jsonMode. If set
1160- * to true, it will be a stdClass instance, optimising for JSON serialisation. Otherwise (the default case),
1161- * it will be an empty array.
1166+ * Returns [$rels, $rel_urls, $alternates].
1167+ * For $rels and $rel_urls, if they are empty and $this->jsonMode = true, they will be returned as stdClass,
1168+ * optimizing for JSON serialization. Otherwise they will be returned as an empty array.
1169+ * Note that $alternates is deprecated in the microformats spec in favor of $rel_urls. $alternates only appears
1170+ * in parsed results if $this->enableAlternates = true.
1171+ * @return array|stdClass
11621172 */
11631173 public function parseRelsAndAlternates () {
11641174 $ rels = array ();
1175+ $ rel_urls = array ();
11651176 $ alternates = array ();
11661177
11671178 // Iterate through all a, area and link elements with rel attributes
11681179 foreach ($ this ->xpath ->query ('//a[@rel and @href] | //link[@rel and @href] | //area[@rel and @href] ' ) as $ hyperlink ) {
1169- if ($ hyperlink ->getAttribute ('rel ' ) == '' )
1180+ if ($ hyperlink ->getAttribute ('rel ' ) == '' ) {
11701181 continue ;
1182+ }
11711183
11721184 // Resolve the href
11731185 $ href = $ this ->resolveUrl ($ hyperlink ->getAttribute ('href ' ));
11741186
11751187 // Split up the rel into space-separated values
11761188 $ linkRels = array_filter (explode (' ' , $ hyperlink ->getAttribute ('rel ' )));
11771189
1178- // If alternate in rels, create alternate structure, append
1179- if (in_array ('alternate ' , $ linkRels )) {
1180- $ alt = array (
1181- 'url ' => $ href ,
1182- 'rel ' => implode (' ' , array_diff ($ linkRels , array ('alternate ' )))
1183- );
1184- if ($ hyperlink ->hasAttribute ('media ' ))
1185- $ alt ['media ' ] = $ hyperlink ->getAttribute ('media ' );
1190+ $ rel_attributes = array ();
11861191
1187- if ($ hyperlink ->hasAttribute ('hreflang ' ))
1188- $ alt ['hreflang ' ] = $ hyperlink ->getAttribute ('hreflang ' );
1192+ if ($ hyperlink ->hasAttribute ('media ' )) {
1193+ $ rel_attributes ['media ' ] = $ hyperlink ->getAttribute ('media ' );
1194+ }
11891195
1190- if ($ hyperlink ->hasAttribute ('title ' ))
1191- $ alt ['title ' ] = $ hyperlink ->getAttribute ('title ' );
1196+ if ($ hyperlink ->hasAttribute ('hreflang ' )) {
1197+ $ rel_attributes ['hreflang ' ] = $ hyperlink ->getAttribute ('hreflang ' );
1198+ }
1199+
1200+ if ($ hyperlink ->hasAttribute ('title ' )) {
1201+ $ rel_attributes ['title ' ] = $ hyperlink ->getAttribute ('title ' );
1202+ }
11921203
1193- if ($ hyperlink ->hasAttribute ('type ' ))
1194- $ alt ['type ' ] = $ hyperlink ->getAttribute ('type ' );
1204+ if ($ hyperlink ->hasAttribute ('type ' )) {
1205+ $ rel_attributes ['type ' ] = $ hyperlink ->getAttribute ('type ' );
1206+ }
11951207
1196- if ($ hyperlink ->nodeValue )
1197- $ alt ['text ' ] = $ hyperlink ->nodeValue ;
1208+ if ($ hyperlink ->nodeValue ) {
1209+ $ rel_attributes ['text ' ] = $ hyperlink ->nodeValue ;
1210+ }
11981211
1199- $ alternates [] = $ alt ;
1200- } else {
1201- foreach ($ linkRels as $ rel ) {
1202- $ rels [$ rel ][] = $ href ;
1212+ if ($ this ->enableAlternates ) {
1213+ // If 'alternate' in rels, create 'alternates' structure, append
1214+ if (in_array ('alternate ' , $ linkRels )) {
1215+ $ alternates [] = array_merge (
1216+ $ rel_attributes ,
1217+ array (
1218+ 'url ' => $ href ,
1219+ 'rel ' => implode (' ' , array_diff ($ linkRels , array ('alternate ' )))
1220+ )
1221+ );
12031222 }
12041223 }
1224+
1225+ foreach ($ linkRels as $ rel ) {
1226+ $ rels [$ rel ][] = $ href ;
1227+ }
1228+
1229+ if (!in_array ($ href , $ rel_urls )) {
1230+ $ rel_urls [$ href ] = array_merge (
1231+ $ rel_attributes ,
1232+ array ('rels ' => $ linkRels )
1233+ );
1234+ }
1235+
12051236 }
12061237
12071238 if (empty ($ rels ) and $ this ->jsonMode ) {
12081239 $ rels = new stdClass ();
12091240 }
12101241
1211- return array ($ rels , $ alternates );
1242+ if (empty ($ rel_urls ) and $ this ->jsonMode ) {
1243+ $ rel_urls = new stdClass ();
1244+ }
1245+
1246+ return array ($ rels , $ rel_urls , $ alternates );
12121247 }
12131248
12141249 /**
@@ -1239,14 +1274,15 @@ public function parse($convertClassic = true, DOMElement $context = null) {
12391274 }
12401275
12411276 // Parse rels
1242- list ($ rels , $ alternates ) = $ this ->parseRelsAndAlternates ();
1277+ list ($ rels , $ rel_urls , $ alternates ) = $ this ->parseRelsAndAlternates ();
12431278
12441279 $ top = array (
12451280 'items ' => array_values (array_filter ($ mfs )),
1246- 'rels ' => $ rels
1281+ 'rels ' => $ rels ,
1282+ 'rel-urls ' => $ rel_urls ,
12471283 );
12481284
1249- if (count ($ alternates )) {
1285+ if ($ this -> enableAlternates && count ($ alternates )) {
12501286 $ top ['alternates ' ] = $ alternates ;
12511287 }
12521288
0 commit comments