(ns scan.lang.php.laravel (:require [clojure.string :as str] [clojure.java.io :as io])) (def ^{} omit-comments (fn [source] (str/replace source #"\/\*.+\*\/" ""))) (def ^{} load-method-signature! (fn [route] (cond (.exists (io/file (:ctl route))) (let [src (slurp (:ctl route))] (->> (-> (re-pattern (str "function " (:act route) "\\((.*)\\)")) (re-find src) last (or "") (str/split #",")) (map str/trim) (filter (fn [e] (not (str/includes? e "Request")))) (into []))) :else nil))) (def ^{} to-openapi (fn [routes] (reduce (fn [acc el] (assoc-in acc [(:path el) (:verb el)] {:description (:act el) :parameters (into [] (map (fn [e] (if (< 0 (count e)) (let [[type name] (str/split e #" ")] {:name (re-find #"\w" name) :in "query" :required true ;; depends on param optionality :schema {:type type}}) [])) (:signature el)))})) {} routes))) (def ^{} routes (fn [project-path] (to-openapi (map (fn [route] (assoc route :signature (load-method-signature! route))) (let [route-file (str project-path "/routes/web.php")] (filter (fn [e] (not (nil? e))) (map (fn [hit] (let [[_ verb raw-params] hit params (map (fn [e] (str/trim (str/escape e {\' ""}))) (str/split raw-params #",")) [route ctl] params] (if ctl {:verb verb :path route :ctl (str project-path "/app/Http/Controllers/" (str/replace (str/replace ctl #"\@(.*)" ".php") "\\" "/")) :act (str/replace ctl #"(.*)\@" "")} nil))) (re-seq #"router->(.*)\((.*)\)" (omit-comments (slurp route-file)))))))))) (comment )