1: <?php
2: /**
3: * @filesource Kotchasan/Router.php
4: *
5: * @copyright 2016 Goragod.com
6: * @license http://www.kotchasan.com/license/
7: *
8: * @see http://www.kotchasan.com/
9: */
10:
11: namespace Kotchasan;
12:
13: /**
14: * Router class.
15: *
16: * @author Goragod Wiriya <admin@goragod.com>
17: *
18: * @since 1.0
19: */
20: class Router extends \Kotchasan\KBase
21: {
22: /**
23: * กฏของ Router สำหรับการแยกหน้าเว็บไซต์.
24: *
25: * @var array
26: */
27: protected $rules = array(
28: // index.php/module/model/folder/_dir/_method
29: '/^[a-z0-9]+\.php\/([a-z]+)\/(model)(\/([\/a-z0-9_]+)\/([a-z0-9_]+))?$/i' => array('module', '_mvc', '', '_dir', '_method'),
30: // index/model/_dir
31: '/([a-z]+)\/(model|controller|view)\/([a-z0-9_]+)/i' => array('module', '_mvc', '_dir'),
32: // module/alias
33: '/^([a-z]+)\/(.*)$/' => array('module', 'alias'),
34: // module, module.php
35: '/^([a-z0-9_]+)(\.php)?$/' => array('module'),
36: // alias
37: '/^(.*)$/' => array('alias'),
38: );
39:
40: /**
41: * Initial Router.
42: *
43: * @param string $className คลาสที่จะรับค่าจาก Router
44: *
45: * @throws \InvalidArgumentException หากไม่พบคลาสเป้าหมาย
46: *
47: * @return \static
48: */
49: public function init($className)
50: {
51: // ตรวจสอบโมดูล
52: $modules = $this->parseRoutes(self::$request->getUri()->getPath(), self::$request->getQueryParams());
53: if (isset($modules['module']) && isset($modules['_mvc']) && isset($modules['_dir'])) {
54: // คลาสจาก URL
55: $className = str_replace(' ', '\\', ucwords($modules['module'].' '.str_replace(array('\\', '/'), ' ', $modules['_dir']).' '.$modules['_mvc']));
56: $method = empty($modules['_method']) ? 'index' : $modules['_method'];
57: } elseif (isset($modules['_class']) && isset($modules['_method'])) {
58: // ระบุ Class และ Method มาตรงๆ
59: // ต้องเขียนกฏของ Router เองให้รัดกุม
60: $className = str_replace('/', '\\', $modules['_class']);
61: $method = $modules['_method'];
62: } else {
63: // ไม่ระบุเมธอดมา เรียกเมธอด index
64: $method = empty($modules['_method']) ? 'index' : $modules['_method'];
65: }
66: if (!class_exists($className)) {
67: throw new \InvalidArgumentException('Class '.$className.' not found');
68: } elseif (method_exists($className, $method)) {
69: // สร้างคลาส
70: $obj = new $className();
71: // เรียกเมธอด
72: $obj->$method(self::$request->withQueryParams($modules));
73: } else {
74: throw new \InvalidArgumentException('Method '.$method.' not found in '.$className);
75: }
76:
77: return $this;
78: }
79:
80: /**
81: * แยก path คืนค่าเป็น query string.
82: *
83: * @assert ('/print.php/css/view/index', array()) [==] array( '_mvc' => 'view', '_dir' => 'index', 'module' => 'css')
84: * @assert ('/index/model/updateprofile.php', array()) [==] array( '_mvc' => 'model', '_dir' => 'updateprofile', 'module' => 'index')
85: * @assert ('/index.php/alias/model/admin/settings/save', array()) [==] array('module' => 'alias', '_mvc' => 'model', '_dir' => 'admin/settings', '_method' => 'save')
86: * @assert ('/css/view/index.php', array()) [==] array('module' => 'css', '_mvc' => 'view', '_dir' => 'index')
87: * @assert ('/module/ทดสอบ.html', array()) [==] array('alias' => 'ทดสอบ', 'module' => 'module')
88: * @assert ('/module.html', array()) [==] array('module' => 'module')
89: * @assert ('/ทดสอบ.html', array()) [==] array('alias' => 'ทดสอบ')
90: * @assert ('/ทดสอบ.html', array('module' => 'test')) [==] array('alias' => 'ทดสอบ', 'module' => 'test')
91: * @assert ('/index.php', array('_action' => 'one')) [==] array('_action' => 'one')
92: * @assert ('/admin_index.php', array('_action' => 'one')) [==] array('_action' => 'one', 'module' => 'admin_index')
93: *
94: * @param string path เช่น /a/b/c.html
95: * @param array $modules query string
96: *
97: * @return array
98: */
99: public function parseRoutes($path, $modules)
100: {
101: $base_path = preg_quote(BASE_PATH, '/');
102: // แยกเอาฉพาะ path ที่ส่งมา ไม่รวม path ของ application และ นามสกุล
103: if (preg_match('/^'.$base_path.'(.*)(\.html?|\/)$/u', $path, $match)) {
104: $my_path = $match[1];
105: } elseif (preg_match('/^'.$base_path.'(.*)$/u', $path, $match)) {
106: $my_path = $match[1];
107: }
108: if (!empty($my_path) && !preg_match('/^[a-z0-9]+\.php$/i', $my_path)) {
109: $my_path = rawurldecode($my_path);
110: foreach ($this->rules as $patt => $items) {
111: if (preg_match($patt, $my_path, $match)) {
112: foreach ($items as $i => $key) {
113: if (!empty($key) && isset($match[$i + 1])) {
114: $modules[$key] = $match[$i + 1];
115: }
116: }
117: break;
118: }
119: }
120: }
121:
122: return $modules;
123: }
124: }
125: