Files
piratepoet/lib/Listing/Handler.php
Rostislav Wolny 115738845d Fix deprecated FILTER_SANITIZE_STRING
I'm not sure why FILTER_SANITIZE_STRING was needed here so to be safe
I decided to replace it with a polyfill function.
See https://stackoverflow.com/questions/69207368/constant-filter-sanitize-string-is-deprecated
[MAILPOET-3890]
2021-12-13 09:36:43 +01:00

165 lines
4.4 KiB
PHP

<?php
namespace MailPoet\Listing;
use MailPoetVendor\Paris\Model;
use MailPoetVendor\Paris\ORMWrapper;
class Handler {
const DEFAULT_LIMIT_PER_PAGE = 20;
public function get($modelClass, array $data) {
$data = $this->processData($data);
$tableName = $modelClass::$_table;
$model = Model::factory($modelClass);
// get groups
$groups = [];
$groupsCallback = [$modelClass, 'groups'];
if (method_exists($modelClass, 'groups') && is_callable($groupsCallback)) {
$groups = call_user_func_array(
$groupsCallback,
[$data]
);
}
// get filters
$filters = [];
$filtersCallback = [$modelClass, 'filters'];
if (method_exists($modelClass, 'filters') && is_callable($filtersCallback)) {
$filters = call_user_func_array(
$filtersCallback,
[$data]
);
}
// get items and total count
$listingCallback = [$modelClass, 'listingQuery'];
if (method_exists($modelClass, 'listingQuery') && is_callable($listingCallback)) {
$customQuery = call_user_func_array(
$listingCallback,
[$data]
);
$count = $customQuery->count();
$items = $customQuery
->offset($data['offset'])
->limit($data['limit'])
->{'order_by_' . $data['sort_order']}(
$tableName . '.' . $data['sort_by']
)
->findMany();
} else {
$model = $this->setFilter($model, $data);
$this->setGroup($model, $data);
$this->setSearch($model, $data);
$this->setOrder($model, $data, $tableName);
$count = $model->count();
$items = $model
->offset($data['offset'])
->limit($data['limit'])
->findMany();
}
return [
'count' => $count,
'filters' => $filters,
'groups' => $groups,
'items' => $items,
];
}
public function getListingDefinition(array $data): ListingDefinition {
$data = $this->processData($data);
return new ListingDefinition(
$data['group'],
$data['filter'] ?? [],
$data['search'],
$data['params'] ?? [],
$data['sort_by'],
$data['sort_order'],
$data['offset'],
$data['limit'],
$data['selection'] ?? []
);
}
private function setSearch(ORMWrapper $model, array $data) {
if (empty($data['search'])) {
return;
}
return $model->filter('search', $data['search']);
}
private function setOrder(ORMWrapper $model, array $data, $tableName) {
return $model
->{'order_by_' . $data['sort_order']}(
$tableName . '.' . $data['sort_by']);
}
private function setGroup(ORMWrapper $model, array $data) {
if ($data['group'] === null) {
return;
}
$model->filter('groupBy', $data['group']);
}
private function setFilter(ORMWrapper $model, array $data) {
if ($data['filter'] === null) {
return $model;
}
return $model->filter('filterBy', $data['filter']);
}
/**
* Polyfill for deprecated FILTER_SANITIZE_STRING which was used to sanitize
* $data['sort_by'].
*/
private function filterString(string $string): string {
$str = (string)preg_replace('/\x00|<[^>]*>?/', '', $string);
return str_replace(["'", '"'], ['&#39;', '&#34;'], $str);
}
private function processData(array $data) {
// check if sort order was specified or default to "asc"
$sortOrder = (!empty($data['sort_order'])) ? $data['sort_order'] : 'asc';
// constrain sort order value to either be "asc" or "desc"
$sortOrder = ($sortOrder === 'asc') ? 'asc' : 'desc';
// sanitize sort by
$sortBy = (!empty($data['sort_by']))
? $this->filterString($data['sort_by'])
: '';
if (empty($sortBy)) {
$sortBy = 'id';
}
$data = [
// extra parameters
'params' => (isset($data['params']) ? $data['params'] : []),
// pagination
'offset' => (isset($data['offset']) ? (int)$data['offset'] : 0),
'limit' => (isset($data['limit'])
? (int)$data['limit']
: PageLimit::DEFAULT_LIMIT_PER_PAGE
),
// searching
'search' => (isset($data['search']) ? $data['search'] : null),
// sorting
'sort_by' => $sortBy,
'sort_order' => $sortOrder,
// grouping
'group' => (isset($data['group']) ? $data['group'] : null),
// filters
'filter' => (isset($data['filter']) ? $data['filter'] : null),
// selection
'selection' => (isset($data['selection']) ? $data['selection'] : null),
];
return $data;
}
}