0
0
Fork 0
mirror of https://github.com/nextcloud/server.git synced 2025-05-09 16:20:42 +00:00
nextcloud_server/lib/private/AppFramework/Routing/RouteConfig.php
Christoph Wurst caff1023ea
Format control structures, classes, methods and function
To continue this formatting madness, here's a tiny patch that adds
unified formatting for control structures like if and loops as well as
classes, their methods and anonymous functions. This basically forces
the constructs to start on the same line. This is not exactly what PSR2
wants, but I think we can have a few exceptions with "our" style. The
starting of braces on the same line is pracrically standard for our
code.

This also removes and empty lines from method/function bodies at the
beginning and end.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
2020-04-10 14:19:56 +02:00

334 lines
9.9 KiB
PHP

<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bernhard Posselt <dev@bernhard-posselt.com>
* @author Joas Schilling <coding@schilljs.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Patrick Paysant <ppaysant@linagora.com>
* @author Robin Appelman <robin@icewind.nl>
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\AppFramework\Routing;
use OC\AppFramework\DependencyInjection\DIContainer;
use OCP\AppFramework\App;
use OCP\Route\IRouter;
/**
* Class RouteConfig
* @package OC\AppFramework\routing
*/
class RouteConfig {
/** @var DIContainer */
private $container;
/** @var IRouter */
private $router;
/** @var array */
private $routes;
/** @var string */
private $appName;
/** @var string[] */
private $controllerNameCache = [];
/**
* @param \OC\AppFramework\DependencyInjection\DIContainer $container
* @param \OCP\Route\IRouter $router
* @param array $routes
* @internal param $appName
*/
public function __construct(DIContainer $container, IRouter $router, $routes) {
$this->routes = $routes;
$this->container = $container;
$this->router = $router;
$this->appName = $container['AppName'];
}
/**
* The routes and resource will be registered to the \OCP\Route\IRouter
*/
public function register() {
// parse simple
$this->processSimpleRoutes($this->routes);
// parse resources
$this->processResources($this->routes);
/*
* OCS routes go into a different collection
*/
$oldCollection = $this->router->getCurrentCollection();
$this->router->useCollection($oldCollection . '.ocs');
// parse ocs simple routes
$this->processOCS($this->routes);
// parse ocs simple routes
$this->processOCSResources($this->routes);
$this->router->useCollection($oldCollection);
}
private function processOCS(array $routes): void {
$ocsRoutes = $routes['ocs'] ?? [];
foreach ($ocsRoutes as $ocsRoute) {
$name = $ocsRoute['name'];
$postfix = $ocsRoute['postfix'] ?? '';
$root = $ocsRoute['root'] ?? '/apps/' . $this->appName;
$url = $root . $ocsRoute['url'];
$verb = strtoupper($ocsRoute['verb'] ?? 'GET');
$split = explode('#', $name, 2);
if (count($split) !== 2) {
throw new \UnexpectedValueException('Invalid route name');
}
list($controller, $action) = $split;
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($action);
$routeName = 'ocs.' . $this->appName . '.' . $controller . '.' . $action . $postfix;
// register the route
$handler = new RouteActionHandler($this->container, $controllerName, $actionName);
$router = $this->router->create($routeName, $url)
->method($verb)
->action($handler);
// optionally register requirements for route. This is used to
// tell the route parser how url parameters should be matched
if (array_key_exists('requirements', $ocsRoute)) {
$router->requirements($ocsRoute['requirements']);
}
// optionally register defaults for route. This is used to
// tell the route parser how url parameters should be default valued
if (array_key_exists('defaults', $ocsRoute)) {
$router->defaults($ocsRoute['defaults']);
}
}
}
/**
* Creates one route base on the give configuration
* @param array $routes
* @throws \UnexpectedValueException
*/
private function processSimpleRoutes(array $routes): void {
$simpleRoutes = $routes['routes'] ?? [];
foreach ($simpleRoutes as $simpleRoute) {
$name = $simpleRoute['name'];
$postfix = $simpleRoute['postfix'] ?? '';
$url = $simpleRoute['url'];
$verb = strtoupper($simpleRoute['verb'] ?? 'GET');
$split = explode('#', $name, 2);
if (count($split) !== 2) {
throw new \UnexpectedValueException('Invalid route name');
}
list($controller, $action) = $split;
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($action);
$appName = $simpleRoute['app'] ?? $this->appName;
if (isset($simpleRoute['app'])) {
// Legacy routes that need to be globally available while they are handled by an app
// E.g. '/f/{id}', '/s/{token}', '/call/{token}', …
$controllerName = str_replace('controllerController', 'Controller', $controllerName);
if ($controllerName === 'PublicpreviewController') {
$controllerName = 'PublicPreviewController';
} elseif ($controllerName === 'RequesthandlerController') {
$controllerName = 'RequestHandlerController';
}
$controllerName = App::buildAppNamespace($appName) . '\\Controller\\' . $controllerName;
}
$routeName = $appName . '.' . $controller . '.' . $action . $postfix;
// register the route
$handler = new RouteActionHandler($this->container, $controllerName, $actionName);
$router = $this->router->create($routeName, $url)
->method($verb)
->action($handler);
// optionally register requirements for route. This is used to
// tell the route parser how url parameters should be matched
if (array_key_exists('requirements', $simpleRoute)) {
$router->requirements($simpleRoute['requirements']);
}
// optionally register defaults for route. This is used to
// tell the route parser how url parameters should be default valued
if (array_key_exists('defaults', $simpleRoute)) {
$router->defaults($simpleRoute['defaults']);
}
}
}
/**
* For a given name and url restful OCS routes are created:
* - index
* - show
* - create
* - update
* - destroy
*
* @param array $routes
*/
private function processOCSResources(array $routes): void {
// declaration of all restful actions
$actions = [
['name' => 'index', 'verb' => 'GET', 'on-collection' => true],
['name' => 'show', 'verb' => 'GET'],
['name' => 'create', 'verb' => 'POST', 'on-collection' => true],
['name' => 'update', 'verb' => 'PUT'],
['name' => 'destroy', 'verb' => 'DELETE'],
];
$resources = $routes['ocs-resources'] ?? [];
foreach ($resources as $resource => $config) {
$root = $config['root'] ?? '/apps/' . $this->appName;
// the url parameter used as id to the resource
foreach ($actions as $action) {
$url = $root . $config['url'];
$method = $action['name'];
$verb = strtoupper($action['verb'] ?? 'GET');
$collectionAction = $action['on-collection'] ?? false;
if (!$collectionAction) {
$url .= '/{id}';
}
if (isset($action['url-postfix'])) {
$url .= '/' . $action['url-postfix'];
}
$controller = $resource;
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($method);
$routeName = 'ocs.' . $this->appName . '.' . strtolower($resource) . '.' . strtolower($method);
$this->router->create($routeName, $url)->method($verb)->action(
new RouteActionHandler($this->container, $controllerName, $actionName)
);
}
}
}
/**
* For a given name and url restful routes are created:
* - index
* - show
* - create
* - update
* - destroy
*
* @param array $routes
*/
private function processResources(array $routes): void {
// declaration of all restful actions
$actions = [
['name' => 'index', 'verb' => 'GET', 'on-collection' => true],
['name' => 'show', 'verb' => 'GET'],
['name' => 'create', 'verb' => 'POST', 'on-collection' => true],
['name' => 'update', 'verb' => 'PUT'],
['name' => 'destroy', 'verb' => 'DELETE'],
];
$resources = $routes['resources'] ?? [];
foreach ($resources as $resource => $config) {
// the url parameter used as id to the resource
foreach ($actions as $action) {
$url = $config['url'];
$method = $action['name'];
$verb = strtoupper($action['verb'] ?? 'GET');
$collectionAction = $action['on-collection'] ?? false;
if (!$collectionAction) {
$url .= '/{id}';
}
if (isset($action['url-postfix'])) {
$url .= '/' . $action['url-postfix'];
}
$controller = $resource;
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($method);
$routeName = $this->appName . '.' . strtolower($resource) . '.' . strtolower($method);
$this->router->create($routeName, $url)->method($verb)->action(
new RouteActionHandler($this->container, $controllerName, $actionName)
);
}
}
}
/**
* Based on a given route name the controller name is generated
* @param string $controller
* @return string
*/
private function buildControllerName(string $controller): string {
if (!isset($this->controllerNameCache[$controller])) {
$this->controllerNameCache[$controller] = $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller';
}
return $this->controllerNameCache[$controller];
}
/**
* Based on the action part of the route name the controller method name is generated
* @param string $action
* @return string
*/
private function buildActionName(string $action): string {
return $this->underScoreToCamelCase($action);
}
/**
* Underscored strings are converted to camel case strings
* @param string $str
* @return string
*/
private function underScoreToCamelCase(string $str): string {
$pattern = '/_[a-z]?/';
return preg_replace_callback(
$pattern,
function ($matches) {
return strtoupper(ltrim($matches[0], '_'));
},
$str);
}
}