Skip to content

Commit

Permalink
Sanitization fixes.
Browse files Browse the repository at this point in the history
Adds `$wpdb->esc_like` sanitization inside builder. Added wildcard sanitization options inside builder and fixed sanitization algorithm. Unit testing added.
  • Loading branch information
amostajo committed Dec 15, 2019
1 parent 0b2ae98 commit fb8d5a6
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 6 deletions.
57 changes: 54 additions & 3 deletions src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -542,19 +542,70 @@ private function _query_offset( &$query )
private function sanitize_value( $callback, $value )
{
if ( $callback === true )
$callback = is_float( $value )
$callback = ( is_numeric( $value ) && strpos( $value, '.' ) !== false )
? 'floatval'
: ( is_integer( $value )
: ( is_numeric( $value )
? 'absint'
: ( is_string( $value )
? 'sanitize_text_field'
: null
)
);
if ( strpos( $callback, '_builder' ) !== false )
$callback = [&$this, $callback];
if ( is_array( $value ) )
for ( $i = count( $value ) -1; $i >= 0; --$i ) {
$value[$i] = $this->sanitize_value( true, $value[$i] );
}
return $callback ? call_user_func_array( $callback, [$value] ) : $value;
return $callback && is_callable( $callback ) ? call_user_func_array( $callback, [$value] ) : $value;
}
/**
* Returns value escaped with WPDB `esc_like`,
* @since 1.0.6
*
* @param mixed $value
*
* @return string
*/
private function _builder_esc_like( $value )
{
global $wpdb;
return $wpdb->esc_like( $value );
}
/**
* Returns escaped value for LIKE comparison and appends wild card at the beggining.
* @since 1.0.6
*
* @param mixed $value
*
* @return string
*/
private function _builder_esc_like_wild_value( $value )
{
return '%' . $this->_builder_esc_like( $value );
}
/**
* Returns escaped value for LIKE comparison and appends wild card at the end.
* @since 1.0.6
*
* @param mixed $value
*
* @return string
*/
private function _builder_esc_like_value_wild( $value )
{
return $this->_builder_esc_like( $value ) . '%';
}
/**
* Returns escaped value for LIKE comparison and appends wild cards at both ends.
* @since 1.0.6
*
* @param mixed $value
*
* @return string
*/
private function _builder_esc_like_wild_wild( $value )
{
return '%' . $this->_builder_esc_like( $value ) . '%';
}
}
5 changes: 4 additions & 1 deletion tests/cases/QueryBuilderStatementsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,10 @@ public function testWhereRawStatement()
->from( 'test_table' )
->where([
'test_field' => 1,
'raw' => 'a = b',
'raw' => [
'value' => 'a = b',
'sanitize_callback' => false,
],
])
->get();
// Assert
Expand Down
207 changes: 207 additions & 0 deletions tests/cases/SanitizationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
<?php

use TenQuality\WP\Database\QueryBuilder;

/**
* Test.
*
* @author Local Vibes <https://localvibes.co/> Hyper Tribal
* @author 10 Quality <[email protected]>
* @license MIT
* @package wp-query-builder
* @version 1.0.6
*/
class SanitizationTest extends PHPUnit_Framework_TestCase
{
/**
* Test query builder
* @since 1.0.6
*/
public function testSanitizeInt()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => '123',
] )
->get();
$args_int = $wpdb->filter_prepare_args(123);
$args_string = $wpdb->filter_prepare_args('123');
// Assert
$this->assertTrue(count($args_int) >= 1);
$this->assertTrue(count($args_string) == 0);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testSanitizeFloat()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => '99.99',
] )
->get();
$args_float = $wpdb->filter_prepare_args(99.99);
$args_string = $wpdb->filter_prepare_args('99.99');
// Assert
$this->assertTrue(count($args_float) >= 1);
$this->assertTrue(count($args_string) == 0);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testSanitizeString()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => 'string val',
] )
->get();
$args = $wpdb->filter_prepare_args('sanitized(string val)');
// Assert
$this->assertTrue(count($args) >= 1);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testSanitizeCustomCallable()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => [
'value' => 'string val',
'sanitize_callback' => 'custom_sanitize',
],
] )
->get();
$args = $wpdb->filter_prepare_args('custom(string val)');
// Assert
$this->assertTrue(count($args) >= 1);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testEscLike()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => [
'operator' => 'LIKE',
'value' => 'test esc like',
'sanitize_callback' => '_builder_esc_like',
],
] )
->get();
$args = $wpdb->filter_prepare_args('esc_like(test esc like)');
// Assert
$this->assertTrue(count($args) >= 1);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testEscLikeWildValue()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => [
'operator' => 'LIKE',
'value' => 'test esc like',
'sanitize_callback' => '_builder_esc_like_wild_value',
],
] )
->get();
$args = $wpdb->filter_prepare_args('%esc_like(test esc like)');
// Assert
$this->assertTrue(count($args) >= 1);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testEscLikeValueWild()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => [
'operator' => 'LIKE',
'value' => 'test esc like',
'sanitize_callback' => '_builder_esc_like_value_wild',
],
] )
->get();
$args = $wpdb->filter_prepare_args('esc_like(test esc like)%');
// Assert
$this->assertTrue(count($args) >= 1);
}
/**
* Test query builder
* @since 1.0.6
*/
public function testEscLikeWildWild()
{
// Preapre
global $wpdb;
$builder = QueryBuilder::create( 'test' );
// Prepare
// Prepare
$builder->select( '*' )
->from( 'test_table' )
->where( [
'field' => [
'operator' => 'LIKE',
'value' => 'test esc like',
'sanitize_callback' => '_builder_esc_like_wild_wild',
],
] )
->get();
$args = $wpdb->filter_prepare_args('%esc_like(test esc like)%');
// Assert
$this->assertTrue(count($args) >= 1);
}
}
5 changes: 4 additions & 1 deletion tests/framework/wp.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ function absint( $value ) {
return intval( $value );
}
function sanitize_text_field( $value ) {
return $value;
return 'sanitized(' . $value . ')';
}
function custom_sanitize( $value ) {
return 'custom(' . $value . ')';
}
20 changes: 19 additions & 1 deletion tests/framework/wpdb.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* WP mockery class.
* @version 1.0.0
* @version 1.0.6
*/
class WPDB
{
Expand All @@ -11,6 +11,12 @@ class WPDB
* @var string
*/
public static $query = '';
/**
* Last query executed.
* @since 1.0.0
* @var string
*/
public static $prepare_args = '';
/**
* Last table used.
* @since 1.0.0
Expand All @@ -23,6 +29,8 @@ public function prepare()
{
$args = func_get_args();
$query = $args[0];
unset( $args[0] );
static::$prepare_args = $args;
return $query;
}
public function get_results( $query, $output = OBJECT )
Expand Down Expand Up @@ -93,4 +101,14 @@ public function get_table()
{
return static::$table;
}
public function esc_like($val)
{
return 'esc_like('.$val.')';
}
public function filter_prepare_args($value)
{
return array_filter( static::$prepare_args, function($arg) use(&$value) {
return $arg === $value;
} );
}
}

0 comments on commit fb8d5a6

Please sign in to comment.