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