root/trunk/lib/SGL/FrontController.php

Revision 4418, 14.2 kB (checked in by demian, 2 years ago)

improving db error detection

Line 
1 <?php
2 /* Reminder: always indent with 4 spaces (no tabs). */
3 // +---------------------------------------------------------------------------+
4 // | Copyright (c) 2010, Demian Turner                                         |
5 // | All rights reserved.                                                      |
6 // |                                                                           |
7 // | Redistribution and use in source and binary forms, with or without        |
8 // | modification, are permitted provided that the following conditions        |
9 // | are met:                                                                  |
10 // |                                                                           |
11 // | o Redistributions of source code must retain the above copyright          |
12 // |   notice, this list of conditions and the following disclaimer.           |
13 // | o Redistributions in binary form must reproduce the above copyright       |
14 // |   notice, this list of conditions and the following disclaimer in the     |
15 // |   documentation and/or other materials provided with the distribution.    |
16 // | o The names of the authors may not be used to endorse or promote          |
17 // |   products derived from this software without specific prior written      |
18 // |   permission.                                                             |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
21 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
22 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
23 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
24 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
25 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
26 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
27 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
28 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
29 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
30 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
31 // |                                                                           |
32 // +---------------------------------------------------------------------------+
33 // | Seagull 1.0                                                               |
34 // +---------------------------------------------------------------------------+
35 // | FrontController.php                                                       |
36 // +---------------------------------------------------------------------------+
37 // | Author:   Demian Turner <demian@phpkitchen.com>                           |
38 // +---------------------------------------------------------------------------+
39 // $Id: FrontController.php,v 1.49 2005/06/23 19:15:25 demian Exp $
40
41 require_once dirname(__FILE__)  . '/../SGL.php';
42 require_once dirname(__FILE__)  . '/Task/Init.php';
43
44 /**
45  * Application controller.
46  *
47  * @package SGL
48  * @author  Demian Turner <demian@phpkitchen.com>
49  * @version $Revision: 1.49 $
50  */
51 class SGL_FrontController
52 {
53     /**
54      * Allow SGL_Output with its template methods to be extended.
55      *
56      * If you want to work with your own Seagull classes create your own namespace in
57      * the seagull/lib directory, ie, seagull/lib/FOO.  To override the SGL_Output
58      * class you would then create seagull/lib/FOO/Output.php, extend it from
59      * SGL_Output and provide the classname "FOO_Output" in "site.customOutputClassName"
60      * so it can be loaded automatically.
61      *
62      *  class FOO_Output extends SGL_Output {}
63      *
64      */
65     function getOutputClass()
66     {
67         if (SGL_Config::get('site.customOutputClassName')) {
68             $className = SGL_Config::get('site.customOutputClassName');
69             $path = trim(preg_replace('/_/', '/', $className)) . '.php';
70             require_once $path;
71         } else {
72             $className = 'SGL_Output';
73         }
74         return $className;
75     }
76
77     /**
78      * Main invocation, init tasks plus main process.
79      *
80      */
81     public static function run()
82     {
83         if (!defined('SGL_INITIALISED')) {
84             SGL_FrontController::init();
85         }
86         //  create app resources
87         $input = SGL_Registry::singleton();
88         $req   = SGL_Request::singleton();
89
90         //  ensure local config loaded and merged
91         $c = SGL_Config::singleton();
92
93         $outputClass = SGL_FrontController::getOutputClass();
94         $output = new $outputClass();
95
96         // test db connection
97         SGL_FrontController::testDbConnection($output);
98
99         //  initialise request
100         $req->init();
101         if (PEAR::isError($req)) {
102             //  stop with error page
103             SGL::displayStaticPage($req->getMessage());
104         }
105         $input->setRequest($req);
106         $c->ensureModuleConfigLoaded($req->getModuleName());
107
108         // run module init tasks
109         SGL_Task_InitialiseModules::run();
110
111
112         // see http://trac.seagullproject.org/wiki/Howto/PragmaticPatterns/InterceptingFilter
113         if (!SGL_FrontController::customFilterChain($input)) {
114             $process =
115                 //  pre-process (order: top down)
116                 new SGL_Task_Init(
117                 new SGL_Task_SetupORM(
118                 new SGL_Task_StripMagicQuotes(
119                 new SGL_Task_DiscoverClientOs(
120                 new SGL_Task_ResolveManager(
121                 new SGL_Task_CreateSession(
122                 new SGL_Task_SetupLangSupport(
123                 new SGL_Task_SetupLocale(
124                 new SGL_Task_AuthenticateRequest(
125                 new SGL_Task_DetectAdminMode(
126                 new SGL_Task_MaintenanceModeIntercept(
127                 new SGL_Task_DetectSessionDebug(
128                 new SGL_Task_SetupPerms(
129
130                 //  post-process (order: bottom up)
131                 new SGL_Task_BuildHeaders(
132                 new SGL_Task_BuildView(
133                 new SGL_Task_BuildDebugBlock(
134                 new SGL_Task_SetupBlocks(
135                 new SGL_Task_SetupNavigation(
136                 new SGL_Task_SetupGui(
137                 new SGL_Task_SetupWysiwyg(
138                 new SGL_Task_BuildOutputData(
139
140                 //  target
141                 new SGL_MainProcess()
142                 )))))))))))))))))))));
143             $process->process($input, $output);
144
145         } else {
146             require_once dirname(__FILE__)  . '/FilterChain.php';
147             $chain = new SGL_FilterChain($input->getFilters());
148             $chain->doFilter($input, $output);
149         }
150         if (SGL_Config::get('site.outputBuffering')) {
151             ob_end_flush();
152         }
153         echo $output->data;
154     }
155
156     function customFilterChain($input)
157     {
158         $req = $input->getRequest();
159
160         switch ($req->getType()) {
161         case SGL_REQUEST_BROWSER:
162         case SGL_REQUEST_CLI:
163             $mgr = SGL_Inflector::getManagerNameFromSimplifiedName(
164                 $req->getManagerName());
165             //  load filters defined by specific manager
166             if (SGL_Config::get("$mgr.filterChain")) {
167                 $aFilters = explode(',', SGL_Config::get("$mgr.filterChain"));
168                 $input->setFilters($aFilters);
169                 $ret = true;
170
171             //  load sitewide custom filters
172             } elseif (SGL_Config::get('site.filterChain')) {
173                 $aFilters = explode(',', SGL_Config::get('site.filterChain'));
174                 $input->setFilters($aFilters);
175                 $ret = true;
176             } else {
177                 $ret = false;
178             }
179             break;
180
181         case SGL_REQUEST_AJAX:
182             $moduleName = ucfirst($req->getModuleName());
183             $providerName = $moduleName . 'AjaxProvider';
184             if (SGL_Config::get("$providerName.filterChain")) {
185                 $aFilters = explode(',', SGL_Config::get("$providerName.filterChain"));
186             } else {
187                 $aFilters = array(
188                     'SGL_Task_Init',
189                     'SGL_Task_SetupORM',
190                     'SGL_Task_CreateSession',
191                     'SGL_Task_SetupLangSupport',
192                     'SGL_Task_AuthenticateAjaxRequest',
193                     'SGL_Task_BuildAjaxHeaders',
194                     'SGL_Task_CustomBuildOutputData',
195                     'SGL_Task_ExecuteAjaxAction2',
196                 );
197             }
198             $input->setFilters($aFilters);
199             $ret = true;
200             break;
201
202         case SGL_REQUEST_AMF:
203             $moduleName = ucfirst($req->getModuleName());
204             $providerName = $moduleName . 'AmfProvider';
205             if (SGL_Config::get("$providerName.filterChain")) {
206                 $aFilters = explode(',', SGL_Config::get("$providerName.filterChain"));
207             } else {
208                 $aFilters = array(
209                     'SGL_Task_Init',
210                     'SGL_Task_SetupORM',
211                     'SGL_Task_CreateSession',
212                     'SGL_Task_SetupLangSupport',
213                     'SGL_Task_ExecuteAmfAction',
214                 );
215             }
216             $input->setFilters($aFilters);
217             $ret = true;
218             break;
219         }
220         return $ret;
221     }
222
223     function testDbConnection($output)
224     {
225         $originalErrorLevel = error_reporting(0);
226
227         //  clear error stack of existing db errors
228         if (SGL_Error::count()) {
229             $oTmpErrors = SGL_Error::getAll();
230             while ($oError = array_pop($oTmpErrors)) {
231                 if (PEAR::isError($oError, DB_ERROR_CONNECT_FAILED)) {
232                     SGL_Error::reset(); break;
233                 }
234             }
235         }
236         // test db connection
237         if (defined('SGL_INSTALLED')) {
238             $dbh = SGL_DB::singleton();
239             if (PEAR::isError($dbh)) {
240                 // stop with error page
241                 SGL::displayErrorPage($output);
242             }
243         }
244         error_reporting($originalErrorLevel);
245     }
246
247
248     public static function init()
249     {
250         SGL_FrontController::setupMinimumEnv();
251         SGL_FrontController::loadRequiredFiles();
252
253         $autoLoad = (is_file(SGL_VAR_DIR  . '/INSTALL_COMPLETE.php'))
254             ? true
255             : false;
256         $c = SGL_Config::singleton($autoLoad);
257
258         $init = new SGL_TaskRunner();
259         $init->addData($c->getAll());
260         $init->addTask(new SGL_Task_SetupConstantsFinish());
261         $init->addTask(new SGL_Task_EnsurePlaceholderDbPrefixIsNull());
262         $init->addTask(new SGL_Task_SetGlobals());
263         $init->addTask(new SGL_Task_ModifyIniSettings());
264         $init->addTask(new SGL_Task_SetupPearErrorCallback());
265         $init->addTask(new SGL_Task_SetupCustomErrorHandler());
266         $init->addTask(new SGL_Task_SetBaseUrl());
267         $init->addTask(new SGL_Task_RegisterTrustedIPs());
268         $init->addTask(new SGL_Task_LoadCustomConfig());
269         $init->main();
270         define('SGL_INITIALISED', true);
271     }
272
273     function loadRequiredFiles()
274     {
275         $cachedLibs = SGL_VAR_DIR . '/cachedLibs.php';
276         $cachedLibsEnabled = (defined('SGL_CACHE_LIBS') && SGL_CACHE_LIBS === true)
277             ? true
278             : false;
279         if (is_file($cachedLibs) && $cachedLibsEnabled) {
280             require_once $cachedLibs;
281         } else {
282             $coreLibs = dirname(__FILE__);
283             $aRequiredFiles = array(
284                 $coreLibs  . '/Url.php',
285                 $coreLibs  . '/HTTP.php',
286                 $coreLibs  . '/Manager.php',
287                 $coreLibs  . '/Output.php',
288                 $coreLibs  . '/String.php',
289                 $coreLibs  . '/Task/Process.php',
290                 $coreLibs  . '/Session.php',
291                 $coreLibs  . '/Util.php',
292                 $coreLibs  . '/Config.php',
293                 $coreLibs  . '/ParamHandler.php',
294                 $coreLibs  . '/Registry.php',
295                 $coreLibs  . '/Request.php',
296                 $coreLibs  . '/Inflector.php',
297                 $coreLibs  . '/Date.php',
298                 $coreLibs  . '/Array.php',
299                 $coreLibs  . '/Error.php',
300                 $coreLibs  . '/Cache.php',
301                 $coreLibs  . '/DB.php',
302                 $coreLibs  . '/BlockLoader.php',
303                 $coreLibs  . '/Translation.php',
304                 $coreLibs  . '/../data/ary.languages.php',
305             );
306             $fileCache = '';
307             foreach ($aRequiredFiles as $file) {
308                 require_once $file;
309                 if ($cachedLibsEnabled) {
310                     // 270kb vs 104kb
311                     $fileCache .= php_strip_whitespace($file);
312                 }
313             }
314             if ($cachedLibsEnabled) {
315                 $ok = file_put_contents($cachedLibs, $fileCache);
316             }
317         }
318         require_once 'PEAR.php';
319         require_once 'DB.php';
320     }
321
322     public static function setupMinimumEnv()
323     {
324         $init = new SGL_TaskRunner();
325         $init->addTask(new SGL_Task_EnsureFC());
326         $init->addTask(new SGL_Task_SetupPaths());
327         $init->addTask(new SGL_Task_SetupConstantsStart());
328         $init->main();
329     }
330 }
331
332 /**
333  * Abstract request processor.
334  *
335  * @abstract
336  * @package SGL
337  *
338  */
339 class SGL_ProcessRequest
340 {
341     function process(/*SGL_Registry*/ $input, /*SGL_Output*/ $output) {}
342 }
343
344 /**
345  * Decorator.
346  *
347  * @abstract
348  * @package SGL
349  */
350 class SGL_DecorateProcess extends SGL_ProcessRequest
351 {
352     var $processRequest;
353
354     function SGL_DecorateProcess(/* SGL_ProcessRequest */ $pr)
355     {
356         $this->processRequest = $pr;
357     }
358 }
359
360 /**
361  * Core data processing routine.
362  *
363  * @package SGL
364  * @author  Demian Turner <demian@phpkitchen.com>
365  */
366 class SGL_MainProcess extends SGL_ProcessRequest
367 {
368     function process($input, $output)
369     {
370         SGL::logMessage(null, PEAR_LOG_DEBUG);
371
372         $req  = $input->getRequest();
373         $mgr  = $input->get('manager');
374
375         $mgr->validate($req, $input);
376         $input->aggregate($output);
377
378         //  process data if valid
379         if ($mgr->isValid()) {
380             $ok = $mgr->process($input, $output);
381             if (SGL_Error::count() && SGL_Session::getRoleId() != SGL_ADMIN
382                     && SGL_Config::get('debug.production')) {
383                 $mgr->handleError(SGL_Error::getLast(), $output);
384             }
385         }
386         SGL_Manager::display($output);
387         $mgr->display($output);
388     }
389 }
390 ?>
Note: See TracBrowser for help on using the browser.