Skip to content

Commit

Permalink
Fix formatting, do some refactoring and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Benestar committed Oct 1, 2015
1 parent e08d746 commit 68a5253
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
composer.phar
vendor/
composer.lock
.idea/
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -183,6 +183,10 @@ via TravisCI, as a TravisCI configuration file is also provided in the root dire

## Release notes

### 0.3.2 (2015-10-01)

* Added `QueryBuilder::describe`

### 0.3.1 (2015-09-06)

* Added support for native values in selects
Expand Down
119 changes: 72 additions & 47 deletions src/QueryBuilder.php
Expand Up @@ -4,6 +4,7 @@

use InvalidArgumentException;
use RangeException;
use RuntimeException;

/**
* Abstraction layer to build SPARQL queries
Expand All @@ -18,23 +19,6 @@
*/
class QueryBuilder {

/**
* Select query
*/
CONST TYPE_SELECT = 'SELECT';

/**
* Describe query
*/
CONST TYPE_DESCRIBE = 'DESCRIBE';

/**
* Current type defaults to select)
*
* @var string
*/
private $currentType = self::TYPE_SELECT;

/**
* @var ExpressionValidator
*/
Expand All @@ -60,6 +44,11 @@ class QueryBuilder {
*/
private $uniqueness = '';

/**
* @var string form of the query, one of SELECT or DESCRIBE
*/
private $queryForm = null;

/**
* @var GraphBuilder
*/
Expand Down Expand Up @@ -90,48 +79,25 @@ public function __construct( array $prefixes = array() ) {
public function getSelects() {
return $this->selects;
}

/**
* Specifies the expressions to describe.
*
* @param string|string[] $expressions
* @return self
* @throws InvalidArgumentException
*/
public function describe($expressions) {
$this->currentType = self::TYPE_DESCRIBE;
return $this->select($expressions);
}

/**
* Specifies the expressions to select.
*
* @param string|string[] $expressions
* @return self
* @throws InvalidArgumentException
* @throws RuntimeException
*/
public function select( $expressions /* expressions ... */ ) {
$expressions = is_array( $expressions ) ? $expressions : func_get_args();

foreach ( $expressions as $expression ) {
$this->expressionValidator->validate( $expression,
ExpressionValidator::VALIDATE_VARIABLE | ExpressionValidator::VALIDATE_FUNCTION_AS
);

// @todo temp hack to add AS definitions to defined variables
$regexHelper = new RegexHelper();
$matches = $regexHelper->getMatches( 'AS \{variable}', $expression );
$this->usageValidator->trackDefinedVariables( $matches );

// @todo detect functions and wrap with brackets automatically
$this->usageValidator->trackUsedVariables( $expression );
$this->selects[] = $expression;
}
$this->setQueryForm( 'SELECT' );
$this->addExpressions( $expressions );

return $this;
}

/**
/**
* Specifies the expressions to select. Duplicate results are eliminated.
*
* @since 0.3
Expand All @@ -141,8 +107,12 @@ public function select( $expressions /* expressions ... */ ) {
* @throws InvalidArgumentException
*/
public function selectDistinct( $expressions /* expressions ... */ ) {
call_user_func_array( array( $this, 'select' ), func_get_args() );
$expressions = is_array( $expressions ) ? $expressions : func_get_args();

$this->setQueryForm( 'SELECT' );
$this->uniqueness = 'DISTINCT ';
$this->addExpressions( $expressions );

return $this;
}

Expand All @@ -156,11 +126,65 @@ public function selectDistinct( $expressions /* expressions ... */ ) {
* @throws InvalidArgumentException
*/
public function selectReduced( $expressions /* expressions ... */ ) {
call_user_func_array( array( $this, 'select' ), func_get_args() );
$expressions = is_array( $expressions ) ? $expressions : func_get_args();

$this->setQueryForm( 'SELECT' );
$this->uniqueness = 'REDUCED ';
$this->addExpressions( $expressions );

return $this;
}

/**
* Specifies the expressions to describe.
*
* @since 0.4
*
* @param string|string[] $expressions
* @return self
* @throws InvalidArgumentException
* @throws RuntimeException
*/
public function describe( $expressions /* expressions ... */ ) {
$expressions = is_array( $expressions ) ? $expressions : func_get_args();

$this->setQueryForm( 'DESCRIBE' );
$this->addExpressions(
$expressions,
ExpressionValidator::VALIDATE_VARIABLE | ExpressionValidator::VALIDATE_FUNCTION_AS
| ExpressionValidator::VALIDATE_IRI | ExpressionValidator::VALIDATE_PREFIXED_IRI
);

return $this;
}

private function setQueryForm( $queryForm ) {
if ( $this->queryForm !== null ) {
throw new RuntimeException( 'Query type is already set to ' . $this->queryForm );
}

$this->queryForm = $queryForm;
}

private function addExpressions( array $expressions, $options = null ) {
foreach ( $expressions as $expression ) {
$this->expressionValidator->validate(
$expression,
$options ?: ExpressionValidator::VALIDATE_VARIABLE | ExpressionValidator::VALIDATE_FUNCTION_AS
);

// @todo temp hack to add AS definitions to defined variables
$regexHelper = new RegexHelper();
$matches = $regexHelper->getMatches( 'AS \{variable}', $expression );
$this->usageValidator->trackDefinedVariables( $matches );

// @todo detect functions and wrap with brackets automatically
$this->usageValidator->trackUsedVariables( $expression );
$this->usageValidator->trackUsedPrefixes( $expression );
$this->selects[] = $expression;
}
}

/**
* Adds the given triple as a condition.
*
Expand Down Expand Up @@ -377,7 +401,8 @@ public function getSPARQL( $includePrefixes = true ) {
$this->usageValidator->validate();

$sparql = $includePrefixes ? $this->prefixBuilder->getSPARQL() : '';
$sparql .= $this->currentType . ' ' . $this->uniqueness . $this->formatSelects() . ' WHERE';
$sparql .= $this->queryForm ?: 'SELECT';
$sparql .= ' ' . $this->uniqueness . $this->formatSelects() . ' WHERE';
$sparql .= ' {' . $this->graphBuilder->getSPARQL() . ' }';
$sparql .= $this->modifierBuilder->getSPARQL();

Expand Down
30 changes: 30 additions & 0 deletions tests/unit/QueryBuilderTest.php
Expand Up @@ -67,6 +67,36 @@ public function testSelectReduced() {
);
}

public function testDescribe() {
$queryBuilder = new QueryBuilder();
$this->assertSame(
$queryBuilder,
$queryBuilder->describe( '?a', '?b', '<foo:bar>' )
);

// use variables ?a and ?b
$queryBuilder->where( '?a', '?b', '?c' );

$this->assertEquals(
'DESCRIBE ?a ?b <foo:bar> WHERE { ?a ?b ?c . }',
$queryBuilder->getSPARQL()
);
}

public function testDescribe_undefinedPrefix() {
$queryBuilder = new QueryBuilder();
$this->assertSame(
$queryBuilder,
$queryBuilder->describe( 'foo:bar' )
);

// use variables ?a and ?b
$queryBuilder->where( '?a', '?b', '?c' );

$this->setExpectedException( 'RangeException' );
$queryBuilder->getSPARQL();
}

public function testWhere() {
$queryBuilder = new QueryBuilder();
$this->assertSame(
Expand Down

0 comments on commit 68a5253

Please sign in to comment.