Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
Simple REST provider for CRUD-ing a resource, based on nicik/fast-rou…
Browse files Browse the repository at this point in the history
…te. Empty task provider.
  • Loading branch information
cdujeu committed May 10, 2016
1 parent 42c0243 commit 7c649a8
Show file tree
Hide file tree
Showing 20 changed files with 1,450 additions and 44 deletions.
3 changes: 2 additions & 1 deletion core/src/core/composer.json
Expand Up @@ -12,7 +12,8 @@
"guzzlehttp/command": "~0.7",
"guzzlehttp/guzzle-services": "~0.5",
"gimler/guzzle-description-loader" : "*",
"commerceguys/guzzle-oauth2-plugin": "~2.0"
"commerceguys/guzzle-oauth2-plugin": "~2.0",
"nikic/fast-route":"~1.0"
}

}
43 changes: 0 additions & 43 deletions core/src/core/src/pydio/Core/Controller/Controller.php
Expand Up @@ -254,49 +254,6 @@ public static function run(ServerRequestInterface $request, &$actionNode = null)

return $response;

/*
if ($captureCalls !== false) {
// Make sure the ShutdownScheduler has its own OB started BEFORE, as it will presumabily be
// executed AFTER the end of this one.
ShutdownScheduler::getInstance();
ob_start();
$params = array("pre_processor_results" => array(), "post_processor_results" => array());
}
if ($preCalls !== false) {
foreach ($preCalls as $preCall) {
// A Preprocessing callback can modify its input arguments (passed by ref)
$preResult = self::applyCallback($preCall, $actionName, $httpVars, $fileVars);
if (isSet($params)) {
$params["pre_processor_results"][$preCall->getAttribute("pluginId")] = $preResult;
}
}
}
if ($mainCall) {
$result = self::applyCallback($mainCall, $actionName, $httpVars, $fileVars);
if (isSet($params)) {
$params["processor_result"] = $result;
}
}
if ($postCalls !== false) {
foreach ($postCalls as $postCall) {
// A Preprocessing callback can modify its input arguments (passed by ref)
$postResult = self::applyCallback($postCall, $actionName, $httpVars, $fileVars);
if (isSet($params)) {
$params["post_processor_results"][$postCall->getAttribute("pluginId")] = $postResult;
}
}
}
if ($captureCalls !== false) {
$params["ob_output"] = ob_get_contents();
ob_end_clean();
foreach ($captureCalls as $captureCall) {
self::applyCallback($captureCall, $actionName, $httpVars, $params);
}
} else {
if(isSet($result)) return $result;
}
return null;
*/
}

/**
Expand Down
214 changes: 214 additions & 0 deletions core/src/core/src/pydio/Core/Http/SimpleRestResourceRouter.php
@@ -0,0 +1,214 @@
<?php
/*
* Copyright 2007-2015 Abstrium <contact (at) pydio.com>
* This file is part of Pydio.
*
* Pydio is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pydio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Pydio. If not, see <http://www.gnu.org/licenses/>.
*
* The latest code can be found at <http://pyd.io/>.
*/
namespace Pydio\Core\Http;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

defined('AJXP_EXEC') or die('Access not allowed');


class SimpleRestResourceRouter
{
/**
* @var array
* ["resourceName" => "name",
* "parameterName" => "object_id"
* "crudCallbacks" => ["CREATE" => methodName,
* "RETRIEVE_MANY"=> methodName,
* "RETRIEVE_ONE"=> methodName,
* "UPDATE" => methodName,
* "DELETE" => methodName],
* "linkedResources" => [NESTED CONFIG ARRAY]
* "additionalRoutes" => [[method=>"GET", uri=>"/path/to/route", callable]]
* ]
*/
private $config;
/**
* @var array
* "cacheOptions" => ["cacheFile" => "path", "cacheDisabled" => true],
*/
private $cacheOptions;
/**
* @var object Will be used as '$this' for triggering the callbacks
*/
private $callbacksContext;

private $base = "/api/{repository_id}";

/**
* SimpleRestResourceRouter constructor.
* @param object $callbacksContext
* @param array $config
* @param array $cacheOptions
*/
public function __construct($callbacksContext, $config, $cacheOptions){
$this->config = $config;
$this->cacheOptions = $cacheOptions;
$this->callbacksContext = $callbacksContext;
}

public function addRoute($method, $uri, $callable){
$this->config["additional_routes"][] = ["method" => $method, "uri" => $uri, "callable" => $callable];
}

/**
* @param array $configObject
* @param \FastRoute\RouteCollector $r
*/
public function configureRoutes($base, $configObject, \FastRoute\RouteCollector &$r){

$parameterName = $configObject["parameterName"];
$resName = $configObject["resourceName"];
$callbacks = $configObject["crudCallbacks"];
if(isSet($callbacks["RETRIEVE_MANY"])){
$r->addRoute('GET', $base."/".$resName, ['simpleHandler', $callbacks["RETRIEVE_MANY"]]);
}
if(isset($callbacks["RETRIEVE_ONE"])){
$r->addRoute('GET', $base."/".$resName.'/{'.$parameterName.'}', ['simpleHandler', $callbacks["RETRIEVE_ONE"]]);
}
if(isSet($callbacks["CREATE"])){
$r->addRoute('POST', $base."/".$resName, ['bodyHandler', $callbacks["CREATE"]]);
}
if(isSet($callbacks["UPDATE"])){
$r->addRoute('PUT', $base."/".$resName.'/{'.$parameterName.'}', ['bodyHandler', $callbacks["UPDATE"]]);
$r->addRoute('PATCH', $base."/".$resName.'/{'.$parameterName.'}', ['bodyHandler', $callbacks["UPDATE"]]);
}
if(isSet($callbacks["DELETE"])){
$r->addRoute('DELETE', $base."/".$resName.'/{'.$parameterName.'}', ['simpleHandler', $callbacks["DELETE"]]);
}

if(is_array($configObject["additionalRoutes"])){
foreach ($configObject["additionalRoutes"] as $additional_route){
if(in_array($additional_route["method"], ["GET", "DELETE", "HEAD"])){
$r->addRoute($additional_route["method"], $base.$additional_route["route"], ['simpleHandler', $additional_route["callback"]]);
}else if(in_array($additional_route["method"], ["POST", "PUT", "PATCH"])){
$r->addRoute($additional_route["method"], $base.$additional_route["route"], ['bodyHandler', $additional_route["callback"]]);
}
}
}

if(is_array($configObject["linkedResources"])){
foreach ($configObject["linkedResources"] as $linkedResource){
$this->configureRoutes($base."/".$resName."/{".$parameterName."}", $linkedResource, $r);
}
}

}

public function getURIForRequest(ServerRequestInterface $request){

$uri = $request->getServerParams()['REQUEST_URI'];
// Strip query string (?foo=bar) and decode URI
if (false !== $pos = strpos($uri, '?')) {
$uri = substr($uri, 0, $pos);
}
return rawurldecode($uri);
}

public function route(ServerRequestInterface &$request, ResponseInterface &$response){

$dispatcher = \FastRoute\cachedDispatcher(function(\FastRoute\RouteCollector $r) {

$this->configureRoutes($this->base, $this->config, $r);

}, $this->cacheOptions);

$httpMethod = $request->getServerParams()['REQUEST_METHOD'];
$uri = $this->getURIForRequest($request);
$routeInfo = $dispatcher->dispatch($httpMethod, $uri);

switch ($routeInfo[0]) {
case \FastRoute\Dispatcher::NOT_FOUND:
//$response = $response->withStatus(404);
break;
case \FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
$allowedMethods = $routeInfo[1];
//$response = $response->withStatus(405);
break;
case \FastRoute\Dispatcher::FOUND:
$handler = $routeInfo[1][0];
$callback = $routeInfo[1][1];
$vars = $routeInfo[2];

$request = $request->withParsedBody(array_merge($request->getParsedBody(), $vars));
$this->$handler($callback, $request, $response);
return true;
default:
break;
}

return false;
}

protected function simpleHandler($callback, ServerRequestInterface &$requestInterface, ResponseInterface &$responseInterface){

$data = $this->callbacksContext->$callback($requestInterface, $responseInterface);

$responseInterface = $responseInterface->withHeader("Content-type", "application/json");
$responseInterface->getBody()->write(json_encode($data));
}


protected function bodyHandler($callback, ServerRequestInterface &$request, ResponseInterface &$response){

$postedObject = json_decode($request->getBody()->getContents());
$request = $request->withParsedBody(array_merge($request->getParsedBody(), ["postedObject" => $postedObject]));
$data = $this->callbacksContext->$callback($request, $response);

$response = $response->withHeader("Content-Type", "application/json");
$response->getBody()->write(json_encode($data));

}


/**
* Class casting
*
* @param string|object $destination
* @param object $sourceObject
* @return object
*/
public static function cast($destination, $sourceObject)
{
if (is_string($destination)) {
$destination = new $destination();
}
$sourceReflection = new \ReflectionObject($sourceObject);
$destinationReflection = new \ReflectionObject($destination);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationReflection->hasProperty($name)) {
$propDest = $destinationReflection->getProperty($name);
$propDest->setAccessible(true);
$propDest->setValue($destination,$value);
} else {
$destination->$name = $value;
}
}
return $destination;
}


}
11 changes: 11 additions & 0 deletions core/src/plugins/core.tasks/composer.json
@@ -0,0 +1,11 @@
{
"name": "Tasks Management",
"description": "Centralized task management",
"homepage": "https://pydio.com/",
"license":"AGPL-3.0",
"autoload": {
"psr-4": {
"Pydio\\Tasks\\": "./src"
}
}
}
14 changes: 14 additions & 0 deletions core/src/plugins/core.tasks/manifest.xml
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<ajxp_plugin label="CONF_MESSAGE[Tasks Service]" description="CONF_MESSAGE[Centralize background tasks and scheduling]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="file:../core.ajaxplorer/ajxp_registry.xsd">
<class_definition classname="Pydio\Tasks\TaskController" filename="plugins/core.tasks/src/TaskController.php"/>
<registry_contributions>
<actions>
<action name="tasks">
<processing>
<serverCallback methodName="route" restParams="/"/>
</processing>
</action>
</actions>
</registry_contributions>
</ajxp_plugin>
84 changes: 84 additions & 0 deletions core/src/plugins/core.tasks/src/ITasksProvider.php
@@ -0,0 +1,84 @@
<?php
/*
* Copyright 2007-2015 Abstrium <contact (at) pydio.com>
* This file is part of Pydio.
*
* Pydio is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pydio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Pydio. If not, see <http://www.gnu.org/licenses/>.
*
* The latest code can be found at <http://pyd.io/>.
*/
namespace Pydio\Tasks;

use Pydio\Access\Core\Model\AJXP_Node;
use Pydio\Access\Core\Model\Repository;
use Pydio\Conf\Core\AbstractAjxpUser;

defined('AJXP_EXEC') or die('Access not allowed');

interface ITasksProvider
{
/**
* @param Task $task
* @param Schedule $when
* @return Task
*/
public function createTask(Task $task, Schedule $when);

/**
* @param string $taskId
* @return Task
*/
public function getTaskById($taskId);


/**
* @param Task $task
* @return Task
*/
public function updateTask(Task $task);

/**
* @param string $taskId
* @param int $status
* @return Task
*/
public function updateTaskStatus($taskId, $status);

/**
* @param string $taskId
* @return bool
*/
public function deleteTask($taskId);


/**
* @return Task[]
*/
public function getPendingTasks();


/**
* @param AJXP_Node $node
* @return Task[]
*/
public function getTasksForNode(AJXP_Node $node);

/**
* @param AbstractAjxpUser $user
* @param Repository $repository
* @param int $status
* @return Task[]
*/
public function getTasks($user = null, $repository = null, $status = -1);
}

0 comments on commit 7c649a8

Please sign in to comment.