Skip to content
Closed
60 changes: 60 additions & 0 deletions ContentNegotiator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
require_once(dirname(__FILE__) . '/config/content-negotiation.php');
require_once(dirname(__FILE__) . '/modules/HttpException/HttpException.php');

require_once(dirname(__FILE__) . '/JsonConverter.php');
require_once(dirname(__FILE__) . '/YamlConverter.php');

class ContentNegotiator {
private static $output_handlers = array('application/json' => 'JsonConverter' /*, 'text/x-yaml' => 'YamlConverter'*/);

public static function SupportedMimeTypes() {
$mimes = array();
$instances = array();

foreach (self::$output_handlers AS $mime => $handler) {
if (!isset($instances[$handler])) {
if (!class_exists($handler)) {
continue;
}
$instances[$handler] = new $handler();
if (!($instances[$handler] instanceof OutputConverter)) {
throw new HttpException(500, NULL, 'Unsupported converter for mime type "' . $mime . '"!');
}
}

if ($instances[$handler]->canRun()) {
$mimes[] = $mime;
}
}

return $mimes;
}

public static function MimeType() {
$additional = func_get_args();
$mimes = array_unique(array_merge(self::SupportedMimeTypes(), $additional));

if (isset($_SERVER['HTTP_ACCEPT'])) {
foreach(explode(',', $_SERVER['HTTP_ACCEPT']) as $value) {
list($suggested_mime) = explode(';', $value);
if (in_array($suggested_mime, $mimes)) {
return $suggested_mime;
}
}
throw new HttpException(406, array('Content-Type' => implode($mimes, ',')));
}
return DEFAULT_MIME_TYPE;
}

public static function Output(array $data, $namespace) {
$mime = self::MimeType();
$conv = new self::$output_handlers[$mime]();
$content = $conv->convert($data, $namespace); # canRun() is checked by <SupportedMimeTypes> already

header('Content-Type: ' . $mime);
echo $content;
exit;
}
}
?>
13 changes: 13 additions & 0 deletions JsonConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
require_once(dirname(__FILE__) . '/OutputConverter.php');

class JsonConverter implements OutputConverter {
public function canRun() {
return function_exists('json_encode');
}

public function convert($data, $namespace = NULL) {
return json_encode($data);
}
}
?>
6 changes: 6 additions & 0 deletions OutputConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
interface OutputConverter {
public function canRun();
public function convert($data, $namespace);
}
?>
13 changes: 13 additions & 0 deletions YamlConverter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php
require_once(dirname(__FILE__) . '/OutputConverter.php');

class YamlConverter implements OutputConverter {
public function canRun() {
return function_exists('yaml_emit');
}

public function convert($data, $namespace = NULL) {
return yaml_emit($data);
}
}
?>
10 changes: 10 additions & 0 deletions config/content-negotiation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php
# The default output content type if no Accept header is given
define('DEFAULT_MIME_TYPE', 'application/json');
# This content type should of course be supported. For supported
# content types, see the ContentNegotiator class.
# To add support for a new content type, you must do the following:
# 1) add a converter class that implements OutputConverter. for an example, see YamlConverter.php.
# 2) require() the class in ContentNegotiator.php
# 3) map it to the according content types in the ContentNegotiator class
?>
3 changes: 2 additions & 1 deletion items/describe.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_once("../modules/HttpException/HttpException.php");
require_once("../db.php");
require_once("../util.php");
require_once('../ContentNegotiator.php');
require_once("../Assert.php");
require_once("../modules/semver/semver.php");
require_once('../Item.php');
Expand All @@ -15,7 +16,7 @@
Assert::GetParameters("id", array("name", "version"));

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml", "application/x-ald-package"), "application/json");
$content_type = ContentNegotiator::MimeType('application/x-ald-package');

# connect to database server
$db_connection = db_ensure_connection();
Expand Down
3 changes: 2 additions & 1 deletion items/list.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_once("../modules/HttpException/HttpException.php");
require_once("../db.php");
require_once("../util.php");
require_once('../ContentNegotiator.php');
require_once('../SortHelper.php');
require_once('../FilterHelper.php');
require_once("../User.php");
Expand All @@ -18,7 +19,7 @@
Assert::RequestMethod(Assert::REQUEST_METHOD_GET); # only allow GET requests

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

# connect to database server
$db_connection = db_ensure_connection();
Expand Down
3 changes: 2 additions & 1 deletion items/rating.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_once("../Item.php");
require_once("../Assert.php");
require_once("../util.php");
require_once('../ContentNegotiator.php');
require_once("../db.php");
require_once('../sql2array.php');
require_once("../config/rating.php"); # import config settings
Expand Down Expand Up @@ -60,7 +61,7 @@

} else if ($request_method == Assert::REQUEST_METHOD_GET) {
# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml", "application/x-ald-package"), "application/json");
$content_type = ContentNegotiator::MimeType();

$db_query = 'SELECT name AS user, rating FROM ' . DB_TABLE_RATINGS . ', ' . DB_TABLE_USERS . ' WHERE item = UNHEX("' . $id . '") AND `user` = `id`';
$db_result = $db_connection->query($db_query);
Expand Down
3 changes: 2 additions & 1 deletion items/tags.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
require_once('../modules/HttpException/HttpException.php');
require_once('../db.php');
require_once('../util.php');
require_once('../ContentNegotiator.php');
require_once('../Assert.php');

try {
Assert::RequestMethod(Assert::REQUEST_METHOD_GET); # only allow GET requests

# validate accept header of request
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

# connect to database server
$db_connection = db_ensure_connection();
Expand Down
4 changes: 2 additions & 2 deletions items/types.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php
require_once('../util.php');
require_once('../ContentNegotiator.php');
require_once('../Assert.php');
require_once('ItemType.php');

Assert::RequestMethod(Assert::REQUEST_METHOD_GET);
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$types = ItemType::getAllNames();

Expand Down
3 changes: 2 additions & 1 deletion stdlib/candidates/create.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../Assert.php');
require_once('../../User.php');
require_once('../../Item.php');
Expand All @@ -16,7 +17,7 @@
Assert::GetParameters('id', array('name', 'version'));
Assert::PostParameters('reason');

$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

if (!isset($_GET['id'])) {
$item = Item::getId($_GET['name'], $_GET['version']);
Expand Down
3 changes: 2 additions & 1 deletion stdlib/candidates/describe.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<?php
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../Assert.php');
require_once('Candidate.php');

try {
Assert::RequestMethod(Assert::REQUEST_METHOD_GET);
Assert::GetParameters('id');

$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$candidate = Candidate::describe($_GET['id']);

Expand Down
3 changes: 2 additions & 1 deletion stdlib/candidates/list.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../Assert.php');
require_once('../../SortHelper.php');
require_once('../../FilterHelper.php');
Expand All @@ -9,7 +10,7 @@
try {
Assert::RequestMethod(Assert::REQUEST_METHOD_GET);

$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$filters = FilterHelper::FromParams(array('user', 'item', 'created', 'created-after', 'created-before', 'approved', 'owner'));
$sort_list = SortHelper::getListFromParam(isset($_GET['sort']) ? $_GET['sort'] : '');
Expand Down
3 changes: 2 additions & 1 deletion stdlib/candidates/voting.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../Assert.php');
require_once('../../SortHelper.php');
require_once('../../User.php');
Expand Down Expand Up @@ -46,7 +47,7 @@

} else {
Assert::GetParameters('id');
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$filters = FilterHelper::FromParams(array('user', 'final', 'accept', 'voted', 'voted-after', 'voted-before'));
$sort_list = SortHelper::getListFromParam(isset($_GET['sort']) ? $_GET['sort'] : '');
Expand Down
3 changes: 2 additions & 1 deletion stdlib/items.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
require_once('../modules/HttpException/HttpException.php');
require_once('../util.php');
require_once('../ContentNegotiator.php');
require_once('../sql2array.php');
require_once('../db.php');
require_once('../Assert.php');
Expand All @@ -9,7 +10,7 @@

try {
Assert::RequestMethod(Assert::REQUEST_METHOD_GET);
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$db_connection = db_ensure_connection();
$db_sort = '';
Expand Down
3 changes: 2 additions & 1 deletion stdlib/pending/list.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<?php
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../Assert.php');
require_once('../../UpdateType.php');
require_once('../StdlibPending.php');
require_once('../releases/StdlibRelease.php');

try {
Assert::RequestMethod(Assert::REQUEST_METHOD_GET);
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml'), 'application/json');
$content_type = ContentNegotiator::MimeType();

if (isset($_GET['action'])) {
$action = UpdateType::getCode($_GET['action'], UpdateType::USAGE_STDLIB);
Expand Down
3 changes: 2 additions & 1 deletion stdlib/releases/create.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
require_once("../../util.php");
require_once('../../ContentNegotiator.php');
require_once("../../Assert.php");
require_once("../../modules/HttpException/HttpException.php");
require_once("../../UpdateType.php");
Expand All @@ -12,7 +13,7 @@
Assert::RequestMethod(Assert::REQUEST_METHOD_POST);
Assert::GetParameters("type");

$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

$publish_status = StdlibRelease::PUBLISHED_BOTH;
if (!empty($_GET["base"]))
Expand Down
3 changes: 2 additions & 1 deletion stdlib/releases/describe.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_once("../../db.php");
require_once("../../sql2array.php");
require_once("../../util.php");
require_once('../../ContentNegotiator.php');
require_once("../../modules/semver/semver.php");
require_once("../../Assert.php");
require_once("../../User.php");
Expand All @@ -17,7 +18,7 @@
Assert::GetParameters("version");

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

$publish_status = StdlibRelease::PUBLISHED_YES;
if (isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"]))
Expand Down
3 changes: 2 additions & 1 deletion stdlib/releases/list.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
require_once("../../modules/HttpException/HttpException.php");
require_once("../../util.php");
require_once('../../ContentNegotiator.php');
require_once("../../User.php");
require_once('../../SortHelper.php');
require_once("../../Assert.php");
Expand All @@ -11,7 +12,7 @@
Assert::RequestMethod(Assert::REQUEST_METHOD_GET);

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

$publish_status = StdlibRelease::PUBLISHED_YES;
if (!empty($_GET["published"]))
Expand Down
3 changes: 2 additions & 1 deletion users/describe.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_once("../modules/HttpException/HttpException.php");
require_once("../db.php");
require_once("../util.php");
require_once('../ContentNegotiator.php');
require_once("../User.php");
require_once("../Assert.php");
require_once("Suspension.php");
Expand All @@ -13,7 +14,7 @@
Assert::GetParameters("name", "id");

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

# connect to database server
$db_connection = db_ensure_connection();
Expand Down
5 changes: 3 additions & 2 deletions users/list.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?php
require_once("../modules/HttpException/HttpException.php");
require_once("../db.php");
require_once("../util.php");
require_once('../util.php');
require_once('../ContentNegotiator.php');
require_once('../SortHelper.php');
require_once('../sql2array.php');
require_once("../Assert.php");
Expand All @@ -12,7 +13,7 @@
Assert::RequestMethod(Assert::REQUEST_METHOD_GET); # only allow GET requests

# validate accept header of request
$content_type = get_preferred_mimetype(array("application/json", "text/xml", "application/xml"), "application/json");
$content_type = ContentNegotiator::MimeType();

# connect to database server
$db_connection = db_ensure_connection();
Expand Down
3 changes: 2 additions & 1 deletion users/suspensions/list.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_once('../../Assert.php');
require_once('../../modules/HttpException/HttpException.php');
require_once('../../util.php');
require_once('../../ContentNegotiator.php');
require_once('../../SortHelper.php');
require_once('../../FilterHelper.php');
require_once('../../User.php');
Expand All @@ -27,7 +28,7 @@
}

# validate accept header of request
$content_type = get_preferred_mimetype(array('application/json', 'text/xml', 'application/xml', 'application/x-ald-package'), 'application/json');
$content_type = ContentNegotiator::MimeType();

$filters = FilterHelper::FromParams(array('active', 'created', 'created-after', 'created-before', 'expires', 'expires-after', 'expires-before', 'infinite', 'restricted'));
$sort_list = SortHelper::getListFromParam(isset($_GET['sort']) ? $_GET['sort'] : '');
Expand Down
Loading