first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
<?php
namespace security\wordpress\DynamicTables;
class DataTable {
/**
* @var mixed
*/
public $post;
/**
* @var array|int[]
*/
private $paging;
private $queryBuilder;
/**
* @var array
*/
private $validateRaw;
public function __construct( $POST, QueryBuilder $queryBuilder ) {
$this->post = $POST;
$this->queryBuilder = $queryBuilder;
}
/**
* This class validates all sorting parameters
* @throws Exception
*/
public function validateSorting() {
//first we check if the sortColumn and sortDirection are set
if ( isset( $this->post['sortColumn'] ) && isset( $this->post['sortDirection'] ) ) {
//then we check if the sortColumn is a valid column
if (
! in_array( $this->post['sortColumn']['column'], $this->queryBuilder->getColumns() )
) {
//we also check if it is in the validateRaw array
if ( ! in_array( $this->post['sortColumn']['column'], $this->validateRaw ) ) {
throw new Exception( 'Invalid sort column' );
}
}
//then we check if the sortDirection is a valid direction
if ( ! in_array( $this->post['sortDirection'], array( 'asc', 'desc' ) ) ) {
throw new Exception( 'Invalid sort direction' );
}
$this->queryBuilder->orderBy( $this->post['sortColumn']['column'], $this->post['sortDirection'] );
}
return $this;
}
private function getColumns() {
return $this->queryBuilder->getColumns();
}
/**
* @throws Exception
*/
public function setSelect( array $array ) {
//we loop through the array and check if the column is valid
// and if the column starts with raw: we exclude it from the check
$rawColumns = [];
foreach ( $array as $column ) {
if ( strpos( $column, 'raw:' ) === false ) {
if ( ! in_array( $column, $this->getColumns() ) ) {
throw new Exception( 'Invalid column' );
}
} else {
//we remove the column from the array and add it to the rawColumns array
unset( $array[ array_search( $column, $array ) ] );
$rawColumns[] = str_replace( 'raw:', '', $column );
}
}
//we get the first array element and add it to the query
$this->queryBuilder->select( $array[0] );
//we loop through the rest of the array and add it to the query
for ( $i = 1; $i < count( $array ); $i ++ ) {
$this->queryBuilder->addSelect( $array[ $i ] );
}
//we add the raw columns to the query
foreach ( $rawColumns as $rawColumn ) {
$this->queryBuilder->addSelect( $rawColumn );
//we extract the column name from the raw column
$columnName = explode( ' as ', $rawColumn )[1];
//we add the column name to the columns array
$this->validateRaw[] = $columnName;
}
return $this;
}
public function getResults() {
return $this->queryBuilder->paginate( ...$this->paging );
}
/**
* @throws Exception
*/
public function validatePagination() {
$perPage = 10;
$page = 1;
//we check if the paging parameters are set
if ( isset( $this->post['page'] ) ) {
//we check if the page is a number
if ( ! is_numeric( $this->post['page'] ) ) {
throw new Exception( 'Invalid page number' );
}
$page = $this->post['page'];
}
if ( isset( $this->post['currentRowsPerPage'] ) ) {
//we check if the perPage is a number
if ( ! is_numeric( $this->post['currentRowsPerPage'] ) ) {
throw new Exception( 'Invalid per page number' );
}
$perPage = $this->post['currentRowsPerPage'];
}
$this->paging = [ $perPage, $page ];
return $this;
}
public function validateSearch() {
if ( isset( $this->post['search'] ) && count( $this->post['searchColumns'] ) > 0 ) {
//we check if the searchColumns are valid
foreach ( $this->post['searchColumns'] as $column ) {
if ( ! in_array( $column, $this->getColumns() ) ) {
throw new Exception( 'Invalid search column' );
}
}
//we add the search to the query
foreach ( $this->post['searchColumns'] as $column ) {
$this->queryBuilder->where( $column, 'like', '%' . $this->post['search'] . '%' );
}
}
return $this;
}
}

View File

@@ -0,0 +1,213 @@
<?php
namespace security\wordpress\DynamicTables;
class QueryBuilder {
private $table;
private $columns = '*';
private $orderBy = '';
private $limit = '';
private $offset = '';
private $query = '';
private $where;
private $results = array();
public function __construct( $table ) {
$this->table = $table;
}
public function select( $columns ) {
$this->columns = $columns;
return $this;
}
public function addSelect( $columns ) {
$this->columns .= ", $columns";
return $this;
}
public function orderBy( $column, $direction = 'ASC' ) {
$column = str_replace( "'", "", $column );
$this->orderBy = "ORDER BY $column $direction";
return $this;
}
public function limit( $limit, $offset = 0 ) {
$this->limit = "LIMIT $limit";
$this->offset = "OFFSET $offset";
return $this;
}
public function getQuery( $skipLimit = false ) {
$query = "SELECT $this->columns FROM $this->table";
//we loop through the $this->>where array and add it to the query
if ( ! empty( $this->where ) ) {
$query .= " WHERE ";
foreach ( $this->where as $where ) {
$query .= "$where OR ";
}
//we remove the last AND
$query = substr( $query, 0, - 4 );
}
if ( ! empty( $this->orderBy ) ) {
$query .= " $this->orderBy";
}
if ( ! $skipLimit ) {
if ( ! empty( $this->limit ) ) {
$query .= " $this->limit";
}
if ( ! empty( $this->offset ) ) {
$query .= " $this->offset";
}
}
$this->query = $query;
//we validate and cleanup the query
$this->query = str_replace( ';', '', $this->query );
//we look for a double space and replace it with a single space
$this->query = str_replace( ' ', ' ', $this->query );
//we look for a double , and replace it with a single ,
$this->query = str_replace( ', ,', ',', $this->query );
return $this->query;
}
public function get() {
$this->results = $this->execute( $this->getQuery() );
return $this->results;
}
public function toSql() {
$this->getQuery();
return $this->query;
}
public function count() {
$query = $this->getQuery( true );
$countQuery = "SELECT COUNT(*) as count FROM ($query) as subquery";
return $this->execute($countQuery)[0]->count;
}
private function execute( $query ) {
global $wpdb;
return $wpdb->get_results( $query );
}
public function insert( $data ) {
$columns = array();
$values = array();
foreach ( $data as $column => $value ) {
$columns[] = $column;
$values[] = "'" . esc_sql( $value ) . "'";
}
$columns = implode( ', ', $columns );
$values = implode( ', ', $values );
$query = "INSERT INTO $this->table ($columns) VALUES ($values)";
$this->execute( $query );
}
public function update( $data ) {
$set = array();
foreach ( $data as $column => $value ) {
$set[] = "$column = '" . esc_sql( $value ) . "'";
}
$set = implode( ', ', $set );
$query = "UPDATE $this->table SET $set";
$this->execute( $query );
}
public function where( $column, $operator, $value ) {
//we add it to an array so we can build the query later
$this->where[] = "$column $operator '" . esc_sql( $value ) . "'";
return $this;
}
public function whereIn( $column, $values ) {
$column = str_replace( "'", "", $column );
$values = array_map( 'esc_sql', $values );
$values = "'" . implode( "', '", $values ) . "'";
$query = "WHERE $column IN ($values)";
return $query;
}
public function whereNotIn( $column, $values ) {
$column = str_replace( "'", "", $column );
$values = array_map( 'esc_sql', $values );
$values = "'" . implode( "', '", $values ) . "'";
$query = "WHERE $column NOT IN ($values)";
return $query;
}
public function first() {
$this->limit( 1 );
$result = $this->execute( $this->getQuery() );
return isset( $result[0] ) ? $result[0] : null;
}
public function paginate( $rows = 0, $page = 0 ) {
if ( $page > 0 ) {
$offset = ( $page - 1 ) * $rows;
} else {
$offset = 0;
}
$this->limit( $rows, $offset );
$results = $this->get();
$total = $this->count();
$lastPage = ceil( $total / $rows );
return [
'data' => $results,
'pagination' => [
'totalRows' => $total,
'perPage' => $rows,
'offset' => $offset,
'currentPage' => $page,
'lastPage' => $lastPage,
],
//if the debug option in WordPress is set to true, the query will be returned
'query' => $this->toSql(), //- uncomment this line if you want to see the query
];
}
/**
* Get all columns from the table
*
* @return array
*/
public function getColumns(): array {
//we return all columns from the table
$query = "SHOW COLUMNS FROM $this->table";
$result = $this->execute( $query );
return array_column($result, 'Field');
}
}