Skip to content

Commit e1a87ab

Browse files
committed
Adding completed modules with some unit tests
1 parent acd1755 commit e1a87ab

25 files changed

+1739
-0
lines changed

public/favicon.ico

Whitespace-only changes.

public/index.php

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* index.php
4+
* data-api
5+
* @author: Matthew License, B023339
6+
* @date: 2013/09
7+
*/
8+
9+
require_once("../vendor/autoload.php");
10+
11+
use Hugo\Data\Controller\ControllerFactory,
12+
Hugo\Data\Application\Logger,
13+
Hugo\Data\Storage\FileSystem,
14+
Hugo\Data\Routing\Router,
15+
Hugo\Data\API;
16+
17+
$log = new Logger(new FileSystem('/media/vagrant/www/api.hugowolferton.co.uk/logs/api.log'));
18+
$router = new Router(new ControllerFactory(), $log);
19+
20+
$api = new API($router, $log);
21+
22+
$api->register("/", function() {
23+
return new \Symfony\Component\HttpFoundation\Response(
24+
json_encode(['api' => [
25+
'access-point' => 'https://api.hugowolferton.co.uk'
26+
, 'documentation' => 'http://docs.api.hugowolferton.co.uk'
27+
, 'description' => 'Hugo Wolferton Data Analysis API'
28+
, 'version' => '1.0'
29+
]], JSON_PRETTY_PRINT),
30+
200,
31+
['Content-Type' => 'application/json;charset=utf-8']
32+
);
33+
});
34+
35+
$api->run();

src/Hugo/Data/API.php

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* API.php
4+
* data-api
5+
* @author: Matthew License, B023339
6+
* @date: 2013/09
7+
*/
8+
9+
namespace Hugo\Data;
10+
11+
use Psr\Log\LoggerInterface,
12+
Hugo\Data\Storage\DB\MySQL,
13+
Hugo\Data\Routing\RouterInterface,
14+
Hugo\Data\Application\AppInterface,
15+
Symfony\Component\HttpFoundation\Request,
16+
Symfony\Component\HttpFoundation\Response;
17+
18+
class API implements AppInterface, RouterInterface
19+
{
20+
/**
21+
* @var \Psr\Log\LoggerInterface
22+
*/
23+
private $log;
24+
25+
/**
26+
* @var \Hugo\Data\Routing\RouterInterface
27+
*/
28+
private $router;
29+
30+
/**
31+
* @param \Hugo\Data\Routing\RouterInterface $router
32+
* @param \Psr\Log\LoggerInterface $log
33+
*/
34+
public function __construct(RouterInterface $router, LoggerInterface $log)
35+
{
36+
$this->log = $log;
37+
$this->router = $router;
38+
}
39+
40+
/**
41+
* @param Request $request
42+
* @return Response
43+
*/
44+
public function run(Request $request = null)
45+
{
46+
if(null === $request) {
47+
$request = Request::createFromGlobals();
48+
} else {
49+
$this->log->debug('Request made from {req}', ['req' => $request->getPathInfo()]);
50+
}
51+
52+
return $this->handle($request)->send();
53+
}
54+
55+
/**
56+
* @param Request $request
57+
* @return Response
58+
*/
59+
public function handle(Request $request)
60+
{
61+
try {
62+
$response = $this->router->route($request);
63+
} catch(\Exception $e) {
64+
$code = ($e->getCode() < 200 || $e->getCode() > 510) ? 500 : $e->getCode(); // make sure that the exception code is a valid HTTP code
65+
$this->log->error(get_class($e). ' ['. $code .'] - ' . $e->getMessage());
66+
$response = new Response(json_encode([ 'error' => $e->getMessage(),
67+
'response-code' => $code,
68+
'exception' => get_class($e)], JSON_PRETTY_PRINT),
69+
$code,
70+
['Content-Type' => 'application/json;charset=utf-8']);
71+
}
72+
73+
return $response;
74+
}
75+
76+
/**
77+
* @param $route
78+
* @param callable $callback
79+
*/
80+
public function register($route, callable $callback)
81+
{
82+
$this->router->register($route, $callback);
83+
}
84+
85+
/**
86+
* @param Request $request
87+
* @return Response
88+
*/
89+
public function route(Request $request)
90+
{
91+
return $this->router->route($request);
92+
}
93+
}

src/Hugo/Data/Application/Logger.php

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
/**
3+
* Logger.php
4+
* data-api
5+
* @author: Matthew License, B023339
6+
* @date: 2013/10
7+
*/
8+
9+
namespace Hugo\Data\Application;
10+
11+
use Psr\Log\LogLevel,
12+
Psr\Log\LoggerInterface,
13+
Hugo\Data\Model\LogItem,
14+
Hugo\Data\Storage\DataSource,
15+
Hugo\Data\Storage\FileSystem,
16+
Psr\Log\InvalidArgumentException;
17+
18+
class Logger implements LoggerInterface
19+
{
20+
21+
/**
22+
* @var \Hugo\Data\Storage\DataSource
23+
*/
24+
protected $store;
25+
26+
/**
27+
* @var array
28+
*/
29+
protected $logs = [];
30+
31+
public function __construct(DataSource $store = null)
32+
{
33+
if(null === $store) {
34+
// if no DataSource is declared, we'll use a FileSystem
35+
$store = new FileSystem('/media/vagrant/www/api.hugowolferton.co.uk/logs/api.log');
36+
}
37+
$this->store = $store;
38+
}
39+
40+
public function log($level, $message, array $context = [])
41+
{
42+
switch($level) {
43+
case LogLevel::EMERGENCY:
44+
case LogLevel::CRITICAL:
45+
case LogLevel::ERROR:
46+
case LogLevel::ALERT:
47+
case LogLevel::WARNING:
48+
case LogLevel::INFO:
49+
case LogLevel::NOTICE:
50+
case LogLevel::DEBUG:
51+
return $this->_log($level, $message, $context);
52+
break;
53+
default:
54+
throw new InvalidArgumentException("Logging level {$level} doesn't exist");
55+
}
56+
}
57+
58+
public function getLogs()
59+
{
60+
return $this->logs;
61+
}
62+
63+
public function resetLogs()
64+
{
65+
$this->logs = [];
66+
}
67+
68+
private function _log($level, $message, array $context = [])
69+
{
70+
$log = new LogItem($this->store);
71+
$log->set(['level' => $level, 'message' => $message, 'context' => $context]);
72+
$this->logs[] = trim((string)($log));
73+
if($log->save()) {
74+
return $log;
75+
} else {
76+
return false;
77+
}
78+
}
79+
80+
public function emergency($message, array $context = [])
81+
{
82+
$this->_log(LogLevel::EMERGENCY, $message, $context);
83+
}
84+
85+
public function alert($message, array $context = [])
86+
{
87+
$this->_log(LogLevel::ALERT, $message, $context);
88+
}
89+
90+
public function critical($message, array $context = [])
91+
{
92+
$this->_log(LogLevel::CRITICAL, $message, $context);
93+
}
94+
95+
public function error($message, array $context = [])
96+
{
97+
$this->_log(LogLevel::ERROR, $message, $context);
98+
}
99+
100+
public function warning($message, array $context = [])
101+
{
102+
$this->_log(LogLevel::WARNING, $message, $context);
103+
}
104+
105+
public function notice($message, array $context = [])
106+
{
107+
$this->_log(LogLevel::NOTICE, $message, $context);
108+
}
109+
110+
public function info($message, array $context = [])
111+
{
112+
$this->_log(LogLevel::INFO, $message, $context);
113+
}
114+
115+
public function debug($message, array $context = [])
116+
{
117+
$this->_log(LogLevel::DEBUG, $message, $context);
118+
}
119+
120+
}
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
4+
namespace Hugo\Data\Controller;
5+
6+
7+
class Constants {
8+
9+
const CONTROLLER_NS = '\\Hugo\\Data\\Controller';
10+
const CONTENT_TYPE = 'application/json;charset=utf-8';
11+
12+
// 2xx response codes - request OK
13+
const HTTP_OK = 200;
14+
const HTTP_CREATED = 201;
15+
const HTTP_ACCEPTED = 202;
16+
const HTTP_NO_CONTENT = 204;
17+
18+
// 3xx response codes - redirects
19+
const HTTP_MOVED = 301;
20+
const HTTP_FOUND = 302;
21+
const HTTP_SEE_OTHER = 303;
22+
const HTTP_NOT_MODIFIED = 304;
23+
24+
// 4xx response codes - client errors
25+
const HTTP_BAD_REQ = 400;
26+
const HTTP_UNAUTHORISED = 401;
27+
const HTTP_FORBIDDEN = 403;
28+
const HTTP_NOT_FOUND = 404;
29+
const HTTP_BAD_METHOD = 405;
30+
const HTTP_NOT_ACCEPTABLE = 406;
31+
const HTTP_TIMEOUT = 408;
32+
const HTTP_GONE = 410;
33+
const HTTP_UNSUPPORTED_MEDIA = 415;
34+
const HTTP_TEAPOT = 418;
35+
36+
// 5xx response codes - server errors
37+
const HTTP_SERVER_ERROR = 500;
38+
const HTTP_NOT_IMPLEMENTED = 501;
39+
const HTTP_BAD_GATEWAY = 502;
40+
const HTTP_SERVICE_UNAVAILABLE = 503;
41+
const HTTP_GATEWAY_TIMEOUT = 504;
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* BadMethodCallException.php
4+
* data-api
5+
* @author: Matt
6+
* @date: 2013/12
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
12+
class BadMethodCallException extends \Exception { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: Matt
5+
* Date: 15/11/13
6+
* Time: 23:44
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
class DuplicateRouteException extends \Exception { }
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: Matt
5+
* Date: 11/17/13
6+
* Time: 3:07 AM
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
class IOException extends \Exception { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
/**
3+
* InvalidDataSourceException.php
4+
* data-api
5+
* @author: Matthew License, B023339
6+
* @date: 2013/10
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
class InvalidDataSourceException extends \Exception {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* InvalidQueryException.php
4+
* data-api
5+
* @author: Matt
6+
* @date: 2014/02
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
12+
class InvalidQueryException extends \Exception { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* InvalidRequestException.php
4+
* data-api
5+
* @author: Matt
6+
* @date: 2014/02
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
12+
class InvalidRequestException extends \Exception { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* InvalidTokenException.php
4+
* data-api
5+
* @author: Matt
6+
* @date: 2013/12
7+
*/
8+
9+
namespace Hugo\Data\Exception;
10+
11+
12+
class InvalidTokenException extends \Exception { }

0 commit comments

Comments
 (0)