/**
* Helper method to generate an alternative form of an URL, where array indices have either
* been added or removed. foo[] is transformed into foo[0], while foo[0] is transformed into foo[].
*
* The result for URLs with both formats is undefined, or for URLs that intermingle their parameters,
* i.e. t[]=foo&b[]=bar&t[]=baz
*
* This was introduced because of differences between the URLs generated by the different clients, and
* because Facebook (at least) generates URLs were []s in URL arguments are expanded to [0] when
* requested from the backend. Since we sign our URLs, this breaks the token generation and thus breaks
* URLs when Facebook attempts to retrieve them.
*
* @param string $url The URL to generate the alternative form of
* @param int $encoding The encoding to use - from GuzzleHttp\Psr7
* @return string
*/
protected function getAlternativeURL($url, $encoding = PHP_QUERY_RFC3986)
{
$urlParts = parse_url($url);
if (!isset($urlParts['query'])) {
return $url;
}
$queryString = $urlParts['query'];
$fixKeyPattern = '#\\[[0-9]+\\]$#';
$parsed = Psr7\parse_query($queryString);
$newArguments = array();
foreach ($parsed as $key => $value) {
$fixedKey = preg_replace($fixKeyPattern, '', $key);
// if the key came out different, we're talking about a t[x] format - so we store those
// to allow for the correct sequence when regenerating the URL further below.
if ($fixedKey != $key) {
$fixedKey .= '[]';
if (!isset($newArguments[$fixedKey])) {
$newArguments[$fixedKey] = array();
}
$newArguments[$fixedKey][] = $value;
} else {
if (is_array($value) && substr($key, -2) == '[]') {
// if the value is an array, and we have the [] format already, we expand the keys
foreach ($value as $innerKey => $innerValue) {
// remove [] from the key and append the inner array key
$indexedKey = substr($key, 0, -2) . '[' . $innerKey . ']';
$newArguments[$indexedKey] = $innerValue;
}
} else {
$newArguments[$key] = $value;
}
}
}
$urlParts['query'] = Psr7\build_query($newArguments, $encoding);
$url = Urls::buildFromParseUrlParts($urlParts);
return $url;
}