Skip to content

Commit

Permalink
Merge pull request #92 from weierophinney/feature/plus-part-matching
Browse files Browse the repository at this point in the history
Handle wildcard "+" segments
  • Loading branch information
willdurand authored May 4, 2017
2 parents 25cd801 + 01e760c commit 154ddcd
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
53 changes: 46 additions & 7 deletions src/Negotiation/Negotiator.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,62 @@ protected function match(AcceptHeader $accept, AcceptHeader $priority, $index)
return null;
}

$ab = $accept->getBasePart();
$pb = $priority->getBasePart();
$acceptBase = $accept->getBasePart();
$priorityBase = $priority->getBasePart();

$as = $accept->getSubPart();
$ps = $priority->getSubPart();
$acceptSub = $accept->getSubPart();
$prioritySub = $priority->getSubPart();

$intersection = array_intersect_assoc($accept->getParameters(), $priority->getParameters());

$baseEqual = !strcasecmp($ab, $pb);
$subEqual = !strcasecmp($as, $ps);
$baseEqual = !strcasecmp($acceptBase, $priorityBase);
$subEqual = !strcasecmp($acceptSub, $prioritySub);

if (($ab === '*' || $baseEqual) && ($as === '*' || $subEqual) && count($intersection) === count($accept->getParameters())) {
if (($acceptBase === '*' || $baseEqual)
&& ($acceptSub === '*' || $subEqual)
&& count($intersection) === count($accept->getParameters())
) {
$score = 100 * $baseEqual + 10 * $subEqual + count($intersection);

return new Match($accept->getQuality() * $priority->getQuality(), $score, $index);
}

if (!strstr($acceptSub, '+') || !strstr($prioritySub, '+')) {
return null;
}

// Handle "+" segment wildcards
list($acceptSub, $acceptPlus) = $this->splitSubPart($acceptSub);
list($prioritySub, $priorityPlus) = $this->splitSubPart($prioritySub);

$subEqual = !strcasecmp($acceptSub, $prioritySub);
$plusEqual = !strcasecmp($acceptPlus, $priorityPlus);

if (($acceptBase === '*' || $baseEqual)
&& ($acceptSub === '*' || $subEqual || $acceptPlus === '*' || $plusEqual)
&& count($intersection) === count($accept->getParameters())
) {
$score = 100 * $baseEqual + 10 * $subEqual + $plusEqual + count($intersection);

return new Match($accept->getQuality() * $priority->getQuality(), $score, $index);
}

return null;
}

/**
* Split a subpart into the subpart and "plus" part.
*
* For media-types of the form "application/vnd.example+json", matching
* should allow wildcards for either the portion before the "+" or
* after. This method splits the subpart to allow such matching.
*/
protected function splitSubPart($subPart)
{
if (!strstr($subPart, '+')) {
return [$subPart, ''];
}

return explode('+', $subPart, 2);
}
}
3 changes: 3 additions & 0 deletions tests/Negotiation/Tests/NegotiatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public static function dataProviderForTestGetBest()
array('image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, */*', array( 'text/html', 'application/xhtml+xml'), array('text/html', array())),
# Quality of source factors
array($rfcHeader, array('text/html;q=0.4', 'text/plain'), array('text/plain', array())),
# Wildcard "plus" parts (e.g., application/vnd.api+json)
array('application/vnd.api+json', array('application/json', 'application/*+json'), array('application/*+json', array())),
array($pearAcceptHeader, array('application/*+xml'), array('application/*+xml', array())),
);
}

Expand Down

0 comments on commit 154ddcd

Please sign in to comment.