Route.php

<?php

namespace Lia\Obj;

/**
 * A simple object to hold route information for a matched route. 
 *
 * Nothing documented here is enforced by this class. It's all passed TO it. 
 * If a different Routing component is used, it might not follow the currently documented usage in this class.
 */
class Route {

    /**
     * Paramaters extracted from the url, based upon the route.
     * Ex: `/blog/{slug}/` requested by `/blog/happy-cats/` would yield `['slug'=>'happy-cats']`
     */
    protected $paramaters = [];

    
    /**
     * The requeted URL without any GET params
     */
    protected $url;
    /**
     * The request method, like GET, POST, etc
     */
    protected $method;
    /**
     * The regex that captured the url
     */
    protected $urlRegex;


    /**
     * The declared route, unparsed, like `/blog/{slug}/`
     */
    protected $paramaterizedPattern;
    /**
     * A simplified pattern for the route-selection algorithm
     * For declared route `/blog/{slug}/`, $placeholderPattern would be `blog/?/`
     */
    protected $placeholderPattern;
    /**
     * Array of methods that are valid for this route. Such as GET, PUT, POST, DELETE, etc
     */
    protected $allowedMethods = [];
    /**
     * The thing being routed to. A callable or an absolute file path
     */
    protected $target;
    /**
     * The package that create the route which was matched.
     */
    protected $package;



    /**
     * Make a route
     * Sorry, I'm not documenting this further. 
     * Usage is in Router component, in the route() method.
     * @param $details an array of route info. 
     */
    public function __construct($details){
        foreach ($details as $name => $d){
            if (property_exists($this,$name)){
                $this->$name = $d;
            }
        }
        foreach ($details['optionalParamaters']??[] as $op){
            $index = array_search($op, $details['paramaters']);
//             print_r($details['paramaters']);
//             print_r($details['optionalParamaters']);
            if (!isset($this->paramaters[$op]))$this->paramaters[$op] = null;
        }
    }

    /**
     * The piece of the url to return
     * Ex url: `/part1/part2/part3.php`
     * `part(0)` returns `part1`. 
     */
    public function part($index){
        //@TODO should part() check parts between forward slashes (/) or parts between all valid delimiters? Should this be decided by route?
        return explode('/',$this->url)[1+$index] ?? null;
    }
    /**
     * Get a named url paramater.
     * Ex: for `/blog/{slug}/`, `param('slug')` returns the slug
     */
    public function param($key){
        return $this->paramaters[$key] ?? null;
    }
    /**
     * Get a named url paramater by index (zero-based)
     */
    public function var($index){
        return array_values($this->paramaters)[$index] ?? null;
    }

    /**
     * @return a package object
     */
    public function package(){
        return $this->package;
    }
    /**
     * return the requested url
     */
    public function url(){
        return $this->url;
    }
    /**
     * return the requested method (GET/POST/etc)
     */
    public function method(){
        return $this->method;
    }
    /**
     * Get the callable or file this route points to
     */
    public function target(){
        return $this->target;
    }
    /**
     * get the type (is callable vs. is file)
     */
    public function type(){
        $t = $this->target;
        if ($this->isFile())return 'file';
        else if ($this->isCallable())return 'callable';
        else return null;
    }
    /** check if target is callable */
    public function isCallable(){
        $t = $this->target;
        return is_callable($t);
    }
    /** check if target is a file */
    public function isFile(){
        $t = $this->target;
        return is_string($t) && is_file($t);
    }
    /** get the file extension if target is a file 
     *  @return file path or false
     */
    public function fileExt(){
        if (!$this->isFile())return false;
        $ext = pathinfo($this->target, PATHINFO_EXTENSION);
        return $ext;
    }

    /**
     * Get the target pattern for this route with {param} declarations
     */
    public function paramaterizedPattern(){
        return $this->paramaterizedPattern;
    }
    /**
     * Get the target pattern for this route with placeholders (?)
     */
    public function placeholderPattern(){
        return $this->placeholderPattern;
    }
    /** array of methods allowed for this route */
    public function allowedMethods(){
        return $this->allowedMethods;
    }
    /** number of url paramaters */
    public function paramaterCount(){
        return count($this->paramaters);
    }
    /** names of url paramaters */
    public function paramaterNames(){
        return array_keys($this->paramaters);
    }
    /** array of paramaters */
    public function paramaters(){
        return $this->paramaters;
    }
    /** true if there are no paramaters in the route pattern */
    public function isStatic(){
        return ($this->paramaterCount()===0);
    }
    /** true if there are paramaters in the route pattern */
    public function isDynamic(){
        return !$this->isStatic();
    }

}