jitRequest = $jitRequest; $this->routes = $this->prepareRoutes(); $this->context = $this->prepareContext(); } public function handle() { $route = $this->parseRoute(); $request = $this->jitRequest->asArray(); foreach ($route as $key => $value) { if (! in_array($key, ['controller', 'action', '_route']) && ! isset($request[$key])) { $request[$key] = $value; if ($key == 'confirmForm') { $_POST[$key] = $value; } } } $this->jitRequest = new JitFilter($request); if ($route['_route'] == 'home') { $this->renderDocs(); } elseif ($route['_route'] == 'docs') { $this->renderDocsYaml(); } elseif ($route['_route'] == 'version') { $this->renderVersion(); } else { $broker = TikiLib::lib('service')->getBroker(); $broker->process($route['controller'], $route['action'], $this->jitRequest); } } public function getRoutes() { return $this->routes; } public function generateRoute($name, $args = []) { $generator = new UrlGenerator($this->routes, $this->context); $relative_path = $generator->generate($name, $args, UrlGenerator::RELATIVE_PATH); return preg_replace('/^(\.\.\/)*/', '', $relative_path); } protected function parseRoute() { try { $route = $this->jitRequest->route->none(); $matcher = new UrlMatcher($this->routes, $this->context); return $matcher->match('/' . $route); } catch (ResourceNotFoundException $e) { TikiLib::lib('access')->display_error('API', $e->getMessage(), 404); } catch (RouteNotFoundException $e) { TikiLib::lib('access')->display_error('API', $e->getMessage(), 404); } catch (ExceptionInterface $e) { TikiLib::lib('access')->display_error('API', $e->getMessage(), 400); } } protected function prepareContext() { global $base_uri, $base_host, $url_host, $url_scheme, $prefs; $path_info = str_replace($base_host, '', $base_uri); if (false !== $pos = strpos($path_info, '?')) { $path_info = substr($path_info, 0, $pos); } return new RequestContext($base_uri, $_SERVER['REQUEST_METHOD'] ?? '', $url_host, $url_scheme, $prefs['http_port'] ? $prefs['http_port'] : 80, $prefs['https_port'] ? $prefs['https_port'] : 443, $path_info, http_build_query($_GET)); } protected function prepareRoutes() { $routes = new RouteCollection(); $routes->add('home', (new Route(''))->setMethods(['GET'])); $routes->add('docs', (new Route('docs/{path}.yaml', ['_format' => 'yaml']))->setMethods(['GET'])); $routes->add('version', (new Route('version'))->setMethods(['GET'])); $routes->add('oauth-public-key', (new Route('oauth/public-key', ['controller' => 'oauthserver', 'action' => 'public_key']))->setMethods(['GET'])); $routes->add('oauth-authorize', (new Route('oauth/authorize', ['controller' => 'oauthserver', 'action' => 'authorize']))->setMethods(['GET'])); $routes->add('oauth-access_token', (new Route('oauth/access_token', ['controller' => 'oauthserver', 'action' => 'access_token']))->setMethods(['GET', 'POST'])); $routes->add('categories', (new Route('categories', ['controller' => 'category', 'action' => 'list_categories']))->setMethods(['GET'])); $routes->add('categories-create', (new Route('categories', ['controller' => 'category', 'action' => 'create']))->setMethods(['POST'])); $routes->add('categories-update', (new Route('categories/{categId}', ['controller' => 'category', 'action' => 'update']))->setMethods(['POST'])); $routes->add('categories-delete', (new Route('categories/{categId}', ['controller' => 'category', 'action' => 'remove']))->setMethods(['DELETE'])); $routes->add('categorize', (new Route('categorize', ['controller' => 'category', 'action' => 'categorize']))->setMethods(['POST'])); $routes->add('uncategorize', (new Route('uncategorize', ['controller' => 'category', 'action' => 'uncategorize']))->setMethods(['POST'])); $routes->add('comments', (new Route('comments', ['controller' => 'comment', 'action' => 'list']))->setMethods(['GET'])); $routes->add('comments-create', (new Route('comments', ['controller' => 'comment', 'action' => 'post', 'post' => 1]))->setMethods(['POST'])); $routes->add('comments-update', (new Route('comments/{threadId}', ['controller' => 'comment', 'action' => 'edit', 'edit' => 1]))->setMethods(['POST'])); $routes->add('comments-delete', (new Route('comments/{threadId}', ['controller' => 'comment', 'action' => 'remove', 'confirm' => 1]))->setMethods(['DELETE'])); $routes->add('comments-lock', (new Route('comments/lock', ['controller' => 'comment', 'action' => 'lock', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('comments-unlock', (new Route('comments/unlock', ['controller' => 'comment', 'action' => 'unlock', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('comments-approve', (new Route('comments/{threadId}/approve', ['controller' => 'comment', 'action' => 'moderate', 'do' => 'approve', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('comments-reject', (new Route('comments/{threadId}/reject', ['controller' => 'comment', 'action' => 'moderate', 'do' => 'reject', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('comments-archive', (new Route('comments/{threadId}/archive', ['controller' => 'comment', 'action' => 'archive', 'do' => 'archive', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('comments-unarchive', (new Route('comments/{threadId}/unacrhive', ['controller' => 'comment', 'action' => 'archive', 'do' => 'unarchive', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('connect-new', (new Route('connect/new', ['controller' => 'connect_server', 'action' => 'new']))->setMethods(['POST'])); $routes->add('connect-confirm', (new Route('connect/confirm', ['controller' => 'connect_server', 'action' => 'confirm']))->setMethods(['POST'])); $routes->add('connect-receive', (new Route('connect/receive', ['controller' => 'connect_server', 'action' => 'receive']))->setMethods(['POST'])); $routes->add('connect-cancel', (new Route('connect/cancel', ['controller' => 'connect_server', 'action' => 'cancel']))->setMethods(['POST'])); $routes->add('export-sync', (new Route('export/sync', ['controller' => 'export', 'action' => 'sync_content']))->setMethods(['GET'])); $routes->add('groups', (new Route('groups', ['controller' => 'group', 'action' => 'list']))->setMethods(['GET'])); $routes->add('groups-add', (new Route('groups/add_users', ['controller' => 'group', 'action' => 'add_user', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('groups-ban', (new Route('groups/ban_users', ['controller' => 'group', 'action' => 'ban_user', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('groups-create', (new Route('groups', ['controller' => 'group', 'action' => 'new_group', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('groups-delete', (new Route('groups/delete', ['controller' => 'group', 'action' => 'remove_groups', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('groups-update', (new Route('groups/{olgroup}', ['controller' => 'group', 'action' => 'modify_group', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('search-lookup', (new Route('search/lookup', ['controller' => 'search', 'action' => 'lookup']))->setMethods(['GET'])); $routes->add('search-process-queue', (new Route('search/process-queue', ['controller' => 'search', 'action' => 'process_queue']))->setMethods(['POST'])); $routes->add('search-rebuild', (new Route('search/rebuild', ['controller' => 'search', 'action' => 'rebuild']))->setMethods(['POST'])); $routes->add('tabulars', (new Route('tabulars', ['controller' => 'tabular', 'action' => 'manage']))->setMethods(['GET'])); $routes->add('tabulars-view', (new Route('tabulars/{tabularId}', ['controller' => 'tabular', 'action' => 'edit']))->setMethods(['GET'])); $routes->add('tabulars-export', (new Route('tabulars/{tabularId}/export', ['controller' => 'tabular', 'action' => 'export_full_csv']))->setMethods(['GET'])); $routes->add('tabulars-import', (new Route('tabulars/{tabularId}/import', ['controller' => 'tabular', 'action' => 'import_csv']))->setMethods(['POST'])); $routes->add('trackers', (new Route('trackers', ['controller' => 'tracker', 'action' => 'list_trackers']))->setMethods(['GET'])); $routes->add('trackers-create', (new Route('trackers', ['controller' => 'tracker', 'action' => 'replace', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('trackers-view', (new Route('trackers/{trackerId}', ['controller' => 'tracker', 'action' => 'list_items', 'offset' => -1, 'maxRecords' => -1]))->setMethods(['GET'])); $routes->add('trackers-update', (new Route('trackers/{trackerId}', ['controller' => 'tracker', 'action' => 'replace', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('trackers-delete', (new Route('trackers/{trackerId}', ['controller' => 'tracker', 'action' => 'remove', 'confirm' => 1]))->setMethods(['DELETE'])); $routes->add('trackers-clear', (new Route('trackers/{trackerId}/clear', ['controller' => 'tracker', 'action' => 'clear', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('trackers-duplicate', (new Route('trackers/{trackerId}/duplicate', ['controller' => 'tracker', 'action' => 'duplicate', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('trackers-dump', (new Route('trackers/{trackerId}/dump', ['controller' => 'tracker', 'action' => 'dump_items']))->setMethods(['GET'])); $routes->add('trackers-export', (new Route('trackers/{trackerId}/export', ['controller' => 'tracker', 'action' => 'export_profile']))->setMethods(['GET'])); $routes->add('trackerfields', (new Route('trackers/{trackerId}/fields', ['controller' => 'tracker', 'action' => 'list_fields']))->setMethods(['GET'])); $routes->add('trackerfields-create', (new Route('trackers/{trackerId}/fields', ['controller' => 'tracker', 'action' => 'add_field']))->setMethods(['POST'])); $routes->add('trackerfields-update', (new Route('trackers/{trackerId}/fields/{fieldId}', ['controller' => 'tracker', 'action' => 'edit_field']))->setMethods(['POST'])); $routes->add('trackerfields-delete', (new Route('trackers/{trackerId}/fields', ['controller' => 'tracker', 'action' => 'remove_fields', 'confirm' => 1]))->setMethods(['DELETE'])); $routes->add('trackerfields-export', (new Route('trackers/{trackerId}/fields/export', ['controller' => 'tracker', 'action' => 'export_fields']))->setMethods(['GET'])); $routes->add('trackeritems-view', (new Route('trackers/{trackerId}/items/{itemId}', ['controller' => 'tracker', 'action' => 'view']))->setMethods(['GET'])); $routes->add('trackeritems-clone', (new Route('trackers/{trackerId}/items/{itemId}/clone', ['controller' => 'tracker', 'action' => 'clone_item']))->setMethods(['POST'])); $routes->add('trackeritems-create', (new Route('trackers/{trackerId}/items', ['controller' => 'tracker', 'action' => 'insert_item']))->setMethods(['POST'])); $routes->add('trackeritems-update', (new Route('trackers/{trackerId}/items/{itemId}', ['controller' => 'tracker', 'action' => 'update_item']))->setMethods(['POST'])); $routes->add('trackeritems-delete', (new Route('trackers/{trackerId}/items/{itemId}', ['controller' => 'tracker', 'action' => 'remove_item']))->setMethods(['DELETE'])); $routes->add('trackeritems-status', (new Route('trackers/{trackerId}/items/{itemId}/status', ['controller' => 'tracker', 'action' => 'update_item_status', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('translations', (new Route('translations/{type}/{source}', ['controller' => 'translation', 'action' => 'manage']))->setMethods(['GET'])); $routes->add('translations-attach', (new Route('translations/{type}/{source}/attach', ['controller' => 'translation', 'action' => 'attach']))->setMethods(['POST'])); $routes->add('translations-detach', (new Route('translations/{type}/{source}/detach', ['controller' => 'translation', 'action' => 'detach', 'confirm' => 1]))->setMethods(['POST'])); $routes->add('translate', (new Route('translate', ['controller' => 'translation', 'action' => 'translate']))->setMethods(['POST'])); $routes->add('users', (new Route('users', ['controller' => 'user', 'action' => 'list_users', 'offset' => 0, 'maxRecords' => -1]))->setMethods(['GET'])); $routes->add('users-register', (new Route('users', ['controller' => 'user', 'action' => 'register']))->setMethods(['POST'])); $routes->add('users-info', (new Route('users/{username}', ['controller' => 'user', 'action' => 'info']))->setMethods(['GET'])); $routes->add('users-delete', (new Route('users/delete', ['controller' => 'user', 'action' => 'remove_users', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('users-groups', (new Route('users/groups', ['controller' => 'user', 'action' => 'manage_groups', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('users-email-wikipage', (new Route('users/email-wikipage', ['controller' => 'user', 'action' => 'email_wikipage', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('users-send-message', (new Route('users/send-message', ['controller' => 'user', 'action' => 'send_message', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('users-message-count', (new Route('message-count', ['controller' => 'user', 'action' => 'get_message_count']))->setMethods(['GET'])); $routes->add('wiki', (new Route('wiki', ['controller' => 'wiki', 'action' => 'pages']))->setMethods(['GET'])); $routes->add('wiki-create', (new Route('wiki', ['controller' => 'wiki', 'action' => 'create_update_page', 'create' => 1]))->setMethods(['POST'])); $routes->add('wiki-view', (new Route('wiki/page/{page}', ['controller' => 'wiki', 'action' => 'get_page']))->setMethods(['GET'])); $routes->add('wiki-update', (new Route('wiki/page/{page}', ['controller' => 'wiki', 'action' => 'create_update_page', 'update' => 1]))->setMethods(['POST'])); $routes->add('wiki-delete', (new Route('wiki/delete', ['controller' => 'wiki', 'action' => 'remove_pages', 'confirmForm' => 'y', 'version' => 'all']))->setMethods(['POST'])); $routes->add('wiki-title', (new Route('wiki/title', ['controller' => 'wiki', 'action' => 'title', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('wiki-lock', (new Route('wiki/lock', ['controller' => 'wiki', 'action' => 'lock_pages', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('wiki-unlock', (new Route('wiki/unlock', ['controller' => 'wiki', 'action' => 'unlock_pages', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('wiki-preview', (new Route('wiki/preview', ['controller' => 'wiki', 'action' => 'preview']))->setMethods(['POST'])); $routes->add('wiki-zip', (new Route('wiki/zip', ['controller' => 'wiki', 'action' => 'zip', 'confirmForm' => 'y']))->setMethods(['POST'])); $routes->add('wiki-versions-delete', (new Route('wiki/{page}/delete', ['controller' => 'wiki', 'action' => 'remove_page_versions', 'confirmForm' => 'y']))->setMethods(['POST'])); return $routes; } protected function renderDocs() { global $base_url; $smarty = TikiLib::lib('smarty'); $smarty->assign('asset_path', $base_url . 'vendor_bundled/vendor/swagger-api/swagger-ui/dist/'); echo $smarty->fetch('api/docs.tpl'); } protected function renderDocsYaml() { global $base_url, $tikipath; $path = $this->jitRequest->path->xss(); $base = $tikipath . 'templates/api/docs'; $real = realpath($base . '/' . str_replace('-', '/', $path) . '.yaml'); if (empty($path) || ! strstr(dirname($real), $base)) { $real = $base . '/index.yaml'; } if (is_file($real)) { $docs = file_get_contents($real); $docs = str_replace('{server-url}', $base_url . 'api/', $docs); echo $docs; } } protected function renderVersion() { global $TWV; echo json_encode(['version' => $TWV->version]); } }