66 */
77final class AppBuilder {
88
9+ /**
10+ * @var AppContext
11+ */
12+ private static $ appContext ;
13+
14+ /**
15+ * @var array
16+ */
917 private static $ config = array ();
1018
1119 /**
@@ -87,12 +95,27 @@ public static function useSession($opions = null) {
8795 self ::$ config ['session ' ] = (!empty ($ opions ) ? $ opions : true );
8896 }
8997
98+ /**
99+ * Sets custom handlers.
100+ *
101+ * @param callback $callback
102+ * For example:
103+ * AppBuilder::use(function($appContext: AppContext) {
104+ * // ...
105+ * });
106+ *
107+ * @return void
108+ */
109+ public static function use ($ callback ) {
110+ self ::$ config ['customHandlers ' ] = $ callback ;
111+ }
112+
90113 /**
91114 * Registers routes.
92115 *
93116 * @param callback $routes A function in which an instance of the route provider will be passed, through which routing rules are created.
94117 * For example:
95- * AppBuilder::routes(function($routes) {
118+ * AppBuilder::routes(function($routes: RouteProvider ) {
96119 * $routes->ignore('content/{*file}');
97120 * $routes->add('default', '{controller=Home}/{action=index}/{id?}');
98121 * });
@@ -146,16 +169,31 @@ private static function headers() {
146169 * @return void
147170 */
148171 private static function init () {
149- if (empty (self ::$ config ['appNamespace ' ])) {
172+ self ::$ appContext = new AppContext (self ::$ config );
173+
174+ if (isset (self ::$ config ['customHandlers ' ])) {
175+ if (is_callable (self ::$ config ['customHandlers ' ])) {
176+ self ::$ config ['customHandlers ' ](self ::$ appContext );
177+ }
178+ else {
179+ throw new \Exception ('Function is expected. ' );
180+ }
181+ }
182+
183+ self ::invokeAll (self ::$ appContext ->getPreInit (), array (self ::$ appContext ));
184+
185+ $ config = self ::$ appContext ->getConfig ();
186+
187+ if (empty ($ config ['appNamespace ' ])) {
150188 throw new \Exception ('The root namespace for the application is required. To specify the namespace of your application, use the useNamespace method. The value must not be null or empty. ' );
151189 }
152190
153- if (empty (self :: $ config ['basePath ' ])) {
154- self :: $ config ['basePath ' ] = getcwd ();
191+ if (empty ($ config ['basePath ' ])) {
192+ $ config ['basePath ' ] = getcwd ();
155193 }
156194
157195 if (!defined ('PHPMVC_DS ' )) { define ('PHPMVC_DS ' , DIRECTORY_SEPARATOR ); }
158- if (!defined ('PHPMVC_ROOT_PATH ' )) { define ('PHPMVC_ROOT_PATH ' , self :: $ config ['basePath ' ] . PHPMVC_DS ); }
196+ if (!defined ('PHPMVC_ROOT_PATH ' )) { define ('PHPMVC_ROOT_PATH ' , $ config ['basePath ' ] . PHPMVC_DS ); }
159197 if (!defined ('PHPMVC_CORE_PATH ' )) { define ('PHPMVC_CORE_PATH ' , __DIR__ .PHPMVC_DS ); }
160198 if (!defined ('PHPMVC_CONFIG_PATH ' )) { define ('PHPMVC_CONFIG_PATH ' , PHPMVC_ROOT_PATH . 'config ' . PHPMVC_DS ); }
161199 if (!defined ('PHPMVC_FILTER_PATH ' )) { define ('PHPMVC_FILTER_PATH ' , PHPMVC_ROOT_PATH . 'filters ' . PHPMVC_DS ); }
@@ -166,80 +204,84 @@ private static function init() {
166204 if (!defined ('PHPMVC_UPLOAD_PATH ' )) { define ('PHPMVC_UPLOAD_PATH ' , PHPMVC_ROOT_PATH . 'upload ' . PHPMVC_DS ); }
167205
168206 if (!defined ('PHPMVC_APP_NAMESPACE ' )) {
169- define ('PHPMVC_APP_NAMESPACE ' , self :: $ config ['appNamespace ' ]);
207+ define ('PHPMVC_APP_NAMESPACE ' , $ config ['appNamespace ' ]);
170208 }
171- elseif (PHPMVC_APP_NAMESPACE !== self :: $ config ['appNamespace ' ]) {
209+ elseif (PHPMVC_APP_NAMESPACE !== $ config ['appNamespace ' ]) {
172210 throw new \Exception ('Constant PHPMVC_CONTROLLER already defined. Re-define with other value is not possible. ' );
173211 }
174212
175- if (empty (self :: $ config ['routeProvider ' ])) {
176- self :: $ config ['routeProvider ' ] = new DefaultRouteProvider ();
213+ if (empty ($ config ['routeProvider ' ])) {
214+ $ config ['routeProvider ' ] = new DefaultRouteProvider ();
177215 }
178- elseif (!self :: $ config ['routeProvider ' ] instanceof RouteProvider) {
216+ elseif (!$ config ['routeProvider ' ] instanceof RouteProvider) {
179217 throw new \Exception ('The routeProvider type must be the base of "\PhpMvc\RouteProvider". ' );
180218 }
181219
182- self :: $ config ['routeProvider ' ]->init ();
220+ $ config ['routeProvider ' ]->init ();
183221
184- if (isset (self :: $ config ['routes ' ])) {
185- if (is_callable (self :: $ config ['routes ' ])) {
186- self :: $ config ['routes ' ](self :: $ config ['routeProvider ' ]);
222+ if (isset ($ config ['routes ' ])) {
223+ if (is_callable ($ config ['routes ' ])) {
224+ $ config ['routes ' ]($ config ['routeProvider ' ]);
187225 }
188- elseif (is_array (self :: $ config ['routes ' ])) {
189- $ provider = self :: $ config ['routeProvider ' ];
226+ elseif (is_array ($ config ['routes ' ])) {
227+ $ provider = $ config ['routeProvider ' ];
190228
191- foreach (self :: $ config ['routes ' ][0 ] as $ route ) {
229+ foreach ($ config ['routes ' ][0 ] as $ route ) {
192230 $ provider ->add ($ route ->name , $ route ->template , $ route ->defaults , $ route ->constraints );
193231 }
194232
195- if (count (self :: $ config ['routes ' ]) > 1 ) {
196- foreach (self :: $ config ['routes ' ][1 ] as $ route ) {
233+ if (count ($ config ['routes ' ]) > 1 ) {
234+ foreach ($ config ['routes ' ][1 ] as $ route ) {
197235 $ provider ->ingnore ($ route ->template , $ route ->constraints );
198236 }
199237 }
200238 }
201- elseif (self :: $ config ['routes ' ] instanceof RouteCollection) {
202- $ provider = self :: $ config ['routeProvider ' ];
239+ elseif ($ config ['routes ' ] instanceof RouteCollection) {
240+ $ provider = $ config ['routeProvider ' ];
203241
204- foreach (self :: $ config ['routes ' ] as $ route ) {
242+ foreach ($ config ['routes ' ] as $ route ) {
205243 $ provider ->add ($ route ->name , $ route ->template , $ route ->defaults , $ route ->constraints );
206244 }
207245 }
208246 }
209247
210- if (empty (self :: $ config ['cacheProvider ' ])) {
211- self :: $ config ['cacheProvider ' ] = new IdleCacheProvider ();
248+ if (empty ($ config ['cacheProvider ' ])) {
249+ $ config ['cacheProvider ' ] = new IdleCacheProvider ();
212250 }
213- elseif (!self :: $ config ['cacheProvider ' ] instanceof CacheProvider) {
251+ elseif (!$ config ['cacheProvider ' ] instanceof CacheProvider) {
214252 throw new \Exception ('The $cacheProvider type must be the base of "\PhpMvc\CacheProvider". ' );
215253 }
216254
217- self :: $ config ['cacheProvider ' ]->init ();
255+ $ config ['cacheProvider ' ]->init ();
218256
219- if (empty (self :: $ config ['httpContext ' ])) {
257+ if (empty ($ config ['httpContext ' ])) {
220258 $ info = new HttpContextInfo ();
221- $ info ->routeProvider = self :: $ config ['routeProvider ' ];
222- $ info ->cacheProvider = self :: $ config ['cacheProvider ' ];
259+ $ info ->routeProvider = $ config ['routeProvider ' ];
260+ $ info ->cacheProvider = $ config ['cacheProvider ' ];
223261 $ info ->request = new HttpRequest ();
224262 $ info ->response = new HttpResponse ();
225263
226- self :: $ config ['httpContext ' ] = new HttpContext ($ info );
264+ $ config ['httpContext ' ] = new HttpContext ($ info );
227265 }
228- elseif (!self :: $ config ['httpContext ' ] instanceof HttpContextBase) {
266+ elseif (!$ config ['httpContext ' ] instanceof HttpContextBase) {
229267 throw new \Exception ('The httpContext type must be the base of "\PhpMvc\HttpContextBase". ' );
230268 }
231269
232- if (isset (self :: $ config ['session ' ])) {
270+ if (isset ($ config ['session ' ])) {
233271 // TODO: session provider
234- if (is_array (self :: $ config ['session ' ])) {
235- session_start (self :: $ config ['session ' ]);
272+ if (is_array ($ config ['session ' ])) {
273+ session_start ($ config ['session ' ]);
236274 }
237275 else {
238276 session_start ();
239277 }
240278 }
241279
242- InternalHelper::setStaticPropertyValue ('\\PhpMvc \\HttpContext ' , 'current ' , self ::$ config ['httpContext ' ]);
280+ InternalHelper::setStaticPropertyValue ('\\PhpMvc \\HttpContext ' , 'current ' , $ config ['httpContext ' ]);
281+
282+ self ::$ appContext ->setConfig ($ config );
283+ self ::invokeAll (self ::$ appContext ->getInit (), array (self ::$ appContext ));
284+ self ::$ config = self ::$ appContext ->getConfig ();
243285 }
244286
245287 /**
@@ -335,14 +377,17 @@ private static function actionContext($route) {
335377 // response handling
336378 $ httpContext ->getResponse ()->setFlushHandler (function ($ eventArgs ) use ($ actionContext ) {
337379 self ::cachingPartial ($ actionContext , $ eventArgs );
380+ self ::invokeAll (self ::$ appContext ->getFlush (), array ($ actionContext , $ eventArgs ));
338381 });
339382
340383 $ httpContext ->getResponse ()->setEndHandler (function () use ($ actionContext ) {
341384 self ::caching ($ actionContext );
385+ self ::invokeAll (self ::$ appContext ->getEnd (), array ($ actionContext ));
342386 });
343387
344388 $ httpContext ->getResponse ()->setPreSendHandler (function () use ($ actionContext ) {
345389 self ::cachingClient ($ actionContext );
390+ self ::invokeAll (self ::$ appContext ->getPreSend (), array ($ actionContext ));
346391 });
347392
348393 // arguments and model state
@@ -1108,4 +1153,15 @@ private static function exceptionFilters($actionContext, $exception) {
11081153 return $ context ;
11091154 }
11101155
1156+ /**
1157+ * @param callback[] $callbacks
1158+ *
1159+ * @return void
1160+ */
1161+ private static function invokeAll ($ callbacks , $ parameters = array ()) {
1162+ foreach ($ callbacks as $ callback ) {
1163+ call_user_func_array ($ callback , $ parameters );
1164+ }
1165+ }
1166+
11111167}
0 commit comments