forked from friendica/php-json-ld
Added resolve method for @context URLs.
This commit is contained in:
parent
093e3277d8
commit
a7206c8331
193
jsonld.php
193
jsonld.php
|
@ -70,6 +70,12 @@ function jsonld_compact($ctx, $input)
|
||||||
$tmp = array($input);
|
$tmp = array($input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// merge context if it is an array
|
||||||
|
if(is_array($ctx))
|
||||||
|
{
|
||||||
|
$ctx = jsonld_merge_contexts(new stdClass, $ctx);
|
||||||
|
}
|
||||||
|
|
||||||
foreach($tmp as $value)
|
foreach($tmp as $value)
|
||||||
{
|
{
|
||||||
// setup output context
|
// setup output context
|
||||||
|
@ -109,50 +115,67 @@ function jsonld_compact($ctx, $input)
|
||||||
*/
|
*/
|
||||||
function jsonld_merge_contexts($ctx1, $ctx2)
|
function jsonld_merge_contexts($ctx1, $ctx2)
|
||||||
{
|
{
|
||||||
|
// merge first context if it is an array
|
||||||
|
if(is_array($ctx1))
|
||||||
|
{
|
||||||
|
$ctx1 = jsonld_merge_contexts($ctx1, $ctx2);
|
||||||
|
}
|
||||||
|
|
||||||
// copy context to merged output
|
// copy context to merged output
|
||||||
$merged = _clone($ctx1);
|
$merged = _clone($ctx1);
|
||||||
|
|
||||||
// if the new context contains any IRIs that are in the merged context,
|
if(is_array($ctx2))
|
||||||
// remove them from the merged context, they will be overwritten
|
|
||||||
foreach($ctx2 as $key => $value)
|
|
||||||
{
|
{
|
||||||
// ignore special keys starting with '@'
|
// merge array of contexts in order
|
||||||
if(strpos($key, '@') !== 0)
|
foreach($ctx2 as $ctx)
|
||||||
{
|
{
|
||||||
foreach($merged as $mkey => $mvalue)
|
$merged = jsonld_merge_contexts($merged, $ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if the new context contains any IRIs that are in the merged context,
|
||||||
|
// remove them from the merged context, they will be overwritten
|
||||||
|
foreach($ctx2 as $key => $value)
|
||||||
|
{
|
||||||
|
// ignore special keys starting with '@'
|
||||||
|
if(strpos($key, '@') !== 0)
|
||||||
{
|
{
|
||||||
if($mvalue === $value)
|
foreach($merged as $mkey => $mvalue)
|
||||||
{
|
{
|
||||||
// FIXME: update related @coerce rules
|
if($mvalue === $value)
|
||||||
unset($merged->$mkey);
|
{
|
||||||
break;
|
// FIXME: update related @coerce rules
|
||||||
|
unset($merged->$mkey);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// merge contexts
|
// merge contexts
|
||||||
foreach($ctx2 as $key => $value)
|
foreach($ctx2 as $key => $value)
|
||||||
{
|
|
||||||
// skip @coerce, to be merged below
|
|
||||||
if($key !== '@coerce')
|
|
||||||
{
|
{
|
||||||
$merged->$key = _clone($value);
|
// skip @coerce, to be merged below
|
||||||
}
|
if($key !== '@coerce')
|
||||||
}
|
|
||||||
|
|
||||||
// merge @coerce
|
|
||||||
if(property_exists($ctx2, '@coerce'))
|
|
||||||
{
|
|
||||||
if(!property_exists($merged, '@coerce'))
|
|
||||||
{
|
|
||||||
$merged->{'@coerce'} = _clone($ctx2->{'@coerce'});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach($ctx2->{'@coerce'} as $p => $type)
|
|
||||||
{
|
{
|
||||||
$merged->{'@coerce'}->$p = $type;
|
$merged->$key = _clone($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge @coerce
|
||||||
|
if(property_exists($ctx2, '@coerce'))
|
||||||
|
{
|
||||||
|
if(!property_exists($merged, '@coerce'))
|
||||||
|
{
|
||||||
|
$merged->{'@coerce'} = _clone($ctx2->{'@coerce'});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach($ctx2->{'@coerce'} as $p => $type)
|
||||||
|
{
|
||||||
|
$merged->{'@coerce'}->$p = $type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,6 +267,114 @@ function jsonld_frame($input, $frame, $options=null)
|
||||||
return $rval;
|
return $rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves external @context URLs. Every @context URL in the given JSON-LD
|
||||||
|
* object is resolved using the given URL-resolver function. Once all of
|
||||||
|
* the @contexts have been resolved, the method will return. If an error
|
||||||
|
* is encountered, an exception will be thrown.
|
||||||
|
*
|
||||||
|
* @param input the JSON-LD input object (or array).
|
||||||
|
* @param resolver the resolver method that takes a URL and returns a JSON-LD
|
||||||
|
* serialized @context or throws an exception.
|
||||||
|
*
|
||||||
|
* @return the fully-resolved JSON-LD output (object or array).
|
||||||
|
*/
|
||||||
|
function jsonld_resolve($input, $resolver)
|
||||||
|
{
|
||||||
|
// find all @context URLs
|
||||||
|
$urls = new ArrayObject();
|
||||||
|
_findUrls($input, $urls, false);
|
||||||
|
|
||||||
|
// resolve all URLs
|
||||||
|
foreach($urls as $url => $value)
|
||||||
|
{
|
||||||
|
$result = call_user_func($resolver, $url);
|
||||||
|
if(!is_string($result))
|
||||||
|
{
|
||||||
|
// already deserialized
|
||||||
|
$urls[$url] = $result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// deserialize JSON
|
||||||
|
$tmp = json_decode($result);
|
||||||
|
if($tmp === null)
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
'Could not resolve @context URL ("$url"), ' .
|
||||||
|
'malformed JSON detected.');
|
||||||
|
}
|
||||||
|
$urls[$url] = $tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace @context URLs in input
|
||||||
|
_findUrls($input, $urls, true);
|
||||||
|
|
||||||
|
return $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all of the @context URLs in the given input and replaces them
|
||||||
|
* if requested by their associated values in the given URL map.
|
||||||
|
*
|
||||||
|
* @param input the JSON-LD input object.
|
||||||
|
* @param urls the URLs ArrayObject.
|
||||||
|
* @param replace true to replace, false not to.
|
||||||
|
*/
|
||||||
|
function _findUrls($input, $urls, $replace)
|
||||||
|
{
|
||||||
|
if(is_array($input))
|
||||||
|
{
|
||||||
|
foreach($input as $v)
|
||||||
|
{
|
||||||
|
_findUrls($v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_object($input))
|
||||||
|
{
|
||||||
|
foreach($input as $key => $value)
|
||||||
|
{
|
||||||
|
if($key === '@context')
|
||||||
|
{
|
||||||
|
// @context is an array that might contain URLs
|
||||||
|
if(is_array($value))
|
||||||
|
{
|
||||||
|
foreach($value as $idx => $v)
|
||||||
|
{
|
||||||
|
if(is_string($v))
|
||||||
|
{
|
||||||
|
// replace w/resolved @context if appropriate
|
||||||
|
if($replace)
|
||||||
|
{
|
||||||
|
$input->{$key}[$idx] = $urls[$v];
|
||||||
|
}
|
||||||
|
// unresolved @context found
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$urls[$v] = new stdClass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(is_string($value))
|
||||||
|
{
|
||||||
|
// replace w/resolved @context if appropriate
|
||||||
|
if($replace)
|
||||||
|
{
|
||||||
|
$input->$key = $urls[$value];
|
||||||
|
}
|
||||||
|
// unresolved @context found
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$urls[$value] = new stdClass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the keywords from a context.
|
* Gets the keywords from a context.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue