/** * 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; }