<commit_before><?PHP
namespace Cora;

class Route extends Framework
{
    
    protected $debug;
    protected $container;
    protected $pathString;
    protected $path;
    protected $controllerPath;      // STRING - filepath to controller .php file.
    protected $controllerOffset;    // INT - The offset within the path array of the controller.
    protected $controllerName;      // STRING
    protected $controllerNamespace; // STRING
    
    
    public function __construct($container = false)
    {
        parent::__construct(); // Call parent constructor too so we don't lose functionality.
        
        spl_autoload_register(array($this, 'autoLoader'));
        
        // For site specific data. This will be passed to Cora's controllers when they
        // are invoked in the routeExec() method.
        $this->container = $container;
        
        // Figure out and set pathString. E.g. "/controller/method/id"
        $cleanURI = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
        $this->pathString = explode($this->config['site_url'], $cleanURI, 2)[1];
        
        // Setup Path array
        $this->path = explode('/', $this->pathString);
        
        // Debug
        $this->debug('Route: ' . $this->pathString);

    }
    
    
    /**
     *  Searches through $path to figure out what part of it is the controller.
     *  This requires searching through the filesystem.
     *
     *  If   $path = /folder1/folder2/Controller/Method/Id
     *  Then $controllerPath    = '/folder1/folder2/Controller'
     *  And  $controllerOffset  = 2
     *
     *  NOTE: This is a recursive function.
     */
    public function routeFind($basePath = '', $offset = 0)
    {
        $this->debug('');
        
        // Vars setup
        $curPath = $this->partialPathArray($offset, 1);
        $controller = '';
        $controllerFileName = '';
        
        $this->debug('Current Path: '.implode('/', $curPath));

        // if $curPath isn't empty
        if (is_array($curPath) and !empty($curPath) and $curPath[0] != '') {
            $controller = $curPath[0];
            $controllerFileName =   $this->config['controllersPrefix'] .
                                    $this->getClassName($controller) .
                                    $this->config['controllersPostfix'] .
                                    '.php';
        }
        
        // Else grab the default controller.
        else {
            $controller = $this->config['default_controller'];
            $controllerFileName =   $this->config['controllersPrefix'] .
                                    $this->getClassName($this->config['default_controller']) .
                                    $this->config['controllersPostfix'] .
                                    '.php';
        }

        // Set working filepath.
        $dirpath = $this->config['pathToControllers'].$basePath.$controller;
        $filepath = $this->config['pathToControllers'].$basePath.$controllerFileName;

        // Debug
        $this->debug('Searching for: ' . $filepath);
        
        //$this->debug('Namespace: '.$this->controllerNamespace);

        // Check if the controller .php file exists in this directory.
        if (file_exists($filepath)) {
            $this->controllerPath = $this->partialPathString(0, $offset+1);
            $this->controllerOffset = $offset;
            $this->controllerName = $controller;
            
            $this->debug('File Found: ' . $controllerFileName);
            $this->debug('Controller Path: ' . $this->controllerPath);
            
            // Create instance of controller and check if that method exists in it. Otherwise we want to keep
            // looking for other sub-folder classes that might map to the url.
            $controllerInstance = $this->getController();
            $method = $this->getMethod();
            $this->debug("getMethod() call in routeFind() returns: ".$method);
            
            if (!method_exists($controllerInstance, $method)) {
                
                // Update namespace
                $this->controllerNamespace .= $this->getClassName($controller).'\\';
                
                //  Controller->Method combo doesn't exist, so undo previously set data.
                $this->controllerPath = null;
                $this->controllerOffset = null;
                $this->controllerName = null;
                
                // Debug
                $this->debug('Not matching method within controller. Continuing search.');
                
                // Recursive call
                //$this->routeFind($basePath . $controller . '/', $offset+1);
            }
            else {
                return false;
            }
        }

        // Else check if there's a matching directory we can look through.
        if (is_dir($dirpath)) {
            $this->debug('Directory Found: ' . $basePath . $controller);
            
            // Recursive call
            $this->routeFind($basePath . $controller . '/', $offset+1);
        }
        
    } // end routeFind
    
    
    /**
     *  Uses the info generated by routeFind() to then create an instance of the
     *  appropriate controller and call the desired method.
     */
    public function routeExec()
    {
        
        // If no controller was found by routeFind()...
        if (!isset($this->controllerPath)) {
            $this->debug('routeExec: No controllerPath set. Routing to 404.');
            $this->error404();
            exit;
        }
        
        $controller = $this->getController();
        $method = $this->getMethod();
        
        // If that method exists, call it or output 404 error.
        if (method_exists($controller, $method)) {
            
            // Setup and clean method arguments in URL
            $methodArgs = $this->partialPathArray($this->controllerOffset+2);

            if (empty($methodArgs)) {
                array_push($methodArgs, '');
            }
            $input = new Input($methodArgs);
            $methodArgs = $input->getData();
            
            // PHP7 Version
            // $controller->$method(...$this->partialPathArray($this->controllerOffset+2));
            
            // Older PHP compatible version
            /** Maps an array of arguments derived from the URL into a method with a comma
             *  delimited list of parameters. Calls the method.
             *
             *  I.E. If the URL is:
             *  'www.mySite.com/MyController/FooBar/Param1/Param2/Param3'
             *
             *  And the FooBar method within MyController is defined as:
             *  public function FooBar($a, $b, $c) {}
             *
             *  $a will have the value 'Param1'
             *  $b will have the value 'Param2'  ... and so forth.
             */
            call_user_func_array(array($controller, $method), $methodArgs);
            
        }
        else {
            $this->error404();
        }
        
    } // end routeExec
    
    
    public function exists()
    {
        if (!isset($this->controllerPath)) {
            return false;
        }
        return true;
    }
    
    
    protected function getController()
    {
        
        // Load generic Cora parent class
        require_once('Cora.php');
        
        // If the config specifies an application specific class that extends Cora, load that.
        if ($this->config['cora_extension'] != '') {
            require_once(dirname(__FILE__).'/../extensions/'.$this->config['cora_extension'].'.php');
        }
        
        // Include the controller code.
        $cPath =    $this->config['pathToControllers'] .
                    $this->getPath($this->controllerPath) .
                    $this->config['controllersPrefix'] .
                    $this->controllerName .
                    $this->config['controllersPostfix'] .<commit_msg>Cleaned up route a bit.<commit_after><?PHP
namespace Cora;

class Route extends Framework
{
    
    protected $container;           // VARIES   - For passing data to controllers.
    protected $pathString;          // STRING   - URL excluding siteURL. mysite.com/FROM/HERE/ONWARD/
    protected $path;                // ARRAY    - Array version of pathString. URL pieces after baseURL.
    protected $controllerPath;      // STRING   - filepath to controller .php file.
    protected $controllerOffset;    // INT      - The offset within the path array of the controller.
    protected $controllerName;      // STRING
    protected $controllerNamespace; // STRING
    protected $controller;          // OBJECT
    protected $method;              // STRING
    
    
    public function __construct($container = false)
    {
        parent::__construct(); // Call parent constructor too so we don't lose functionality.
        
        // Register a autoloader function. Is called when an unloaded class is invoked.
        spl_autoload_register(array($this, 'autoLoader'));
        
        // For site specific data. This will be passed to Cora's controllers when they
        // are invoked in the routeExec() method.
        $this->container = $container;
        
        // Set PATH info.
        $this->setPath($_SERVER['REQUEST_URI']);       
        
        // Debug
        $this->debug('Route: ' . $this->pathString);

    }
    
    
    /**
     *  Given a URL, sets needed PATH information.
     *
     *  NOTE: $_SERVER['QUERY_STRING'] is set by the server and may not be available
     *  depending on the server being used.
     */
    public function setPath($url) 
    {
        // Removes any GET data from the url.
        // Makes 'mysite.com/websites/build/?somevalue=test' INTO '/websites/build'
        $cleanURI = str_replace('?'.$_SERVER['QUERY_STRING'], '', $url);

        // Removes the 'mysite.com' from 'mysite.com/controller/method/id/'
        // Resulting pathString will be 'controller/method/id/'
        $this->pathString = explode($this->config['site_url'], $cleanURI, 2)[1];
        
        // Setup Path array
        $this->path = explode('/', $this->pathString);
    }
    
    
    /**
     *  Searches through $path to figure out what part of it is the controller.
     *  This requires searching through the filesystem.
     *
     *  If   $path = /folder1/folder2/Controller/Method/Id
     *  Then $controllerPath    = '/folder1/folder2/Controller'
     *  And  $controllerOffset  = 2
     *
     *  NOTE: This is a recursive function.
     */
    public function routeFind($basePath = '', $offset = 0)
    {
        $this->debug('');
        
        // Vars setup
        $curPath = $this->partialPathArray($offset, 1);
        $controller = '';
        $controllerFileName = '';
        
        $this->debug('Current Path: '.implode('/', $curPath));

        // if $curPath isn't empty
        if (is_array($curPath) and !empty($curPath) and $curPath[0] != '') {
            $controller = $curPath[0];
            $controllerFileName =   $this->config['controllersPrefix'] .
                                    $this->getClassName($controller) .
                                    $this->config['controllersPostfix'] .
                                    '.php';
        }
        
        // Else grab the default controller.
        else {
            $controller = $this->config['default_controller'];
            $controllerFileName =   $this->config['controllersPrefix'] .
                                    $this->getClassName($this->config['default_controller']) .
                                    $this->config['controllersPostfix'] .
                                    '.php';
        }

        // Set working filepath.
        $dirpath = $this->config['pathToControllers'].$basePath.$controller;
        $filepath = $this->config['pathToControllers'].$basePath.$controllerFileName;

        // Debug
        $this->debug('Searching for: ' . $filepath);

        // Check if the controller .php file exists in this directory.
        if (file_exists($filepath)) {
            $this->controllerPath = $this->partialPathString(0, $offset+1);
            $this->controllerOffset = $offset;
            $this->controllerName = $controller;
            
            $this->debug('File Found: ' . $controllerFileName);
            $this->debug('Controller Path: ' . $this->controllerPath);
            
            // Create instance of controller and check if that method exists in it. Otherwise we want to keep
            // looking for other sub-folder classes that might map to the url.
            $controllerInstance = $this->getController();
            $method = $this->getMethod();
            $this->debug("getMethod() call in routeFind() returns: ".$method);
            
            if (!method_exists($controllerInstance, $method)) {
                
                // Update namespace
                $this->controllerNamespace .= $this->getClassName($controller).'\\';
                
                //  Controller->Method combo doesn't exist, so undo previously set data.
                $this->controllerPath = null;
                $this->controllerOffset = null;
                $this->controllerName = null;
                
                // Debug
                $this->debug('Not matching method within controller. Continuing search.');
                
            }
            else {
                // Valid controller+method combination found, so stop searching further.
                $this->controller   = $controllerInstance;
                $this->method       = $method;
                return true;
            }
        }

        // Else check if there's a matching directory we can look through.
        if (is_dir($dirpath)) {
            $this->debug('Directory Found: ' . $basePath . $controller);
            
            // Recursive call
            $this->routeFind($basePath . $controller . '/', $offset+1);
        }
        
    } // end routeFind
    
    
    /**
     *  Uses the info generated by routeFind() to then create an instance of the
     *  appropriate controller and call the desired method.
     */
    public function routeExec()
    {
        
        // If no controller was found by routeFind()...
        if (!isset($this->controllerPath)) {
            $this->debug('routeExec: No controllerPath set. Routing to 404.');
            $this->error404();
            exit;
        }

        // Grab method arguments from the URL.
        $methodArgs = $this->partialPathArray($this->controllerOffset+2);
        
        // Push empty string if no arguments are set.
        if (empty($methodArgs)) {
            array_push($methodArgs, '');
        }
        
        // Sanitize arguments.
        $input = new Input($methodArgs);
        $methodArgs = $input->getData();

        /** Maps an array of arguments derived from the URL into a method with a comma
         *  delimited list of parameters. Calls the method.
         *
         *  I.E. If the URL is:
         *  'www.mySite.com/MyController/FooBar/Param1/Param2/Param3'
         *
         *  And the FooBar method within MyController is defined as:
         *  public function FooBar($a, $b, $c) {}
         *
         *  $a will have the value 'Param1'
         *  $b will have the value 'Param2'  ... and so forth.
         */
        call_user_func_array(array($this->controller, $this->method), $methodArgs);
        
    } // end routeExec
    
    
    /**
     *  Checks if routeFind found a path to a controller. Check this before calling
     *  routeExec.
     *
     *  Note: This helps with integrating Cora into legacy applications.
     *  You can check if a matching controller was found in the directory you're putting
     *  Cora controllers in, and if not, then run legacy routing instead.
     */
    public function exists()
    {
        if (!isset($this->controllerPath)) {
            return false;
        }
        return true;
    }
    
    
    protected function getController()
    {
        
        // Load generic Cora parent class
        require_once('Cora.php');
        
        // If the config specifies an application specific class that extends Cora, load that.
        if ($this->config['cora_extension'] != '') {
            require_once(dirname(__FILE__).'/../extensions/'.$this->config['cora_extension'].'.php');
        }
        
        // Include the controller code.
        $cPath =    $this->config['pathToControllers'] .
                    $this->getPath($this->controllerPath) .
                    $this->config['controllersPrefix'] .
                    $this->controllerName .
                    $this->config['controllersPostfix'] .
{'fraction_non_alphanumeric': 0.11806093852483454, 'fraction_numerical': 0.003637230934350963, 'mean_word_length': 1.655478150728309, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 127, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1320388', 'n_tokens_mistral': 4331, 'n_tokens_neox': 4203, 'n_words': 1142}