PageRenderTime 226ms CodeModel.GetById 181ms app.highlight 10ms RepoModel.GetById 31ms app.codeStats 0ms

/ROUTER.php

https://bitbucket.org/vodolaz095/trivia_core
PHP | 284 lines | 209 code | 23 blank | 52 comment | 20 complexity | 433798a452fdab380db1a98b6ab50ef6 MD5 | raw file
  1<?php
  2class RouterException extends Exception
  3{
  4
  5}
  6
  7class ROUTER
  8{
  9    protected static $instance;
 10
 11    private $assigns = array();
 12    private $current_dir;
 13    private $path;
 14    private $args = array();
 15    private $is_deployed = false;
 16
 17
 18    private static function init()
 19    {
 20        if (is_null(self::$instance))
 21        {
 22            self::$instance = new ROUTER();
 23        }
 24        return self::$instance;
 25    }
 26
 27    private function __construct()
 28    {
 29
 30    }
 31
 32    /**
 33     * Sets the current directory for project, where controllers and folder for modules are placed
 34     * @param string $current_dir - directory, where the BOOTLOADER.php file and main controllers are placed
 35     * @throws RouterException
 36     */
 37    public static function setCurrentDir($current_dir)
 38    {
 39        if(is_dir($current_dir))
 40        {
 41            $router=ROUTER::init();
 42            $router->current_dir=$current_dir;
 43        }
 44        else
 45        {
 46            throw new RouterException('Router can not set '.$currendDir.' as Current Directory for project!');
 47        }
 48    }
 49
 50    /**
 51     * @return string - directory
 52     */
 53        public static function getCurrentDir()
 54    {
 55        $router=ROUTER::init();
 56        return($router->current_dir);
 57    }
 58    /**
 59     * Assign module action for route
 60     * @param string-regex $route - route to be assigned -
 61     * @param string $module - module name (consists only from letters, _ and digits) - in folder `modules` subfolder `indx` is a module name
 62     * @param string $action - action name (consists only from letters, _ and digits) - in folder `indx` `indx.action.php` is a action name
 63     * @throws RouterException - when something is wrong
 64     */
 65    public static function assign($route, $module, $action)
 66    {
 67        $router = ROUTER::init();
 68        if($router->current_dir)
 69        {
 70            if (preg_match('~^[a-z0-9_]+$~i', $module) and preg_match('~^[a-z0-9_]+$~i', $action))
 71            {
 72
 73                $path = $router->current_dir . '/modules/' . $module . '/' . $action . '.action.php';
 74
 75                if (is_readable($path))
 76                {
 77//*
 78                    if(isset($router->assigns[$route]))
 79                    {
 80                        throw new RouterException('Route '.$route.' is already assignet to '.$module.'-'.$action.' via path '.$router->assigns[$module.'-'.$action]['path']);
 81                    }
 82                    else
 83                    {
 84                    $router->assigns[$route] = array(
 85                        'route' => $route,
 86                        'module' => $module,
 87                        'action' => $action,
 88                        'path' => $path
 89                    );
 90                    }
 91//*/
 92/*
 93                    $router->assigns[$route] = array(
 94                        'route' => $route,
 95                        'module' => $module,
 96                        'action' => $action,
 97                        'path' => $path
 98                    );
 99//*/
100                }
101                else
102                {
103                    throw new RouterException('File "' . $path . '" does\'t exists!');
104                }
105            }
106            else
107            {
108                throw new RouterException('Bad Folder and Module names!');
109            }
110        }
111        else
112        {
113            throw new RouterException('Set the current directory from bootloader via command ROUTER::setCurrentDir(__DIR__)!!!');
114        }
115    }
116
117    /**
118     * Assign callback function to be executed when route matches the pattern
119     * @param string-regex $route
120     * @param $closure - function
121     * @throws RouterException - when something is wrong
122     */
123    public static function assignFunction($route, $closure)
124    {
125        $router = ROUTER::init();
126        if($router->current_dir)
127        {
128            if (is_callable($closure))
129            {
130                $router->assigns[] = array(
131                    'route' => $route,
132                    'function' => $closure
133                );
134            }
135            else
136            {
137                throw new RouterException('Wrong object type for closure');
138            }
139        }
140        else
141        {
142            throw new RouterException('Set the current directory from bootloader via command ROUTER::setCurrentDir(__DIR__)!!!');
143        }
144    }
145
146    /**
147     * Sets the module as a default module - server route. So, request with pattern example.com example/dosmth example/list
148     * goes to actions index.action.php, dosmth.action.php and list.action.php of a module, defined as ServerRoute
149     * @param $dirname
150     * @throws RouterException
151     */
152    public static function setServerRoot($module_name)
153    {
154        $router = ROUTER::init();
155        if($router->current_dir)
156        {
157            if(preg_match('~^[0-9a-z_]+$~i',$module_name))
158            {
159                if(is_dir($router->current_dir . '/modules/' . $module_name))
160                {
161                    $path = $router->current_dir . '/modules/' . $module_name . '/*.action.php';
162                    foreach (glob($path) as $filename)
163                    {
164                        $name=basename($filename,'.action.php');
165                        if($name=='index')
166                            $router->assign('~^/$~',$module_name,'index');
167                        else
168                            $router->assign('~^/'.$name.'/?$~',$module_name,$name);
169                    }
170                }
171                else
172                {
173                    throw new RouterException('Wrong directory name!');
174                }
175            }
176            else
177            {
178                throw new RouterException('Wrong directory name!');
179            }
180        }
181        else
182        {
183            throw new RouterException('Set the current directory from bootloader via command ROUTER::setCurrentDir(__DIR__)!!!');
184        }
185    }
186
187    /**
188     * Get array of all assigned routes
189     * @return array
190     */
191    public static function getRoutes()
192    {
193        $a = array();
194        $router = ROUTER::init();
195        foreach ($router->assigns as $ass)
196        {
197            if (isset($ass['module']) and isset($ass['action']))
198            {
199                $a[] = array('route' => $ass['route'], 'execute' => $router->current_dir . '/' . $ass['module'] . '/' . $ass['action'] . '.action.php');
200            }
201            elseif (isset($ass['function']))
202            {
203                $a[] = array('route' => $ass['route'], 'function' => $ass['function']);
204            }
205            else
206            {
207                /*do nothing*/;
208            }
209        }
210        return $a;
211    }
212
213    /**
214     * Returns the route parameters
215     * @param  $number_of_argument - if assignet,returns the number of argument in query string
216     * @return array
217     */
218    public static function getParameters($number_of_argument=false)
219    {
220        $router = ROUTER::init();
221        if($number_of_argument)
222            {
223                return isset($router->args[$number_of_argument]) ? $router->args[$number_of_argument] : false;
224            }
225        else return $router->args;
226    }
227
228    /**
229     * The main function for router!!!
230     * @param string $override_request_uri - string to override URL of pages from cli enviroment
231     * @return true on success, false on errors (no action to route et cetera)
232     * @throws RouterException
233     */
234    public static function deploy($override_request_uri = false)
235    {
236        $unknown_route = true;
237        $router = ROUTER::init();
238
239        if ($router->is_deployed === false)
240        {
241            $router->is_deployed = true;
242
243            if (PHP_SAPI == 'cli' and $override_request_uri)
244            {
245                $router->path = $override_request_uri;
246            }
247            else
248            {
249                $router->path = parse_url('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], PHP_URL_PATH);
250            }
251
252            foreach ($router->assigns as $assign)
253            {
254                if (preg_match($assign['route'], $router->path, $router->args))
255                {
256                    $unknown_route = false;
257                    if (isset($assign['path']))
258                    {
259                        require_once $assign['path'];
260                    }
261                    elseif(isset($assign['function']))
262                    {
263                        $a = $assign['function'];
264                        $a($router->args);
265                    }
266                    else
267                    {
268                        throw new RouterException('Wrong type of route?');
269                    }
270                    break;
271                }
272            }
273
274            return (!$unknown_route);
275        }
276        else
277        {
278            throw new RouterException('Router Already Deployed!');
279        }
280
281    }
282
283
284}