[WIP] Begin implementing support for nested/sequential queries
This commit is contained in:
parent
5d643fd3ec
commit
4398f543dc
@ -31,6 +31,7 @@ class ObjectsService
|
|||||||
// TODO validate object fields?
|
// TODO validate object fields?
|
||||||
// TODO don't create the object if it already exists
|
// TODO don't create the object if it already exists
|
||||||
// i.e. (an 'id' field exists with the same value as this one)
|
// i.e. (an 'id' field exists with the same value as this one)
|
||||||
|
// TODO attempt to fetch and create any values that are URLs
|
||||||
$object = new ActivityPubObject();
|
$object = new ActivityPubObject();
|
||||||
$this->entityManager->persist( $object );
|
$this->entityManager->persist( $object );
|
||||||
foreach ( $fields as $name => $value ) {
|
foreach ( $fields as $name => $value ) {
|
||||||
@ -86,28 +87,66 @@ class ObjectsService
|
|||||||
*/
|
*/
|
||||||
public function query( $queryTerms )
|
public function query( $queryTerms )
|
||||||
{
|
{
|
||||||
// TODO make it search for nested objects like the comment says
|
|
||||||
$qb = $this->entityManager->createQueryBuilder();
|
$qb = $this->entityManager->createQueryBuilder();
|
||||||
$qb->select( 'object' )
|
$depth = 0;
|
||||||
->from( '\ActivityPub\Entities\ActivityPubObject', 'object' )
|
$qb->select( "object$depth" )
|
||||||
->join( 'object.fields', 'field' );
|
->from( '\ActivityPub\Entities\ActivityPubObject', "object$depth" )
|
||||||
foreach ( $queryTerms as $fieldName => $fieldValue ) {
|
->join( "object$depth.fields", "field$depth" )
|
||||||
if ( is_array( $fieldValue ) ) {
|
->where( $this->getWhereExpr( $qb, $queryTerms, $depth ) );
|
||||||
// The following two branches will need to be recursive
|
|
||||||
if ( Util::isAssoc( $fieldValue ) ) {
|
|
||||||
// TODO support querying for associative arrays (nested objects)
|
|
||||||
} else {
|
|
||||||
// TODO support querying for sequential arrays
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$qb->where( $qb->expr()->andX(
|
|
||||||
$qb->expr()->like( 'field.name', $qb->expr()->literal( $fieldName ) ),
|
|
||||||
$qb->expr()->like( 'field.value', $qb->expr()->literal( $fieldValue ) )
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$query = $qb->getQuery();
|
$query = $qb->getQuery();
|
||||||
return $query->getResult();
|
return $query->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the expression that gets passed into the query WHERE clause
|
||||||
|
*
|
||||||
|
* This function is recursive; it traverses the query tree to build up the
|
||||||
|
* final expression
|
||||||
|
*
|
||||||
|
* @param QueryBuilder $qb The query builder that the WHERE clause will be attached to
|
||||||
|
* @param array $queryTerms The query terms from which to generate the expressions
|
||||||
|
* @param int $depth The recursion depth
|
||||||
|
* @return Expr The expression
|
||||||
|
*/
|
||||||
|
protected function getWhereExpr( &$qb, $queryTerms, $depth = 0 )
|
||||||
|
{
|
||||||
|
$nextDepth = $depth + 1;
|
||||||
|
$exprs = array();
|
||||||
|
foreach( $queryTerms as $fieldName => $fieldValue ) {
|
||||||
|
if ( is_array( $fieldValue ) ) {
|
||||||
|
if ( Util::isAssoc( $fieldValue ) ) {
|
||||||
|
$subQuery = $this->entityManager->createQueryBuilder();
|
||||||
|
$subQuery->select( "object$nextDepth" )
|
||||||
|
->from( '\ActivityPub\Entities\ActivityPubObject', "object$nextDepth" )
|
||||||
|
->join( "object$nextDepth.fields", "field$nextDepth" )
|
||||||
|
->where( $this->getWhereExpr( $subQuery, $fieldValue, $nextDepth ) );
|
||||||
|
$exprs[] = $qb->expr()->in(
|
||||||
|
"field$depth.targetObject",
|
||||||
|
$subQuery->getDql()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$subExprs = array();
|
||||||
|
foreach ( $fieldValue as $subFieldName => $subFieldValue ) {
|
||||||
|
$subExprs[] = $this->getWhereExpr(
|
||||||
|
$qb, array( $subFieldName => $subFieldValue ), $nextDepth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$exprs[] = call_user_func_array(
|
||||||
|
array( $qb->expr(), 'orX' ),
|
||||||
|
$subExprs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$exprs[] = $qb->expr()->andX(
|
||||||
|
$qb->expr()->like( "field$depth.name", $qb->expr()->literal( $fieldName ) ),
|
||||||
|
$qb->expr()->like( "field$depth.value", $qb->expr()->literal( $fieldValue ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return call_user_func_array(
|
||||||
|
array( $qb->expr(), 'andX' ),
|
||||||
|
$exprs
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -527,5 +527,40 @@ class ObjectsServiceTest extends SQLiteTestCase
|
|||||||
$this->assertContainsOnlyInstancesOf( ActivityPubObject::class, $results );
|
$this->assertContainsOnlyInstancesOf( ActivityPubObject::class, $results );
|
||||||
$this->assertEquals( $object, $results[0] );
|
$this->assertEquals( $object, $results[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testMultiNestedSequentialObjectQueryResults()
|
||||||
|
{
|
||||||
|
$fields = array(
|
||||||
|
'id' => 'https://example.com/notes/1',
|
||||||
|
'type' => 'Note',
|
||||||
|
'content' => 'This is a note',
|
||||||
|
'attributedTo' => array(
|
||||||
|
'id' => 'https://example.com/actors/2',
|
||||||
|
'type' => 'Person',
|
||||||
|
'following' => array(
|
||||||
|
'id' => 'https://example.com/collections/1',
|
||||||
|
'type' => 'Collection',
|
||||||
|
'items' => array(
|
||||||
|
array( 'id' => 'https://example.com/actors/1' ),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$object = $this->objectsService->createObject( $fields );
|
||||||
|
$query = array(
|
||||||
|
'attributedTo' => array(
|
||||||
|
'following' => array(
|
||||||
|
'items' => array(
|
||||||
|
array( 'id' => 'https://example.com/actors/1' )
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
$results = $this->objectsService->query( $query );
|
||||||
|
$this->assertCount( 1, $results );
|
||||||
|
$this->assertContainsOnlyInstancesOf( ActivityPubObject::class, $results );
|
||||||
|
$this->assertEquals( $object, $results[0] );
|
||||||
|
$this->assertEquals( $fields, $results[0]->asArray() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
Loading…
Reference in New Issue
Block a user