Remove blank node relabeling from expansion.

This commit is contained in:
Dave Longley 2013-03-27 10:52:25 -04:00
parent d5c0460356
commit 0778e0f7c3
1 changed files with 254 additions and 292 deletions

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP implementation of the JSON-LD API. * PHP implementation of the JSON-LD API.
* Version: 0.0.17 * Version: 0.0.18
* *
* @author Dave Longley * @author Dave Longley
* *
@ -352,26 +352,26 @@ function jsonld_parse_url($url) {
// parse authority for unparsed relative network-path reference // parse authority for unparsed relative network-path reference
if(strpos($rval['href'], ':') === false && if(strpos($rval['href'], ':') === false &&
strpos($rval['href'], '//') === 0 && $rval['host'] === '') { strpos($rval['href'], '//') === 0 && $rval['host'] === '') {
// must parse authority from pathname // must parse authority from pathname
$rval['path'] = substr($rval['path'], 2); $rval['path'] = substr($rval['path'], 2);
$idx = strpos($rval['path'], '/'); $idx = strpos($rval['path'], '/');
if($idx === false) { if($idx === false) {
$rval['authority'] = $rval['path']; $rval['authority'] = $rval['path'];
$rval['path'] = ''; $rval['path'] = '';
} }
else { else {
$rval['authority'] = substr($rval['path'], 0, $idx); $rval['authority'] = substr($rval['path'], 0, $idx);
$rval['path'] = substr($rval['path'], $idx); $rval['path'] = substr($rval['path'], $idx);
} }
} }
else { else {
$rval['authority'] = $rval['host']; $rval['authority'] = $rval['host'];
if(isset($rval['port'])) { if(isset($rval['port'])) {
$rval['authority'] .= ":{$rval['port']}"; $rval['authority'] .= ":{$rval['port']}";
} }
if(isset($rval['auth'])) { if(isset($rval['auth'])) {
$rval['authority'] = "{$rval['auth']}@{$rval['authority']}"; $rval['authority'] = "{$rval['auth']}@{$rval['authority']}";
} }
} }
$rval['normalizedPath'] = jsonld_remove_dot_segments( $rval['normalizedPath'] = jsonld_remove_dot_segments(
$rval['path'], $rval['authority'] !== ''); $rval['path'], $rval['authority'] !== '');
@ -379,44 +379,44 @@ function jsonld_parse_url($url) {
return $rval; return $rval;
} }
/** /**
* Removes dot segments from a URL path. * Removes dot segments from a URL path.
* *
* @param string $path the path to remove dot segments from. * @param string $path the path to remove dot segments from.
* @param bool $has_authority true if the URL has an authority, false if not. * @param bool $has_authority true if the URL has an authority, false if not.
*/ */
function jsonld_remove_dot_segments($path, $has_authority) { function jsonld_remove_dot_segments($path, $has_authority) {
$rval = ''; $rval = '';
if(strpos($path, '/') === 0) { if(strpos($path, '/') === 0) {
$rval = '/'; $rval = '/';
} }
// RFC 3986 5.2.4 (reworked) // RFC 3986 5.2.4 (reworked)
$input = explode('/', $path); $input = explode('/', $path);
$output = array(); $output = array();
while(count($input) > 0) { while(count($input) > 0) {
if($input[0] === '.' || ($input[0] === '' && count($input) > 1)) { if($input[0] === '.' || ($input[0] === '' && count($input) > 1)) {
array_shift($input); array_shift($input);
continue; continue;
} }
if($input[0] === '..') { if($input[0] === '..') {
array_shift($input); array_shift($input);
if($has_authority || if($has_authority ||
(count($output) > 0 && $output[count($output) - 1] !== '..')) { (count($output) > 0 && $output[count($output) - 1] !== '..')) {
array_pop($output); array_pop($output);
} }
// leading relative URL '..' // leading relative URL '..'
else { else {
$output[] = '..'; $output[] = '..';
} }
continue; continue;
} }
$output[] = array_shift($input); $output[] = array_shift($input);
} }
return $rval . implode('/', $output); return $rval . implode('/', $output);
} }
/** /**
* Prepends a base IRI to the given relative IRI. * Prepends a base IRI to the given relative IRI.
@ -548,13 +548,13 @@ function jsonld_remove_base($base, $iri) {
// prepend remaining segments // prepend remaining segments
$rval .= implode('/', $iri_segments); $rval .= implode('/', $iri_segments);
// add query and hash // add query and hash
if(isset($rel['query'])) { if(isset($rel['query'])) {
$rval .= "?{$rel['query']}"; $rval .= "?{$rel['query']}";
} }
if(isset($rel['fragment'])) { if(isset($rel['fragment'])) {
$rval .= "#{$rel['fragment']}"; $rval .= "#{$rel['fragment']}";
} }
if($rval === '') { if($rval === '') {
$rval = './'; $rval = './';
@ -620,8 +620,6 @@ class JsonLdProcessor {
// set default options // set default options
isset($options['base']) or $options['base'] = ''; isset($options['base']) or $options['base'] = '';
isset($options['strict']) or $options['strict'] = true; isset($options['strict']) or $options['strict'] = true;
isset($options['renameBlankNodes']) or $options['renameBlankNodes'] =
true;
isset($options['compactArrays']) or $options['compactArrays'] = true; isset($options['compactArrays']) or $options['compactArrays'] = true;
isset($options['graph']) or $options['graph'] = false; isset($options['graph']) or $options['graph'] = false;
isset($options['skipExpansion']) or $options['skipExpansion'] = false; isset($options['skipExpansion']) or $options['skipExpansion'] = false;
@ -735,8 +733,6 @@ class JsonLdProcessor {
* @param mixed $input the JSON-LD object to expand. * @param mixed $input the JSON-LD object to expand.
* @param assoc $options the options to use: * @param assoc $options the options to use:
* [base] the base IRI to use. * [base] the base IRI to use.
* [renameBlankNodes] true to rename blank nodes, false not to,
* defaults to true.
* [keepFreeFloatingNodes] true to keep free-floating nodes, * [keepFreeFloatingNodes] true to keep free-floating nodes,
* false not to, defaults to false. * false not to, defaults to false.
* [loadContext(url)] the context loader. * [loadContext(url)] the context loader.
@ -746,8 +742,6 @@ class JsonLdProcessor {
public function expand($input, $options) { public function expand($input, $options) {
// set default options // set default options
isset($options['base']) or $options['base'] = ''; isset($options['base']) or $options['base'] = '';
isset($options['renameBlankNodes']) or $options['renameBlankNodes'] =
true;
isset($options['keepFreeFloatingNodes']) or isset($options['keepFreeFloatingNodes']) or
$options['keepFreeFloatingNodes'] = false; $options['keepFreeFloatingNodes'] = false;
isset($options['loadContext']) or $options['loadContext'] = isset($options['loadContext']) or $options['loadContext'] =
@ -1062,8 +1056,6 @@ class JsonLdProcessor {
* @param stdClass $active_ctx the current active context. * @param stdClass $active_ctx the current active context.
* @param mixed $local_ctx the local context to process. * @param mixed $local_ctx the local context to process.
* @param assoc $options the options to use: * @param assoc $options the options to use:
* [renameBlankNodes] true to rename blank nodes, false not to,
* defaults to true.
* [loadContext(url)] the context loader. * [loadContext(url)] the context loader.
* *
* @return stdClass the new active context. * @return stdClass the new active context.
@ -1071,8 +1063,6 @@ class JsonLdProcessor {
public function processContext($active_ctx, $local_ctx, $options) { public function processContext($active_ctx, $local_ctx, $options) {
// set default options // set default options
isset($options['base']) or $options['base'] = ''; isset($options['base']) or $options['base'] = '';
isset($options['renameBlankNodes']) or $options['renameBlankNodes'] =
true;
isset($options['loadContext']) or $options['loadContext'] = isset($options['loadContext']) or $options['loadContext'] =
'jsonld_get_url'; 'jsonld_get_url';
@ -1698,7 +1688,7 @@ class JsonLdProcessor {
return $this->_compactValue($active_ctx, $active_property, $element); return $this->_compactValue($active_ctx, $active_property, $element);
} }
// FIXME: avoid misuse of active property as an expanded property? // FIXME: avoid misuse of active property as an expanded property?
$inside_reverse = ($active_property === '@reverse'); $inside_reverse = ($active_property === '@reverse');
// process element keys in order // process element keys in order
@ -1735,33 +1725,33 @@ class JsonLdProcessor {
continue; continue;
} }
// handle @reverse // handle @reverse
if($expanded_property === '@reverse') { if($expanded_property === '@reverse') {
// recursively compact expanded value // recursively compact expanded value
$compacted_value = $this->_compact( $compacted_value = $this->_compact(
$active_ctx, '@reverse', $expanded_value, $options); $active_ctx, '@reverse', $expanded_value, $options);
// handle double-reversed properties // handle double-reversed properties
foreach($compacted_value as $compacted_property => $value) { foreach($compacted_value as $compacted_property => $value) {
if(property_exists($active_ctx->mappings, $compacted_property) && if(property_exists($active_ctx->mappings, $compacted_property) &&
$active_ctx->mappings->{$compacted_property} && $active_ctx->mappings->{$compacted_property} &&
$active_ctx->mappings->{$compacted_property}->reverse) { $active_ctx->mappings->{$compacted_property}->reverse) {
if(!property_exists($rval, $compacted_property) && if(!property_exists($rval, $compacted_property) &&
!$options['compactArrays']) { !$options['compactArrays']) {
$rval->{$compacted_property} = array(); $rval->{$compacted_property} = array();
} }
self::addValue($rval, $compacted_property, $value); self::addValue($rval, $compacted_property, $value);
unset($compacted_value->{$compacted_property}); unset($compacted_value->{$compacted_property});
} }
} }
if(count(array_keys((array)$compacted_value)) > 0) { if(count(array_keys((array)$compacted_value)) > 0) {
// use keyword alias and add value // use keyword alias and add value
$alias = $this->_compactIri($active_ctx, $expanded_property); $alias = $this->_compactIri($active_ctx, $expanded_property);
self::addValue($rval, $alias, $compacted_value); self::addValue($rval, $alias, $compacted_value);
} }
continue; continue;
} }
// handle @index property // handle @index property
@ -1971,11 +1961,11 @@ class JsonLdProcessor {
continue; continue;
} }
if(self::_isKeyword($expanded_property) && if(self::_isKeyword($expanded_property) &&
$expanded_active_property === '@reverse') { $expanded_active_property === '@reverse') {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; a keyword cannot be used as a @reverse ' . 'Invalid JSON-LD syntax; a keyword cannot be used as a @reverse ' .
'property.', 'property.',
'jsonld.SyntaxError', array('value' => $value)); 'jsonld.SyntaxError', array('value' => $value));
} }
@ -2027,58 +2017,58 @@ class JsonLdProcessor {
} }
} }
// @reverse must be an object // @reverse must be an object
if($expanded_property === '@reverse') { if($expanded_property === '@reverse') {
if(!is_object($value)) { if(!is_object($value)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must be an object.', 'Invalid JSON-LD syntax; "@reverse" value must be an object.',
'jsonld.SyntaxError', array('value' => $value)); 'jsonld.SyntaxError', array('value' => $value));
} }
$expanded_value = $this->_expand( $expanded_value = $this->_expand(
$active_ctx, '@reverse', $value, $options, $inside_list); $active_ctx, '@reverse', $value, $options, $inside_list);
// properties double-reversed // properties double-reversed
if(property_exists($expanded_value, '@reverse')) { if(property_exists($expanded_value, '@reverse')) {
foreach($expanded_value->{'@reverse'} as $rproperty => $rvalue) { foreach($expanded_value->{'@reverse'} as $rproperty => $rvalue) {
self::addValue( self::addValue(
$rval, $rproperty, $rvalue, array('propertyIsArray' => true)); $rval, $rproperty, $rvalue, array('propertyIsArray' => true));
} }
} }
// FIXME: can this be merged with code below to simplify? // FIXME: can this be merged with code below to simplify?
// merge in all reversed properties // merge in all reversed properties
if(property_exists($rval, '@reverse')) { if(property_exists($rval, '@reverse')) {
$reverse_map = $rval->{'@reverse'}; $reverse_map = $rval->{'@reverse'};
} }
else { else {
$reverse_map = null; $reverse_map = null;
} }
foreach($expanded_value as $property => $items) { foreach($expanded_value as $property => $items) {
if($property === '@reverse') { if($property === '@reverse') {
continue; continue;
} }
if($reverse_map === null) { if($reverse_map === null) {
$reverse_map = $rval->{'@reverse'} = new stdClass(); $reverse_map = $rval->{'@reverse'} = new stdClass();
} }
self::addValue( self::addValue(
$reverse_map, $property, array(), $reverse_map, $property, array(),
array('propertyIsArray' => true)); array('propertyIsArray' => true));
foreach($items as $item) { foreach($items as $item) {
if(self::_isValue($item) || self::_isList($item)) { if(self::_isValue($item) || self::_isList($item)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must not be a ' + 'Invalid JSON-LD syntax; "@reverse" value must not be a ' +
'@value or an @list.', '@value or an @list.',
'jsonld.SyntaxError', 'jsonld.SyntaxError',
array('value' => $expanded_value)); array('value' => $expanded_value));
} }
self::addValue( self::addValue(
$reverse_map, $property, $item, $reverse_map, $property, $item,
array('propertyIsArray' => true)); array('propertyIsArray' => true));
} }
} }
continue; continue;
} }
$container = self::getContextValue($active_ctx, $key, '@container'); $container = self::getContextValue($active_ctx, $key, '@container');
@ -2146,25 +2136,25 @@ class JsonLdProcessor {
'@list' => self::arrayify($expanded_value)); '@list' => self::arrayify($expanded_value));
} }
// FIXME: can this be merged with code above to simplify? // FIXME: can this be merged with code above to simplify?
// merge in reverse properties // merge in reverse properties
if(property_exists($active_ctx->mappings, $key) && if(property_exists($active_ctx->mappings, $key) &&
$active_ctx->mappings->{$key} && $active_ctx->mappings->{$key} &&
$active_ctx->mappings->{$key}->reverse) { $active_ctx->mappings->{$key}->reverse) {
$reverse_map = $rval->{'@reverse'} = new stdClass(); $reverse_map = $rval->{'@reverse'} = new stdClass();
$expanded_value = self::arrayify($expanded_value); $expanded_value = self::arrayify($expanded_value);
foreach($expanded_value as $item) { foreach($expanded_value as $item) {
if(self::_isValue($item) || self::_isList($item)) { if(self::_isValue($item) || self::_isList($item)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must not be a ' + 'Invalid JSON-LD syntax; "@reverse" value must not be a ' +
'@value or an @list.', '@value or an @list.',
'jsonld.SyntaxError', array('value' => $expanded_value)); 'jsonld.SyntaxError', array('value' => $expanded_value));
} }
self::addValue( self::addValue(
$reverse_map, $expanded_property, $item, $reverse_map, $expanded_property, $item,
array('propertyIsArray' => true)); array('propertyIsArray' => true));
} }
continue; continue;
} }
// add value for property // add value for property
@ -2695,7 +2685,6 @@ class JsonLdProcessor {
if(property_exists($jsonld_cache, 'activeCtx')) { if(property_exists($jsonld_cache, 'activeCtx')) {
$rval = $jsonld_cache->activeCtx->get($active_ctx, $local_ctx); $rval = $jsonld_cache->activeCtx->get($active_ctx, $local_ctx);
if($rval) { if($rval) {
$rval->namer = $active_ctx->namer;
return $rval; return $rval;
} }
} }
@ -2715,7 +2704,6 @@ class JsonLdProcessor {
// reset to initial context // reset to initial context
if($ctx === null) { if($ctx === null) {
$rval = $this->_getInitialContext($options); $rval = $this->_getInitialContext($options);
$rval->namer = $active_ctx->namer;
continue; continue;
} }
@ -2734,26 +2722,26 @@ class JsonLdProcessor {
// define context mappings for keys in local context // define context mappings for keys in local context
$defined = new stdClass(); $defined = new stdClass();
// handle @base // handle @base
if(property_exists($ctx, '@base')) { if(property_exists($ctx, '@base')) {
$base = $ctx->{'@base'}; $base = $ctx->{'@base'};
if($base === null) { if($base === null) {
$base = $options['base']; $base = $options['base'];
} }
else if(!is_string($base)) { else if(!is_string($base)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; the value of "@base" in a ' . 'Invalid JSON-LD syntax; the value of "@base" in a ' .
'@context must be a string or null.', '@context must be a string or null.',
'jsonld.SyntaxError', array('context' => $ctx)); 'jsonld.SyntaxError', array('context' => $ctx));
} }
else if($base !== '' && !self::_isAbsoluteIri($base)) { else if($base !== '' && !self::_isAbsoluteIri($base)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; the value of "@base" in a ' . 'Invalid JSON-LD syntax; the value of "@base" in a ' .
'@context must be an absolute IRI or the empty string.', '@context must be an absolute IRI or the empty string.',
'jsonld.SyntaxError', array('context' => $ctx)); 'jsonld.SyntaxError', array('context' => $ctx));
} }
$rval->{'@base'} = jsonld_parse_url($base); $rval->{'@base'} = jsonld_parse_url($base);
$defined->{'@base'} = true; $defined->{'@base'} = true;
} }
// handle @vocab // handle @vocab
@ -2933,10 +2921,6 @@ class JsonLdProcessor {
// other type // other type
if($type !== null) { if($type !== null) {
// rename blank node if requested
if($active_ctx->namer !== null && strpos($type, '_:') === 0) {
$type = $active_ctx->namer->getName($type);
}
$rval->{'@type'} = $type; $rval->{'@type'} = $type;
} }
// check for language tagging for strings // check for language tagging for strings
@ -3253,20 +3237,20 @@ class JsonLdProcessor {
continue; continue;
} }
// handle reverse properties // handle reverse properties
if($property === '@reverse') { if($property === '@reverse') {
$referenced_node = (object)array('@id' => $name); $referenced_node = (object)array('@id' => $name);
$reverse_map = $input->{'@reverse'}; $reverse_map = $input->{'@reverse'};
foreach($reverse_map as $reverse_property => $items) { foreach($reverse_map as $reverse_property => $items) {
foreach($items as $item) { foreach($items as $item) {
self::addValue( self::addValue(
$item, $reverse_property, $referenced_node, $item, $reverse_property, $referenced_node,
array('propertyIsArray' => true, 'allowDuplicate' => false)); array('propertyIsArray' => true, 'allowDuplicate' => false));
$this->_createNodeMap($item, $graphs, $graph, $namer); $this->_createNodeMap($item, $graphs, $graph, $namer);
} }
} }
continue; continue;
} }
// recurse into graph // recurse into graph
if($property === '@graph') { if($property === '@graph') {
@ -3282,11 +3266,11 @@ class JsonLdProcessor {
// copy non-@type keywords // copy non-@type keywords
if($property !== '@type' && self::_isKeyword($property)) { if($property !== '@type' && self::_isKeyword($property)) {
if($property === '@index' && property_exists($subject, '@index')) { if($property === '@index' && property_exists($subject, '@index')) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; conflicting @index property detected.', 'Invalid JSON-LD syntax; conflicting @index property detected.',
'jsonld.SyntaxError', array('subject' => $subject)); 'jsonld.SyntaxError', array('subject' => $subject));
} }
$subject->{$property} = $input->{$property}; $subject->{$property} = $input->{$property};
continue; continue;
} }
@ -4120,10 +4104,10 @@ class JsonLdProcessor {
$type_or_language = '@language'; $type_or_language = '@language';
$type_or_language_value = '@null'; $type_or_language_value = '@null';
if($reverse) { if($reverse) {
$type_or_language = '@type'; $type_or_language = '@type';
$type_or_language_value = '@reverse'; $type_or_language_value = '@reverse';
$containers[] = '@set'; $containers[] = '@set';
} }
// choose the most specific term that works for all elements in @list // choose the most specific term that works for all elements in @list
else if(self::_isList($value)) { else if(self::_isList($value)) {
@ -4205,7 +4189,7 @@ class JsonLdProcessor {
} }
// do term selection // do term selection
$containers[] = '@none'; $containers[] = '@none';
$term = $this->_selectTerm( $term = $this->_selectTerm(
$active_ctx, $iri, $value, $active_ctx, $iri, $value,
$containers, $type_or_language, $type_or_language_value); $containers, $type_or_language, $type_or_language_value);
@ -4451,28 +4435,28 @@ class JsonLdProcessor {
$mapping = new stdClass(); $mapping = new stdClass();
$mapping->reverse = false; $mapping->reverse = false;
if(property_exists($value, '@reverse')) { if(property_exists($value, '@reverse')) {
if(property_exists($value, '@id') || if(property_exists($value, '@id') ||
property_exists($value, '@type') || property_exists($value, '@type') ||
property_exists($value, '@language')) { property_exists($value, '@language')) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; a @reverse term definition must not ' + 'Invalid JSON-LD syntax; a @reverse term definition must not ' +
'contain @id, @type, or @language.', 'contain @id, @type, or @language.',
'jsonld.SyntaxError', array('context' => $local_ctx)); 'jsonld.SyntaxError', array('context' => $local_ctx));
} }
$reverse = $value->{'@reverse'}; $reverse = $value->{'@reverse'};
if(!is_string($reverse)) { if(!is_string($reverse)) {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; a @context @reverse value must be a string.', 'Invalid JSON-LD syntax; a @context @reverse value must be a string.',
'jsonld.SyntaxError', array('context' => $local_ctx)); 'jsonld.SyntaxError', array('context' => $local_ctx));
} }
// expand and add @id mapping, set @type to @id // expand and add @id mapping, set @type to @id
$mapping->{'@id'} = $this->_expandIri( $mapping->{'@id'} = $this->_expandIri(
$active_ctx, $reverse, array('vocab' => true, 'base' => true), $active_ctx, $reverse, array('vocab' => true, 'base' => true),
$local_ctx, $defined); $local_ctx, $defined);
$mapping->{'@type'} = '@id'; $mapping->{'@type'} = '@id';
$mapping->reverse = true; $mapping->reverse = true;
} }
else if(property_exists($value, '@id')) { else if(property_exists($value, '@id')) {
$id = $value->{'@id'}; $id = $value->{'@id'};
@ -4551,11 +4535,11 @@ class JsonLdProcessor {
'one of the following: @list, @set, @index, or @language.', 'one of the following: @list, @set, @index, or @language.',
'jsonld.SyntaxError', array('context' => $local_ctx)); 'jsonld.SyntaxError', array('context' => $local_ctx));
} }
if($mapping->reverse && $container !== '@index') { if($mapping->reverse && $container !== '@index') {
throw new JsonLdException( throw new JsonLdException(
'Invalid JSON-LD syntax; @context @container value for a @reverse ' + 'Invalid JSON-LD syntax; @context @container value for a @reverse ' +
'type definition must be @index.', 'type definition must be @index.',
'jsonld.SyntaxError', array('context' => $local_ctx)); 'jsonld.SyntaxError', array('context' => $local_ctx));
} }
// add @container to mapping // add @container to mapping
@ -4614,8 +4598,6 @@ class JsonLdProcessor {
$this->_createTermDefinition($active_ctx, $local_ctx, $value, $defined); $this->_createTermDefinition($active_ctx, $local_ctx, $value, $defined);
} }
$rval = null;
if(isset($relative_to['vocab']) && $relative_to['vocab']) { if(isset($relative_to['vocab']) && $relative_to['vocab']) {
if(property_exists($active_ctx->mappings, $value)) { if(property_exists($active_ctx->mappings, $value)) {
$mapping = $active_ctx->mappings->{$value}; $mapping = $active_ctx->mappings->{$value};
@ -4626,55 +4608,44 @@ class JsonLdProcessor {
} }
// value is a term // value is a term
$rval = $mapping->{'@id'}; return $mapping->{'@id'};
} }
} }
if($rval === null) { // split value into prefix:suffix
// split value into prefix:suffix $colon = strpos($value, ':');
$colon = strpos($value, ':'); if($colon !== false) {
if($colon !== false) { $prefix = substr($value, 0, $colon);
$prefix = substr($value, 0, $colon); $suffix = substr($value, $colon + 1);
$suffix = substr($value, $colon + 1);
// do not expand blank nodes (prefix of '_') or already-absolute // do not expand blank nodes (prefix of '_') or already-absolute
// IRIs (suffix of '//') // IRIs (suffix of '//')
if($prefix !== '_' && strpos($suffix, '//') !== 0) { if($prefix !== '_' && strpos($suffix, '//') !== 0) {
// prefix dependency not defined, define it // prefix dependency not defined, define it
if($local_ctx !== null && property_exists($local_ctx, $prefix)) { if($local_ctx !== null && property_exists($local_ctx, $prefix)) {
$this->_createTermDefinition( $this->_createTermDefinition(
$active_ctx, $local_ctx, $prefix, $defined); $active_ctx, $local_ctx, $prefix, $defined);
} }
// use mapping if prefix is defined // use mapping if prefix is defined
if(property_exists($active_ctx->mappings, $prefix)) { if(property_exists($active_ctx->mappings, $prefix)) {
$mapping = $active_ctx->mappings->{$prefix}; $mapping = $active_ctx->mappings->{$prefix};
if($mapping) { if($mapping) {
$rval = $mapping->{'@id'} . $suffix; return $mapping->{'@id'} . $suffix;
}
} }
} }
} }
} }
if($rval === null) { // already absolute IRI
$rval = $value; if(self::_isAbsoluteIri($value)) {
return $value;
} }
// keywords need no expanding (aliasing already handled by now) $rval = $value;
if(self::_isKeyword($rval)) {
return $rval;
}
if(self::_isAbsoluteIri($rval)) {
// rename blank node if requested
if(!$local_ctx && strpos($rval, '_:') === 0 &&
$active_ctx->namer !== null) {
$rval = $active_ctx->namer->getName($rval);
}
}
// prepend vocab // prepend vocab
else if(isset($relative_to['vocab']) && $relative_to['vocab'] && if(isset($relative_to['vocab']) && $relative_to['vocab'] &&
property_exists($active_ctx, '@vocab')) { property_exists($active_ctx, '@vocab')) {
$rval = $active_ctx->{'@vocab'} . $rval; $rval = $active_ctx->{'@vocab'} . $rval;
} }
@ -4869,14 +4840,9 @@ class JsonLdProcessor {
* @return stdClass the initial context. * @return stdClass the initial context.
*/ */
protected function _getInitialContext($options) { protected function _getInitialContext($options) {
$namer = null;
if(isset($options['renameBlankNodes']) && $options['renameBlankNodes']) {
$namer = new UniqueNamer('_:b');
}
return (object)array( return (object)array(
'@base' => jsonld_parse_url($options['base']), '@base' => jsonld_parse_url($options['base']),
'mappings' => new stdClass(), 'mappings' => new stdClass(),
'namer' => $namer,
'inverse' => null); 'inverse' => null);
} }
@ -4934,37 +4900,37 @@ class JsonLdProcessor {
} }
$entry = $container_map->{$container}; $entry = $container_map->{$container};
// term is preferred for values using @reverse // term is preferred for values using @reverse
if($mapping->reverse) { if($mapping->reverse) {
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@type'}, '@reverse'); $mapping, $term, $entry->{'@type'}, '@reverse');
} }
// term is preferred for values using specific type // term is preferred for values using specific type
else if(property_exists($mapping, '@type')) { else if(property_exists($mapping, '@type')) {
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@type'}, $mapping->{'@type'}); $mapping, $term, $entry->{'@type'}, $mapping->{'@type'});
} }
// term is preferred for values using specific language // term is preferred for values using specific language
else if(property_exists($mapping, '@language')) { else if(property_exists($mapping, '@language')) {
$language = $mapping->{'@language'}; $language = $mapping->{'@language'};
if($language === null) { if($language === null) {
$language = '@null'; $language = '@null';
} }
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@language'}, $language); $mapping, $term, $entry->{'@language'}, $language);
} }
// term is preferred for values w/default language or no type and // term is preferred for values w/default language or no type and
// no language // no language
else { else {
// add an entry for the default language // add an entry for the default language
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@language'}, $default_language); $mapping, $term, $entry->{'@language'}, $default_language);
// add entries for no type and no language // add entries for no type and no language
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@type'}, '@none'); $mapping, $term, $entry->{'@type'}, '@none');
$this->_addPreferredTerm( $this->_addPreferredTerm(
$mapping, $term, $entry->{'@language'}, '@none'); $mapping, $term, $entry->{'@language'}, '@none');
} }
} }
} }
@ -4996,7 +4962,6 @@ class JsonLdProcessor {
$child = new stdClass(); $child = new stdClass();
$child->{'@base'} = $active_ctx->{'@base'}; $child->{'@base'} = $active_ctx->{'@base'};
$child->mappings = self::copy($active_ctx->mappings); $child->mappings = self::copy($active_ctx->mappings);
$child->namer = $active_ctx->namer;
$child->inverse = null; $child->inverse = null;
if(property_exists($active_ctx, '@language')) { if(property_exists($active_ctx, '@language')) {
$child->{'@language'} = $active_ctx->{'@language'}; $child->{'@language'} = $active_ctx->{'@language'};
@ -5020,9 +4985,6 @@ class JsonLdProcessor {
$rval = new stdClass(); $rval = new stdClass();
$rval->{'@base'} = $active_ctx->{'@base'}; $rval->{'@base'} = $active_ctx->{'@base'};
$rval->mappings = $active_ctx->mappings; $rval->mappings = $active_ctx->mappings;
if($active_ctx->namer !== null) {
$rval->namer = new UniqueNamer('_:b');
}
$rval->inverse = $active_ctx->inverse; $rval->inverse = $active_ctx->inverse;
if(property_exists($active_ctx, '@language')) { if(property_exists($active_ctx, '@language')) {
$rval->{'@language'} = $active_ctx->{'@language'}; $rval->{'@language'} = $active_ctx->{'@language'};