1: <?php
2: /**
3: * This file is part of the PHPLucidFrame library.
4: * Core utility for pagination
5: *
6: * @package PHPLucidFrame\Core
7: * @since PHPLucidFrame v 2.0.0
8: * @copyright Copyright (c), PHPLucidFrame.
9: * @link http://phplucidframe.com
10: * @license http://www.opensource.org/licenses/mit-license.php MIT License
11: *
12: * This source file is subject to the MIT license that is bundled
13: * with this source code in the file LICENSE
14: */
15:
16: namespace LucidFrame\Core;
17:
18: /**
19: * Middleware Class
20: */
21: class Middleware
22: {
23: private static $instance = null;
24:
25: const BEFORE = 'before';
26: const AFTER = 'after';
27:
28: const FILTER_START_WITH = 'startWith';
29: const FILTER_CONTAIN = 'contain';
30: const FILTER_EQUAL = 'equal';
31: const FILTER_EXCEPT = 'except';
32:
33: /** @var array Array of registered middlewares (before) */
34: private static $before = array();
35: /** @var array Array of registered middlewares (after) */
36: private static $after = array();
37: /** @var string Unique id */
38: private static $id;
39: /** @var array Array of route filters by each middleware */
40: private static $routeFilters = array();
41: /** @var array Array of order by each middleware */
42: private static $orders = array();
43:
44: /**
45: * # Make the constructor private to prevent instantiation from outside
46: */
47: private function __construct() { }
48:
49: /**
50: * Prevent cloning of the instance
51: */
52: private function __clone() { }
53:
54: /**
55: * Static method to provide access to the single instance
56: */
57: public static function getInstance()
58: {
59: if (!self::$instance) {
60: self::$instance = new Middleware();
61: }
62:
63: return self::$instance;
64: }
65:
66: /**
67: * Register a middleware
68: * @param \Closure $closure Anonymous function
69: * @param string $event before or after
70: * @return $this
71: */
72: public function register(\Closure $closure, $event = self::BEFORE)
73: {
74: self::$id = uniqid();
75:
76: if (in_array($event, array(self::BEFORE, self::AFTER))) {
77: self::${$event}[self::$id] = $closure;
78: $this->order(count(self::${$event}), $event);
79: }
80:
81: return $this;
82: }
83:
84: /**
85: * Register route filter for the middleware
86: * @param string $key One of the values - startWith, contain, equal, except
87: * @param string $value URI or a part of URI
88: * @return $this
89: */
90: public function on($key, $value)
91: {
92: if (self::$id) {
93: self::$routeFilters[self::$id][$key][] = $value;
94: }
95:
96: return $this;
97: }
98:
99: /**
100: * Register precedence of the middleware
101: * @param int $sort Ascending order (smaller value runs first)
102: * @param string $event before (default) or after
103: * @return $this
104: */
105: public function order($sort, $event = self::BEFORE)
106: {
107: if (self::$id) {
108: self::$orders[$event][self::$id] = $sort;
109: }
110:
111: return $this;
112: }
113:
114: /**
115: * Run all registered middlewares (before)
116: */
117: public static function runBefore()
118: {
119: asort(self::$orders[self::BEFORE]);
120: self::invoke(self::BEFORE);
121: }
122:
123: /**
124: * Run all registered middlewares (after)
125: */
126: public static function runAfter()
127: {
128: asort(self::$orders[self::AFTER]);
129: self::invoke(self::AFTER);
130: }
131:
132: /**
133: * Run the registered middlewares
134: * @param string $event before or after
135: */
136: private static function invoke($event)
137: {
138: $middlewares = $event == self::AFTER ? self::$after : self::$before;
139:
140: foreach (self::$orders[$event] as $id => $order) {
141: $closure = $middlewares[$id];
142:
143: if (isset(self::$routeFilters[$id])) {
144: $except = array();
145: if (isset(self::$routeFilters[$id][self::FILTER_EXCEPT])) {
146: foreach (self::$routeFilters[$id][self::FILTER_EXCEPT] as $exp) {
147: $exp = is_array($exp) ? $exp : array($exp);
148: $except = array_merge($except, $exp);
149: }
150: unset(self::$routeFilters[$id][self::FILTER_EXCEPT]);
151: }
152:
153: if (count(self::$routeFilters[$id])) {
154: foreach (self::$routeFilters[$id] as $filter => $value) {
155: foreach ($value as $val) {
156: switch($filter) {
157: case self::FILTER_START_WITH:
158: if (route_start($val, $except)) {
159: $closure();
160: }
161: break;
162:
163: case self::FILTER_CONTAIN:
164: $val = is_array($val) ? $val : array($val);
165: if (route_contain($val, $except)) {
166: $closure();
167: }
168: break;
169:
170: case self::FILTER_EQUAL:
171: if (route_equal($val)) {
172: $closure();
173: }
174: break;
175: }
176: }
177: }
178: } else {
179: if (count($except) && call_user_func_array('route_except', $except)) {
180: $closure();
181: }
182: }
183: } else {
184: $closure();
185: }
186: }
187: }
188: }
189: