Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cube-php/core",
"description": "PHP Cube core utilities",
"version": "0.1.21",
"version": "0.1.22",
"type": "library",
"license": "MIT",
"authors": [
Expand All @@ -22,6 +22,7 @@
"twig/twig": "^3.2",
"symfony/console": "^5.2",
"symfony/process": "^5.2",
"symfony/cache": "^5.2"
"symfony/cache": "^5.2",
"dammynex/pagenator": "^0.1.4"
}
}
42 changes: 41 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 40 additions & 1 deletion src/Http/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
namespace Cube\Http;

use Cube\Exceptions\ModelException;
use Cube\Modules\DB;
use Cube\Modules\Db\DBTable;
use Cube\Modules\Db\DBSelect;
use Cube\Interfaces\ModelInterface;
use Cube\Misc\ModelCollection;
use Cube\Misc\PaginatedModelQueryResult;
use Cube\Modules\Db\DBConnection;
use Cube\Modules\Db\DBConnector;
use Cube\Modules\Db\DBUpdate;
use Cube\Modules\Db\DBDelete;
use Cube\Traits\Onceable;
use Dammynex\Pagenator\Pagenator;
use InvalidArgumentException;
use ReflectionClass;

Expand Down Expand Up @@ -893,6 +894,44 @@ public static function lock(): DBSelect
return self::select()->lock();
}

/**
* Run paginated query
*
* @param integer $page
* @param integer $limit
* @param callable $fn
* @return PaginatedModelQueryResult
*/
public static function paginated(int $page, int $limit, callable $fn)
{
$queries = array(
static::getCountQuery(),
static::select()
);

list($query1, $query2) = multi_query($queries, $fn);
$total = $query1->getCount();

$pager = new Pagenator(
items_count: $total,
current_page: $page,
perpage: $limit
);

$query2->orderByDesc(static::$primary_key);

/** @var ModelCollection */
$result = $query2->fetch(
offset: $pager->getOffset(),
limit: $limit
);

return new PaginatedModelQueryResult(
pager: $pager,
result: $result
);
}

/**
* Query schema's table directly
*
Expand Down
26 changes: 26 additions & 0 deletions src/Misc/PaginatedModelQueryResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Cube\Misc;

use Dammynex\Pagenator\Pagenator;

readonly class PaginatedModelQueryResult
{
public function __construct(
public ModelCollection $result,
public Pagenator $pager,
) {
}

public function toResponse(): array
{
return array(
'items' => model2array($this->result),
'pages' => array(
'next' => $this->pager->getNextPage(),
'prev' => $this->pager->getPreviousPage(),
'total' => $this->pager->getTotalPages(),
)
);
}
}
2 changes: 1 addition & 1 deletion src/Modules/Db/DBSelect.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function explain()
* @param int $offset
* @param int $limit
*
* @return object[]|null results
* @return ModelCollection[]|object[]|null results
*/
public function fetch($offset, $limit = null)
{
Expand Down
26 changes: 21 additions & 5 deletions src/Router/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Cube\App\App;
use Closure;

use Cube\Exceptions\AppException;
use InvalidArgumentException;

use Cube\Router\RouteParser;
Expand All @@ -13,6 +13,7 @@
use Cube\Http\AnonController;
use Cube\Http\Model;
use Cube\Misc\ModelCollection;
use Cube\Misc\PaginatedModelQueryResult;
use Stringable;

class Route
Expand Down Expand Up @@ -371,7 +372,12 @@ public function initController(Request $request, Response $response)
$this->_parseController();

if ($this->_is_callble_controller) {
$controller = Closure::bind($this->_controller, new AnonController(), AnonController::class);
$controller = Closure::bind(
$this->_controller,
new AnonController(),
AnonController::class
);

return $this->_analyzeControllerResult($controller, $request, $response);
}

Expand All @@ -390,7 +396,10 @@ public function initController(Request $request, Response $response)
$middleware_fn_name = '__middleware';

if (is_callable([$controller, $middleware_fn_name])) {
$result = call_user_func_array([$controller, $middleware_fn_name], [$request, $response]);
$result = call_user_func_array(
[$controller, $middleware_fn_name],
[$request, $response]
);

if ($result instanceof Response) {
return $result;
Expand Down Expand Up @@ -471,9 +480,10 @@ public function path()
*/
public function use($wares)
{
if (is_array($wares)) {
if (is_array($wares) && count($wares)) {
foreach ($wares as $ware) {
$this->_middlewares[] = class_exists($ware) ? new $ware() : $ware;
$this->_middlewares[] = (is_string($ware) && class_exists($ware))
? new $ware() : $ware;
}
return $this;
}
Expand Down Expand Up @@ -540,6 +550,12 @@ private function _analyzeControllerResult($controller, Request $request, Respons
);
}

if ($result instanceof PaginatedModelQueryResult) {
return $response->json(
$result->toResponse()
);
}

if (is_string($result) || $result instanceof Stringable) {
return $response->write($result);
}
Expand Down