Commit e091ff78 authored by Σταύρος Παπαδάκης's avatar Σταύρος Παπαδάκης
Browse files

API support, serving JSON formatted data

Paged api endpoints accept "page" and "pagesize" params.
New config file config/settings/open_data.global.php
ACL is dynamically manipulated by the module.
The "index" endpoint provides links to available endpoints.
Documentation is provided in swagger.
Add doc links to open data page itminedu/gredu_labs#14
parent 9a4e9ac8
......@@ -6,21 +6,20 @@
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
return [
'acl' => [
'default_role' => 'guest',
'roles' => [
'guest' => [],
'user' => [],
'roles' => [
'guest' => [],
'user' => [],
'school' => ['user'],
'admin' => ['user'],
'admin' => ['user'],
],
'resoures' => [],
'guards' => [
'guards' => [
'resources' => [],
'callables' => [],
'routes' => [
'routes' => [
['/', ['guest', 'user'], ['get']],
['/about', ['guest', 'user'], ['get']],
['/school', ['school'], ['get']],
......
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
return [
'open_data' => [
'pagesize' => 20, // default page size
'maxpagesize' => 200, // maximum page size
],
];
......@@ -43,6 +43,7 @@ return function (App $app) {
'ID',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Ονομασία χώρου',
'Τύπος χώρου',
'Ειδικότητα υπευθύνου',
......@@ -65,6 +66,7 @@ return function (App $app) {
'Τύπος χώρου',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Σχόλια - Παρατηρήσεις',
],
],
......@@ -74,6 +76,7 @@ return function (App $app) {
'Τύπος',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'ID χώρου',
'Τύπος χώρου',
'Ονομασία',
......@@ -87,6 +90,7 @@ return function (App $app) {
'ID',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Ημερομηνία υποβολής',
'Σχόλια - Παρατηρήσεις',
],
......@@ -98,6 +102,7 @@ return function (App $app) {
'ID',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Ημερομηνία υποβολής',
'Σχόλια - Παρατηρήσεις',
],
......@@ -110,6 +115,7 @@ return function (App $app) {
'ID',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Ημερομηνία υποβολής',
'ID χώρου',
'Τύπος χώρου',
......@@ -125,9 +131,14 @@ return function (App $app) {
'ID',
'Κωδικός σχολείου',
'Ονομασία σχολείου',
'Περιφερειακή διεύθυνση εκπαίδευσης',
'Ημερομηνία υποβολής',
'ID χώρου',
'Τύπος χώρου',
'Νέος χώρος',
'Είδος',
'Πλήθος Υπαρχόντων που λειτουργούν',
'Πλήθος Αιτουμένων',
'Πλήθος Υπαρχόντων που λειτουργούν',
'Αιτιολογία χρήσης',
],
],
......@@ -198,6 +209,7 @@ return function (App $app) {
$sql = 'SELECT lab.id AS id, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' TRIM(lab.name) AS name, '
. ' TRIM(labtype.name) AS type, '
. ' branch.name AS responsible_branch, '
......@@ -211,6 +223,8 @@ return function (App $app) {
. ' FROM lab '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
. ' LEFT JOIN school ON lab.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN lab_lesson ON lab_lesson.lab_id = lab.id '
. ' LEFT JOIN lesson ON lab_lesson.lesson_id = lesson.id '
. ' LEFT JOIN teacher ON lab.responsible_id = teacher.id '
......@@ -234,10 +248,13 @@ return function (App $app) {
. ' TRIM(labtype.name) AS lab_type, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' schoolasset.comments AS comments '
. ' FROM schoolasset '
. ' LEFT JOIN itemcategory ON schoolasset.itemcategory_id = itemcategory.id '
. ' LEFT JOIN school ON schoolasset.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN lab ON schoolasset.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
. ' GROUP BY schoolasset.id '
......@@ -249,15 +266,13 @@ return function (App $app) {
};
};
$c['csv_export_software'] = function ($c) {
$c['csv_export_software'] = function ($c) {
return function () {
$sql = 'SELECT softwarecategory.name AS name, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' lab.id AS lab_id, '
. ' TRIM(labtype.name) AS lab_type, '
. ' TRIM(software.title) AS title, '
......@@ -266,6 +281,8 @@ return function (App $app) {
. ' FROM software '
. ' LEFT JOIN softwarecategory ON software.softwarecategory_id = softwarecategory.id '
. ' LEFT JOIN school ON software.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN lab ON software.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
. ' ORDER BY school_name ';
......@@ -284,17 +301,8 @@ return function (App $app) {
};
};
$c['csv_export_appforms'] = function ($c) {
//return function () {
return function () use ($c) {
$settings = $c->get('settings');
$version = $settings['application_form']['itemcategory']['currentversion'];
......@@ -322,11 +330,14 @@ return function (App $app) {
$sql = 'SELECT applicationform.id AS id, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' FROM_UNIXTIME(applicationform.submitted) AS submitted, '
. ' TRIM(applicationform.comments) AS comments'
. ' FROM applicationformitem '
. ' LEFT JOIN applicationform ON applicationformitem.applicationform_id = applicationform.id '
. ' LEFT JOIN school ON applicationform.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN itemcategory ON applicationformitem.itemcategory_id = itemcategory.id '
. ' LEFT JOIN lab ON applicationformitem.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
......@@ -337,51 +348,35 @@ return function (App $app) {
return $appForms;
// $sql = 'SELECT applicationform.id AS id, '
// . ' school.registry_no AS school_registry_no, '
// . ' school.name AS school_name, '
// . ' FROM_UNIXTIME(applicationform.submitted) AS submitted, '
// . ' TRIM(applicationform.comments) AS comments '
// . ' FROM applicationform '
// . ' LEFT JOIN school ON applicationform.school_id = school.id '
// . ' GROUP BY school.id '
// . ' HAVING MAX(applicationform.submitted)';
// $appForms = R::getAll($sql);
// return $appForms;
};
};
$c['csv_export_appnewforms'] = function ($c) {
return function () use ($c) {
return function () use ($c) {
$appFormIdsSql = 'SELECT id FROM applicationform WHERE (submitted) IN( SELECT MAX(submitted) FROM applicationform GROUP BY school_id)';
$appFormIds = R::getCol($appFormIdsSql);
if (empty($appFormIds)) {
return [];
}
$in = implode(',', array_fill(0, count($appFormIds), '?'));
$settings = $c->get('settings');
$version = $settings['application_form']['itemcategory']['currentversion'];
$sql = 'SELECT applicationform.id AS id, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' FROM_UNIXTIME(applicationform.submitted) AS submitted, '
. ' TRIM(applicationform.comments) AS comments'
. ' FROM applicationformitem '
. ' LEFT JOIN applicationform ON applicationformitem.applicationform_id = applicationform.id '
. ' LEFT JOIN school ON applicationform.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN itemcategory ON applicationformitem.itemcategory_id = itemcategory.id '
. ' LEFT JOIN lab ON applicationformitem.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
......@@ -395,8 +390,6 @@ return function (App $app) {
};
};
$c['csv_export_appforms_items'] = function ($c) {
return function () use ($c){
......@@ -413,14 +406,6 @@ return function (App $app) {
. ' WHERE itemcategory.groupflag NOT IN(' . $version . ')'
. ' GROUP BY school.id)';
// $appFormIdsSql = 'SELECT applicationform.id '
// . ' FROM applicationform '
// . ' GROUP BY school_id '
// . ' HAVING MAX(applicationform.submitted)';
$appFormIds = R::getCol($appFormIdsSql);
if (empty($appFormIds)) {
......@@ -431,6 +416,7 @@ return function (App $app) {
$sql = 'SELECT applicationform.id AS id, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' FROM_UNIXTIME(applicationform.submitted) AS submitted, '
. ' lab.id AS lab_id, '
. ' TRIM(labtype.name) AS lab_type, '
......@@ -441,6 +427,8 @@ return function (App $app) {
. ' FROM applicationformitem '
. ' LEFT JOIN applicationform ON applicationformitem.applicationform_id = applicationform.id '
. ' LEFT JOIN school ON applicationform.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN itemcategory ON applicationformitem.itemcategory_id = itemcategory.id '
. ' LEFT JOIN lab ON applicationformitem.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
......@@ -452,12 +440,10 @@ return function (App $app) {
};
};
$c['csv_export_newapplication'] = function ($c) {
return function () use ($c) {
$appFormIdsSql = 'SELECT id FROM applicationform WHERE (submitted) IN( SELECT MAX(submitted) FROM applicationform GROUP BY school_id)';
$appFormIds = R::getCol($appFormIdsSql);
......@@ -475,6 +461,11 @@ return function (App $app) {
$sql = 'SELECT applicationform.id AS id, '
. ' school.registry_no AS school_registry_no, '
. ' school.name AS school_name, '
. ' regioneduadmin.name AS region_edu_admin, '
. ' FROM_UNIXTIME(applicationform.submitted) AS submitted, '
. ' lab.id AS lab_id, '
. ' TRIM(labtype.name) AS lab_type, '
. ' IF(lab.is_new = 1, "ΝΑΙ", "ΟΧΙ") AS is_new, '
. ' TRIM(itemcategory.name) AS category, '
. ' applicationformitem.qty AS qty, '
. ' applicationformitem.qtyacquired AS qtyacquired, '
......@@ -482,6 +473,8 @@ return function (App $app) {
. ' FROM applicationformitem '
. ' LEFT JOIN applicationform ON applicationformitem.applicationform_id = applicationform.id '
. ' LEFT JOIN school ON applicationform.school_id = school.id '
. ' LEFT JOIN eduadmin ON school.eduadmin_id = eduadmin.id '
. ' LEFT JOIN regioneduadmin ON eduadmin.regioneduadmin_id = regioneduadmin.id '
. ' LEFT JOIN itemcategory ON applicationformitem.itemcategory_id = itemcategory.id '
. ' LEFT JOIN lab ON applicationformitem.lab_id = lab.id '
. ' LEFT JOIN labtype ON lab.labtype_id = labtype.id '
......@@ -494,6 +487,7 @@ return function (App $app) {
return $appForms;
};
};
});
$events('on', 'app.bootstrap', function (App $app, Container $c) {
......
This diff is collapsed.
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\OpenData\Action;
/**
* @inheritdoc
*/
class AllSchools extends PagedApiAction
{
}
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\OpenData\Action;
use Slim\Container;
use Slim\Http\Request;
use Slim\Http\Response;
use GrEduLabs\OpenData\Service\DataProviderInterface;
use GrEduLabs\OpenData\Service\RedBeanQueryPagedDataProvider;
/**
* Base class implementaing the api action.
* A dataprovider object is used to retrieve data.
*
* @see GrEduLabs\OpenData\Service\DataProviderInterface
*/
class ApiAction
{
/**
* @var GrEduLabs\OpenData\Service\DataProviderInterface
*/
protected $dataProvider;
/**
* @var Slim\Container
*/
protected $container;
/**
* @var boolean Respond with a 404 instead of 200 if data from dataprovider is an empty array.
*/
protected $empty_data_404;
public function __construct(Container $container, DataProviderInterface $dataProvider, $empty_data_404 = false)
{
$this->container = $container;
$this->dataProvider = $dataProvider;
$this->empty_data_404 = $empty_data_404;
}
public function setEmptyData404()
{
$this->empty_data_404 = true;
}
public function setEmptyData200()
{
$this->empty_data_404 = false;
}
public function __invoke(Request $req, Response $res, array $args = [])
{
/**
* Get data from dataprovider.
* If data is null, respond with a 500 status.
* If data is empty, respond with a 404 when $empty_data_404 is true.
* In any other case respond with a 200 status.
*
* @see GrEduLabs\OpenData\Service\DataProviderInterface
*/
$data = $this->dataProvider->getData();
$status = 200;
if ($data === null) {
$status = 500;
$data = ['message' => 'An error occured while retrieving data'];
} elseif (!is_array($data)) {
$status = 500;
$data = ['message' => 'Unexpected data: ' . var_export($data, true)];
} elseif (count($data) === 0) {
$status = (($this->empty_data_404 === true) ? 404 : 200);
}
return $this->respond($res, 'JSON', $this->prepareResponseData($status, $data), $status);
}
/**
*
* @param int $status HTTP status code
* @param type $data the real data to wrap in response
* @return array An array with predetermined keys:
* - status HTTP status code
* - success boolean
* - data The actual data
* - labels Data labels
* - count Data count in resultset
* - countall Data count without paging
* - page Data current page
* - pages Data number of pages available
*/
protected function prepareResponseData($status, $data = null)
{
$is_success = ($status == 200);
$has_data = $is_success && isset($data);
$has_paging = $this->dataProvider instanceof RedBeanQueryPagedDataProvider && $has_data;
$response_data = [
'status' => $status,
'success' => $is_success,
'count' => ($has_data ? $this->dataProvider->getCount() : null),
'countall' => ($has_paging ? $this->dataProvider->getCountAll() : null),
'page' => ($has_paging ? $this->dataProvider->getPage() : null),
'pages' => ($has_paging ? $this->dataProvider->getPages() : null),
'labels' => ($has_data ? $this->dataProvider->getLabels() : null),
'data' => $data,
];
return $response_data;
}
/**
* Send the final response. Only Json format is currently supported.
*
* @param string $outputFormat i.e. JSON
* @param array $response_data typically an array to send ot data to the client
* @param int $status HTTP status code
* @return mixed response object
*/
protected function respond(Response $res, $outputFormat, array $response_data, $status)
{
switch ($outputFormat) {
case 'JSON':
default:
return $res->withJson($response_data, $status, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
}
}
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\OpenData\Action;
use Slim\Container;
use Slim\Http\Request;
use Slim\Http\Response;
use GrEduLabs\OpenData\Service\DataProviderInterface;
use GrEduLabs\OpenData\InputFilter\EduadminNameInputFilter;
use GrEduLabs\OpenData\InputFilter\RegioneduadminNameInputFilter;
/**
* @inheritdoc
*/
class EduadminFilteredPagedApiAction extends PagedApiAction
{
/**
* @var InputFilter for eduadmin name
*/
private $_eduadminInputFilter;
/**
* @var InputFilter for region eduadmin name
*/
private $_regioneduadminInputFilter;
public function __construct(Container $container, DataProviderInterface $dataProvider, $empty_data_404 = false)
{
parent::__construct($container, $dataProvider, $empty_data_404);
$this->_eduadminInputFilter = new EduadminNameInputFilter();
$this->_regioneduadminInputFilter = new RegioneduadminNameInputFilter();
}
public function __invoke(Request $req, Response $res, array $args = [])
{
$this->_eduadminInputFilter->setData([
'name' => (isset($args['eduadmin']) ? $args['eduadmin'] : null)
]);
$this->_regioneduadminInputFilter->setData([
'name' => (isset($args['regioneduadmin']) ? $args['regioneduadmin'] : null)
]);
if ($this->_eduadminInputFilter->isValid() &&
$this->_regioneduadminInputFilter->isValid()) {
$this->dataProvider->queryFilter('eduadmin.name', $this->_eduadminInputFilter->getValue('name'), 'LIKE');
$this->dataProvider->queryFilter('regioneduadmin.name', $this->_regioneduadminInputFilter->getValue('name'), 'LIKE');
return parent::__invoke($req, $res, $args);
} else {
$messages = array_merge($this->_eduadminInputFilter->getMessages(), $this->_regioneduadminInputFilter->getMessages());
$responseData = $this->prepareResponseData(400, [
'errors' => array_reduce(array_keys($messages), function ($m, $k) use ($messages) {
$m[$k] = array_values($messages[$k]);
return $m;
}, [])
]);
return $this->respond($res, 'JSON', $responseData, 400);
}
}
}
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\OpenData\Action;
//use Slim\Container;
//use Slim\Http\Request;
//use Slim\Http\Response;
//use GrEduLabs\OpenData\Service\DataProviderInterface;
/**
* @inheritdoc
*/
class Index extends ApiAction
{
}
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\OpenData\Action;
use Slim\Container;
use Slim\Http\Request;
use Slim\Http\Response;
use GrEduLabs\OpenData\Service\DataProviderInterface;
use GrEduLabs\OpenData\InputFilter\GroupFlagInputFilter;
/**
* @inheritdoc
*/
class ItemCategoryNames extends ApiAction
{
/**
* @var InputFilter
*/
private $inputFilter;
public function __construct(Container $container, DataProviderInterface $dataProvider, $empty_data_404 = false)
{
parent::__construct($container, $dataProvider, $empty_data_404);
$this->inputFilter = new GroupFlagInputFilter();
}
public function __invoke(Request $req, Response $res, array $args = [])
{
$this->inputFilter->setData([
'group' => $req->getParam('group', null),
]);
if ($this->inputFilter->isValid()) {
$this->dataProvider->filterGroupflag($this->inputFilter->getValue('group'));
return parent::__invoke($req, $res, $args);
} else {