Support more error conditions in expand.

This commit is contained in:
Dave Longley 2013-09-13 16:42:10 -04:00
parent 12a9ccc9e8
commit 60c335a6e9
1 changed files with 79 additions and 60 deletions

View File

@ -2079,6 +2079,9 @@ class JsonLdProcessor {
// recursively expand array
if(is_array($element)) {
$rval = array();
$container = self::getContextValue(
$active_ctx, $active_property, '@container');
$inside_list = $inside_list || $container === '@list';
foreach($element as $e) {
// expand element
$e = $this->_expand(
@ -2087,10 +2090,10 @@ class JsonLdProcessor {
// lists of lists are illegal
throw new JsonLdException(
'Invalid JSON-LD syntax; lists of lists are not permitted.',
'jsonld.SyntaxError');
'jsonld.SyntaxError', 'list of lists');
}
// drop null values
else if($e !== null) {
if($e !== null) {
if(is_array($e)) {
$rval = array_merge($rval, $e);
}
@ -2103,7 +2106,7 @@ class JsonLdProcessor {
}
if(!is_object($element)) {
// drop top-level scalars that are not in lists
// drop free-floating scalars that are not in lists
if(!$inside_list &&
($active_property === null ||
$this->_expandIri($active_ctx, $active_property,
@ -2137,14 +2140,6 @@ class JsonLdProcessor {
continue;
}
// get term definition for key
if(property_exists($active_ctx->mappings, $key)) {
$mapping = $active_ctx->mappings->{$key};
}
else {
$mapping = null;
}
// expand key to IRI
$expanded_property = $this->_expandIri(
$active_ctx, $key, array('vocab' => true));
@ -2156,19 +2151,35 @@ class JsonLdProcessor {
continue;
}
if(self::_isKeyword($expanded_property) &&
$expanded_active_property === '@reverse') {
throw new JsonLdException(
'Invalid JSON-LD syntax; a keyword cannot be used as a @reverse ' .
'property.',
'jsonld.SyntaxError', array('value' => $value));
if(self::_isKeyword($expanded_property)) {
if($expanded_active_property === '@reverse') {
throw new JsonLdException(
'Invalid JSON-LD syntax; a keyword cannot be used as a @reverse ' .
'property.', 'jsonld.SyntaxError', 'invalid reverse property map',
array('value' => $value));
}
if(property_exists($rval, $expanded_property)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; colliding keywords detected.',
'jsonld.SyntaxError', 'colliding keywords',
array('keyword' => $expanded_property));
}
}
// syntax error if @id is not a string
if($expanded_property === '@id' && !is_string($value)) {
throw new JsonLdException(
if(!isset($options['isFrame']) && !$options['isFrame']) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@id" value must a string.',
'jsonld.SyntaxError', array('value' => $value));
'jsonld.SyntaxError', 'invalid @id value',
array('value' => $value));
}
if(!is_object($value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@id" value must a string or an object.',
'jsonld.SyntaxError', 'invalid @id value',
array('value' => $value));
}
}
// validate @type value
@ -2180,9 +2191,9 @@ class JsonLdProcessor {
if($expanded_property === '@graph' &&
!(is_object($value) || is_array($value))) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@value" value must not be an ' .
'object or an array.',
'jsonld.SyntaxError', array('value' => $value));
'Invalid JSON-LD syntax; "@graph" value must not be an ' .
'object or an array.', 'jsonld.SyntaxError',
'invalid @graph value', array('value' => $value));
}
// @value must not be an object or an array
@ -2190,15 +2201,18 @@ class JsonLdProcessor {
(is_object($value) || is_array($value))) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@value" value must not be an ' .
'object or an array.',
'jsonld.SyntaxError', array('value' => $value));
'object or an array.', 'jsonld.SyntaxError',
'invalid value object value', array('value' => $value));
}
// @language must be a string
if($expanded_property === '@language' && !is_string($value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@language" value must not be a string.',
'jsonld.SyntaxError', array('value' => $value));
if($expanded_property === '@language') {
if(!is_string($value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@language" value must not be a string.',
'jsonld.SyntaxError', 'invalid language-tagged string',
array('value' => $value));
}
// ensure language value is lowercase
$value = strtolower($value);
}
@ -2208,7 +2222,8 @@ class JsonLdProcessor {
if(!is_string($value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@index" value must be a string.',
'jsonld.SyntaxError', array('value' => $value));
'jsonld.SyntaxError', 'invalid @index value',
array('value' => $value));
}
}
@ -2217,7 +2232,8 @@ class JsonLdProcessor {
if(!is_object($value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must be an object.',
'jsonld.SyntaxError', array('value' => $value));
'jsonld.SyntaxError', 'invalid @reverse value',
array('value' => $value));
}
$expanded_value = $this->_expand(
@ -2253,8 +2269,8 @@ class JsonLdProcessor {
if(self::_isValue($item) || self::_isList($item)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must not be a ' +
'@value or an @list.',
'jsonld.SyntaxError',
'@value or an @list.', 'jsonld.SyntaxError',
'invalid reverse property value',
array('value' => $expanded_value));
}
self::addValue(
@ -2290,7 +2306,7 @@ class JsonLdProcessor {
}
}
else {
// recurse into @list or @set keeping the active property
// recurse into @list or @set
$is_list = ($expanded_property === '@list');
if($is_list || $expanded_property === '@set') {
$next_active_property = $active_property;
@ -2302,7 +2318,7 @@ class JsonLdProcessor {
if($is_list && self::_isList($expanded_value)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; lists of lists are not permitted.',
'jsonld.SyntaxError');
'jsonld.SyntaxError', 'list of lists');
}
}
else {
@ -2336,8 +2352,9 @@ class JsonLdProcessor {
if(self::_isValue($item) || self::_isList($item)) {
throw new JsonLdException(
'Invalid JSON-LD syntax; "@reverse" value must not be a ' +
'@value or an @list.',
'jsonld.SyntaxError', array('value' => $expanded_value));
'@value or an @list.', 'jsonld.SyntaxError',
'invalid reverse property value',
array('value' => $expanded_value));
}
self::addValue(
$reverse_map, $expanded_property, $item,
@ -2368,7 +2385,8 @@ class JsonLdProcessor {
throw new JsonLdException(
'Invalid JSON-LD syntax; an element containing "@value" may not ' .
'contain both "@type" and "@language".',
'jsonld.SyntaxError', array('element' => $rval));
'jsonld.SyntaxError', 'invalid value object',
array('element' => $rval));
}
$valid_count = $count - 1;
if(property_exists($rval, '@type')) {
@ -2385,16 +2403,29 @@ class JsonLdProcessor {
'Invalid JSON-LD syntax; an element containing "@value" may only ' .
'have an "@index" property and at most one other property ' .
'which can be "@type" or "@language".',
'jsonld.SyntaxError', array('element' => $rval));
'jsonld.SyntaxError', 'invalid value object',
array('element' => $rval));
}
// drop null @values
if($rval->{'@value'} === null) {
$rval = null;
}
// drop @language if @value isn't a string
// if @language is present, @value must be a string
else if(property_exists($rval, '@language') &&
!is_string($rval->{'@value'})) {
unset($rval->{'@language'});
throw new JsonLdException(
'Invalid JSON-LD syntax; only strings may be language-tagged.',
'jsonld.SyntaxError', 'invalid language-tagged value',
array('element' => $rval));
}
else if(property_exists($rval, '@type') &&
!self::_isAbsoluteIri($rval->{'@type'}) ||
strpos($rval->{'@type'}, '_:') === 0) {
throw new JsonLdException(
'Invalid JSON-LD syntax; an element containing "@value" ' .
'and "@type" must have an absolute IRI for the value ' .
'of "@type".', 'jsonld.SyntaxError', 'invalid typed value',
array('element' => $rval));
}
}
// convert @type to an array
@ -2408,8 +2439,8 @@ class JsonLdProcessor {
throw new JsonLdException(
'Invalid JSON-LD syntax; if an element has the property "@set" ' .
'or "@list", then it can have at most one other property that is ' .
'"@index".',
'jsonld.SyntaxError', array('element' => $rval));
'"@index".', 'jsonld.SyntaxError', 'invalid set or list object',
array('element' => $rval));
}
// optimize away @set
if(property_exists($rval, '@set')) {
@ -2427,24 +2458,12 @@ class JsonLdProcessor {
if(is_object($rval) &&
!$options['keepFreeFloatingNodes'] && !$inside_list &&
($active_property === null || $expanded_active_property === '@graph')) {
// drop empty object or top-level @value
if($count === 0 || property_exists($rval, '@value')) {
// drop empty object or top-level @value/@list, or object with only @id
if($count === 0 || property_exists($rval, '@value') ||
property_exists($rval, '@list') ||
($count === 1 && property_exists($rval, '@id'))) {
$rval = null;
}
else {
// drop subjects that generate no triples
$has_triples = false;
$ignore = array('@graph', '@type');
foreach($keys as $key) {
if(!self::_isKeyword($key) || in_array($key, $ignore)) {
$has_triples = true;
break;
}
}
if(!$has_triples) {
$rval = null;
}
}
}
return $rval;
@ -5430,9 +5449,9 @@ jsonld_register_rdf_parser(
*/
class JsonLdException extends Exception {
public function __construct(
$msg, $type, /*$code='error',*/ $details=null, $previous=null) {
$msg, $type, $code='error', $details=null, $previous=null) {
$this->type = $type;
//$this->code = $code;
$this->code = $code;
$this->details = $details;
$this->cause = $previous;
parent::__construct($msg, 0, $previous);