use std::path::PathBuf;
use anyhow::Context;
use fancy_regex::Regex;
#[derive(Debug)]
pub struct PhpFeature {
pub path: PathBuf,
pub name: String,
pub constants: String,
pub functions: String,
pub hooks: String,
}
impl PhpFeature {
pub fn new(feature: PathBuf) -> Self {
let code = std::fs::read_to_string(&feature)
.with_context(|| format!("Could not read the feature file at '{}'", feature.display()))
.unwrap();
let name = Self::compute_feature_name(&feature);
Self {
path: feature,
name,
constants: Self::extract_constants(&code),
functions: Self::extract_functions(&code),
hooks: Self::extract_hooks(&code),
}
}
fn extract_constants(code: &str) -> String {
Self::extract(code, "constants", "end")
}
fn extract_functions(code: &str) -> String {
Self::extract(code, "functions", "end")
}
fn extract_hooks(code: &str) -> String {
Self::extract(code, "hooks", "end")
}
fn extract(code: &str, prefix: &str, suffix: &str) -> String {
let regex = Regex::new(format!(r#"\/\/ section\.{}((?>\s|.)*?)\/\/ section\.{}\.{}"#, prefix, prefix, suffix).as_str()).unwrap();
let captures = regex.captures(code);
if captures.is_err() {
return String::new();
}
let captures = captures.unwrap();
match captures {
Some(captures) => captures.get(1).unwrap().as_str().to_string(),
None => String::new(),
}
}
fn compute_feature_name(feature_path: &PathBuf) -> String {
let level_1_parent = feature_path.parent().unwrap();
let level_2_parent = level_1_parent.parent().unwrap();
if level_1_parent.file_name().unwrap().to_str().unwrap() == "features" {
feature_path.file_stem().unwrap().to_str().unwrap().to_string()
} else {
format!(
"{}/{}",
level_2_parent.file_name().unwrap().to_str().unwrap(),
feature_path.file_stem().unwrap().to_str().unwrap()
)
}
}
}