From a7cd85a13141c70885e11ef55fed021aacda751d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kucha=C5=99?= <honza.kuchar@grifart.cz>
Date: Sat, 21 May 2016 17:44:45 +0200
Subject: [PATCH] Updated README.md, added example and added
 SemanticTrackedCursor (experiment)

---
 README.md                     | 33 +++++++++++++++++++++---
 examples/basic-example.php    | 45 ++++++++++++++++++++++++++++++++
 src/SemanticTrackedCursor.php | 48 +++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+), 3 deletions(-)
 create mode 100644 examples/basic-example.php
 create mode 100644 src/SemanticTrackedCursor.php

diff --git a/README.md b/README.md
index b2f1675..53af6bc 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,31 @@
-# mappi/store
+# mappi/cursor
 
-Provides API for reading data from database using cursors. 
-This allows you to read huge data without fetching everything into memory.
\ No newline at end of file
+Provides API for reading data from database using cursors. This allows you to read huge data without all of them into memory.
+
+Example usage:
+````php
+use Grifart\Mappi\Cursor;
+$connection = new \Dibi\Connection([/* ... */]);
+$cursorFactory = new Cursor\Driver\PostgresCursorFactory($connection);
+
+// cursor allow to do basic operations
+$cursor = $cursorFactory->create("SELECT * FROM mytable", TRUE);
+
+// tracked cursor can tell current position
+$trackedCursor = new Cursor\TrackedCursor($cursor, Cursor\Position::fromLeft(0));
+
+// semantic cursor provides nicer API for cursor
+$semanticCursor = new Cursor\SemanticCursor($cursor);
+
+while($row = $semanticCursor->fetchNext()) {
+    echo $trackedCursor->getPosition();
+    print_r($row);
+    echo "<hr>";
+}
+
+while($row = $semanticCursor->fetchPrevious()) {
+    echo $trackedCursor->getPosition();
+    print_r($row);
+    echo "<hr>";
+}
+````
\ No newline at end of file
diff --git a/examples/basic-example.php b/examples/basic-example.php
new file mode 100644
index 0000000..34257ca
--- /dev/null
+++ b/examples/basic-example.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types = 1);
+
+require_once __DIR__ . "/../vendor/autoload.php";
+
+use Grifart\Mappi\Cursor;
+
+// using PostgreSQL 9.5 cursor simulation using in-memory data
+$driver = new \Grifart\Mappi\Tests\Cursor\Driver\ArrayCursorDriver();
+$driver->createTestCursor("test-cursor", 26684);
+
+// cursor allow to do basic operations
+$cursor = new Cursor\Cursor($driver, "test-cursor");
+
+// tracked cursor can tell current position
+$trackedCursor = new Cursor\TrackedCursor($cursor, Cursor\Position::fromLeft(0));
+
+// semantic cursor provides nicer API for cursor
+$semanticCursor = new Cursor\SemanticTrackedCursor($trackedCursor);
+
+echo "<pre>\n";
+
+echo "first row: " . print_r($semanticCursor->fetchNext(), true) . "\n";
+
+
+$start = 547;
+$limit = 20;
+
+echo "position before move: " . $trackedCursor->getPosition() . "\n";
+$semanticCursor->moveTo(547);
+echo "position after move: " . $trackedCursor->getPosition() . "\n";
+
+echo "\nposition\tvalue\n";
+$i = $start;
+foreach($trackedCursor->fetchRange($limit) as $row) {
+	$i++;
+	/** @var array $row */
+	echo $i . "\t\t" . json_encode($row) . "\n";
+}
+echo "\n";
+echo "position after fetchRange(): " . $trackedCursor->getPosition() . "\n";
+
+echo "There is " . $semanticCursor->getTotal() . " rows in the data set\n";
+echo "position after getTotal(): " . $trackedCursor->getPosition() . "\n";
+
+echo "</pre>";
diff --git a/src/SemanticTrackedCursor.php b/src/SemanticTrackedCursor.php
new file mode 100644
index 0000000..52fd6e8
--- /dev/null
+++ b/src/SemanticTrackedCursor.php
@@ -0,0 +1,48 @@
+<?php declare(strict_types = 1);
+/**
+ * This file is part of mappi/cursor.
+ */
+
+namespace Grifart\Mappi\Cursor;
+
+/**
+ * Semantic cursor with tracked extensions
+ * @todo remove inheritance and use composition instead
+ * @todo add tests
+ * @package Grifart\Mappi\Cursor
+ */
+class SemanticTrackedCursor extends SemanticCursor
+{
+	/** @var TrackedCursor */
+	protected $cursor;
+
+	/**
+	 * @param TrackedCursor $cursor
+	 */
+	public function __construct(TrackedCursor $cursor)
+	{
+		parent::__construct($cursor);
+	}
+
+	public function getPosition() : Position
+	{
+		return $this->cursor->getPosition();
+	}
+
+	/**
+	 * Get total number of rows in cursor
+	 * Caution! This will scroll through cursor to the BEGINNING or to the END
+	 * @return int the number of rows in cursor
+	 */
+	public function getTotal() : int
+	{
+		$fromLeft = $this->cursor->getPosition()->getOrigin()->is(PositionOrigin::FROM_LEFT);
+		if($fromLeft) {
+			$this->scrollToEnd();
+		} else {
+			$this->scrollToBeginning();
+		}
+		return $this->cursor->getPosition()->getPosition() - 1;
+	}
+
+}
\ No newline at end of file
-- 
GitLab