Skip to content

Commit

Permalink
chore: update demo (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi authored Jul 27, 2024
1 parent dbbb67b commit 8574f1d
Show file tree
Hide file tree
Showing 9 changed files with 539 additions and 224 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# 0.16.1

* fix: fix `QueryBuilderAdapter` error when WHERE statement is empty
* chore: update demo

# 0.16.0

Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ your data.

### Queries

This library supports queries with multiple sort columns.
Multiple sort columns are supported. The library will automatically generate the
WHERE query for you, including the complex cases involving more than two sort
columns. The only requirement is that the query needs to have a deterministic
sort order.

The required query for performing keyset pagination is complex, especially if
more than one column is used for sorting. This library handles that task
automatically. The only requirement is that the query needs to have a
deterministic sort order.
Some backends also have the option to use SQL row values syntax for a slightly
better performance.

### Bidirectional Navigation and Page Skipping

Expand Down
183 changes: 181 additions & 2 deletions tests/public/prism.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,182 @@
/* PrismJS 1.29.0
https://prismjs.com/download.html#themes=prism&languages=markup+markup-templating+php */
code[class*=language-],pre[class*=language-]{color:#000;font-weight:500;background:0 0;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-]:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
https://prismjs.com/download.html#themes=prism-coy&languages=markup+markup-templating+php+sql */
code[class*=language-],
pre[class*=language-] {
color: #000;
background: 0 0;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre-wrap;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none
}

pre[class*=language-] {
position: relative;
margin: .5em 0;
overflow: visible;
padding: 1px
}

pre[class*=language-]>code {
position: relative;
z-index: 1;
border-left: 10px solid #358ccb;
box-shadow: -1px 0 0 0 #358ccb, 0 0 0 1px #dfdfdf;
background-color: #fdfdfd;
background-size: 3em 3em;
background-origin: content-box;
background-attachment: local
}

code[class*=language-] {
max-height: inherit;
height: inherit;
padding: 0 1em;
display: block;
overflow: auto
}

:not(pre)>code[class*=language-],
pre[class*=language-] {
background-color: #fdfdfd;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-bottom: 1em
}

:not(pre)>code[class*=language-] {
position: relative;
padding: .2em;
border-radius: .3em;
color: #c92c2c;
border: 1px solid rgba(0, 0, 0, .1);
display: inline;
white-space: normal
}

.token.block-comment,
.token.cdata,
.token.comment,
.token.doctype,
.token.prolog {
color: #7d8b99
}

.token.punctuation {
color: #5f6364
}

.token.boolean,
.token.constant,
.token.deleted,
.token.function-name,
.token.number,
.token.property,
.token.symbol,
.token.tag {
color: #c92c2c
}

.token.attr-name,
.token.builtin,
.token.char,
.token.function,
.token.inserted,
.token.selector,
.token.string {
color: #2f9c0a
}

.token.entity,
.token.operator,
.token.url,
.token.variable {
color: #a67f59;
background: rgba(255, 255, 255, .5)
}

.token.atrule,
.token.attr-value,
.token.class-name,
.token.keyword {
color: #1990b8
}

.token.important,
.token.regex {
color: #e90
}

.language-css .token.string,
.style .token.string {
color: #a67f59;
background: rgba(255, 255, 255, .5)
}

.token.important {
font-weight: 400
}

.token.bold {
font-weight: 700
}

.token.italic {
font-style: italic
}

.token.entity {
cursor: help
}

.token.namespace {
opacity: .7
}

@media screen and (max-width:767px) {

pre[class*=language-]:after,
pre[class*=language-]:before {
bottom: 14px;
box-shadow: none
}
}

pre[class*=language-].line-numbers.line-numbers {
padding-left: 0
}

pre[class*=language-].line-numbers.line-numbers code {
padding-left: 3.8em
}

pre[class*=language-].line-numbers.line-numbers .line-numbers-rows {
left: 0
}

pre[class*=language-][data-line] {
padding-top: 0;
padding-bottom: 0;
padding-left: 0
}

pre[data-line] code {
position: relative;
padding-left: 4em
}

pre .line-highlight {
margin-top: 0
}
3 changes: 2 additions & 1 deletion tests/public/prism.js

Large diffs are not rendered by default.

124 changes: 96 additions & 28 deletions tests/src/App/Controller/DemoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,59 @@

namespace Rekalogika\Rekapager\Tests\App\Controller;

use Doctrine\ORM\EntityManagerInterface;
use Rekalogika\Contracts\Rekapager\PageableInterface;
use Rekalogika\Rekapager\Bundle\Contracts\PagerFactoryInterface;
use Rekalogika\Rekapager\Bundle\PagerOptions;
use Rekalogika\Rekapager\Tests\App\Contracts\PageableGeneratorInterface;
use Rekalogika\Rekapager\Tests\App\Doctrine\SqlLogger;
use Rekalogika\Rekapager\Tests\App\Entity\Post;
use Rekalogika\Rekapager\Tests\App\Form\PagerParameters;
use Rekalogika\Rekapager\Tests\App\Form\PagerParametersType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
use Symfony\Component\DependencyInjection\Attribute\AutowireIterator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;

/** @psalm-suppress PropertyNotSetInConstructor */
class DemoController extends AbstractController
{
/**
* @var array<array-key,PageableGeneratorInterface<array-key,mixed>>
*/
private readonly array $pageableGenerators;

/**
* @param iterable<PageableGeneratorInterface<array-key,mixed>> $pageableGenerators
* @psalm-suppress DeprecatedClass
*/
public function __construct(
#[TaggedIterator('rekalogika.rekapager.pageable_generator', defaultIndexMethod: 'getKey')]
private readonly iterable $pageableGenerators,
#[AutowireIterator('rekalogika.rekapager.pageable_generator', defaultIndexMethod: 'getKey')]
iterable $pageableGenerators
) {
/**
* @psalm-suppress InvalidArgument
* @psalm-suppress MixedPropertyTypeCoercion
*/
$this->pageableGenerators = iterator_to_array($pageableGenerators);
}

#[Route('/', name: 'index')]
public function index(): Response
{
return $this->render('app/index.html.twig', [
'pageable_generators' => $this->pageableGenerators,
]);
}

/**
* @param PagerFactoryInterface<PagerOptions> $pagerFactory
*/
#[Route('/{key?}', name: 'rekapager')]
public function index(
#[Route('/page/{key?}', name: 'page')]
public function page(
Request $request,
SqlLogger $logger,
PagerFactoryInterface $pagerFactory,
Expand All @@ -53,27 +76,7 @@ public function index(
/** @var PagerParameters */
$pagerParameters = $form->getData();


/** @psalm-suppress InvalidArgument */
$pageableGenerators = iterator_to_array($this->pageableGenerators);

/** @var array<string,PageableGeneratorInterface<array-key,mixed>> $pageableGenerators */

if ($key === null) {
foreach ($pageableGenerators as $pageableGenerator) {
$key = $pageableGenerator::getKey();
break;
}

\assert($key !== null);
$pageableGenerator = $pageableGenerators[$key];
} else {
$pageableGenerator = $pageableGenerators[$key] ?? null;
}

if ($pageableGenerator === null) {
throw $this->createNotFoundException();
}
$pageableGenerator = $this->pageableGenerators[$key] ?? throw $this->createNotFoundException();

$pageable = $pageableGenerator->generatePageable(
itemsPerPage: $pagerParameters->itemsPerPage,
Expand All @@ -93,11 +96,21 @@ public function index(

$title = $pageableGenerator->getTitle();

return $this->render('app/index.html.twig', [
$pageIdentifier = $pager->getCurrentPage()->getPageIdentifier();
$cloner = new VarCloner();
$dumper = new HtmlDumper();

$dumper->setTheme('light');
$output = fopen('php://memory', 'r+b') ?: throw new \RuntimeException('Failed to open memory stream');
$dumper->dump($cloner->cloneVar($pageIdentifier), $output);
$output = stream_get_contents($output, -1, 0);

return $this->render('app/page.html.twig', [
'title' => $title,
'pager' => $pager,
'sql' => $logger,
'pageable_generators' => $pageableGenerators,
'page_identifier' => $output,
'pageable_generators' => $this->pageableGenerators,
'source_code' => $this->getSourceCode($pageableGenerator::class),
'form' => $form->createView(),
'template' => $pagerParameters->template,
Expand All @@ -106,6 +119,61 @@ public function index(
]);
}

#[Route('/batch/{key?}', name: 'batch')]
public function batch(
SqlLogger $logger,
EntityManagerInterface $entityManager,
?string $key,
): Response {
$pageableGenerator = $this->pageableGenerators[$key] ?? throw $this->createNotFoundException();

/** @var PageableInterface<array-key,Post> */
$pageable = $pageableGenerator->generatePageable(
itemsPerPage: 5,
count: false,
setName: 'medium',
);

// @highlight-start

$output = '<ul>';

foreach ($pageable->withItemsPerPage(5)->getPages() as $page) {
$output .= '<li>';
$output .= sprintf('Processing page %d', $page->getPageNumber() ?? 'null');

$output .= '<ul>';

foreach ($page as $item) {
$output .= sprintf(
'<li>Processing item id %s, date %s, title %s</li>',
$item->getId(),
$item->getDate()?->format('Y-m-d') ?? 'null',
$item->getTitle() ?? 'null'
);
}

$output .= '</ul>';
$output .= '</li>';

$entityManager->clear();
}

$output .= '</ul>';
// @highlight-end

$title = $pageableGenerator->getTitle();

return $this->render('app/batch.html.twig', [
'title' => $title,
'sql' => $logger,
'pageable_generators' => $this->pageableGenerators,
'source_code' => $this->getSourceCode($pageableGenerator::class) . "\n" .
$this->getSourceCode(self::class),
'output' => $output,
]);
}

/**
* @param class-string $class
*/
Expand Down
Loading

0 comments on commit 8574f1d

Please sign in to comment.