Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Enhance API endpoint to support additional filters #7285

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
10 changes: 8 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@
"test": "./vendor/bin/phpunit --colors --stop-on-failure",
"unreleased": "./vendor/bin/since-unreleased.sh",
"strauss": [
"test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/download/0.14.0/strauss.phar",
"vendor/stellarwp/validation/bin/set-domain domain=give",
"test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/download/0.19.1/strauss.phar",
"sed -i 's/PHP_EOL/\"\\n\"/' vendor/stellarwp/validation/bin/set-domain",
"@php vendor/stellarwp/validation/bin/set-domain domain=give",
"@php bin/strauss.phar"
],
"post-install-cmd": [
Expand Down Expand Up @@ -106,6 +107,11 @@
"symfony/deprecation-contracts"
]
},
"exclude_from_prefix": {
"namespaces": [
"session"
]
},
"delete_vendor_packages": true,
"override_autoload": {
"symfony/polyfill-ctype": {},
Expand Down
281 changes: 164 additions & 117 deletions src/Donations/Endpoints/ListDonations.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ class ListDonations extends Endpoint
protected $endpoint = 'admin/donations';

/**
* @unreleased becomes public to be usable in hooks
* @var WP_REST_Request
*/
protected $request;
public $request;

/**
* @unreleased becomes public to be usable in hooks
* @var DonationsListTable
*/
protected $listTable;
public $listTable;

/**
* @since 3.4.0
Expand All @@ -46,6 +48,77 @@ public function __construct(DonationsListTable $listTable)
*/
public function registerRoute()
{
$args = [
'page' => [
'type' => 'integer',
'required' => false,
'default' => 1,
'minimum' => 1
],
'perPage' => [
'type' => 'integer',
'required' => false,
'default' => 30,
'minimum' => 1
],
'form' => [
'type' => 'integer',
'required' => false,
'default' => 0
],
'search' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'start' => [
'type' => 'string',
'required' => false,
'validate_callback' => [$this, 'validateDate']
],
'end' => [
'type' => 'string',
'required' => false,
'validate_callback' => [$this, 'validateDate']
],
'donor' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'sortColumn' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'sortDirection' => [
'type' => 'string',
'required' => false,
'enum' => [
'asc',
'desc',
],
],
'locale' => [
'type' => 'string',
'required' => false,
'default' => get_locale(),
],
'testMode' => [
'type' => 'boolean',
'required' => false,
'default' => give_is_test_mode(),
],
'return' => [
'type' => 'string',
'required' => false,
'default' => 'columns',
'enum' => [
'model',
'columns',
],
],
];
register_rest_route(
'give-api/v2',
$this->endpoint,
Expand All @@ -55,77 +128,22 @@ public function registerRoute()
'callback' => [$this, 'handleRequest'],
'permission_callback' => [$this, 'permissionsCheck'],
],
'args' => [
'page' => [
'type' => 'integer',
'required' => false,
'default' => 1,
'minimum' => 1
],
'perPage' => [
'type' => 'integer',
'required' => false,
'default' => 30,
'minimum' => 1
],
'form' => [
'type' => 'integer',
'required' => false,
'default' => 0
],
'search' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'start' => [
'type' => 'string',
'required' => false,
'validate_callback' => [$this, 'validateDate']
],
'end' => [
'type' => 'string',
'required' => false,
'validate_callback' => [$this, 'validateDate']
],
'donor' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'sortColumn' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'sortDirection' => [
'type' => 'string',
'required' => false,
'enum' => [
'asc',
'desc',
],
],
'locale' => [
'type' => 'string',
'required' => false,
'default' => get_locale(),
],
'testMode' => [
'type' => 'boolean',
'required' => false,
'default' => give_is_test_mode(),
],
'return' => [
'type' => 'string',
'required' => false,
'default' => 'columns',
'enum' => [
'model',
'columns',
],
],
],
/**
* Allow adding API endpoint args
*
* @unreleased
* @param array $args Array of api args {
* Arg details
*
* @type string $type Type of value
* @type boolean $required Is this arg required for each request
* @type mixed $default Optional - Default value for this arg
* @type callable $validate_callback Optional
* @type callable $sanitize_callback Optional
* @type mixed[] $enum Optional - Array of allowed values
* }[]
*/
'args' => apply_filters('give_list-donation_api_args', $args),
]
);
}
Expand Down Expand Up @@ -171,20 +189,22 @@ public function handleRequest(WP_REST_Request $request): WP_REST_Response
*/
public function getDonations(): array
{
$query = give()->donations->prepareQuery();

// Pagination
$page = $this->request->get_param('page');
$perPage = $this->request->get_param('perPage');
$query->limit($perPage)->offset(($page - 1) * $perPage);

// Sort
$sortColumns = $this->listTable->getSortColumnById($this->request->get_param('sortColumn') ?: 'id');
$sortDirection = $this->request->get_param('sortDirection') ?: 'desc';

$query = give()->donations->prepareQuery();
list($query) = $this->getWhereConditions($query);

foreach ($sortColumns as $sortColumn) {
$query->orderBy($sortColumn, $sortDirection);
}

$query->limit($perPage)
->offset(($page - 1) * $perPage);
// Where
list($query) = $this->getWhereConditions($query);

$donations = $query->getAll();

Expand All @@ -203,12 +223,11 @@ public function getDonations(): array
*/
public function getTotalDonationsCount(): int
{
$query = DB::table('posts')
->where('post_type', 'give_payment')
->groupBy('mode');
$query = DB::table('posts')->where('post_type', 'give_payment');

list($query, $dependencies) = $this->getWhereConditions($query);

$dependencies = array_unique($dependencies);
$query->attachMeta(
'give_donationmeta',
'ID',
Expand All @@ -231,35 +250,49 @@ public function getTotalDonationsCount(): int
*/
protected function getWhereConditions(QueryBuilder $query): array
{
$search = $this->request->get_param('search');
$start = $this->request->get_param('start');
$end = $this->request->get_param('end');
$form = $this->request->get_param('form');
$donor = $this->request->get_param('donor');
$testMode = $this->request->get_param('testMode');
$dependencies = [];
list($query, $dependencies) = $this->getSearchWhereCondition($query, $dependencies);
list($query, $dependencies) = $this->getDonorWhereCondition($query, $dependencies);
list($query, $dependencies) = $this->getFormWhereCondition($query, $dependencies);
list($query, $dependencies) = $this->getDateWhereCondition($query, $dependencies);
list($query, $dependencies) = $this->getModeWhereCondition($query, $dependencies);

$dependencies = [
DonationMetaKeys::MODE(),
];

$hasWhereConditions = $search || $start || $end || $form || $donor;
/**
* Allow adding request clauses
*
* @unreleased
* @param array $value {
* @type ModelQueryBuilder $query Donation query builder
* @type DonationMetaKeys[] $dependencies List of meta dependencies for added where clauses
* }
* @param ListDonations $endpoint API Endpoint instance
*/
return apply_filters('give_list-donation_where_conditions', [$query, $dependencies], $this);
}

if ($search) {
if (ctype_digit($search)) {
$query->where('id', $search);
} elseif (strpos($search, '@') !== false) {
$query
->whereLike('give_donationmeta_attach_meta_email.meta_value', $search);
$dependencies[] = DonationMetaKeys::EMAIL();
} else {
$query
->whereLike('give_donationmeta_attach_meta_firstName.meta_value', $search)
->orWhereLike('give_donationmeta_attach_meta_lastName.meta_value', $search);
$dependencies[] = DonationMetaKeys::FIRST_NAME();
$dependencies[] = DonationMetaKeys::LAST_NAME();
}
private function getSearchWhereCondition (QueryBuilder $query, array $dependencies)
{
$search = $this->request->get_param('search');
if (!$search) return [$query, $dependencies];
if (ctype_digit($search)) {
$query->where('id', $search);
} elseif (strpos($search, '@') !== false) {
$query
->whereLike('give_donationmeta_attach_meta_email.meta_value', $search);
$dependencies[] = DonationMetaKeys::EMAIL();
} else {
$query
->whereLike('give_donationmeta_attach_meta_firstName.meta_value', $search)
->orWhereLike('give_donationmeta_attach_meta_lastName.meta_value', $search);
$dependencies[] = DonationMetaKeys::FIRST_NAME();
$dependencies[] = DonationMetaKeys::LAST_NAME();
}
return [$query, $dependencies];
}

private function getDonorWhereCondition (QueryBuilder $query, array $dependencies)
{
$donor = $this->request->get_param('donor');
if ($donor) {
if (ctype_digit($donor)) {
$query
Expand All @@ -273,33 +306,47 @@ protected function getWhereConditions(QueryBuilder $query): array
$dependencies[] = DonationMetaKeys::LAST_NAME();
}
}
return [$query, $dependencies];
}

private function getFormWhereCondition (QueryBuilder $query, array $dependencies)
{
$form = $this->request->get_param('form');
if ($form) {
$query
->where('give_donationmeta_attach_meta_formId.meta_value', $form);
$dependencies[] = DonationMetaKeys::FORM_ID();
}
return [$query, $dependencies];
}

private function getDateWhereCondition (QueryBuilder $query, array $dependencies)
{
$start = $this->request->get_param('start');
$end = $this->request->get_param('end');
if ($start && $end) {
$query->whereBetween('post_date', $start, $end);
} elseif ($start) {
$query->where('post_date', $start, '>=');
} elseif ($end) {
$query->where('post_date', $end, '<=');
}
return [$query, $dependencies];
}

if ($hasWhereConditions) {
$query->havingRaw('HAVING COALESCE(give_donationmeta_attach_meta_mode.meta_value, %s) = %s', DonationMode::LIVE, $testMode ? DonationMode::TEST : DonationMode::LIVE);
} elseif ($testMode) {
private function getModeWhereCondition (QueryBuilder $query, array $dependencies)
{
$dependencies[] = DonationMetaKeys::MODE();
$testMode = $this->request->get_param('testMode');
if ($testMode) {
$query->where('give_donationmeta_attach_meta_mode.meta_value', DonationMode::TEST);
} else {
$query->whereIsNull('give_donationmeta_attach_meta_mode.meta_value')
->orWhere('give_donationmeta_attach_meta_mode.meta_value', DonationMode::TEST, '<>');
$query->where(function ($whereBuilder) {
$whereBuilder
->whereIsNull('give_donationmeta_attach_meta_mode.meta_value')
->orWhere('give_donationmeta_attach_meta_mode.meta_value', DonationMode::TEST, '<>');
});
}

return [
$query,
$dependencies,
];
return [$query, $dependencies];
}
}
Loading
Loading