Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
261 commits
Select commit Hold shift + click to select a range
0f237e9
add SQL files for new DB tables
Sep 3, 2012
5d00883
add better exception handling for stdlib release listing
Sep 3, 2012
4fd4d7f
Merge branch 'master' into stdlib
Oct 29, 2012
4f77dc5
use Assert class for stdlib release listing
Oct 29, 2012
6b20a29
add basic .htaccess file
Oct 29, 2012
eeef997
begin: stdlib release description API
Oct 29, 2012
2216566
add a new semver method: parse array to string
Oct 31, 2012
53d9d6d
add basic class for update type handling
Oct 31, 2012
ab44949
begin implementing stdlib release creation
Oct 31, 2012
2e5602f
fix release creation: retrieve latest release even when unpublished
Oct 31, 2012
8f80a72
release creation: require authentication
Oct 31, 2012
224d14b
uncomment HTTP method check
Oct 31, 2012
4ca4b5c
implement deletion of release
Oct 31, 2012
5d4776a
release creation: support basing on latest published release
Nov 1, 2012
da41327
shorten some code by adding a new method to the UpdateType class
Nov 1, 2012
c6f4a4c
add StdlibRelease class
Nov 1, 2012
d1afffe
simplify code with new class
Nov 1, 2012
4c4273a
minor creation improvement
Nov 1, 2012
d817f7f
remove no longer used function
Nov 1, 2012
0ee6dde
move release creation to StdlibRelease class
Nov 1, 2012
688c215
further simplification of release creation
Nov 1, 2012
bff0ff1
shorten code: do escaping for all items in one place
Nov 1, 2012
b41e3af
release listing: implement "published" filter
Nov 2, 2012
b87f68c
begin implementing release metadata modification
Nov 2, 2012
bbf9c8b
show unpublished releases to stdlib team
Nov 2, 2012
fc18e8e
delete old rewrites
Nov 2, 2012
b75a10a
small fix to StdlibRelease: do not update published releases
Nov 4, 2012
e5b1798
release metadata modification: validate specified date / time
Nov 4, 2012
36abb1f
change DB table: use timestamp to include time
Nov 16, 2012
992a4e5
implement stdlib release publishing
Nov 16, 2012
875af53
new ListReleases() method to StdlibRelease class
Nov 17, 2012
d461395
change system for publish status
Nov 17, 2012
45c13ff
change release listing to use StdlibRelease class
Nov 17, 2012
9536a67
DB change: drop `user` from DB_TABLE_STDLIB
Nov 17, 2012
f5aa886
Merge branch 'master' into stdlib
Nov 18, 2012
174ffd6
begin "update" API
Nov 18, 2012
35cdc9c
change how update types work
Nov 22, 2012
1ad829e
remove config for removed DB table
Nov 22, 2012
134b1f4
fix typo
Nov 22, 2012
3361e03
fix syntax errors and path problems in Stdlib class
Nov 22, 2012
3e2010f
fix StdlibPending class
Nov 22, 2012
3f02ac8
write code to retrieve update type for two semver versions
Nov 22, 2012
e3d0c9c
correct usage mapping for update types
Nov 22, 2012
f5c26ea
supporting addition and removal from / to stdlib
Nov 22, 2012
e9a4c25
release modification: require min. version
Jan 17, 2013
a738a4a
Merge branch 'master' into stdlib
Feb 18, 2013
31f690e
pull changes from submodules
Feb 18, 2013
ecdc94e
PHP 5.2 compatibility: remove usages of __DIR__
Feb 18, 2013
cb71bfa
fix paths for HttpException and semver
Feb 18, 2013
e03b10d
use Assert class constants
Feb 18, 2013
5bfb900
shorten code with sql2array()
Feb 18, 2013
38c308c
fix SQL with binary
Feb 18, 2013
3772afc
fix UpdateType class for array index 0
Feb 19, 2013
07eaf5e
PHP 5.2: no anonymous functions
Feb 19, 2013
f16ae2a
First work on sorting support for item listing
Feb 22, 2013
224bf81
shorten code for listing authentication
Feb 23, 2013
72dcd55
remove unnecessary constant definitions
Feb 23, 2013
9e5e148
add small comment
Feb 23, 2013
a28e847
work on release creation version checks
Feb 23, 2013
19214bd
fix old copy-paste error
Feb 23, 2013
15c2528
fix typo from 72dcd55f2
Feb 23, 2013
dcdd6a0
change release table: allow date to be NULL
Feb 23, 2013
77af0d7
move release creation to a new StdlibRelease::create() method
Feb 23, 2013
4519bcb
entirely delete obsolete item modification code
Feb 23, 2013
621f699
item description: item list
Feb 23, 2013
9ab3ceb
update STDLIB_PENDING table
Feb 23, 2013
5946b55
rename StdlibPending method
Feb 23, 2013
697e508
move get_update function into UpdateType class
Feb 23, 2013
3122e7a
fix relative require_once() calls in StdlibRelease.php
Feb 23, 2013
93b5553
move logic for finding pending entries for a release
Feb 23, 2013
ac0cdca
support release description item list for unpublished releases
Feb 23, 2013
587f5bf
Stdlib::GetItems() - support unpublished releases
Feb 23, 2013
9eed1f8
modify StdlibPending::GetAllEntries() output
Feb 23, 2013
535652e
support changelog for unpublished releases
Feb 23, 2013
333e625
remove update type from release description
Feb 23, 2013
547588f
add a method for getting the diff between 2 releases
Feb 24, 2013
b9a08d4
support changelogs for published releases
Feb 24, 2013
7011758
remove unused `update` DB columns
Feb 24, 2013
47187a7
StdlibPending::GetEntries() - remove check for published release
Feb 24, 2013
6931662
remove obsolete and useless API
Feb 24, 2013
d71596a
Add Stdlib::writeEntry()
Feb 24, 2013
0ce0a7f
Add Stdlib::GetItemsUnpublished()
Feb 24, 2013
7ee6e70
add method for previous release to StdlibRelease class
Feb 24, 2013
590b8c3
fix StdlibPending::DeleteEntry() column name
Feb 24, 2013
0c458db
add a force_unpublished parameter to StdlibRelease::update()
Feb 24, 2013
b137114
one more SQL fix to StdlibPending::DeleteEntry()
Feb 24, 2013
0bd61b0
add new StdlibRelease::publish() method
Feb 24, 2013
c42c796
workaround for releases with timed publication
Feb 24, 2013
4a36666
rename privilege for stdlib
Feb 24, 2013
2477ebc
move most of sorting logic to separate file
Feb 24, 2013
2c2f1a3
support user sorting
Feb 24, 2013
a657a67
fix regression: include rating if it is used for sorting
Feb 24, 2013
a924a8b
fix sorting according to rating
Feb 24, 2013
d24cc53
simplify publication code with a new DB field
Feb 27, 2013
944a25b
delete pending removals on publish
Feb 28, 2013
20adf6f
delete unused table
Feb 28, 2013
67646c6
add new privilege STDLIB_ADMIN
Feb 28, 2013
9ed1637
require STDLIB_ADMIN privilege for release publication and deletion
Feb 28, 2013
fb9ae27
add DB tables for candidate handling
Feb 28, 2013
bcd5a1e
Add methods to check if an item is pending for or in the stdlib
Feb 28, 2013
8fd7a72
delete config for deleted DB
Feb 28, 2013
148598e
add config for new DBs
Feb 28, 2013
2ec5602
begin a Candidate class for candidate handling
Feb 28, 2013
b83f919
add candidate creation API
Feb 28, 2013
14ba626
fix path
Feb 28, 2013
d32c8c9
add .htaccess file for candidates
Feb 28, 2013
4dffb14
fix DB table constant name
Feb 28, 2013
6d6ee67
add listing function to Candidate class
Feb 28, 2013
3fcaa58
begin listing API for candidates
Feb 28, 2013
de89e5b
begin rating of candidates
Feb 28, 2013
f5856f5
retrieve the user who suggested a candidate
Mar 1, 2013
7448c16
retrieve item for candidate ID and vice versa
Mar 1, 2013
7851fb4
Rename + Add methods
Mar 1, 2013
75861ca
add checks in case a candidate is not found
Mar 1, 2013
5a921d5
Add DB column and method for approval
Mar 1, 2013
c188c85
implement method for acception status retrieval
Mar 1, 2013
8f39cf3
add a method for checking if candidate has been approved
Mar 1, 2013
513e9f4
Add missing config file required for Candidate::accepted()
Mar 1, 2013
ee9e5bf
Begin API method for candidate approval
Mar 1, 2013
3b9561e
implement StdlibPending::AddEntry()
Mar 1, 2013
d8f7fee
Use new StdlibPending method when a candidate is accepted and approved
Mar 1, 2013
1fc680b
Some more restrictions on candidate rating
Mar 1, 2013
f28a8cc
Rename candidate "rating" to "voting"
Mar 1, 2013
f08608a
implement retrieval of candidate votes
Mar 1, 2013
891843f
begin candidate description API
Mar 2, 2013
c6c27f2
begin supporting filters for candidate list
Mar 2, 2013
0ad75be
fix incorrect error check (copy-paste error)
Mar 9, 2013
31e266d
fix StdlibPending SQL syntax error
Mar 9, 2013
09becc8
fix missing content negotiation
Mar 9, 2013
fc80300
fix incorrect variable name
Mar 9, 2013
7f77003
methods without output: return status code 204
Mar 9, 2013
5ed674d
valid XML - corresponds to 88f99ff71bd2
Mar 9, 2013
e5f0e96
valid XML - corresponds to 88f99ff71bd2
Mar 9, 2013
19b92b3
implement release description XML output
Mar 9, 2013
604a252
minor bug fix: release "published" status is boolean, not integer
Mar 9, 2013
21e575c
candidate approval: reject if already approved
Mar 9, 2013
69d311e
one more boolean fix: this time candidate voting list
Mar 9, 2013
fb7dd08
implement planned candidate listing filters
Mar 9, 2013
bae77b3
Merge branch 'stdlib-candidates' into stdlib
Mar 9, 2013
c9583a5
Add API to list items in all releases
Mar 9, 2013
c0b1844
candidate voting API: only redirect matching request methods
Mar 9, 2013
2356cad
Add missing .htaccess for new stdlib API method
Mar 9, 2013
d890a1c
candidate creation: allow requests to remove an item
Mar 9, 2013
27b402d
item list cleanup: remove misplaced output
Mar 10, 2013
70a1218
adjust XML output to recent item list changes
Mar 10, 2013
76080d1
add README
Mar 10, 2013
4fe4297
list pending entries (for all kinds of releases)
Mar 11, 2013
080582c
2 fixes to StdlibPending::GetEntries()
Mar 11, 2013
1ec02cf
change StdlibPending::GetEntries()
Mar 11, 2013
5c8eec8
add 2 filters to pending list
Mar 11, 2013
4f2fa67
implement editing the pending item's changelog comment
Mar 15, 2013
80fdd3b
add method to bump a semver version
Mar 16, 2013
8ddbaf1
Revert "change StdlibPending::GetEntries()"
Mar 16, 2013
b0351f6
Adjust list of pending items to commit 8ddbaf186e
Mar 16, 2013
573442f
implement delay handling
Mar 16, 2013
ed3c2a1
Add new 'release' filter to pending list
Mar 16, 2013
e09fd59
add API for delaying a pending item
Mar 16, 2013
688c9cf
Merge pull request #28 from maul-esel/stdlib-pending
Mar 16, 2013
cb7868e
rename DB columns to fit variable item types
Mar 16, 2013
ca4dbf2
rename param
Mar 16, 2013
75f4ca0
add new config: item types allowed in the stdlib
Mar 16, 2013
05c2dbb
adjust release description to variable item types
Mar 16, 2013
1f2d14a
small fix: use UpdateType constant instead of literal
Mar 16, 2013
b5f4f97
shorten release creation code, minor code shortening for UpdateType
Mar 16, 2013
8e408e7
Merge branch 'stdlib-item-types' into stdlib
Mar 16, 2013
6c710e8
pending items list: add 'name' filter
Mar 16, 2013
9ce47c9
rename config setting to be less misunderstandable
Mar 16, 2013
8d0eb22
add some DB hygiene cleanup code
Mar 16, 2013
2bbbbed
Merge branch 'stdlib' into ALD-API/master
Mar 16, 2013
f25a2c8
Merge branch 'master' into sorting
Mar 17, 2013
e3f89e9
add minimal .travis.yml file for travis testing
Mar 21, 2013
2b0e9e3
add mysql setup script
Mar 21, 2013
e5416aa
add config copy for travis
Mar 21, 2013
52d3cde
add profile config script
Mar 21, 2013
7337774
fix profile script (broken due to unsupported command)
Mar 21, 2013
60ec0e4
fix User class for privilege renamings and additions
Mar 21, 2013
cb16e25
specify tests directory for phpunit
Mar 21, 2013
93b94cf
add first test class UserTest
Mar 21, 2013
acc2379
Merge branch 'master' into testing
Mar 21, 2013
0250690
enable coloured output
Mar 21, 2013
f12bbcb
add more debug info on failing test
Mar 21, 2013
15f5583
remove git submodule cloning (done by travis)
Mar 22, 2013
8b616e0
move common sorting code to new SortHelper class
Mar 22, 2013
7c91da1
fix item retrieval for unpublished stdlib releases
Mar 22, 2013
d589805
return NULL from StdlibRelease::getVersion()
Mar 22, 2013
ec7ac80
implement sorting for suspension list
Mar 22, 2013
dcd1c52
configure travis to only build the testing branch
Mar 22, 2013
1d28988
testing: try changing character set to make tests pass
Mar 22, 2013
0cdb6b8
indent test setup output [ci skip]
Mar 22, 2013
91ec3f8
To be sure, output MySQL encoding during test setup
Mar 22, 2013
a3e2c6c
improve output for MySQL setup [ci skip]
Mar 22, 2013
467ae9d
Adjust mysql encoding to travis
Mar 22, 2013
7bd5e69
try fixing travis builds: set charset to latin1
Mar 22, 2013
94dbe5c
changing the character set worked [ci skip]
Mar 22, 2013
a190dc5
include status images in README
Mar 22, 2013
9edb5ab
fix item list version sorting to obey semver
Mar 23, 2013
29f213d
Update README.md
Mar 23, 2013
c30e931
one more fix for getVersion() returning NULL (d5898054ba)
Mar 23, 2013
858527d
Merge branch 'master' into sorting
Mar 23, 2013
2bbf699
item list sorting: remove literal DB table name
Mar 23, 2013
cdf2034
Fix SortHelper for columns with different names
Mar 23, 2013
4447c07
add sorting support for stdlib release listing
Mar 23, 2013
81d18d7
support sorting by creation and approval date for candidates
Mar 24, 2013
1404928
enable sorting support for candidate voting output
Mar 24, 2013
0cc701b
fix Candidate::accepted() to return a bool
Mar 24, 2013
042bc9d
fix StdlibPending: MAJOR release can hold anything, not PATCH
Mar 24, 2013
6386bf5
fix stdlib release description for first release
Mar 24, 2013
b650f6e
Add sort support for stdlib/items
Mar 24, 2013
4a5fec9
support prerelease and build parts when comparing semver
Mar 24, 2013
9bb2269
Merge pull request #24 from maul-esel/sorting
Mar 24, 2013
1d690a9
minor code shortening in Suspensions class
Mar 24, 2013
bab8c1d
fix Suspension::getSuspensions() to pass on sorting array
Mar 24, 2013
ae78166
add a lot of new filters to suspension listing
Mar 24, 2013
90a3ff3
begin a helper class for filtering
Mar 24, 2013
63dc4ff
Use new FilterHelper class for suspension filters
Mar 24, 2013
9103bfd
fix FilterHelper value conversion
Mar 24, 2013
a167ee3
FilterHelper: escape column names always
Mar 24, 2013
7caa599
fix null-check handling: was inversed
Mar 24, 2013
36d7ad9
Suspension filters: remove duplication
Mar 24, 2013
adbd1cb
Rewrite candidate list filters with new class
Mar 24, 2013
e406935
undo meaningless whitespace change
Mar 24, 2013
7edb1d7
some code shortening when retrieving sort data
Mar 24, 2013
99c808b
cleanup FilterHelper code by breaking it into several methods
Mar 25, 2013
6e19a40
simplify suspension listing by removing duplication (@36d7ad9fb6)
Mar 25, 2013
53a034d
massive changes to FilterHelper to support more complex conditions
Mar 25, 2013
eadc5bf
extend FilterHelper to handle table joins
Mar 25, 2013
571eb97
remove undefined parameter from suspension sorting
Mar 25, 2013
8105a4c
minor code shortening for FilterHelper
Mar 25, 2013
635edd5
Shorten FilterHelper with new getValue() method
Mar 25, 2013
4b52dd1
support values of type "custom" for filters
Mar 25, 2013
3f93641
support REGEXP operator for filters
Mar 25, 2013
62c4e00
Convert item list filters to FilterHelper class
Mar 25, 2013
832dad5
convert stdlib items filtering to FilterHelper class
Mar 25, 2013
d525f48
Merge branch 'rework-filters' into master
Mar 26, 2013
e3bff67
also test on PHP 5.5
Mar 27, 2013
bac017c
undo whitespace and debugging changes
Mar 27, 2013
37a9cff
Merge branch 'fixes' into master
Mar 28, 2013
4971971
remove unused function
Mar 28, 2013
c46140e
switch from MySQL extension to MySQLI
Mar 28, 2013
7bd4f8a
When retrieving a MySQL row, always use fetch_assoc()
Mar 28, 2013
f3ba7c8
bump travis-ci build
Mar 28, 2013
b5bdc8b
Merge pull request #32 from maul-esel/mysqli
Mar 28, 2013
ffe3791
Merge branch 'master' into testing
Mar 28, 2013
7683d37
adjust tests to MySQL changes
Mar 28, 2013
b8d60b7
remove useless output of client encoding
Mar 28, 2013
c03cfc8
Revert "minor code shortening in Suspensions class"
Mar 28, 2013
c5e651c
Merge branches 'master' and 'fixes' into testing
Mar 29, 2013
d133faa
improve User tests
Mar 29, 2013
e81f004
add some tests for suspensions
Mar 29, 2013
d36efe6
Merge branch 'fixes' into testing
Mar 29, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
language: php
php:
- "5.5"
- "5.4"
- "5.3"
- "5.2"

services:
- mysql

before_script:
- ./tests/setup/db-mysql.sh
- ./tests/setup/profile.sh travis

script: phpunit --colors tests

branches:
only:
- testing
262 changes: 262 additions & 0 deletions FilterHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
<?php
require_once(dirname(__FILE__) . '/modules/HttpException/HttpException.php');

class FilterHelper {
private $filters = array();

/*
* Public class instance interface
*/
public function __construct($db_connection, $table) {
$this->connection = $db_connection;
$this->table = $table;
}

public function add($data) { #$name, $db_name = NULL, $method = 'GET', $op = '=', $default = NULL, $force = NULL) {
$this->filters[] = $data; #array('name' => $name, 'db-name' => $db_name, $method => 'GET', 'operator' => $op, 'default' => $default, 'force-value' => $force);
}

public function evaluate($source, $prefix = ' WHERE ') {
$db_cond = '';
$this->source = $source;

foreach ($this->filters AS $filter) {

if (isset($filter['conditions'])) {
if ($filter['type'] != 'switch') {
throw new HttpException(500, NULL, 'Only filters of type "switch" can have conditions');
}
$conditions = $filter['conditions'];
} else {
$conditions = array($filter);
}

# if the filter is a switch and it is disabled: skip the entire thing
if (self::extractType($filter, $null) == 'switch') {
if ($this->extractValue($filter, $value)) {
if (!$this->coerceValue($value, 'switch', $filter)) { # returns false for disabled filters
continue;
}
}
}

$cond = $this->evaluateConditions($conditions, $filter);
if ($cond) {
$db_cond .= ($db_cond ? ' AND ' : '') . $cond;
}
}
return $db_cond ? $prefix . $db_cond : '';
}

public function evaluateJoins() {
$table_list = array();

foreach ($this->filters AS $filter) { # joins are only supported on filter-level
if (isset($filter['db-table']) && $filter['db-table'] != $this->table) {
if (!isset($filter['join-ref']) || !isset($filter['join-key'])) {
throw new HttpException(500, NULL, 'Must specify JOIN key and reference for filters');
}

if (!isset($table_list[$filter['db-table']])) {
$table_list[$filter['db-table']][$filter['join-ref']] = $filter['join-key'];
} else {
$table_list[$filter['db-table']] = array($filter['join-ref'] => $filter['join-key']);
}
}
}

if (count($table_list) > 0) {
array_walk($table_list, array($this, 'extractJoinCondition'));
return ' LEFT JOIN ' . implode(' AND ', array_keys($table_list)) . ' ON (' . implode(' AND ', $table_list) . ')';
}
return '';
}

/*
* Table join condition evaluation
*/
function extractJoinCondition(&$arr, $tbl) {
$join = '';
foreach ($arr AS $ref => $key) {
$join .= ($join ? ' AND ' : '') . '`' . $this->table . '`.`' . $ref . '` = `' . $tbl . '`.`' . $key . '`';
}
$arr = $join;
}

/*
* Main conversion method
*/
private function evaluateConditions($conditions, $filter) {
$logic = self::extractLogic($conditions);

$db_cond = '';
foreach ($conditions AS $condition) {
if (array_key_exists(0, $condition)) { # another array of sub-conditions
# obey the value of the switch containing this condition set by reversing it if the switch was turned off
if ($this->should_reverse_logic($filter, $filter_value)) {
$operator = self::reverseOperator($operator);
$logic = self::reverseLogic($logic);
}

$cond = $this->evaluateConditions($condition, $filter);
if ($cond) {
$db_cond .= ($db_cond ? ' ' . $logic . ' ' : '') . $cond;
}

} else {
$data = array_merge(self::FromParams(array('db-name', 'name', 'type', 'default', 'db-table', 'join-key', 'join-on'), $filter), $condition); # collect data

if (!isset($data['name']) && !isset($data['db-name'])) {
throw new HttpException(500, NULL, 'Must specify "name" or "db-name" for filter');
}
$key = '`' . (isset($data['db-table']) ? $data['db-table'] : $this->table) . '`.`' . (isset($data['db-name']) ? $data['db-name'] : $data['name']) . '`'; # the name is also used as column name if no other is specified

# Get the value for comparison
if (!$this->getValue($data, $value, $null_check)) {
continue;
}

if ($null_check === NULL) {
$operator = isset($data['operator']) ? $data['operator'] : '=';
self::validateOperator($operator);

# obey the value of the switch containing this condition by reversing it if the switch was turned off
if ($this->should_reverse_logic($filter, $filter_value) && $filter_value != $value) {
$operator = self::reverseOperator($operator);
$logic = self::reverseLogic($logic);
}

$db_cond .= ($db_cond ? ' ' . $logic . ' ' : '') . $key . ' ' . $operator . ' ' . $value;
} else {
$db_cond .= ($db_cond ? ' ' . $logic . ' ' : '') . $key . ' IS ' . (($null_check xor $value == 'TRUE') ? 'NOT ' : '') . 'NULL';
}
}
}
return $db_cond ? '(' . $db_cond . ')' : $db_cond;
}

private function should_reverse_logic($filter, &$filter_value) {
return $this->getValue($filter, $filter_value, $filter_null)
&& $this->extractType($filter, $filter_null) == 'switch'
&& !$filter_null
&& $filter_value == 'FALSE';
}

/*
* Logic handling code
*/
private static $logic_map = array('AND' => 'OR', 'OR' => 'AND');

private static function extractLogic(&$conditions) {
$logic = isset($conditions['logic']) ? strtoupper($conditions['logic']) : 'AND'; # default is 'AND'
self::validateLogic($logic);
unset($conditions['logic']); # avoid iterating through it below

return $logic;
}

private static function validateLogic($logic) {
if (!in_array($logic, array_keys(self::$logic_map))) {
throw new HttpException(500, NULL, 'Unsupported filter logic "' . $logic . '"');
}
}

private static function reverseLogic($logic) {
return self::$logic_map[$logic];
}

/*
* Type handling code
*/
private static function extractType($filter, &$null_check) {
$null_check = isset($filter['null']) ? $filter['null'] : NULL;
return $null_check !== NULL ? 'switch' : (isset($filter['type']) ? $filter['type'] : 'string');
}

/*
* Operator handling code
*/
private static $operator_map = array('>' => '<=', '<=' => '>', '<' => '>=', '>=' => '<', '=' => '!=', '!=' => '=', 'REGEXP' => 'NOT REGEXP', 'NOT REGEXP' => 'REGEXP');

private static function reverseOperator($operator) {
return self::$operator_map[$operator];
}

private static function validateOperator($operator) {
if (!in_array($operator, array_keys(self::$operator_map))) {
throw new HttpException(500, NULL, 'Unsupported filter operator "' . $operator . '"');
}
}

/*
* Value handling code
*/
private function extractValue($filter, &$value) {
if (isset($filter['value'])) { # a value has explicitly been specified
$value = $filter['value'];
} else if (isset($filter['name'])) { # a name to look for in the parameters (GET or POST) has been specified
if (isset($this->source[$filter['name']])) {
$value = $this->source[$filter['name']];
} else if (isset($filter['default'])) { # it is not specified in parameters, but a default was provided
$value = $filter['default'];
} else {
return false;
}
} else { # neither name nor value specified => error
throw new HttpException(500, NULL, 'Must specify "name" or "value" for filter');
}

return true;
}

private function getValue($filter, &$value, &$null_check) {
$type = $this->extractType($filter, $null_check);
return $this->extractValue($filter, $value) AND $this->coerceValue($value, $type, $filter);
}

private function coerceValue(&$value, $type, $filter) {
switch ($type) {
case 'string': $value = '"' . $this->connection->real_escape_string($value) . '"';
break;
case 'int': $value = (int)$value;
break;
case 'bool': $value = $value ? 'TRUE' : 'FALSE';
break;
case 'binary': $value = 'UNHEX("' . $this->connection->real_escape_string($value) . '")';
break;
case 'expr': break;
case 'custom':
if (!isset($filter['coerce']) || !is_callable($filter['coerce'])) {
throw new HttpException(500, NULL, 'None or invalid callback for filter value coerce');
}
$value = call_user_func($filter['coerce'], $value, $this->connection);
break;
case 'switch':
if (in_array($value, array('yes', 'true', 1, '+1'))) {
$value = 'TRUE';
} else if (in_array($value, array('no', 'false', -1))) {
$value = 'FALSE';
} else if (in_array($value, array('both', '0'))) {
return false;
} else {
throw new HttpException(400, NULL, 'Invalid value "' . $value . '" for switch specified!');
}
break;
default:
throw new HttpException(500, NULL, 'Unsupported filter type "' . $type . '"');
}
return true;
}

/*
* Public function for filtering HTTP params for supported filters
*/
public static function FromParams($filters, $source = NULL) {
$source = $source !== NULL ? $source : $_GET;
if (!is_array($source)) {
throw new HttpException(500, NULL, 'Must provide valid array as filter source');
}
return array_intersect_key($source, array_flip($filters));
}
}
?>
Loading