Skip to content

Commit 0f8ee75

Browse files
author
pointybeard
committed
Initial Commit
0 parents  commit 0f8ee75

14 files changed

Lines changed: 463 additions & 0 deletions

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Symphony Api Framework
2+
3+
This framework adds a Json renderer to Symphony and helps to quickly build an API with a, event driven, controller interface.

composer.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "pointybeard/symphony-api-framework",
3+
"version": "1.0.0",
4+
"description": "",
5+
"homepage": "http://alistairkearney.com",
6+
"license": "MIT",
7+
"authors": [
8+
{
9+
"name": "Alistair Kearney",
10+
"email": "hi@alistairkearney.com"
11+
}
12+
],
13+
"support": {
14+
"issues": "https://github.com/pointybeard/symphony-api-framework/issues",
15+
"wiki": "https://github.com/pointybeard/symphony-api-framework/wiki"
16+
},
17+
"minimum-stability": "dev",
18+
"require": {
19+
"php": ">=5.6.6",
20+
"monolog/monolog": "^1.16@dev",
21+
"symfony/http-foundation": "^3.0@dev"
22+
},
23+
"autoload": {
24+
"psr-4": {
25+
"Symphony\\ApiFramework\\": "src"
26+
}
27+
},
28+
"autoload-dev": {
29+
"psr-4": {
30+
"Symphony\\ApiFramework\\Tests\\": "tests"
31+
}
32+
}
33+
}

events/event.controller.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
use Symfony\Component\HttpFoundation\Request;
4+
use Symfony\Component\HttpFoundation\JsonResponse;
5+
6+
class eventController extends SectionEvent
7+
{
8+
public static function about()
9+
{
10+
return [
11+
'name' => 'Symphony API Framework: Event Controller',
12+
'author' => array(
13+
'name' => 'Alistair Kearney',
14+
'website' => 'http://cp.kickd',
15+
'email' => 'alistair@ruleandmake.com'),
16+
'version' => 'Symphony 2.6.3',
17+
'release-date' => '2015-08-28T02:10:22+00:00',
18+
'trigger-condition' => 'POST|PUT|PATCH|DELETE'
19+
];
20+
}
21+
22+
public function load()
23+
{
24+
$request = Request::createFromGlobals();
25+
26+
// This ensures the composer autoloader for the framework is included
27+
Symphony::ExtensionManager()->create('api_framework');
28+
29+
// Event controllor only responds to certain methods. GET is handled by the data sources
30+
if($request->getMethod() == 'GET'){
31+
return;
32+
}
33+
34+
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
35+
$data = json_decode($request->getContent(), true, 512, JSON_BIGINT_AS_STRING);
36+
$request->request->replace(is_array($data) ? $data : []);
37+
}
38+
39+
//@TODO: Use the current path to resolve controllers deeper than 1 level
40+
//Frontend::instance()->Page()->Params()['current-path']
41+
42+
$controllerPath = WORKSPACE . '/controllers';
43+
$controllerName = 'Controller' . ucfirst(Frontend::instance()->Page()->pageData()['handle']);
44+
45+
include_once WORKSPACE . "/controllers/$controllerName.php";
46+
$controller = new $controllerName();
47+
$method = strtolower($request->getMethod());
48+
49+
if(!method_exists($controller, $method)){
50+
throw new \Exception("405 method not found (".$request->getMethod().")");
51+
}
52+
53+
$controller->execute();
54+
55+
// Prepare the response.
56+
$response = new JsonResponse();
57+
$response->headers->set('Content-Type', 'application/json');
58+
59+
$response = $controller->$method($request, $response);
60+
$response->send();
61+
exit;
62+
63+
}
64+
65+
public static function documentation()
66+
{
67+
return '<h3>Event Controller</h3><p>Handles passing off work to controllors depending on what has been requested.</p>';
68+
}
69+
}

extension.driver.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
include __DIR__.'/vendor/autoload.php';
4+
5+
Class extension_api_framework extends Extension {
6+
public function getSubscribedDelegates(){
7+
return[
8+
[
9+
'page' => '/all/',
10+
'delegate' => 'ModifySymphonyLauncher',
11+
'callback' => 'setJSONLauncher'
12+
],
13+
[
14+
'page' => '/frontend/',
15+
'delegate' => 'FrontendOutputPreGenerate',
16+
'callback' => 'setBoilerplateXSL'
17+
],
18+
19+
];
20+
}
21+
22+
public function setJSONLauncher($context)
23+
{
24+
if($_REQUEST['mode'] == 'administration') {
25+
return;
26+
}
27+
define('SYMPHONY_LAUNCHER', 'renderer_json');
28+
include __DIR__ . '/src/Includes/JsonRendererLauncher.php';
29+
}
30+
31+
public function setBoilerplateXSL($context)
32+
{
33+
// @todo: This should only be available if logged in
34+
if(!isset($_GET['boilerplate-xsl']) && (!in_array('JSON', Frontend::Page()->pageData()['type'])
35+
|| !in_array('boilerplate-xsl', Frontend::Page()->pageData()['type']))) {
36+
return;
37+
}
38+
39+
$context['xsl'] = <<<'XSL'
40+
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0"
41+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
42+
<xsl:template match="node()|@*">
43+
<xsl:copy>
44+
<xsl:apply-templates select="node()|@*"/>
45+
</xsl:copy>
46+
</xsl:template>
47+
</xsl:stylesheet>
48+
XSL;
49+
}
50+
}

extension.meta.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<extension id="api_framework" status="released" xmlns="http://getsymphony.com/schemas/extension/1.0">
3+
<name>API Framework</name>
4+
<description>Base for a Json API in Symphony</description>
5+
<types>
6+
<type>System</type>
7+
</types>
8+
<authors>
9+
<author>
10+
<name github="pointybeard" symphony="alistair">Alistair Kearney</name>
11+
<website>http://alistairkearney.com</website>
12+
</author>
13+
</authors>
14+
<releases>
15+
<release version="1.0" date="2015-09-06" min="2.6">
16+
- Initial release
17+
</release>
18+
</releases>
19+
</extension>

phpunit.xml.dist

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.3/phpunit.xsd"
5+
backupGlobals="true"
6+
backupStaticAttributes="false"
7+
bootstrap="tests/bootstrap.php"
8+
cacheTokens="false"
9+
colors="true"
10+
convertErrorsToExceptions="true"
11+
convertNoticesToExceptions="true"
12+
convertWarningsToExceptions="true"
13+
processIsolation="false"
14+
stopOnError="false"
15+
stopOnFailure="false"
16+
stopOnIncomplete="false"
17+
stopOnSkipped="false"
18+
verbose="false"
19+
>
20+
<testsuites>
21+
<testsuite name="Symphony Api Framework">
22+
<directory>./tests/src/</directory>
23+
</testsuite>
24+
</testsuites>
25+
26+
<filter>
27+
<whitelist addUncoveredFilesFromWhitelist="true">
28+
<directory suffix=".php">./src/</directory>
29+
</whitelist>
30+
</filter>
31+
32+
</phpunit>

src/.DS_Store

6 KB
Binary file not shown.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
use Symphony\ApiFramework\Lib;
4+
5+
function renderer_json($mode){
6+
if (strtolower($mode) == 'administration') {
7+
throw new Lib\Exceptions\InvalidModeException('JSON Renderer launcher is only availalbe on the frontend');
8+
}
9+
10+
try{
11+
$renderer = Frontend::instance();
12+
13+
// Switch the error handlers over
14+
Lib\ExceptionHandler::initialise(true);
15+
Lib\ErrorHandler::initialise();
16+
17+
// #1808
18+
if (isset($_SERVER['HTTP_MOD_REWRITE']))
19+
{
20+
throw new Exception("mod_rewrite is required, however is not enabled.");
21+
}
22+
23+
$output = $renderer->display(getCurrentPage());
24+
25+
cleanup_session_cookies();
26+
} catch (\SymphonyErrorPage $e) {
27+
// We dont want the SymphonyErrorPage handler to kickd in, so lets re-throw this
28+
throw new Exception($e->getMessage, $e->getCode, $e);
29+
}
30+
31+
32+
if(in_array('JSON', Frontend::Page()->pageData()['type'])) {
33+
// Load the output into a SimpleXML Container and convert to JSON
34+
$xml = new SimpleXMLElement($output);
35+
$output = json_encode($xml, JSON_PRETTY_PRINT);
36+
}
37+
38+
echo $output;
39+
return $renderer;
40+
}

src/Lib/AbstractController.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Symphony\ApiFramework\Lib;
4+
5+
use Symphony\ApiFramework\Lib\Interfaces;
6+
use Symfony\Component\HttpFoundation\Request;
7+
use Symfony\Component\HttpFoundation\Response;
8+
9+
/**
10+
* The base endpoint class that is extended by all API methods.
11+
*/
12+
abstract class AbstractController implements Interfaces\ControllerInterface
13+
{
14+
abstract public function execute();
15+
16+
public function render(Response $response, array $data)
17+
{
18+
$response->setData($data);
19+
return $response;
20+
}
21+
}

src/Lib/ErrorHandler.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
namespace Symphony\ApiFramework\Lib;
3+
4+
use \GenericErrorHandler;
5+
use \ErrorException;
6+
7+
class ErrorHandler extends GenericErrorHandler
8+
{
9+
/**
10+
* Whether the error handler is enabled or not, defaults to true.
11+
* Setting to false will prevent any Symphony error handling from occurring
12+
* @var boolean
13+
*/
14+
public static $enabled = true;
15+
16+
/**
17+
* Initialise will set the error handler to be the `__CLASS__::handler`
18+
* function.
19+
*/
20+
public static function initialise()
21+
{
22+
restore_error_handler();
23+
set_error_handler(array(__CLASS__, 'handler'), error_reporting());
24+
}
25+
26+
/**
27+
* Determines if the error handler is enabled by checking that error_reporting
28+
* is set in the php config and that $enabled is true
29+
*
30+
* @return boolean
31+
*/
32+
public static function isEnabled()
33+
{
34+
return (bool) error_reporting() && self::$enabled;
35+
}
36+
37+
/**
38+
* The handler function will write the error to the `$Log` if it is not `E_NOTICE`
39+
* or `E_STRICT` before raising the error as an Exception. This allows all `E_WARNING`
40+
* to actually be captured by an Exception handler.
41+
*
42+
* @param integer $code
43+
* The error code, one of the PHP error constants
44+
* @param string $message
45+
* The message of the error, this will be written to the log and
46+
* displayed as the exception message
47+
* @param string $file
48+
* The file that holds the logic that caused the error. Defaults to null
49+
* @param integer $line
50+
* The line where the error occurred.
51+
* @throws ErrorException
52+
* @return string
53+
* Usually a string of HTML that will displayed to a user
54+
*/
55+
public static function handler($code, $message, $file = null, $line = null)
56+
{
57+
if (self::isEnabled()) {
58+
throw new ErrorException($message, 0, $code, $file, $line);
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)