Add new framing features.
- Allow filtering based on a specific @id. - Allow ducktyping matches on @type: [{}]. - Allow ducktyping matches when a @default is specified. - Add @requireAll flag for controlling ducktyping requirements.
This commit is contained in:
parent
ba16da5b9f
commit
3402d51dff
64
jsonld.php
64
jsonld.php
|
@ -94,6 +94,7 @@ function jsonld_flatten($input, $ctx, $options=array()) {
|
||||||
* [base] the base IRI to use.
|
* [base] the base IRI to use.
|
||||||
* [embed] default @embed flag (default: true).
|
* [embed] default @embed flag (default: true).
|
||||||
* [explicit] default @explicit flag (default: false).
|
* [explicit] default @explicit flag (default: false).
|
||||||
|
* [requireAll] default @requireAll flag (default: true).
|
||||||
* [omitDefault] default @omitDefault flag (default: false).
|
* [omitDefault] default @omitDefault flag (default: false).
|
||||||
* [documentLoader(url)] the document loader.
|
* [documentLoader(url)] the document loader.
|
||||||
*
|
*
|
||||||
|
@ -1076,6 +1077,7 @@ class JsonLdProcessor {
|
||||||
* [expandContext] a context to expand with.
|
* [expandContext] a context to expand with.
|
||||||
* [embed] default @embed flag (default: true).
|
* [embed] default @embed flag (default: true).
|
||||||
* [explicit] default @explicit flag (default: false).
|
* [explicit] default @explicit flag (default: false).
|
||||||
|
* [requireAll] default @requireAll flag (default: true).
|
||||||
* [omitDefault] default @omitDefault flag (default: false).
|
* [omitDefault] default @omitDefault flag (default: false).
|
||||||
* [documentLoader(url)] the document loader.
|
* [documentLoader(url)] the document loader.
|
||||||
*
|
*
|
||||||
|
@ -1088,6 +1090,7 @@ class JsonLdProcessor {
|
||||||
'compactArrays' => true,
|
'compactArrays' => true,
|
||||||
'embed' => true,
|
'embed' => true,
|
||||||
'explicit' => false,
|
'explicit' => false,
|
||||||
|
'requireAll' => true,
|
||||||
'omitDefault' => false,
|
'omitDefault' => false,
|
||||||
'documentLoader' => $jsonld_default_load_document));
|
'documentLoader' => $jsonld_default_load_document));
|
||||||
|
|
||||||
|
@ -3679,13 +3682,18 @@ class JsonLdProcessor {
|
||||||
$this->_validateFrame($state, $frame);
|
$this->_validateFrame($state, $frame);
|
||||||
$frame = $frame[0];
|
$frame = $frame[0];
|
||||||
|
|
||||||
// filter out subjects that match the frame
|
|
||||||
$matches = $this->_filterSubjects($state, $subjects, $frame);
|
|
||||||
|
|
||||||
// get flags for current frame
|
// get flags for current frame
|
||||||
$options = $state->options;
|
$options = $state->options;
|
||||||
$embed_on = $this->_getFrameFlag($frame, $options, 'embed');
|
$embed_on = $this->_getFrameFlag($frame, $options, 'embed');
|
||||||
$explicit_on = $this->_getFrameFlag($frame, $options, 'explicit');
|
$explicit_on = $this->_getFrameFlag($frame, $options, 'explicit');
|
||||||
|
$require_all_on = $this->_getFrameFlag($frame, $options, 'requireAll');
|
||||||
|
$flags = array(
|
||||||
|
'embed' => $embed_on,
|
||||||
|
'explicit' => $explicit_on,
|
||||||
|
'requireAll' => $require_all_on);
|
||||||
|
|
||||||
|
// filter out subjects that match the frame
|
||||||
|
$matches = $this->_filterSubjects($state, $subjects, $frame, $flags);
|
||||||
|
|
||||||
// add matches to output
|
// add matches to output
|
||||||
foreach($matches as $id => $subject) {
|
foreach($matches as $id => $subject) {
|
||||||
|
@ -3859,15 +3867,16 @@ class JsonLdProcessor {
|
||||||
* @param stdClass $state the current framing state.
|
* @param stdClass $state the current framing state.
|
||||||
* @param array $subjects the set of subjects to filter.
|
* @param array $subjects the set of subjects to filter.
|
||||||
* @param stdClass $frame the parsed frame.
|
* @param stdClass $frame the parsed frame.
|
||||||
|
* @param assoc $flags the frame flags.
|
||||||
*
|
*
|
||||||
* @return stdClass all of the matched subjects.
|
* @return stdClass all of the matched subjects.
|
||||||
*/
|
*/
|
||||||
protected function _filterSubjects($state, $subjects, $frame) {
|
protected function _filterSubjects($state, $subjects, $frame, $flags) {
|
||||||
$rval = new stdClass();
|
$rval = new stdClass();
|
||||||
sort($subjects);
|
sort($subjects);
|
||||||
foreach($subjects as $id) {
|
foreach($subjects as $id) {
|
||||||
$subject = $state->subjects->{$id};
|
$subject = $state->subjects->{$id};
|
||||||
if($this->_filterSubject($subject, $frame)) {
|
if($this->_filterSubject($subject, $frame, $flags)) {
|
||||||
$rval->{$id} = $subject;
|
$rval->{$id} = $subject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3879,10 +3888,11 @@ class JsonLdProcessor {
|
||||||
*
|
*
|
||||||
* @param stdClass $subject the subject to check.
|
* @param stdClass $subject the subject to check.
|
||||||
* @param stdClass $frame the frame to check.
|
* @param stdClass $frame the frame to check.
|
||||||
|
* @param assoc $flags the frame flags.
|
||||||
*
|
*
|
||||||
* @return bool true if the subject matches, false if not.
|
* @return bool true if the subject matches, false if not.
|
||||||
*/
|
*/
|
||||||
protected function _filterSubject($subject, $frame) {
|
protected function _filterSubject($subject, $frame, $flags) {
|
||||||
// check @type (object value means 'any' type, fall through to ducktyping)
|
// check @type (object value means 'any' type, fall through to ducktyping)
|
||||||
if(property_exists($frame, '@type') &&
|
if(property_exists($frame, '@type') &&
|
||||||
!(count($frame->{'@type'}) === 1 && is_object($frame->{'@type'}[0]))) {
|
!(count($frame->{'@type'}) === 1 && is_object($frame->{'@type'}[0]))) {
|
||||||
|
@ -3897,14 +3907,47 @@ class JsonLdProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check ducktype
|
// check ducktype
|
||||||
|
$wildcard = true;
|
||||||
|
$matches_some = false;
|
||||||
foreach($frame as $k => $v) {
|
foreach($frame as $k => $v) {
|
||||||
// only not a duck if @id or non-keyword isn't in subject
|
if(self::_isKeyword($k)) {
|
||||||
if(($k === '@id' || !self::_isKeyword($k)) &&
|
// skip non-@id and non-@type
|
||||||
!property_exists($subject, $k)) {
|
if($k !== '@id' && $k !== '@type') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$wildcard = false;
|
||||||
|
|
||||||
|
// check @id for a specific @id value
|
||||||
|
if($k === '@id' && is_string($v)) {
|
||||||
|
if(!property_exists($subject, $k) || $subject->{$k} !== $v) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$matches_some = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$wildcard = false;
|
||||||
|
|
||||||
|
if(property_exists($subject, $k)) {
|
||||||
|
// $v === [] means do not match if property is present
|
||||||
|
if(is_array($v) && count($v) === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$matches_some = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all properties must match to be a duck unless a @default is specified
|
||||||
|
$has_default = (is_array($v) && count($v) === 1 && is_object($v[0]) &&
|
||||||
|
property_exists($v[0], '@default'));
|
||||||
|
if($flags['requireAll'] && !$has_default) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
// return true if wildcard or subject matches some properties
|
||||||
|
return $wildcard || $matches_some;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5325,6 +5368,7 @@ class JsonLdProcessor {
|
||||||
case '@list':
|
case '@list':
|
||||||
case '@omitDefault':
|
case '@omitDefault':
|
||||||
case '@preserve':
|
case '@preserve':
|
||||||
|
case '@requireAll':
|
||||||
case '@reverse':
|
case '@reverse':
|
||||||
case '@set':
|
case '@set':
|
||||||
case '@type':
|
case '@type':
|
||||||
|
|
Loading…
Reference in a new issue