/** * @param Route $route */ public function addRoute(Route $route) { $slimRoute = new \Slim\Route($route->getPath(), [$this, 'dummyCallable']); $slimRoute->setName($route->getName()); $allowedMethods = $route->getAllowedMethods(); $slimRoute->via($allowedMethods === Route::HTTP_METHOD_ANY ? 'ANY' : $allowedMethods); // Process options $options = $route->getOptions(); if (isset($options['conditions']) && is_array($options['conditions'])) { $slimRoute->setConditions($options['conditions']); } // The middleware is merged with the rest of the route params $params = ['middleware' => $route->getMiddleware()]; if (isset($options['defaults']) && is_array($options['defaults'])) { $params = array_merge($options['defaults'], $params); } $slimRoute->setParams($params); $this->router->map($slimRoute); }
public function testAppendHttpMethodsWithVia() { $route = new \Slim\Route('/foo', function () { }); $route->via('PUT'); $this->assertAttributeContains('PUT', 'methods', $route); }
/** * Test that a Route manages the HTTP methods that it supports * * Case A: Route initially supports no HTTP methods * Case B: Route can set its supported HTTP methods * Case C: Route can append supported HTTP methods * Case D: Route can test if it supports an HTTP method * Case E: Route can lazily declare supported HTTP methods with `via` */ public function testHttpMethods() { //Case A $r = new \Slim\Route('/foo', function () { }); $this->assertEmpty($r->getHttpMethods()); //Case B $r->setHttpMethods('GET'); $this->assertEquals(array('GET'), $r->getHttpMethods()); //Case C $r->appendHttpMethods('POST', 'PUT'); $this->assertEquals(array('GET', 'POST', 'PUT'), $r->getHttpMethods()); //Case D $this->assertTrue($r->supportsHttpMethod('GET')); $this->assertFalse($r->supportsHttpMethod('DELETE')); //Case E $viaResult = $r->via('DELETE'); $this->assertTrue($viaResult instanceof \Slim\Route); $this->assertTrue($r->supportsHttpMethod('DELETE')); }
public function testAppendArrayOfHttpMethodsWithVia() { $arrayOfMethods = array('GET', 'POST', 'PUT'); $route = new \Slim\Route('/foo', function () { }); $route->via($arrayOfMethods); $this->assertAttributeEquals($arrayOfMethods, 'methods', $route); }
/** * Führt das Modul entsprechend der Commands.json und Component.json Definitionen aus */ public function run() { // runs the CConfig $com = new CConfig($this->_prefix, $this->_path, $this->_noInfo, $this->_noHelp); // lädt die Konfiguration des Moduls if ($com->used()) { return; } $conf = $com->loadConfig(); $this->_conf = $conf; $this->_com = $com; $commands = $com->commands(array(), true, true); // multi Requests werden noch nicht unterstützt, das Model soll automatisch die Möglichkeit bieten, // mehrere Anfragen mit einmal zu beantworten ////$commands[] = array('name' => 'postMultiGetRequest','method' => 'POST', 'path' => '/multiGetRequest', 'inputType' => 'Link', 'outputType' => ''); // Erstellt für jeden angebotenen Befehl einen Router // Ein Router stellt einen erlaubten Aufruf dar (mit Methode und URI), sodass geprüft werden kann, // welcher für die Beantwortung zuständig ist $router = new \Slim\Router(); foreach ($commands as &$command) { if (!isset($command['name'])) { continue; } if (!isset($command['method'])) { $command['method'] = 'GET'; } if (!isset($command['callback'])) { $command['callback'] = $command['name']; } if (!isset($command['seqInput'])) { $command['seqInput'] = 'TRUE'; } if (!isset($command['singleOutput'])) { $command['singleOutput'] = 'FALSE'; } if (!isset($command['placeholder'])) { $command['placeholder'] = array(); } // Methoden können durch Komma getrennt aufgelistet sein $methods = explode(',', $command['method']); foreach ($methods as $method) { $route = new \Slim\Route($command['path'], array($this->_class, $command['callback']), false); $route->via(strtoupper($method)); $route->setName($command['name']); $router->map($route); // wenn es ein GET Befehl ist, wird automatisch HEAD unterstützt if (strtoupper($method) == 'GET') { // erzeugt einen HEAD Router $route = new \Slim\Route($command['path'], array($this->_class, $command['callback']), false); $route->via('HEAD'); $route->setName($command['name']); $router->map($route); } } } // hier wird die eingehende URI erzeugt // Bsp.: /user/1 $scriptName = $_SERVER['SCRIPT_NAME']; $requestUri = $_SERVER['REQUEST_URI']; $path = str_replace('?' . (isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''), '', substr_replace($requestUri, '', 0, strlen(strpos($requestUri, $scriptName) !== false ? $scriptName : str_replace('\\', '', dirname($scriptName))))); // ermittelt den zuständigen Befehl $matches = $router->getMatchedRoutes(strtoupper($_SERVER['REQUEST_METHOD']), $path); if (count($matches) > 0) { // mindestens ein zutreffender Befehl wurde gefunden (nimm den Ersten) $matches = $matches[0]; // suche den zugehörigen $commands Eintrag $selectedCommand = null; foreach ($commands as $command) { if ($command['name'] === $matches->getName()) { $selectedCommand = $command; break; } } if ($selectedCommand == null) { http_response_code(500); return; } // lies die eingehenden PHP Daten $rawInput = \Slim\Environment::getInstance()->offsetGet('slim.input'); if (!$rawInput) { $rawInput = @file_get_contents('php://input'); } // wir wollen wissen, ob die Eingabedaten als Liste rein kommen $arr = true; // wenn zu diesem Befehl ein inputType angegeben wurde, wird eine Type::decodeType() aufgerufen if (isset($selectedCommand['inputType']) && trim($selectedCommand['inputType']) != '') { $inputType = $selectedCommand['inputType']; $rawInput = call_user_func_array('\\' . $inputType . '::decode' . $inputType, array($rawInput)); if (!is_array($rawInput)) { // es ist keine Liste, also mach eine daraus (damit man sie einheitlich behandeln kann) $rawInput = array($rawInput); $arr = false; } } if (strtoupper($selectedCommand['seqInput']) != 'TRUE') { $arr = false; } $params = $matches->getParams(); $placeholder = array(); // prüfe die Bedingungen für die Platzhalter foreach ($selectedCommand['placeholder'] as $holder) { if (!isset($holder['name'])) { continue; } if (!isset($holder['regex'])) { continue; } $placeholder[$holder['name']] = $holder['regex']; } /*foreach ($params as $key => $value){ if (isset($placeholder[$key])){ if (is_array($value)){ // wenn es ein Array ist, wurde ein :Element+ verwendet (Slim) // daher wird der Ausdruck auf jedes Element angewendet foreach($value as $val){ $pregRes = @preg_match($placeholder[$key], $val); if ($pregRes === false){ error_log(__FILE__.':'.__LINE__.' '.$placeholder[$key].' konnte nicht interpretiert werden'); $this->finishRequest(self::isError()); return; } else if ($pregRes === 0){ error_log(__FILE__.':'.__LINE__.' '.$val.' passt nicht zu '.$placeholder[$key]); $this->finishRequest(self::isPreconditionError()); return; } } } else { // einzelnes Element für Slim verwendet :Element $pregRes = @preg_match($placeholder[$key], $value); if ($pregRes === false){ error_log(__FILE__.':'.__LINE__.' '.$placeholder[$key].' konnte nicht interpretiert werden'); $this->finishRequest(self::isError()); return; } else if ($pregRes === 0){ error_log(__FILE__.':'.__LINE__.' '.$value.' passt nicht zu '.$placeholder[$key]); $this->finishRequest(self::isPreconditionError()); return; } } } }*/ // nun soll die zugehörige Funktion im Modul aufgerufen werden if (isset($selectedCommand['inputType']) && trim($selectedCommand['inputType']) != '' && isset($rawInput)) { // initialisiert die Ausgabe positiv $result = array("status" => 201, "content" => array()); if (strtoupper($selectedCommand['seqInput']) == 'TRUE') { try { // für jede Eingabe wird die Funktion ausgeführt foreach ($rawInput as $input) { // Aufruf der Modulfunktion $res = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $input, $params)); // wenn es ein Ausgabeobjekt gibt, wird versucht dort einen Status zu setzen if (is_callable(array($res['content'], 'setStatus'))) { $res['content']->setStatus($res['status']); } // setze Status und Ausgabe $result["content"][] = $res['content']; if (isset($res['status'])) { $result["status"] = $res['status']; } } } catch (Exception $e) { header_remove(); error_log($e->getMessage()); $this->finishRequest(self::isError()); return; } } else { try { // Aufruf der Modulfunktion $res = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $rawInput, $params)); // wenn es ein Ausgabeobjekt gibt, wird versucht dort einen Status zu setzen if (is_callable(array($res['content'], 'setStatus'))) { $res['content']->setStatus($res['status']); } // setze Status und Ausgabe $result["content"] = $res['content']; if (isset($res['status'])) { $result["status"] = $res['status']; } } catch (Exception $e) { header_remove(); error_log($e->getMessage()); $this->finishRequest(self::isError()); return; } } } else { // wenn keinen vorgegebenen Eingabetyp gibt, wird die Eingabe direkt an die Modulfunktion weitergegeben $result = call_user_func_array($matches->getCallable(), array($selectedCommand['name'], "input" => $rawInput, $params)); } if ($selectedCommand['method'] == 'HEAD') { // Bei einer HEAD Funktion (die eventuell im Modul als GET bearbeitet wird), // kann die Ausgabe verworfen werden $result['content'] = ''; } elseif (isset($selectedCommand['outputType']) && trim($selectedCommand['outputType']) != '' && trim($selectedCommand['outputType']) != 'binary') { // wenn ein Ausgabetyp angegeben ist, wird eine Typ::encodeTyp() ausgeführt $outputType = $selectedCommand['outputType']; if (isset($result['content'])) { if (!is_array($result['content'])) { $result['content'] = array($result['content']); } if ($command['singleOutput'] !== 'FALSE' && count($result['content']) >= 1) { $result['content'] = $result['content'][0]; } elseif (!$arr && count($result['content']) == 1) { $result['content'] = $result['content'][0]; } $result['content'] = call_user_func_array('\\' . $outputType . '::encode' . $outputType, array($result['content'])); } header('Content-Type: application/json'); } elseif (isset($selectedCommand['outputType']) && trim($selectedCommand['outputType']) == 'binary') { // wenn der Ausgabetyp "binär" ist, erfolgt keine Anpassung } else { // selbst wenn nichts zutrifft, wird json kodiert if (isset($result['content'])) { $result['content'] = json_encode($result['content']); } header('Content-Type: application/json'); } } else { // es wurde kein zutreffender Befehl gefunden, also gibt es eine leere Antwort $this->finishRequest(self::isError()); return; } // ab hier werden die Ergebnisse ausgegeben $this->finishRequest($result); }
public static function show($console, $result, $data) { $isUpdate = isset($data['action']) && $data['action'] == 'update' ? true : false; $text = ''; if (!$console) { $text .= Design::erstelleBeschreibung($console, Language::Get('components', 'description')); $text .= Design::erstelleZeile($console, Language::Get('components', 'init'), 'e', '', 'v', Design::erstelleSubmitButton(self::$onEvents['install']['event'][0]), 'h'); $text .= Design::erstelleZeile($console, Language::Get('components', 'details'), 'e', Design::erstelleAuswahl($console, $data['CO']['co_details'], 'data[CO][co_details]', 'details', null, true), 'v'); } if (isset($result[self::$onEvents['install']['name']]) && $result[self::$onEvents['install']['name']] != null) { $result = $result[self::$onEvents['install']['name']]; } else { $result = array('content' => null, 'fail' => false, 'errno' => null, 'error' => null); } $fail = $result['fail']; $error = $result['error']; $errno = $result['errno']; $content = $result['content']; if (self::$installed) { // counts installed commands $installedCommands = 0; // counts installed components $installedComponents = 0; // counts installed links $installedLinks = 0; foreach ($content as $componentName => &$component) { if (isset($component['init'])) { $component['init'] = Component::decodeComponent(json_encode($component['init'])); } if (isset($component['links'])) { $component['links'] = Link::decodeLink(json_encode($component['links'])); } if (isset($component['commands'])) { $router = new \Slim\Router(); foreach ($component['commands'] as $command) { $route = new \Slim\Route($command['path'], 'is_array'); $route->via(isset($command['method']) ? strtoupper($command['method']) : 'GET'); $router->map($route); } $component['router'] = $router; } } foreach ($content as $componentName => $component) { $linkNames = array(); $linkNamesUnique = array(); $callNames = array(); $links = array(); if (isset($component['links'])) { $links = $component['links']; } foreach ($links as $link) { $linkNames[] = $link->getName(); $linkNamesUnique[$link->getName()] = $link->getName(); } $calls = null; if (isset($component['call'])) { $calls = $component['call']; } if ($calls !== null) { foreach ($calls as $pos => $callList) { if (isset($callList['name'])) { $callNames[$callList['name']] = $callList['name']; } } } $countLinks = 1; if (isset($component['init']) && $component['init'] !== null && $component['init']->getStatus() === 201) { $countLinks += count($linkNames) + count(array_diff($callNames, $linkNamesUnique)) + count($linkNamesUnique) - count(array_diff($linkNamesUnique, $callNames)); $countLinks++; } else { if (!isset($component['init']) || $component['init'] === null) { $fail = true; $error = Language::Get('components', 'componentCrashed'); } } $countCommands = count(isset($component['commands']) ? $component['commands'] : array()); if (isset($component['init']) && isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $defs = explode(";", $component['init']->getDef()); $baseComponent = count($defs) > 2 ? "<br><span class='info-color tiny'>(" . $defs[0] . ")</span>" : ''; $text .= "<tr><td class='e' rowspan='{$countLinks}'>{$componentName}{$baseComponent}</td><td class='v'>{$component['init']->getAddress()}</td><td class='e'><div align ='center'>" . ($component['init']->getStatus() === 201 ? Language::Get('main', 'ok') : "<font color='red'>" . Language::Get('main', 'fail') . " ({$component['init']->getStatus()})</font>") . "</align></td></tr>"; } if (isset($component['init']) && $component['init'] !== null && $component['init']->getStatus() === 201) { $installedComponents++; $installedLinks += count(isset($component['links']) ? $component['links'] : array()); $installedCommands += $countCommands; if (isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $text .= "<tr><td class='v' colspan='2'>" . Language::Get('components', 'installedCalls') . ": {$countCommands}</td></tr>"; } $links = array(); if (isset($component['links'])) { $links = $component['links']; } $lastLink = null; foreach ($links as $link) { $calls = null; if (isset($component['call'])) { $calls = $component['call']; } $linkFound = false; if ($calls !== null) { foreach ($calls as $pos => $callList) { if (isset($callList['name']) && $callList['name'] === $link->getName()) { $linkFound = true; break; } } } if ($lastLink != $link->getName() && $linkFound) { $calls = null; if (isset($component['call'])) { $calls = $component['call']; } $notRoutable = false; if ($calls !== null) { foreach ($calls as $pos => $callList) { if ($link->getName() !== $callList['name']) { continue; } if (isset($callList['links']) && $callList['links'] !== null) { foreach ($callList['links'] as $pos2 => $call) { if (!isset($content[$link->getTargetName()]['router'])) { $notRoutable = true; break; } if ($content[$link->getTargetName()]['router'] == null) { continue; } if ($call === null) { continue; } if (!isset($call['method'])) { continue; } if (!isset($call['path'])) { continue; } $routes = count($content[$link->getTargetName()]['router']->getMatchedRoutes(strtoupper($call['method']), $call['path']), true); if ($routes === 0) { $notRoutable = true; break; } } } if ($notRoutable) { break; } } if (isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $text .= "<tr><td class='v'>{$link->getName()}</td><td class='e'><div align ='center'>" . (!$notRoutable ? Language::Get('main', 'ok') : '<font color="red">' . Language::Get('components', 'notRoutable') . '</font>') . "</align></td></tr>"; } } } if (isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $text .= "<tr><td class='v'>{$link->getName()}" . (!$linkFound ? " (<font color='red'>" . Language::Get('components', 'unknown') . "</font>)" : '') . "</td><td class='v'>{$link->getTargetName()}</td></tr>"; } $lastLink = $link->getName(); } // fehlende links $calls = null; if (isset($component['call'])) { $calls = $component['call']; } if ($calls !== null) { foreach ($calls as $pos => $callList) { $found = false; foreach ($links as $link) { if ($link->getName() == $callList['name']) { $found = true; break; } } if (!$found) { if (isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $text .= "<tr><td class='v'>{$callList['name']}</td><td class='e'><font color='red'>" . Language::Get('components', 'unallocated') . "</font></td></tr>"; } } } } } } if ($installedComponents == 0) { $fail = true; $error = Language::Get('components', 'noComponents'); } else { if ($installedLinks == 0) { $fail = true; $error = Language::Get('components', 'noLinks'); } else { if ($installedCommands == 0) { $fail = true; $error = Language::Get('components', 'noCommands'); } } } if (isset($data['CO']['co_details']) && $data['CO']['co_details'] === 'details' && !$isUpdate) { $text .= Design::erstelleZeile($console, '', '', '', '', '', ''); } $text .= Design::erstelleZeile($console, Language::Get('components', 'installedComponents'), 'e', '', 'v', $installedComponents, 'v'); $text .= Design::erstelleZeile($console, Language::Get('components', 'installedLinks'), 'e', '', 'v', $installedLinks, 'v'); $text .= Design::erstelleZeile($console, Language::Get('components', 'installedCommands'), 'e', '', 'v', $installedCommands, 'v'); $text .= Design::erstelleInstallationszeile($console, $fail, $errno, $error); } echo Design::erstelleBlock($console, Language::Get('components', 'title'), $text); }
/** * the getl function uses a list of links to find a * relevant component for the $data request * * @param $data a slim generated array of URI segments (String[]) */ public function getl($data) { Logger::Log('starts Controller routing', LogLevel::DEBUG); // if no URI is received, abort process if (count($data) == 0) { Logger::Log('Controller nothing to route', LogLevel::DEBUG); $this->_app->response->setStatus(409); $this->_app->stop(); return; } $URI = '/' . implode('/', $data); // get possible links $list = CConfig::getLinks($this->_conf->getLinks(), 'out'); foreach ($list as $links) { $componentURL = $links->getAddress(); $similar = Controller2::UrlAnd($componentURL, $URI); if ($similar != null) { $URI2 = substr($URI, Controller2::UrlAnd($componentURL, $URI)); $relevanz = explode(' ', $links->getRelevanz()); $found = false; foreach ($relevanz as $rel) { if ($rel == 'ALL') { $found = true; break; } $sub = strpos($rel, '_'); if ($sub !== false) { $method = substr($rel, 0, $sub); $path = substr($rel, $sub + 1); if (strtoupper($method) == strtoupper($this->_app->request->getMethod())) { $router = new \Slim\Router(); $route = new \Slim\Route($path, 'is_array'); $route->via(strtoupper($method)); $router->map($route); $routes = count($router->getMatchedRoutes(strtoupper($method), $URI2), true); if ($routes === 0) { continue; } $found = true; break; } } } if (!$found) { continue; } // create a custom request $ch = Request::custom($this->_app->request->getMethod(), $componentURL . substr($URI, $similar), array(), $this->_app->request->getBody()); // checks the answered status code if ($ch['status'] >= 200 && $ch['status'] <= 299) { // finished $this->_app->response->setStatus($ch['status']); $this->_app->response->setBody($ch['content']); if (isset($ch['headers']['Content-Type'])) { $this->_app->response->headers->set('Content-Type', $ch['headers']['Content-Type']); } if (isset($ch['headers']['Content-Disposition'])) { $this->_app->response->headers->set('Content-Disposition', $ch['headers']['Content-Disposition']); } Logger::Log('Controller2 search done', LogLevel::DEBUG); $this->_app->stop(); } } } // no positive response or no operative link $this->_app->response->setStatus(409); $this->_app->response->setBody(''); }