Skip to content

Commit

Permalink
Merge pull request #16 from ipalaus/feature/cursors
Browse files Browse the repository at this point in the history
[Feature] Use cursors to navigate collections.
  • Loading branch information
Phil Sturgeon committed Jan 24, 2014
2 parents 5b5034b + eb502d5 commit 6b3feec
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 7 deletions.
121 changes: 121 additions & 0 deletions src/League/Fractal/Cursor/Cursor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <email@philsturgeon.co.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace League\Fractal\Cursor;

/**
* A generic cursor adapter.
*
* @author Isern Palaus <ipalaus@ipalaus.com>
*/
class Cursor implements CursorInterface
{
/**
* Current cursor value.
*
* @var mixed
*/
protected $current;

/**
* Next cursor value.
*
* @var mixed
*/
protected $next;

/**
* Items being holded for the current cursor position.
*
* @var integer
*/
protected $count;

/**
* Create a new Cursor instance.
*
* @param mixed $current
* @param mixed $next
* @param integer $count
*/
public function __construct($current = null, $next = null, $count = null)
{
$this->current = $current;
$this->next = $next;
$this->count = $count;
}

/**
* Get the current cursor value.
*
* @return mixed
*/
public function getCurrent()
{
return $this->current;
}

/**
* Set the current cursor value.
*
* @param mixed $current
* @return League\Fractal\Cursor\Cursor
*/
public function setCurrent($current)
{
$this->current = $current;
return $this;
}

/**
* Get the next cursor value.
*
* @return mixed
*/
public function getNext()
{
return $this->next;
}

/**
* Set the next cursor value.
*
* @param mixed $next
* @return League\Fractal\Cursor\Cursor
*/
public function setNext($next)
{
$this->next = $next;
return $this;
}

/**
* Returns the total items in the current cursor.
*
* @return integer
*/
public function getCount()
{
return $this->count;
}

/**
* Set the total items in the current cursor.
*
* @param integer $count
* @return League\Fractal\Cursor\Cursor
*/
public function setCount($count)
{
$this->count = $count;
return $this;
}
}
24 changes: 24 additions & 0 deletions src/League/Fractal/Cursor/CursorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <email@philsturgeon.co.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace League\Fractal\Cursor;

/**
* A common interface for cursors to use.
*
* @author Isern Palaus <ipalaus@ipalaus.com>
*/
interface CursorInterface
{
public function getCurrent();
public function getNext();
public function getCount();
}
35 changes: 32 additions & 3 deletions src/League/Fractal/Resource/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@

namespace League\Fractal\Resource;

use League\Fractal\Cursor\CursorInterface;
use League\Fractal\Pagination\PaginatorInterface;

/**
* Resource Collection
*
* The data can be a collection of any sort of data, as long as the
* The data can be a collection of any sort of data, as long as the
* "collection" is either array or an object implementing ArrayIterator.
*/
class Collection implements ResourceInterface
Expand All @@ -27,14 +28,21 @@ class Collection implements ResourceInterface
* @var array|ArrayIterator
*/
protected $data;

/**
* A collection of data
*
* @var League\Fractal\Pagination\PaginatorInterface
*/
protected $paginator;

/**
* Cursor implementation.
*
* @var League\Fractal\Cursor\CursorInterface
*/
protected $cursor;

/**
* A callable to process the data attached to this resource
*
Expand All @@ -51,7 +59,7 @@ public function __construct($data, $transformer)
$this->data = $data;
$this->transformer = $transformer;
}

/**
* Getter for data
*
Expand All @@ -72,6 +80,16 @@ public function getPaginator()
return $this->paginator;
}

/**
* Set the cursor implementation.
*
* @return League\Fractal\Cursor\CursorInterface
*/
public function getCursor()
{
return $this->cursor;
}

/**
* Getter for transformer
*
Expand All @@ -94,4 +112,15 @@ public function setPaginator(PaginatorInterface $paginator)
$this->paginator = $paginator;
return $this;
}

/**
* Set the cursor implementation.
*
* @param League\Fractal\Cursor\CursorInterface $cursor
*/
public function setCursor(CursorInterface $cursor)
{
$this->cursor = $cursor;
return $this;
}
}
31 changes: 28 additions & 3 deletions src/League/Fractal/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Pagination\PaginatorInterface;
use League\Fractal\Cursor\CursorInterface;

class Scope
{
Expand All @@ -39,7 +40,7 @@ public function embedChildScope($scopeIdentifier, $resource)
{
return $this->resourceManager->createData($resource, $scopeIdentifier, $this);
}

/**
* Getter for currentScope
*
Expand All @@ -59,7 +60,7 @@ public function getParentScopes()
{
return $this->parentScopes;
}

public function isRequested($checkScopeSegment)
{
if ($this->parentScopes) {
Expand Down Expand Up @@ -122,6 +123,12 @@ public function toArray()
if ($paginator !== null and $paginator instanceof PaginatorInterface) {
$output['pagination'] = $this->outputPaginator($paginator);
}

$cursor = $this->resource->getCursor();

if ($cursor !== null and $cursor instanceof CursorInterface) {
$output['cursor'] = $this->outputCursor($cursor);
}
}

return $output;
Expand Down Expand Up @@ -157,7 +164,7 @@ protected function fireTransformer($transformer, $data)

$this->availableEmbeds = $transformer->getAvailableEmbeds();
}

return $processedData;
}

Expand Down Expand Up @@ -189,6 +196,24 @@ protected function outputPaginator(PaginatorInterface $paginator)
return $pagination;
}

/**
* Generates output for cursor adapters. We don't type hint current/next
* because they can be either a string or a integer.
*
* @param League\Fractal\Cursor\CursorInterface $cursor
* @return array
*/
protected function outputCursor(CursorInterface $cursor)
{
$cursor = array(
'current' => $cursor->getCurrent(),
'next' => $cursor->getNext(),
'count' => (int) $cursor->getCount(),
);

return $cursor;
}

protected function runAppropriateTransformer()
{
// if's n shit
Expand Down
28 changes: 28 additions & 0 deletions tests/League/Fractal/Test/Cursor/CursorAdapterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace League\Fractal\Test\Cursor;

use League\Fractal\Cursor\Cursor;
use Mockery;

class CursorAdapterTest extends \PHPUnit_Framework_TestCase
{

public function testCursorAdapter()
{
$cursor = new Cursor(100, 110, 10);

$this->assertEquals($cursor->getCurrent(), 100);
$this->assertEquals($cursor->getNext(), 110);
$this->assertEquals($cursor->getCount(), 10);

$cursor->setCurrent(110);
$cursor->setNext(114);
$cursor->setCount(4);

$this->assertEquals($cursor->getCurrent(), 110);
$this->assertEquals($cursor->getNext(), 114);
$this->assertEquals($cursor->getCount(), 4);
}

}
9 changes: 9 additions & 0 deletions tests/League/Fractal/Test/Resource/CollectionTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace League\Fractal\Test;

use League\Fractal\Cursor\Cursor;
use League\Fractal\Resource\Collection;
use Mockery;

Expand Down Expand Up @@ -47,6 +48,14 @@ public function testGetPaginator()
$this->assertInstanceOf('Illuminate\Pagination\Paginator', $collection->getPaginator());
}

public function testGetCursor()
{
$cursor = new Cursor;
$collection = Mockery::mock('League\Fractal\Resource\Collection')->makePartial();
$collection->setCursor($cursor);
$this->assertInstanceOf('League\Fractal\Cursor\Cursor', $collection->getCursor());
}

public function tearDown()
{
Mockery::close();
Expand Down
Loading

0 comments on commit 6b3feec

Please sign in to comment.