diff --git a/.gitignore b/.gitignore
index e7c7906..1ff593d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
-# Ignore generated log files.
-/bin/*.log
-/bin/token.test
\ No newline at end of file
+codekit-config.json
+*.esproj
+.DS_Store
+composer\.lock
+/vendor/
diff --git a/.htaccess b/.htaccess
index 443d190..9e7f0aa 100644
--- a/.htaccess
+++ b/.htaccess
@@ -6,10 +6,10 @@ RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
-RewriteRule ^(transmogrify/(?:info|system|tests))/(.*)\.(.*)$ /lib/delegator-index.php?r=$2&t=$3&c=$1 [L]
-RewriteRule ^(transmogrify/(?:info|system|tests))/$ /lib/delegator-index.php?r=$1&t=LIST [L]
-RewriteRule ^(transmogrify/.*)\.(.*)$ /lib/delegator-index.php?r=$1&t=$2 [L]
-RewriteRule ^(transmogrify/.*)$ /lib/delegator-index.php?r=$1&t=LIST [L]
+RewriteRule ^(introspector/(?:info|system|tests))/(.*)\.(.*)$ /lib/delegator-index.php?r=$2&t=$3&c=$1 [L]
+RewriteRule ^(introspector/(?:info|system|tests))/$ /lib/delegator-index.php?r=$1&t=LIST [L]
+RewriteRule ^(introspector/.*)\.(.*)$ /lib/delegator-index.php?r=$1&t=$2 [L]
+RewriteRule ^(introspector/.*)$ /lib/delegator-index.php?r=$1&t=LIST [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /docs/index.php?presto&page=$1 [NC,QSA,L]
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 863a500..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# Changelog
-
-# 1.1 - *Sim Sala Bim*
-
-**Presto 1.1 breaks compatibility with 1.0 in a few important areas:**
-
-* Adds subfolder delegation
-* Removes add_delegate*, URL, and other unused code (subfolder delegation is much simpler)
-* Improves debugging (PHP errors to error log, added trace mode)
-* Added unit tests
-* Updated setup tests (to use internal API)
-* `API` base startup has been simplified, removing the class pre-scanning mechanism. Presto will throw an exception if 1.0 usage is detected.
-* API parameters are flattened to their obvious parts (get parameters, options, put/post body, resource type). This deprecates the `$ctx` object, which is still available via `self::$call`.
-* `add_delegate` has been removed, as it has been replaced by folder delegation
-* `add_filter` has been removed (a candidate 1.1 feature), as the other features provided enough utility on their own
-* `Request::URI` has been removed in favour of a simpler builder function. URI parsing is now spread over `htaccess` for more obvious routing rules.
-
-## Alpha 1 features
-
-This patch adds a number of features planned for 1.1, including:
-
-* Dispatching to folders of APIs
-* Preflighting dispatch calls for parameter and model processing
-* Adds internal testing and debugging APIs (only available when enabled)
-* Adds command line unit testing tools
-* Adds a trace mode, and better exception logging
-* Adds routing information to exceptions (if trace is enabled)
-
-## Updated parameter passing
-
-The calling convention for delegate API functions has changed from:
-
- public function get($ctx) { }
- public function get_article($ctx) { }
- public function put_article($ctx) { }
-
-To the more verbose form:
-
- public function get($params, $options, $body, $type) { }
- public function get_article($params, $options, $body, $type) { }
- public function put_article($params, $options, $body, $type) { }
-
-This makes the call parameters clearer than they were in the past.
-
-## Example folder delegation
-
-Folder delegation uses Apache rewriting to map folders of APIs to specific URLs. For example, Presto uses it for internal delegation to its `transmogrify` APIs:
-
- RewriteRule ^(transmogrify/(?:info|system|tests))/(.*)\.(.*)$ /lib/delegator-index.php?r=$2&t=$3&c=$1 [L]
-
-This routes all requests to 3 specific folders within `transmogrify` to files within the folders `info/`, `system/`, and `tests/` in `transmogrify/`.
-
-Requests like:
-
- get "transmogrify/system/httpd/headers/content-type.json"
-
-Are mapped to:
-
- transmogrify/system/httpd.php::httpd->get_headers();
-
-## Example preflight delegation
-
-API calls can be split into two parts to simplify handling complex model creation and parameter processing. The split adds a preflight call to a *model* function of the same root name as the API itself.
-
-Consider a simple GET:
-
- get "transmogrify/system/httpd/headers/content-type.json"
-
-This call can optionally be split into the model creation and the API call itself.
-
-The model creation preflight call would be:
-
- http.php::http->get_headers_model($p = array('content-type')) {
- return new Features($p);
- }
-
-The call receives the standard API request parameters, returning a newly created model object of some sort. This call can be used to check parameters, check preconditions, and massage parameters into useful/predictable values for the API call itself:
-
- http.php::http->get_headers($featureModel) {
- }
-
-
-## Example routing trace
-
-If `PRESTO_TRACE` is enabled, exceptions will include:
-
-
- [OPTIONS] transmogrify/info/delegation.json #0 [OK]
- {
- "_presto_trace": {
- "request": "/transmogrify/info/delegation.json",
- "routing_scheme": {
- "action": "options",
- "class": "delegation",
- "container": "transmogrify/info",
- "file": "transmogrify/info/delegation.php",
- "method": "options",
- "options": [],
- "params": [],
- "resource": "",
- "type": "json"
- },
- "version": "presto-v1.10"
- },
- "code": 404,
- "message": "Can't find delegation->options"
- }
-
-
-The `_presto_trace` element is added to make debugging easier. This trace is also available in the error log (in trace mode only):
-
- [Fri Feb 22 16:38:58 2013] [error] [client 127.0.0.1] PRESTO: _presto_trace, {"routing_scheme":{"container":"transmogrify\\/info","class":"delegation","file":"transmogrify\\/info\\/delegation.php","resource":"","type":"json","action":"get","method":"get","params":[],"options":[]},"request":"\\/transmogrify\\/info\\/delegation.json","version":"presto-v1.10"}
-
-
-# 1.0 - A la peanut butter sandwiches
-
-* First public release
-* Adds sub delegates and param filtering
-
-# 0.8
-
-* Adds basic URI -> class/member delegation and auto data return by type
diff --git a/LICENSE.md b/LICENSE.md
index fa17ef1..3f35966 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
# Free, free, share-alike
-Created by [Bruce Alderson](http://warpedvisions.org) (2011).
+Created by [Bruce Alderson](http://warpedvisions.org) (2011 - 2013).
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -9,4 +9,4 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-**PS: use, extend, share, enjoy. Thanks!**
\ No newline at end of file
+**PS: use, extend, share, enjoy.**
\ No newline at end of file
diff --git a/README.md b/README.md
index 0edfd38..48f9d15 100644
--- a/README.md
+++ b/README.md
@@ -1,81 +1,137 @@
-# Presto 1.1
+
-*Frugal PHP + REST toolkit*
+# Presto is different
-Presto is a library for building RESTful APIs in PHP `5.3+`. It's lightweight, decoupled, and focused on making web apps the right way; using APIs and clean URLs to produce output in standard formats like JSON, HTML, and XML. It encourages separating views completely from your model and controller code, and to animate your user interfaces in HTML, CSS, and JavaScript. It also uses existing tools and libraries for what they're good at, like letting Apache deal with routing, and letting PHP load and execute a minimal amount of dynamic code.
+PrestoPHP is a simple way to build RESTful web services APIs. It's a small toolkit that reduces how much code it takes to build a web service, letting you focus on what the service needs to do. It relies on the right tool for each part of a request; the web server for routing and PHP for loading, annotating, and for delegating a request to class member calls.
-## How is Presto different?
+Presto obsesses over APIs as a distinct, straightforward layer, and we think you should too.
-Presto flattens standard MVC to fit REST requests better. It focuses on APIs built from simple classes, relying on the web server for routing and on PHP autoloading for delegating requests to class member calls. User interfaces are left to other toolkits, though Presto can serve up fragments of HTML with ease. Presto focuses on APIs.
+## How simple is simple?
-### A quick example
+An API is built as a PHP class with members named for each resource (or tree of resources). For example, an `apple` is a resource. You can request an `apple` over HTTP.
-An API is a class with members named for each resource (or tree of resources). For example, an `apple` is a resource. You can request an `apple` over HTTP:
+ GET fruit/apples/ripe.json?tags=large+red
- GET fruit/apples/spartan.json?tags=large+red
+Presto maps this request to a PHP file and class, as well as the specific class member. It loads the file, creates an instance of the class, and executes the member that relates to the request.
+ Presto loads 'fruit/apples.php'
-Presto maps the request to a file, class, and class member automatically. It loads the file, creates an instance of the class, and executes the member that best fits:
+The mapping is straightforward enough that navigating your code isn't a chore. Within the class file, it executes member functions based on the nature of the request, passing the parameters split by what they're for. It provides *parameters*, *options*, the *body* (if there is one), and the request *type*.
+ apples->get(
+ array('ripe'), /* parameters */
+ array('tags' => array('large', ''red)), /* options */
+ array() /* body */,
+ 'json' /* requested content type */
+ );
+
+How this mapping works can be configured simply in your Apache rewrite rules, though the built in mappings suffice for the majority of APIs you will encounter.
+
+The `apples` class is based on the PrestoPHP `API` base.
- /* Loaded from 'fruit/apples.php' */
class apples extends API {
public function get($params, $options, $body, $type) {
+ /* All error handling uses exceptions */
+
if (count($params) === 0)
- throw new Exception('Missing required parameter', 400);
+ throw new \Exception('Missing required parameter', 400);
- /* Exceptions are returned as valid HTTP/content type
- responses */
- $thing = (object) array(
+ /* Output is built up as PHP objects (like a DOM) */
+
+ $dom = (object) array(
'name' => $params[0],
'tags' => $options['tags']
);
+
- return $thing; // to client in requested format
+ /* The $dom is converted to the content-type automatically */
+
+ return $dom;
}
}
+There are a few exciting things in the example:
-The `$thing` is automatically converted by Presto to the requested `Content-Type`, either implied by the request or the appropriate HTTP header. For formats not supported by default, *Output Adapters* can be defined and registered, or the type can be passed through for resources that are not based DOM style data.
+1. The `$dom` is converted to the requested `Content-Type`, if it's a type that maps easily. This means that `JSON` and `XML` APIs require no special view code, as they can automatically be serialized.
+2. HTTP status codes are returned automatically from any exception. This simplifies error handling and keeps it easy to read. PrestoPHP guarantees that all errors result in coherent service API responses.
+3. HTTP request *verbs* are mapped to calls automatically. For example, you could request a `LIST` of `apple` types available, `DELETE` a specific `apple`, or provide a map of `OPTIONS`. This makes crafting expressive APIs possible.
-Any HTTP request type is mapped automatically. For example, you can request a list of `apple` types available from the API:
+Mapping verbs allows requests like:
LIST apples.json?colour=red
-A LIST request is mapped to a function of the same name:
+The request is mapped to a function of the same name:
public function list(/* … */) { return array(); }
+More complex resources are possible using container requests a, multipart delegation, and custom rewrite rules. For example, you could add a `seeds` branch to the `apple` resource.
+
+ /* Built in multipart delegation */
+ public function list_seeds(/* … */) { return array(); }
-More complex resources are possible by either delegating (based on regex patterns), or by adding specific handlers. For example, you could add a `seeds` branch to the `apple` resource. Getting a list of seeds would map to:
+Additional segments of a URI automatically map to parameters.
- public function list_seeds(/* … */) { array(); }
+ /* GET apples/seeds/14421.json */
+ public function get_seeds(array(14421), /*…*/) { return array(); }
-### What about errors?
+Containers are just folders of APIs, which are mapped by specific `HTACCESS` rules. By default, all APIs are either in the API root folder, or in a container folder. More specific rules can be added to your `HTACCESS ` routes to improve performance, or just to specifically limit the responses your service gives.
-Errors are handled by the toolkit as standard PHP exceptions and standard PHP errors are remapped (where possible) to exceptions to ensure that logic and code errors are returned to clients as valid API returns. This means that individual APIs do not need to check return values, nor do they need to `try` and `catch` unless they need to do something special. Presto maps the standard exceptions to HTTP statuses and output in whatever format was requested where possible.
+
+## Errors and statuses
+
+Errors are standard PHP exceptions. Additionally, built-in PHP errors are mapped to exceptions (where possible) so that all logic and code errors are returned to clients as valid API returns. This means that individual APIs do not need to check return values, nor do they need to `try` and `catch` unless they need to do something special.
For example, if you encounter a parameter error you can simply throw an exception:
if (empty($param))
- throw new Exception('Missing required parameter', 400);
+ throw new \Exception('Missing required parameter', 400);
-Presto translates the exception into a `400` with an appropriately encoded body.
+Presto translates the exception into an HTTP `400` status with an appropriately encoded body. This is especially interesting for built-in errors, as your code can ignore them entirely and allow PHP and Presto do their magic. Clients of your API will receive well-formed HTTP statuses and encoded bodies for every request.
+
+The API code that results is much more focused on carefully testing parameters, retrieving appropriate resources, and building rich DOMs, rather than boilerplate code, managing responses, excessive error checking, routing, and other complex output generation.
+
+## Version 1.2 wishlist
-The resulting API code is much more focused on carefully testing parameters, retrieving appropriate resources, and building rich DOMs instead of boilerplate code, managing responses, excessive error checking, routing, and other complex output generation.
+*v1.2 toolkit feature candidates.*
+1. **Install and command line helper.** Things like `presto install`, `presto add new-api-name`, and so on.
+2. **Simple DB to object helper.** Allows simple object creation from `SELECT` syntax.
+3. **File listing helper.** *From Chronicle.md*, returns objects from file and folder listings.
+4. **Introspection.** Provides tools for asking Presto about itself, helpful for ops monitoring, setup, and troubleshooting.
+5. **Testing tools.**
+6. **Profiling tools.** *Added by @adam-patterson*
+7. **Documentation tools**
-Other interesting features
-==========================
+The focus of 1.2 is in making standard API code simpler for production. This includes all API tasks, not just code. Development, debugging, deployment, testing, profiling, and documentation. The completion of these and solid install / examples is the goal.
-You can also:
+### Database to object mappings
-* Add additional `content-types` by adding *output adapters* (`JSON`, simple `XML`, and simple `HTML` are built in)
-* Add `content-type` filters to define what types of payloads a given resource supports.
-* Add *custom delegation* for special resource types
+Simple things should be simple. Getting data from a table, for example, can produce simple PHP objects.
-**Note that PHP 5.3 or better is required, as Presto relies on anonymous functions and other newer PHP features. This makes it possible to write very clean, simple web services.**
+ SELECT
+ UserID AS `id:int`,
+ FirstName AS `name.first`,
+ MiddleName AS `name.middle`,
+ LastName AS `name.last`
+ FROM SomeTable;
+
+Using column aliases, Presto creates one set of objects per row, with the types hinted by in the `SELECT` aliases.
+
+ {
+ "people": [
+ {
+ "id": 1234,
+ "name": {
+ "first": "Bob",
+ "middle": "J",
+ "last": "Smith"
+ }
+ }
+ ]
+ }
diff --git a/_tests/simple-table.sql b/_tests/simple-table.sql
deleted file mode 100644
index 1a1ec7c..0000000
--- a/_tests/simple-table.sql
+++ /dev/null
@@ -1,52 +0,0 @@
-# ************************************************************
-# Sequel Pro SQL dump
-# Version 3408
-#
-# http://www.sequelpro.com/
-# http://code.google.com/p/sequel-pro/
-#
-# Host: localhost (MySQL 5.5.19)
-# Database: test
-# Generation Time: 2012-04-25 19:01:40 +0000
-# ************************************************************
-
-
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-/*!40101 SET NAMES utf8 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-
-
-# Dump of table Test
-# ------------------------------------------------------------
-
-DROP TABLE IF EXISTS `Test`;
-
-CREATE TABLE `Test` (
- `name` varchar(255) DEFAULT NULL,
- `id` int(11) DEFAULT NULL,
- `email` varchar(255) DEFAULT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-
-LOCK TABLES `Test` WRITE;
-/*!40000 ALTER TABLE `Test` DISABLE KEYS */;
-
-INSERT INTO `Test` (`name`, `id`, `email`)
-VALUES
- ('Bob',1,'bob@bob.com'),
- ('Ted',1,'ted@bob.com');
-
-/*!40000 ALTER TABLE `Test` ENABLE KEYS */;
-UNLOCK TABLES;
-
-
-
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
diff --git a/_tests/test-view.php b/_tests/test-view.php
deleted file mode 100644
index 4e6779e..0000000
--- a/_tests/test-view.php
+++ /dev/null
@@ -1,9 +0,0 @@
-====
-
-This is a test view.
-
- `= $name ?>` is a variable passed to the view class.
- `= $testsdfdfssfdsdffds ?>` is a variable that does not exist
-
-====
-
diff --git a/bin/detoken.php b/bin/detoken.php
index 9df8e87..9e53a85 100644
--- a/bin/detoken.php
+++ b/bin/detoken.php
@@ -5,7 +5,7 @@
try {
- if (count($argv) < 2) throw new Exception('Missing expected parameters.', 500);
+ if (count($argv) < 2) throw new \Exception('Missing expected parameters.', 500);
if (count($argv) == 3 && $argv[2] == '-urldecode')
$token = urldecode( trim(file_get_contents("php://stdin")) );
@@ -21,7 +21,7 @@
print_r($t);
-} catch (Exception $e) {
+} catch (\Exception $e) {
$c = $e->getCode();
print $c . ': ' . $e->getMessage() . "\n\n";
@@ -40,6 +40,6 @@ function handleError($errno, $errstr, $errfile, $errline, array $errcontext)
if (0 === error_reporting())
return false;
- throw new ErrorException($errstr, 500 + 0, $errno, $errfile, $errline);
+ throw new Error\Exception($errstr, 500 + 0, $errno, $errfile, $errline);
}
diff --git a/bin/shell.php b/bin/shell.php
deleted file mode 100644
index f7694da..0000000
--- a/bin/shell.php
+++ /dev/null
@@ -1,192 +0,0 @@
- ");
-$api = null;
-
-$options = array_merge(
- array(
- 'service' => 'http://localhost/',
- 'extra' => '',
- 'debug' => 0,
- 'log' => 'req'
- ),
- getopt('', array(
- 'service:',
- 'extra:',
- 'debug',
- 'log:')
- )
-);
-
-// Run a simple Presto shell
-function shellinate() {
- print PROMPT;
-
- $last = '';
- while ($cmd = fgets(STDIN)) {
- global $options;
- global $api;
- $service = '';
- $cmd = trim($cmd);
-
- if (empty($cmd))
- /* reuse last command (and do not log) */
- $cmd = $last;
- else {
-
- $last = $cmd;
-
- // log command (handy for testing)
- $history = fopen('hist.log', "a+");
- fwrite($history, $last."\n");
- fclose($history);
- }
-
- $cmd = strtok($cmd, ' ');
- $method = strtok(' ');
- $value = strtok('');
-
- switch ($cmd) {
- case 'help':
- show_help();
- break;
-
- case 'debug':
- case 'dump':
-
- print "\n";
-
- switch ($method) {
-
- case 'call':
- print_r($api->info());
- print_r($api->payload());
- break;
-
- case '':
- default:
- print "Don't know how to dump '$method'.\n";
- }
-
- break;
-
- case 'show':
- print "\n";
- if (in_array($method, array('', '*', 'all')) || !array_key_exists($method, $options))
- foreach ($options as $k => $v) { print "\t$k :\t $v\n"; }
- else
- print "$method = $options[$method]\n";
-
- print "\n";
- break;
-
- case 'set':
- if (strlen($method)) {
- $options[$method] = $value;
- print "Set $method to $value\n";
- }
- break;
-
- case 'get':
- case 'post':
- case 'put':
- case 'delete':
- case 'options':
- case 'head':
-
- try {
-
- if (!isset($api)) $api = new Service( $options );
-
- $params = array();
- $uri = null;
-
- $method = trim($method, "/ \n"); // clean up the method string
-
- // split the method parameter for complex queries
-
- $m1 = strtok($method, '/');
- $p1 = strtok('');
-
- if (!empty($p1)) {
- $uri = $p1;
- $method = $m1;
- }
-
- // process the call parameters
-
- if (strlen($value) && in_array($value[0], array('[', '{'))) {
- // attempt to decode as JSON
- $params = json_decode($value);
- if (empty($params)) throw new Exception('Invalid JSON parameters : ' . $value);
- } else {
- // attempt to decode as key/value set
- $pairs = explode(',', $value);
- foreach ($pairs as $v) {
- $p = explode('=', $v);
- if (count($p) == 2) $params[$p[0]] = $p[1];
- else $params[] = $p;
- }
- }
-
- // make the service call
-
- $call = "{$cmd}_{$method}";
-
- $data = empty($uri) ?
- $api->$call($params) :
- $api->$call($uri, $params);
-
- if (!empty($data)) print_r($data);
-
- } catch (Exception $e) {
- print $e->getCode() . " : " . $e->getMessage() . "\n\n";
- }
-
- break;
-
- case 'quit':
- case 'end':
- case 'die':
- die("Done.\n");
-
- default:
- print "Not sure how to '$cmd'.\n";
-
-
- }
- print PROMPT;
- }
-}
-function show_help() {
-?>
-
-Commands
-
- show [option]
- set [option] [value]
- dump [thing]
- [get|post|put|etc] [uri] [data]
-
-Examples
-
- get test.json
-
- # show the details of the last call
- dump call
-
-
-
-
-The Presto shell
-("help" for some options)
-
-Connecting to = $options['service'] ?> ...
-Connected.
-
-
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 53f4ebd..6a36d40 100644
--- a/composer.json
+++ b/composer.json
@@ -30,7 +30,9 @@
"lib-openssl": ">=0.9",
"lib-curl": ">=7.24.0"
},
- "require-dev": {
-
- }
+ "require-dev": {
+ "phpunit/phpunit": "3.7.*",
+ "dflydev/markdown": "*",
+ "squizlabs/php_codesniffer": "1.*"
+ }
}
\ No newline at end of file
diff --git a/docs/db.md b/docs/db.md
new file mode 100644
index 0000000..d2094a5
--- /dev/null
+++ b/docs/db.md
@@ -0,0 +1,77 @@
+# db.php - PDO wrapper
+
+## select_objects($sql, $parameters)
+
+Uses column aliases and type designation to generate object hierarchy.
+
+ Features:
+
+ * simple key format `any.number.of.subkeys:optional_type`
+ * order of columns is not important
+ * allows values to be type cast
+
+ Not supported:
+
+ * combining rows into sub-objects
+
+ Example:
+
+ SELECT
+ SomeID AS `id:int`,
+ FirstName AS `name.first`,
+ LastName AS `name.last`,
+ AnotherColumn AS `other`
+ FROM SomeTable
+
+
+ [{
+ id: 1234,
+ name: {
+ 'first': "Sideshow",
+ 'last': "Bob"
+ },
+ other: "some value"
+ }, ...]
+
+## bind_parameters
+
+ Generates a PDO bound parameterized array.
+
+ Pass this an array of keys and values that you want to use in your DB query.
+ generate_params() will return you a valid PDO array to use with
+ your INSERT and UPDATE statements.
+
+ View the test harness for this here: https://gist.github.com/ngallagher87/6717925
+
+ Supported types:
+ =================
+ PARAM_BOOL
+ PARAM_NULL
+ PARAM_INT
+ PARAM_STR
+
+ Unsupported types:
+ =================
+ PARAM_LOB
+ PARAM_INPUT_OUTPUT
+ PARAM_STMT (No drivers support this anyways)
+
+ Note:
+
+ If you need to use one of these unsupported types, you'll have to
+ generate the params by hand.
+
+ Example:
+ ========
+
+ $sql = << 'tuesday',
+ 'dayNumber' => 2,
+ 'isHoliday' => true
+ );
+ $this->db->insert($sql, $params);
diff --git a/docs/generating-output.md b/docs/generating-output.md
index 0c660bb..983969b 100644
--- a/docs/generating-output.md
+++ b/docs/generating-output.md
@@ -11,7 +11,7 @@ For example:
The request implies a simple `get` member, which receives parameters as `$ctx`, loading its data by a private member (not shown here). Data is returned in APIs by simply returning the DOM object:
// get a document
- function get($ctx) { $DOM = self::load($ctx->params); return $DOM; }
+ function get($params, $options, $body, $type) { $DOM = self::load($params); return $DOM; }
By the time the member function is called, Presto has marked the expected content-type as `application/json`, and will automatically attempt to convert the data returned by any API to JSON. By default, Presto supports `JSON` and simple `HTML`, but other types can be implemented and registered.
diff --git a/docs/index.php b/docs/index.php
index b2ca449..09ec6c3 100644
--- a/docs/index.php
+++ b/docs/index.php
@@ -81,7 +81,7 @@ function g($k, $d = null) { return array_key_exists($k, $_GET) ? $_GET[$k] : $d;
diff --git a/docs/nav.php b/docs/nav.php
index e90e3b9..d295bfd 100644
--- a/docs/nav.php
+++ b/docs/nav.php
@@ -1,5 +1,6 @@