/** * Loads a remote document or context * * @param string $url The URL of the document to load. * * @return RemoteDocument The remote document. * * @throws JsonLdException If loading the document failed. */ public static function loadDocument($url) { // if input looks like a file, try to retrieve it $input = trim($url); if (false == (isset($input[0]) && "{" === $input[0] || "[" === $input[0])) { $remoteDocument = new RemoteDocument($url); $streamContextOptions = array('method' => 'GET', 'header' => "Accept: application/ld+json, application/json; q=0.9, */*; q=0.1\r\n", 'timeout' => Processor::REMOTE_TIMEOUT); $context = stream_context_create(array('http' => $streamContextOptions, 'https' => $streamContextOptions)); $httpHeadersOffset = 0; stream_context_set_params($context, array('notification' => function ($code, $severity, $msg, $msgCode, $bytesTx, $bytesMax) use(&$remoteDocument, &$http_response_header, &$httpHeadersOffset) { if ($code === STREAM_NOTIFY_MIME_TYPE_IS) { $remoteDocument->mediaType = $msg; } elseif ($code === STREAM_NOTIFY_REDIRECTED) { $remoteDocument->documentUrl = $msg; $remoteDocument->mediaType = null; $httpHeadersOffset = count($http_response_header); } })); if (false === ($input = @file_get_contents($url, false, $context))) { throw new JsonLdException(JsonLdException::LOADING_DOCUMENT_FAILED, sprintf('Unable to load the remote document "%s".', $url), $http_response_header); } // Extract HTTP Link headers $linkHeaderValues = array(); for ($i = count($http_response_header) - 1; $i > $httpHeadersOffset; $i--) { if (0 === substr_compare($http_response_header[$i], 'Link:', 0, 5, true)) { $value = substr($http_response_header[$i], 5); $linkHeaderValues[] = $value; } } $linkHeaderValues = self::parseContextLinkHeaders($linkHeaderValues, new IRI($url)); if (count($linkHeaderValues) === 1) { $remoteDocument->contextUrl = reset($linkHeaderValues); } elseif (count($linkHeaderValues) > 1) { throw new JsonLdException(JsonLdException::MULTIPLE_CONTEXT_LINK_HEADERS, 'Found multiple contexts in HTTP Link headers', $http_response_header); } // If we got a media type, we verify it if ($remoteDocument->mediaType) { // Drop any media type parameters such as profiles if (false !== ($pos = strpos($remoteDocument->mediaType, ';'))) { $remoteDocument->mediaType = substr($remoteDocument->mediaType, 0, $pos); } $remoteDocument->mediaType = trim($remoteDocument->mediaType); if ('application/ld+json' === $remoteDocument->mediaType) { $remoteDocument->contextUrl = null; } elseif ('application/json' !== $remoteDocument->mediaType && 0 !== substr_compare($remoteDocument->mediaType, '+json', -5)) { throw new JsonLdException(JsonLdException::LOADING_DOCUMENT_FAILED, 'Invalid media type', $remoteDocument->mediaType); } } $remoteDocument->document = Processor::parse($input); return $remoteDocument; } return new RemoteDocument($url, Processor::parse($input)); }