init
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Listing;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
class Handler {
|
||||
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'] ?? []
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(["'", '"'], [''', '"'], $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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Listing;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
class ListingDefinition {
|
||||
/** @var string|null */
|
||||
private $group;
|
||||
|
||||
/** @var array */
|
||||
private $filters;
|
||||
|
||||
/** @var string|null */
|
||||
private $search;
|
||||
|
||||
/** @var array */
|
||||
private $parameters;
|
||||
|
||||
/** @var string */
|
||||
private $sortBy;
|
||||
|
||||
/** @var string */
|
||||
private $sortOrder;
|
||||
|
||||
/** @var int */
|
||||
private $offset;
|
||||
|
||||
/** @var int */
|
||||
private $limit;
|
||||
|
||||
/** @var int[] */
|
||||
private $selection;
|
||||
|
||||
public function __construct(
|
||||
string $group = null,
|
||||
array $filters = [],
|
||||
string $search = null,
|
||||
array $parameters = [],
|
||||
string $sortBy = 'created_at',
|
||||
string $sortOrder = 'desc',
|
||||
int $offset = 0,
|
||||
int $limit = 20,
|
||||
array $selection = []
|
||||
) {
|
||||
$this->group = $group;
|
||||
$this->filters = $filters;
|
||||
$this->search = $search;
|
||||
$this->parameters = $parameters;
|
||||
$this->sortBy = $sortBy;
|
||||
$this->sortOrder = $sortOrder;
|
||||
$this->offset = $offset;
|
||||
$this->limit = $limit;
|
||||
$this->selection = array_map('intval', $selection);
|
||||
}
|
||||
|
||||
/** @return string|null */
|
||||
public function getGroup() {
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
public function getFilters(): array {
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
/** @return string|null */
|
||||
public function getSearch() {
|
||||
return $this->search;
|
||||
}
|
||||
|
||||
public function getParameters(): array {
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
public function getSortBy(): string {
|
||||
return $this->sortBy;
|
||||
}
|
||||
|
||||
public function getSortOrder(): string {
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function getOffset(): int {
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
public function getLimit(): int {
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
public function getSelection(): array {
|
||||
return $this->selection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Listing;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Util\Helpers;
|
||||
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
||||
use MailPoetVendor\Doctrine\ORM\QueryBuilder;
|
||||
|
||||
abstract class ListingRepository {
|
||||
/** @var QueryBuilder */
|
||||
protected $queryBuilder;
|
||||
|
||||
public function __construct(
|
||||
EntityManager $entityManager
|
||||
) {
|
||||
$this->queryBuilder = $entityManager->createQueryBuilder();
|
||||
}
|
||||
|
||||
public function getData(ListingDefinition $definition): array {
|
||||
$queryBuilder = clone $this->queryBuilder;
|
||||
$sortBy = Helpers::underscoreToCamelCase($definition->getSortBy());
|
||||
$this->applySelectClause($queryBuilder);
|
||||
$this->applyFromClause($queryBuilder);
|
||||
$this->applyConstraints($queryBuilder, $definition);
|
||||
$this->applySorting($queryBuilder, $sortBy, $definition->getSortOrder());
|
||||
$this->applyPaging($queryBuilder, $definition->getOffset(), $definition->getLimit());
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
}
|
||||
|
||||
public function getCount(ListingDefinition $definition): int {
|
||||
$queryBuilder = clone $this->queryBuilder;
|
||||
$this->applyFromClause($queryBuilder);
|
||||
$this->applyConstraints($queryBuilder, $definition);
|
||||
$alias = $queryBuilder->getRootAliases()[0];
|
||||
$queryBuilder->select("COUNT(DISTINCT $alias)");
|
||||
return (int)$queryBuilder->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
public function getActionableIds(ListingDefinition $definition): array {
|
||||
$ids = $definition->getSelection();
|
||||
if (!empty($ids)) {
|
||||
return $ids;
|
||||
}
|
||||
$queryBuilder = clone $this->queryBuilder;
|
||||
$this->applyFromClause($queryBuilder);
|
||||
$this->applyConstraints($queryBuilder, $definition);
|
||||
$alias = $queryBuilder->getRootAliases()[0];
|
||||
$queryBuilder->select("$alias.id");
|
||||
$ids = $queryBuilder->getQuery()->getScalarResult();
|
||||
return array_column($ids, 'id');
|
||||
}
|
||||
|
||||
public function getGroups(ListingDefinition $definition): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getFilters(ListingDefinition $definition): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
abstract protected function applySelectClause(QueryBuilder $queryBuilder);
|
||||
|
||||
abstract protected function applyFromClause(QueryBuilder $queryBuilder);
|
||||
|
||||
protected function applyConstraints(QueryBuilder $queryBuilder, ListingDefinition $definition) {
|
||||
$group = $definition->getGroup();
|
||||
if ($group) {
|
||||
$this->applyGroup($queryBuilder, $group);
|
||||
}
|
||||
|
||||
$search = $definition->getSearch();
|
||||
$parameters = $definition->getParameters();
|
||||
|
||||
if ($search && strlen(trim($search)) > 0) {
|
||||
$this->applySearch($queryBuilder, $search, $parameters ?: []);
|
||||
}
|
||||
|
||||
$filters = $definition->getFilters();
|
||||
if ($filters) {
|
||||
$this->applyFilters($queryBuilder, $filters);
|
||||
}
|
||||
|
||||
if ($parameters) {
|
||||
$this->applyParameters($queryBuilder, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected function applyGroup(QueryBuilder $queryBuilder, string $group);
|
||||
|
||||
abstract protected function applySearch(QueryBuilder $queryBuilder, string $search, array $parameters);
|
||||
|
||||
abstract protected function applyFilters(QueryBuilder $queryBuilder, array $filters);
|
||||
|
||||
abstract protected function applyParameters(QueryBuilder $queryBuilder, array $parameters);
|
||||
|
||||
protected function applySorting(QueryBuilder $queryBuilder, string $sortBy, string $sortOrder) {
|
||||
$alias = $this->queryBuilder->getRootAliases()[0];
|
||||
$queryBuilder->addOrderBy("$alias.$sortBy", $sortOrder);
|
||||
}
|
||||
|
||||
protected function applyPaging(QueryBuilder $queryBuilder, int $offset, int $limit) {
|
||||
$queryBuilder->setFirstResult($offset);
|
||||
$queryBuilder->setMaxResults($limit);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Listing;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class PageLimit {
|
||||
const DEFAULT_LIMIT_PER_PAGE = 20;
|
||||
|
||||
/** @var WPFunctions */
|
||||
private $wp;
|
||||
|
||||
public function __construct(
|
||||
WPFunctions $wp
|
||||
) {
|
||||
$this->wp = $wp;
|
||||
}
|
||||
|
||||
public function getLimitPerPage($model = null) {
|
||||
if ($model === null) {
|
||||
return self::DEFAULT_LIMIT_PER_PAGE;
|
||||
}
|
||||
|
||||
$listingPerPage = $this->wp->getUserMeta(
|
||||
$this->wp->getCurrentUserId(),
|
||||
'mailpoet_' . $model . '_per_page',
|
||||
true
|
||||
);
|
||||
return (!empty($listingPerPage))
|
||||
? (int)$listingPerPage
|
||||
: self::DEFAULT_LIMIT_PER_PAGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
Reference in New Issue
Block a user