Compact absolute IRIs to relative IRIs.

This commit is contained in:
Dave Longley 2013-02-15 00:58:23 -05:00
parent 6e7f7a3b9a
commit 505202c213

View file

@ -276,6 +276,15 @@ function jsonld_parse_url($url) {
if(!isset($rval['scheme'])) { if(!isset($rval['scheme'])) {
$rval['scheme'] = ''; $rval['scheme'] = '';
} }
if(isset($rval['user']) || isset($rval['pass'])) {
$rval['auth'] = '';
if(isset($rval['user'])) {
$rval['auth'] = $rval['user'];
}
if(isset($rval['pass'])) {
$rval['auth'] .= ":{$rval['pass']}";
}
}
return $rval; return $rval;
} }
@ -373,14 +382,74 @@ function jsonld_prepend_base($base, $iri) {
} }
$absolute_iri = "{$base['scheme']}://"; $absolute_iri = "{$base['scheme']}://";
if(isset($base['user']) || isset($base['pass'])) { if(isset($base['auth'])) {
$absolute_iri .= "{$base['user']}:{$base['pass']}@"; $absolute_iri .= "{$base['auth']}@";
} }
$absolute_iri .= "$authority$path"; $absolute_iri .= "$authority$path";
return $absolute_iri; return $absolute_iri;
} }
/**
* Removes a base IRI from the given absolute IRI.
*
* @param mixed $base the base IRI.
* @param string $iri the absolute IRI.
*
* @return string the relative IRI if relative to base, otherwise the absolute
* IRI.
*/
function jsonld_remove_base($base, $iri) {
if(is_string($base)) {
$base = jsonld_parse_url($base);
}
// establish base root
$root = "{$base['scheme']}://";
if(isset($base['auth'])) {
$root .= "{$base['auth']}@";
}
$authority = $base['host'];
if(isset($base['port'])) {
$authority .= ":{$base['port']}";
}
$root .= $authority;
// IRI not relative to base
if(strpos($iri, $root) !== 0) {
return $iri;
}
// remove path segments that match
$base_segments = explode('/', $base['path']);
$iri_segments = explode('/', substr($iri, strlen($root)));
while(count($base_segments) > 0 && count($iri_segments) > 0) {
if($base_segments[0] !== $iri_segments[0]) {
break;
}
array_shift($base_segments);
array_shift($iri_segments);
}
// use '../' for each non-matching base segment
$rval = '';
if(count($base_segments) > 0) {
// do not count the last segment if it isn't a path (doesn't end in '/')
if(substr($base['path'], -1) !== '/') {
array_pop($base_segments);
}
foreach($base_segments as $segment) {
$rval .= '../';
}
}
// prepend remaining segments
$rval .= implode('/', $iri_segments);
return $rval;
}
/** /**
* A JSON-LD processor. * A JSON-LD processor.
*/ */
@ -1476,8 +1545,8 @@ class JsonLdProcessor {
// compact single @id // compact single @id
if(is_string($expanded_value)) { if(is_string($expanded_value)) {
$compacted_value = $this->_compactIri( $compacted_value = $this->_compactIri(
$active_ctx, $expanded_value, null, array( $active_ctx, $expanded_value, null,
'vocab' => ($expanded_property === '@type'))); array('vocab' => ($expanded_property === '@type')));
} }
// expanded value must be a @type array // expanded value must be a @type array
else { else {
@ -3628,9 +3697,10 @@ class JsonLdProcessor {
if($type_or_language_value === '@id' && self::_isSubjectReference($value)) { if($type_or_language_value === '@id' && self::_isSubjectReference($value)) {
// try to compact value to a term // try to compact value to a term
$term = $this->_compactIri( $term = $this->_compactIri(
$active_ctx, $value->{'@id'}, null, $active_ctx, $value->{'@id'}, null, array('vocab' => true));
array('vocab' => true, 'base' => true)); if(property_exists($active_ctx->mappings, $term) &&
if(property_exists($active_ctx->mappings, $term)) { $active_ctx->mappings->{$term} &&
$active_ctx->mappings->{$term}->{'@id'} === $value->{'@id'}) {
// prefer @vocab // prefer @vocab
$options = array('@vocab', '@id', '@none'); $options = array('@vocab', '@id', '@none');
} }
@ -3698,7 +3768,6 @@ class JsonLdProcessor {
* @param string $iri the IRI to compact. * @param string $iri the IRI to compact.
* @param mixed $value the value to check or null. * @param mixed $value the value to check or null.
* @param assoc $relative_to options for how to compact IRIs: * @param assoc $relative_to options for how to compact IRIs:
* base: true to compact against the base IRI, false not to.
* vocab: true to split after @vocab, false not to. * vocab: true to split after @vocab, false not to.
* @param mixed $parent the parent element for the value. * @param mixed $parent the parent element for the value.
* *
@ -3873,8 +3942,8 @@ class JsonLdProcessor {
} }
} }
// no compaction choices, return IRI as is // compact IRI relative to base
return $iri; return jsonld_remove_base($active_ctx->{'@base'}, $iri);
} }
/** /**
@ -3941,8 +4010,7 @@ class JsonLdProcessor {
// compact @type IRI // compact @type IRI
if(property_exists($value, '@type')) { if(property_exists($value, '@type')) {
$rval->{$this->_compactIri($active_ctx, '@type')} = $this->_compactIri( $rval->{$this->_compactIri($active_ctx, '@type')} = $this->_compactIri(
$active_ctx, $value->{'@type'}, null, $active_ctx, $value->{'@type'}, null, array('vocab' => true));
array('base' => true, 'vocab' => true));
} }
// alias @language // alias @language
else if(property_exists($value, '@language')) { else if(property_exists($value, '@language')) {
@ -3959,18 +4027,18 @@ class JsonLdProcessor {
// value is a subject reference // value is a subject reference
$expanded_property = $this->_expandIri($active_ctx, $active_property); $expanded_property = $this->_expandIri($active_ctx, $active_property);
$type = self::getContextValue($active_ctx, $active_property, '@type'); $type = self::getContextValue($active_ctx, $active_property, '@type');
$term = $this->_compactIri( $compacted = $this->_compactIri(
$active_ctx, $value->{'@id'}, null, $active_ctx, $value->{'@id'}, null,
array('vocab' => ($type === '@vocab'), 'base' => true)); array('vocab' => ($type === '@vocab')));
// compact to scalar // compact to scalar
if($type === '@id' || $type === '@vocab' || if($type === '@id' || $type === '@vocab' ||
$expanded_property === '@graph') { $expanded_property === '@graph') {
return $term; return $compacted;
} }
$rval = (object)array( $rval = (object)array(
$this->_compactIri($active_ctx, '@id') => $term); $this->_compactIri($active_ctx, '@id') => $compacted);
return $rval; return $rval;
} }