created mocks for testing
parent
e53debb98d
commit
1211af09cc
Binary file not shown.
@ -0,0 +1,68 @@
|
||||
index.php
|
||||
web = new NetBiblio()
|
||||
parent::__construct(self::$version)
|
||||
web->Run() <=> parent->Run()
|
||||
| Logger::start(version) // initialize static log array
|
||||
| new Renderer::__construct()
|
||||
| |---ob_start()
|
||||
| $data = []
|
||||
| try {
|
||||
| $result = this->Call() //1) start session,
|
||||
| | //2) call webservice method and params passed in
|
||||
| | // http request after doing a few checks
|
||||
| | //3) log the request
|
||||
| | session_save_path(Configuration::get(session.save_path))
|
||||
| | session_start()
|
||||
| | $paras = GET or POST
|
||||
| | if empty(params) throw NoArguments
|
||||
| | if !isset(params["func"]) throw MissingMethod
|
||||
| | this->func = params["func"]
|
||||
| | unset(params["func"])
|
||||
| | Logger::info([
|
||||
| | "func" => this->func . '(' . implode(',' params) . ')'
|
||||
| | ]) // add func -> string to Logger::data
|
||||
| | if !is_callable([this, this->func]) throw BadMethod
|
||||
| | // descriptive wrapper for NetBiblio method
|
||||
| | $rm = new \ReflectionMethod(this, this->func)
|
||||
| | // check whether provided params match required
|
||||
| | //TODO here is where the magic happens !!!!!!!!!!!!!!!!!!!!
|
||||
| |---return call_user_func_array([this, this->func], params)
|
||||
| $data['result'][this->func] = $result
|
||||
| } catch (WebException $e) {
|
||||
| $data['error'] = ['code' => $e->getCode(), ... ]
|
||||
| $this->status = 400
|
||||
| Logger::info($e->getName(), 'error') // add to log
|
||||
| } catch (\Exception $e) {
|
||||
| $data['failure'] = ['code' => $e->getCode(), 'reason' ...]
|
||||
| Logger::info($e->getMessage, 'error')
|
||||
| }
|
||||
| Logger::stop(['status' => $this->status])
|
||||
| $renderer->render($this->status, $data) // default status:200
|
||||
| | header(sprintf(
|
||||
| | 'HTTP/1.0 %s %s',
|
||||
| | $status, self::$statusMessages[$status]
|
||||
| | ))
|
||||
| | header('Access-Control-Allow-Origin: *')
|
||||
| | ob_clean()
|
||||
| | flush()
|
||||
| | $formatter = Formatter::getFormatter();
|
||||
| | | self::loadFormatters() // call init on all formatters in dir
|
||||
| | | | foreach($files as f) {
|
||||
| | | | //infer class name from file name
|
||||
| | | | //and if it is not this current class
|
||||
| | | | //call init on the class
|
||||
| | | | //Ex:
|
||||
| | | | Json::init()
|
||||
| | | | | self::registerFormats([ //self parent
|
||||
| | | | | 'application/json',
|
||||
| | | | | 'application/x-json',
|
||||
| | | | | ]);
|
||||
| | | | | | forach($formats as $f) { // self
|
||||
| | | | | | self::$formats[$f] = get_called_class()
|
||||
| | | | |---|---}
|
||||
| | | | }
|
||||
| | | $format = self::getFormatFromHeader();
|
||||
| | | |---return 'BSR\Lib\Formatter\Json';
|
||||
| | |---return new $format()
|
||||
| | $formatter->render($data)
|
||||
|---|---|---echo json_encode($data)
|
||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
<h2>{{ func }}</h2>
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<dl>
|
||||
{{ parameters }}
|
||||
</dl>
|
||||
|
||||
<h3>Return</h3>
|
||||
{{ return }}
|
||||
|
||||
<h3>Description</h3>
|
||||
{{ help }}
|
||||
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>BSR WebService - {{ title }}</title>
|
||||
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-static-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">BSR WebService [{{ version }}]</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="help.php">Help</a></li>
|
||||
<li><a href="logs.php">Logs</a></li>
|
||||
<li><a href="phpinfo.php">PHPInfo</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,11 @@
|
||||
<div class="panel panel-{{ status }}">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ title }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{{ content }}
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
Generated in : {{ time }}
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,5 @@
|
||||
<dt>{{ name }} {{ optional }}</dt>
|
||||
<dd>
|
||||
<bold>{{ type }}</bold>
|
||||
{{ doc }}
|
||||
</dd>
|
||||
@ -0,0 +1,2 @@
|
||||
<bold>{{ type }}</bold>
|
||||
{{ doc }}
|
||||
Binary file not shown.
Binary file not shown.
@ -1,78 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace BSR\Webservice\Formatter;
|
||||
|
||||
abstract class Formatter {
|
||||
private static $formats = array();
|
||||
|
||||
/**
|
||||
* @param array $formats New available formats, array(mimetype => class)
|
||||
*/
|
||||
protected static function registerFormats(array $formats) {
|
||||
foreach($formats as $f) {
|
||||
self::$formats[$f] = get_called_class();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Formatter The formatter to use for this request
|
||||
*/
|
||||
public static function getFormatter() {
|
||||
self::loadFormatters();
|
||||
$format = self::getFormatFromHeader();
|
||||
|
||||
return new $format();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all formatters in the current directory
|
||||
*/
|
||||
private static function loadFormatters() {
|
||||
preg_match('/(.+)\\\([a-zA-Z0-9]+)/', get_called_class(), $parts);
|
||||
$us = $parts[2];
|
||||
$namespace = $parts[1];
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
$base = __DIR__.'/';
|
||||
$ext = '.php';
|
||||
$files = glob(sprintf('%s%s%s', $base, '*', $ext));
|
||||
foreach($files as $f) {
|
||||
$c = str_replace(array($base, $ext), '', $f);
|
||||
if($c !== $us) {
|
||||
$c = $namespace.'\\'.$c;
|
||||
call_user_func(array($c, 'init'));
|
||||
}
|
||||
}
|
||||
class FormatterTest extends TestCase
|
||||
{
|
||||
public function testFormatterAllwaysReturnsAJsonFormatter()
|
||||
{
|
||||
$formatter = Formatter::getFormatter();
|
||||
$this->assertEquals($formatter instanceof Json, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string The class name to instantiate in accord to the Accept header
|
||||
*/
|
||||
private static function getFormatFromHeader() {
|
||||
//TODO this is ugly
|
||||
return 'BSR\Webservice\Formatter\Json';
|
||||
if(isset($_SERVER['HTTP_ACCEPT'])) {
|
||||
$formats = array_map(function($f) {
|
||||
$parts = explode(';', $f);
|
||||
$parts[1] = (isset($parts[1]) ? (float) preg_replace('/[^0-9\.]/', '', $parts[1]) : 1.0) * 100;
|
||||
return $parts;
|
||||
}, explode(',', $_SERVER['HTTP_ACCEPT']));
|
||||
|
||||
usort($formats, function($a, $b) { return $b[1] - $a[1]; });
|
||||
|
||||
foreach($formats as $f) {
|
||||
if(isset(self::$formats[$f[0]])) {
|
||||
return self::$formats[$f[0]];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 'BSR\Webservice\Formatter\Json';
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the content for the given data
|
||||
* @param array $data
|
||||
*/
|
||||
abstract public function render($data);
|
||||
}
|
||||
|
||||
@ -1,17 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace BSR\Webservice\Formatter;
|
||||
|
||||
class Json extends Formatter {
|
||||
protected static function init() {
|
||||
self::registerFormats(array(
|
||||
'application/json',
|
||||
'application/x-json',
|
||||
));
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class JsonTest extends TestCase
|
||||
{
|
||||
protected $accept = array(
|
||||
'application/json',
|
||||
'application/x-json',
|
||||
);
|
||||
|
||||
public function testRenderEncodesDataIntoJsonFormat()
|
||||
{
|
||||
$format = new Json();
|
||||
$someArray = array(
|
||||
'asdf' => array(1, 'a', 'b', array()),
|
||||
'1' => array(3 => 'c'),
|
||||
0 => 'hello',
|
||||
);
|
||||
ob_start();
|
||||
$format->render($someArray);
|
||||
$jsonRepresentation = ob_get_clean();
|
||||
$this->assertSame(json_decode($jsonRepresentation, true), $someArray);
|
||||
}
|
||||
|
||||
public function render($data) {
|
||||
echo json_encode($data);
|
||||
public function testRegistersItsFormatAcceptHeader()
|
||||
{
|
||||
Formatter::getFormatter();
|
||||
$formats = Formatter::getRegisterdFormats();
|
||||
$this->assertSame(array_intersect($this->accept, array_keys($formats)), $this->accept);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
namespace BSR\Webservice;
|
||||
|
||||
use BSR\Webservice\Formatter\Formatter;
|
||||
|
||||
class MockRenderer extends Renderer
|
||||
{
|
||||
/**
|
||||
* Override to avoid sending headers and flushing buffers
|
||||
*/
|
||||
public function render($status, $data)
|
||||
{
|
||||
$formatter = Formatter::getFormatter();
|
||||
$formatter->render($data);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace BSR\Webservice;
|
||||
|
||||
class MockWebserviceSubclass extends Webservice
|
||||
{
|
||||
public function someMockFunction($one, $two, $threeOpt = null)
|
||||
{
|
||||
return 'Some Mock Function Return';
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue