Implemented pagination \o/
This commit is contained in:
parent
c1ca02669b
commit
bc307e0a26
|
@ -1,3 +1,3 @@
|
|||
/Carew/Tests/Functional/fixtures/*/web/
|
||||
/Carew/Tests/Command/fixtures/*/web/
|
||||
/composer.lock
|
||||
/vendor/
|
||||
|
|
|
@ -99,7 +99,11 @@ class CoreExtension implements ExtensionInterface
|
|||
});
|
||||
|
||||
$container['twig'] = $container->share(function($container) {
|
||||
$twig = new Twig_Environment($container['twig.loader'], array('strict_variables' => true, 'debug' => true));
|
||||
$twig = new Twig_Environment($container['twig.loader'], array(
|
||||
'strict_variables' => true,
|
||||
'debug' => true,
|
||||
'base_template_class' => 'Carew\Twig\Template',
|
||||
));
|
||||
|
||||
// We will not be able to add new global in Twig 2.0, so we should declare everything now;
|
||||
$twig->addGlobal('carew', new Globals($container['config']));
|
||||
|
|
|
@ -179,4 +179,9 @@ class Document
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,21 +18,25 @@ class Markdown implements EventSubscriberInterface
|
|||
|
||||
public function onDocument(CarewEvent $event)
|
||||
{
|
||||
$subject = $event->getSubject();
|
||||
$documents = $event->getSubject();
|
||||
|
||||
$extension = $subject->getFile()->getExtension();
|
||||
if ('md' !== $extension) {
|
||||
if ('twig' !== $extension) {
|
||||
return;
|
||||
}
|
||||
|
||||
$extension = pathinfo(str_replace('.twig', '', $subject->getFilePath()), PATHINFO_EXTENSION);
|
||||
foreach ($documents as $document) {
|
||||
$extension = $document->getFile()->getExtension();
|
||||
if ('md' !== $extension) {
|
||||
return;
|
||||
if ('twig' !== $extension) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension = pathinfo(str_replace('.twig', '', $document->getFilePath()), PATHINFO_EXTENSION);
|
||||
if ('md' !== $extension) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$document->setBody($this->markdownParser->transform($document->getBody()));
|
||||
}
|
||||
|
||||
$subject->setBody($this->markdownParser->transform($subject->getBody()));
|
||||
$event->setSubject($documents);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
|
|
|
@ -17,32 +17,70 @@ class Twig implements EventSubscriberInterface
|
|||
|
||||
public function preRender(CarewEvent $event)
|
||||
{
|
||||
$document = $event->getSubject();
|
||||
$documents = $event->getSubject();
|
||||
$documentsTmp = array();
|
||||
foreach ($documents as $k => $document) {
|
||||
$documentsTmp[] = $document;
|
||||
if (false === $document->getLayout()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false === $document->getLayout()) {
|
||||
return;
|
||||
$this->setTwigGlobals($event, $document);
|
||||
|
||||
// Force autoloading of Twig_Extension_StringLoader
|
||||
$stringLoader = $this->twig->getExtension('string_loader');
|
||||
|
||||
$template = twig_template_from_string($this->twig, $document->getBody());
|
||||
$nbItems = $template->getNbItems(array());
|
||||
if ($template->getMaxPerPage() >= $nbItems) {
|
||||
$document->setBody($template->render(array()));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($documentsTmp[$k]);
|
||||
|
||||
$nbPages = ceil($nbItems / $template->getMaxPerPage());
|
||||
|
||||
for ($i = 1; $i <= $nbPages; $i++) {
|
||||
$documentTmp = clone $document;
|
||||
|
||||
if (1 < $i) {
|
||||
$pathInfo = pathinfo($documentTmp->getPath());
|
||||
$pathInfo['filename'] = sprintf('%s-page-%d', $pathInfo['filename'], $i);
|
||||
$documentTmp->setPath(sprintf('%s/%s.%s', $pathInfo['dirname'], $pathInfo['filename'], $pathInfo['extension']));
|
||||
}
|
||||
|
||||
$documentTmp->setBody($template->render(array(
|
||||
'__offset__' => ($i - 1) * $template->getMaxPerPage(),
|
||||
)));
|
||||
$documentsTmp[] = $documentTmp;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setTwigGlobals($event);
|
||||
|
||||
$document->setBody($this->twig->render('pre_render_template.html.twig', array('body' => $document->getBody())));
|
||||
$event->setSubject($documentsTmp);
|
||||
}
|
||||
|
||||
public function postRender(CarewEvent $event)
|
||||
{
|
||||
$document = $event->getSubject();
|
||||
$documents = $event->getSubject();
|
||||
|
||||
if (false === $document->getLayout()) {
|
||||
return;
|
||||
foreach ($documents as $document) {
|
||||
if (false === $document->getLayout()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->setTwigGlobals($event, $document);
|
||||
|
||||
$layout = $document->getLayout();
|
||||
if (false === strpos($layout, '.twig')) {
|
||||
$layout .= '.html.twig';
|
||||
}
|
||||
|
||||
$document->setBody($this->twig->render($layout));
|
||||
}
|
||||
|
||||
$this->setTwigGlobals($event);
|
||||
|
||||
$layout = $document->getLayout();
|
||||
if (false === strpos($layout, '.twig')) {
|
||||
$layout .= '.html.twig';
|
||||
}
|
||||
$document->setBody($this->twig->render($layout));
|
||||
$event->setSubject($documents);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
|
@ -55,11 +93,10 @@ class Twig implements EventSubscriberInterface
|
|||
);
|
||||
}
|
||||
|
||||
private function setTwigGlobals(CarewEvent $event)
|
||||
private function setTwigGlobals(CarewEvent $event, $document)
|
||||
{
|
||||
$globals = $event->hasArgument('globalVars') ? $event->getArgument('globalVars') : array();
|
||||
|
||||
$document = $event->getSubject();
|
||||
$globals['relativeRoot'] = $document->getRootPath();
|
||||
$globals['currentPath'] = $document->getPath();
|
||||
$globals['document'] = $document;
|
||||
|
|
|
@ -64,14 +64,14 @@ class Processor
|
|||
|
||||
public function processDocument($document, array $globalVars = array())
|
||||
{
|
||||
$event = new CarewEvent($document, array('globalVars' => $globalVars));
|
||||
$event = new CarewEvent(array($document), array('globalVars' => $globalVars));
|
||||
try {
|
||||
$documents = $this->eventDispatcher->dispatch(Events::DOCUMENT_BODY, $event)->getSubject();
|
||||
} catch (\Exception $e) {
|
||||
throw new \LogicException(sprintf('Could not process: "%s".', (string) $document->getFile()), 0 , $e);
|
||||
}
|
||||
|
||||
return $document;
|
||||
return $documents;
|
||||
}
|
||||
|
||||
public function write(Document $document)
|
||||
|
|
|
@ -12,7 +12,7 @@ class BuildTest extends AbstractTest
|
|||
public function testExecuteWithSite1()
|
||||
{
|
||||
$this->deleteDir($webDir = __DIR__.'/fixtures/site1/web');
|
||||
list(, $statusCode) = $this->runApplication(dirname($webDir));
|
||||
list($application, $statusCode) = $this->runApplication(dirname($webDir));
|
||||
|
||||
$this->assertSame(0, $statusCode);
|
||||
|
||||
|
@ -54,6 +54,72 @@ class BuildTest extends AbstractTest
|
|||
$this->deleteDir($webDir);
|
||||
}
|
||||
|
||||
public function testExecuteWithSiteAndPagination()
|
||||
{
|
||||
$this->deleteDir($webDir = __DIR__.'/fixtures/site2/web');
|
||||
list($application, $statusCode) = $this->runApplication(dirname($webDir));
|
||||
|
||||
$this->assertSame(0, $statusCode);
|
||||
|
||||
$lis = array();
|
||||
|
||||
$this->assertTrue(file_exists($webDir.'/index.html'));
|
||||
$crawler = new Crawler(file_get_contents($webDir.'/index.html'));
|
||||
$this->assertCount(1, $crawler->filter('ul'));
|
||||
$this->assertCount(4, $crawler->filter('ul')->eq(0)->filter('li'));
|
||||
foreach ($crawler->filter('ul')->eq(0)->filter('li') as $li) {
|
||||
$lis[] = trim($li->textContent);
|
||||
}
|
||||
|
||||
$this->assertTrue(file_exists($webDir.'/index-page-2.html'));
|
||||
$crawler = new Crawler(file_get_contents($webDir.'/index-page-2.html'));
|
||||
$this->assertCount(1, $crawler->filter('ul'));
|
||||
$this->assertCount(4, $crawler->filter('ul')->eq(0)->filter('li'));
|
||||
foreach ($crawler->filter('ul')->eq(0)->filter('li') as $li) {
|
||||
$lis[] = trim($li->textContent);
|
||||
}
|
||||
|
||||
$this->assertTrue(file_exists($webDir.'/index-page-3.html'));
|
||||
$crawler = new Crawler(file_get_contents($webDir.'/index-page-3.html'));
|
||||
$this->assertCount(1, $crawler->filter('ul'));
|
||||
$this->assertCount(4, $crawler->filter('ul')->eq(0)->filter('li'));
|
||||
foreach ($crawler->filter('ul')->eq(0)->filter('li') as $li) {
|
||||
$lis[] = trim($li->textContent);
|
||||
}
|
||||
|
||||
$this->assertTrue(file_exists($webDir.'/index-page-4.html'));
|
||||
$crawler = new Crawler(file_get_contents($webDir.'/index-page-4.html'));
|
||||
$this->assertCount(1, $crawler->filter('ul'));
|
||||
$this->assertCount(3, $crawler->filter('ul')->eq(0)->filter('li'));
|
||||
foreach ($crawler->filter('ul')->eq(0)->filter('li') as $li) {
|
||||
$lis[] = trim($li->textContent);
|
||||
}
|
||||
|
||||
$this->assertFalse(file_exists($webDir.'/index-page-5.html'));
|
||||
|
||||
sort($lis);
|
||||
|
||||
$expected = array (
|
||||
'Page1',
|
||||
'Page10',
|
||||
'Page11',
|
||||
'Page12',
|
||||
'Page13',
|
||||
'Page14',
|
||||
'Page2',
|
||||
'Page3',
|
||||
'Page4',
|
||||
'Page5',
|
||||
'Page6',
|
||||
'Page7',
|
||||
'Page8',
|
||||
'Page9',
|
||||
'index',
|
||||
);
|
||||
|
||||
$this->assertSame($expected, $lis);
|
||||
}
|
||||
|
||||
public function testExecuteWithConfigFolder()
|
||||
{
|
||||
$this->deleteDir($webDir = __DIR__.'/fixtures/config-folder/web');
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: index
|
||||
permalink: index.html
|
||||
---
|
||||
|
||||
Hello
|
||||
|
||||
{{ render_documents(paginate(carew.documents, 4)) }}
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page1
|
||||
---
|
||||
|
||||
Page1
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page10
|
||||
---
|
||||
|
||||
Page10
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page11
|
||||
---
|
||||
|
||||
Page11
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page12
|
||||
---
|
||||
|
||||
Page12
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page13
|
||||
---
|
||||
|
||||
Page13
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page14
|
||||
---
|
||||
|
||||
Page14
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page2
|
||||
---
|
||||
|
||||
Page2
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page3
|
||||
---
|
||||
|
||||
Page3
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page4
|
||||
---
|
||||
|
||||
Page4
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page5
|
||||
---
|
||||
|
||||
Page5
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page6
|
||||
---
|
||||
|
||||
Page6
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page7
|
||||
---
|
||||
|
||||
Page7
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page8
|
||||
---
|
||||
|
||||
Page8
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Page9
|
||||
---
|
||||
|
||||
Page9
|
|
@ -1 +0,0 @@
|
|||
local:local-layout
|
|
@ -1 +0,0 @@
|
|||
vendor:vendor-layout
|
|
@ -1,25 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
||||
<title>default-extends</title>
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<body>
|
||||
<h1>title:default-extends</h1>
|
||||
|
||||
<div class="body">
|
||||
<p>Should be wrapped into a div</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<small>
|
||||
Made with help from <a href="http://carew.github.com/" target="_blank">Carew</a>
|
||||
</small>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -25,7 +25,7 @@ class MarkdownTest extends \PHPUnit_Framework_TestCase
|
|||
public function testOnDocument($expected, $file)
|
||||
{
|
||||
$document = $this->createDocument($file);
|
||||
$event = new CarewEvent($document);
|
||||
$event = new CarewEvent(array($document));
|
||||
|
||||
$markdownParser = $this->getMock('Michelf\Markdown');
|
||||
$markdownParser
|
||||
|
@ -42,7 +42,7 @@ class MarkdownTest extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
$document = $this->createDocument('simple.md.twig');
|
||||
$document->setBody('[homepage](<{{ carew.relativeRoot }}>)');
|
||||
$event = new CarewEvent($document);
|
||||
$event = new CarewEvent(array($document));
|
||||
|
||||
$extraction = new Markdown();
|
||||
$extraction->onDocument($event);
|
||||
|
|
|
@ -15,7 +15,9 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
public function setUp()
|
||||
{
|
||||
$this->twigLoader = new \Twig_Loader_Array(array('pre_render_template.html.twig' => '{{ include(template_from_string(body)) }}'));
|
||||
$twig = new \Twig_Environment($this->twigLoader);
|
||||
$twig = new \Twig_Environment($this->twigLoader, array(
|
||||
'base_template_class' => 'Carew\Twig\Template',
|
||||
));
|
||||
$twig->addExtension(new \Twig_Extension_StringLoader());
|
||||
$twig->addGlobal('carew', new Globals());
|
||||
|
||||
|
@ -46,7 +48,9 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
$document->setPath('index.html');
|
||||
$document->setBody($body);
|
||||
|
||||
$this->twigListenner->preRender(new CarewEvent($document));
|
||||
$event = new CarewEvent(array($document));
|
||||
|
||||
$this->twigListenner->preRender($event);
|
||||
|
||||
$this->assertSame($expected, $document->getBody());
|
||||
}
|
||||
|
@ -57,7 +61,8 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
$document->setLayout(false);
|
||||
$document->setBody('{{ foo }}');
|
||||
|
||||
$this->twigListenner->preRender(new CarewEvent($document));
|
||||
$event = new CarewEvent(array($document));
|
||||
$this->twigListenner->preRender($event);
|
||||
|
||||
$this->assertSame('{{ foo }}', $document->getBody());
|
||||
}
|
||||
|
@ -68,7 +73,7 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
$document->setLayout('default');
|
||||
$document->setBody('{{ carew.extra.foo }}');
|
||||
|
||||
$event = new CarewEvent($document);
|
||||
$event = new CarewEvent(array($document));
|
||||
$event['globalVars'] = array('foo' => 'bar');
|
||||
|
||||
$this->twigListenner->preRender($event);
|
||||
|
@ -92,7 +97,8 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
$document = new Document();
|
||||
$document->setBody($body);
|
||||
|
||||
$this->twigListenner->postRender(new CarewEvent($document));
|
||||
$event = new CarewEvent(array($document));
|
||||
$this->twigListenner->postRender($event);
|
||||
|
||||
$this->assertSame($expected, $document->getBody());
|
||||
}
|
||||
|
@ -124,7 +130,7 @@ class TwigTest extends \PHPUnit_Framework_TestCase
|
|||
EOL;
|
||||
$this->twigLoader->setTemplate('default.html.twig', $template);
|
||||
|
||||
$event = new CarewEvent($document);
|
||||
$event = new CarewEvent(array($document));
|
||||
$event['globalVars'] = array('foo' => 'bar', 'relativeRoot' => 'should not appear');
|
||||
$this->twigListenner->postRender($event);
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Carew\Tests\Twig\Node;
|
||||
|
||||
use Carew\Twig\Node\Pagination;
|
||||
|
||||
class PaginationTest extends \Twig_Test_NodeTestCase
|
||||
{
|
||||
public function getTests()
|
||||
{
|
||||
$tests = array();
|
||||
|
||||
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$moduleNode = $env->parse($env->tokenize('{% do range(0, 100)|sort|reverse %}'));
|
||||
$node = $moduleNode->getNode('body')->getNode(0)->getNode('expr');
|
||||
$node = new Pagination($node, 20);
|
||||
$tests[] = array($node, <<<'EOF'
|
||||
public function getNbItems(array $context)
|
||||
{
|
||||
$context = $this->env->mergeGlobals($context);
|
||||
|
||||
return count(twig_reverse_filter($this->env, twig_sort_filter(range(0, 100))));
|
||||
}
|
||||
|
||||
public function getMaxPerPage()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$moduleNode = $env->parse($env->tokenize('{% do collection|reverse %}'));
|
||||
$node = $moduleNode->getNode('body')->getNode(0)->getNode('expr');
|
||||
$node = new Pagination($node, 20);
|
||||
$tests[] = array($node, <<<'EOF'
|
||||
public function getNbItems(array $context)
|
||||
{
|
||||
$context = $this->env->mergeGlobals($context);
|
||||
|
||||
return count(twig_reverse_filter($this->env, (isset($context["collection"]) ? $context["collection"] : null)));
|
||||
}
|
||||
|
||||
public function getMaxPerPage()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
|
||||
return $tests;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace Carew\Tests\Twig\NodeVisitor;
|
||||
|
||||
use Carew\Twig\NodeVisitor\Paginator;
|
||||
|
||||
class PaginatorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function getNodeVisitorAlterNothingIfNotNeededTests()
|
||||
{
|
||||
return array(
|
||||
array('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}'),
|
||||
array('{{ collection|slice(1, 10) }}'),
|
||||
array('{{ collection[2:10] }}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getNodeVisitorAlterNothingIfNotNeededTests
|
||||
*/
|
||||
public function testNodeVisitorAlterNothingIfNotNeeded($template)
|
||||
{
|
||||
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$stream = $env->parse($env->tokenize($template));
|
||||
|
||||
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$env->addNodeVisitor(new Paginator());
|
||||
$streamWithNodeVisitorRegistred = $env->parse($env->tokenize($template));
|
||||
|
||||
$this->assertSame((string) $stream, (string) $streamWithNodeVisitorRegistred);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Syntax
|
||||
* @expectedExceptionMessage Missing first argument of "paginate" function.
|
||||
*/
|
||||
public function testNodeVisitorThrowExceptionIfCollectionIsNotDefined()
|
||||
{
|
||||
$env = $this->createEnv();
|
||||
|
||||
$stream = $env->parse($env->tokenize('{{ paginate() }}'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Twig_Error_Syntax
|
||||
* @expectedExceptionMessage Second argument of "paginate" function should be an integer.
|
||||
*/
|
||||
public function testNodeVisitorThrowExceptionIfMaxPerPageValueIsNotAConstant()
|
||||
{
|
||||
$env = $this->createEnv();
|
||||
|
||||
$stream = $env->parse($env->tokenize('{{ paginate(collection, maxPerPage) }}'));
|
||||
}
|
||||
|
||||
public function testNodeVisitorAddSliceFilter()
|
||||
{
|
||||
$env = $this->createEnv();
|
||||
|
||||
$stream = $env->parse($env->tokenize('{{ paginate(collection, 10) }}'));
|
||||
|
||||
$nodeFilter = $stream->getNode('body')->getNode(0)->getNode('expr');
|
||||
$this->assertInstanceOf('Twig_Node_Expression_Filter', $nodeFilter);
|
||||
$this->assertInstanceOf('Twig_Node_Expression_Constant', $nodeFilter->getNode('filter'));
|
||||
$this->assertSame('slice', $nodeFilter->getNode('filter')->getAttribute('value'));
|
||||
|
||||
$arguments = $nodeFilter->getNode('arguments');
|
||||
$this->assertInstanceOf('Twig_Node_Expression_Name', $arguments->getNode(0));
|
||||
$this->assertSame('__offset__', $arguments->getNode(0)->getAttribute('name'));
|
||||
$this->assertInstanceOf('Twig_Node_Expression_Constant', $arguments->getNode(1));
|
||||
$this->assertSame(10, $arguments->getNode(1)->getAttribute('value'));
|
||||
|
||||
$extraNode = $stream->getNode('extra');
|
||||
$this->assertInstanceOf('Twig_Node_Extra', $extraNode);
|
||||
$this->assertInstanceOf('Carew\Twig\Node\Pagination', $extraNode->getNode(0));
|
||||
$this->assertInstanceOf('Twig_Node_Expression_Name', $extraNode->getNode(0)->getNode('node'));
|
||||
$this->assertSame('collection', $extraNode->getNode(0)->getNode('node')->getAttribute('name'));
|
||||
$this->assertSame(10, $extraNode->getNode(0)->getAttribute('maxPerPage'));
|
||||
}
|
||||
|
||||
private function createEnv()
|
||||
{
|
||||
$env = new \Twig_Environment(new \Twig_Loader_String(), array('cache' => false, 'autoescape' => false));
|
||||
$env->addNodeVisitor(new Paginator());
|
||||
$env->addFunction(new \Twig_SimpleFunction('paginate', function() { }));
|
||||
$env->addGlobal('collection', range(1, 100));
|
||||
|
||||
return $env;
|
||||
}
|
||||
}
|
|
@ -4,8 +4,17 @@ namespace Carew\Twig;
|
|||
|
||||
use Carew\Document;
|
||||
|
||||
use Carew\Twig\NodeVisitor\Paginator;
|
||||
|
||||
class CarewExtension extends \Twig_Extension
|
||||
{
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return array(
|
||||
new Paginator(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
|
@ -15,6 +24,7 @@ class CarewExtension extends \Twig_Extension
|
|||
new \Twig_SimpleFunction('render_document', array($this, 'renderDocument'), array('is_safe' => array('html'), 'needs_environment' => true)),
|
||||
new \Twig_SimpleFunction('render_documents', array($this, 'renderDocuments'), array('is_safe' => array('html'), 'needs_environment' => true)),
|
||||
new \Twig_SimpleFunction('render_*', array($this, 'renderBlock'), array('is_safe' => array('html'), 'needs_environment' => true)),
|
||||
new \Twig_SimpleFunction('paginate', function() { } ),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Carew\Twig\Node;
|
||||
|
||||
class Pagination extends \Twig_Node
|
||||
{
|
||||
public function __construct(\Twig_Node $node, $maxPerPage)
|
||||
{
|
||||
parent::__construct(array('node' => $node), array('maxPerPage' => (integer) $maxPerPage));
|
||||
}
|
||||
|
||||
public function compile(\Twig_Compiler $compiler)
|
||||
{
|
||||
$this->compileGetNbItems($compiler);
|
||||
|
||||
$this->compileMaxPerPage($compiler);
|
||||
}
|
||||
|
||||
private function compileGetNbItems(\Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("public function getNbItems(array \$context)\n", "{\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
$compiler->addIndentation();
|
||||
$compiler->raw("\$context = \$this->env->mergeGlobals(\$context);\n\n", false);
|
||||
$compiler->addIndentation();
|
||||
$compiler->raw('return count(', false);
|
||||
$compiler->subcompile($this->getNode('node'));
|
||||
$compiler->raw(");\n");
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
|
||||
private function compileMaxPerPage(\Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("public function getMaxPerPage()\n", "{\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
$compiler->write(sprintf("return %s;\n", $this->getAttribute('maxPerPage')));
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Carew\Twig\NodeVisitor;
|
||||
|
||||
use Carew\Twig\Node\Pagination as PaginationNode;
|
||||
|
||||
class Paginator implements \Twig_NodeVisitorInterface
|
||||
{
|
||||
private $currentModule;
|
||||
private $maxPerPage;
|
||||
|
||||
public function __construct($maxPerPage = 10)
|
||||
{
|
||||
$this->maxPerPage = $maxPerPage;
|
||||
}
|
||||
|
||||
public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof \Twig_Node_Module) {
|
||||
$this->currentModule = $node;
|
||||
} elseif ($node instanceof \Twig_Node_Expression_Function) {
|
||||
return $this->enterPaginationFilterNode($node, $env);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function enterPaginationFilterNode(\Twig_NodeInterface $node, \Twig_Environment $env)
|
||||
{
|
||||
$name = $node->getAttribute('name');
|
||||
|
||||
if ('paginate' != $name) {
|
||||
return $node;
|
||||
}
|
||||
$args = $node->getNode('arguments');
|
||||
|
||||
if (!$args->hasNode(0)) {
|
||||
throw new \Twig_Error_Syntax('Missing first argument of "paginate" function.');
|
||||
}
|
||||
|
||||
// extract $maxPerPage;
|
||||
if ($args->hasNode(1)) {
|
||||
$arg = $args->getNode(1);
|
||||
if (!$arg instanceof \Twig_Node_Expression_Constant) {
|
||||
throw new \Twig_Error_Syntax('Second argument of "paginate" function should be an integer.');
|
||||
}
|
||||
$maxPerPage = (integer) $arg->getAttribute('value');
|
||||
} else {
|
||||
$maxPerPage = $this->maxPerPage;
|
||||
}
|
||||
|
||||
$nodeToPaginate = $args->getNode(0);
|
||||
|
||||
// Set-up the PaginationNode
|
||||
$extra = $this->currentModule->getNode('extra');
|
||||
$extra->setNode(0, new PaginationNode($nodeToPaginate, $maxPerPage));
|
||||
|
||||
// Filter the node with "|slice(offset, maxPerPage)"
|
||||
$slicedNode = new \Twig_Node_Expression_Filter(
|
||||
$nodeToPaginate,
|
||||
new \Twig_Node_Expression_Constant('slice', 1),
|
||||
new \Twig_Node(array(
|
||||
new \Twig_Node_Expression_Name('__offset__', 1), //
|
||||
new \Twig_Node_Expression_Constant($maxPerPage, 1),
|
||||
)),
|
||||
1
|
||||
);
|
||||
|
||||
return $slicedNode;
|
||||
}
|
||||
|
||||
public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof \Twig_Node_Module) {
|
||||
$this->currentModule = null;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function getPriority()
|
||||
{
|
||||
0;
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
{{ include(template_from_string(body)) }}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Carew\Twig;
|
||||
|
||||
abstract class Template extends \Twig_Template
|
||||
{
|
||||
public function getNbItems(array $context)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getMaxPerPage()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,12 @@
|
|||
"email" : "igor@wiedler.ch"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "git@github.com:lyrixx/Twig.git"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"cocur/slugify": "0.2.*",
|
||||
"michelf/php-markdown": "1.3.*@dev",
|
||||
|
@ -24,7 +30,7 @@
|
|||
"symfony/filesystem": "~2.1",
|
||||
"symfony/finder": "~2.1",
|
||||
"symfony/yaml": "~2.1",
|
||||
"twig/twig": "~1.12"
|
||||
"twig/twig": "dev-extra"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/dom-crawler": "~2.2",
|
||||
|
|
Loading…
Reference in New Issue