nextcloud_route_extractor/
lib.rs1use crate::attribute_routes::extract_attribute_routes;
2use crate::route::{AppRoutes, Route};
3use crate::routes_php::extract_routes_php;
4use glob::{glob, GlobError, Paths, Pattern};
5use std::fs::read_to_string;
6use std::path::{Path, PathBuf};
7use thiserror::Error;
8
9mod attribute_routes;
10mod route;
11mod routes_php;
12
13pub fn core_routes(path: &str) -> Result<AppRoutes, Error> {
14 let mut result = AppRoutes {
15 routes: vec![
16 Route {
17 url: "/core/ajax/update.php".into(),
18 name: "core#ajax_update".into(),
19 ..Route::default()
20 },
21 Route {
22 url: "/heartbeat".into(),
23 name: "core#heartbeat".into(),
24 ..Route::default()
25 },
26 ],
27 ocs: vec![],
28 };
29
30 let controller_paths = glob(&format!(
31 "{}/core/Controller/*Controller.php",
32 Pattern::escape(path)
33 ))
34 .unwrap();
35 for routes in extract_controllers(controller_paths) {
36 let routes = routes?;
37 result.routes.extend_from_slice(&routes.routes);
38 result.ocs.extend_from_slice(&routes.ocs);
39 }
40 Ok(result)
41}
42
43pub fn app_routes(path: &str) -> Result<AppRoutes, Error> {
44 let routes_php_path = <str as AsRef<Path>>::as_ref(path).join("appinfo/routes.php");
45 let mut result = if routes_php_path.exists() {
46 let routes_php = read_to_string(&routes_php_path).map_err(|error| Error::Read {
47 path: routes_php_path,
48 error,
49 })?;
50 extract_routes_php(&routes_php)
51 } else {
52 AppRoutes::default()
53 };
54
55 let controller_paths = glob(&format!(
56 "{}/lib/Controller/*Controller.php",
57 Pattern::escape(path)
58 ))
59 .unwrap();
60 for routes in extract_controllers(controller_paths) {
61 let routes = routes?;
62 result.routes.extend_from_slice(&routes.routes);
63 result.ocs.extend_from_slice(&routes.ocs);
64 }
65 Ok(result)
66}
67
68fn extract_controllers(paths: Paths) -> impl Iterator<Item = Result<AppRoutes, Error>> {
69 paths.map(|controller_path| {
70 let controller_path = controller_path.map_err(Error::Glob)?;
71 let controller_code = read_to_string(&controller_path).map_err(|error| Error::Read {
72 path: controller_path,
73 error,
74 })?;
75 Ok(extract_attribute_routes(&controller_code))
76 })
77}
78
79#[derive(Debug, Error)]
80pub enum Error {
81 #[error("Failed to read {path}: {error:#}")]
82 Read {
83 path: PathBuf,
84 error: std::io::Error,
85 },
86 #[error("Failed to find controller paths: {0:#}")]
87 Glob(GlobError),
88}