merge filemanager
[tine20] / tine20 / Setup / Core.php
1 <?php
2 /**
3  * Tine 2.0
4  * 
5  * @package     Setup
6  * @subpackage  Server
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
9  * @author      Philipp Schuele <p.schuele@metaways.de>
10  *
11  */
12
13 /**
14  * dispatcher and initialisation class (functions are static)
15  * - dispatchRequest() function
16  * - initXYZ() functions 
17  * - has registry and config
18  * 
19  * @package     Setup
20  */
21 class Setup_Core extends Tinebase_Core
22 {
23     /**
24      * constant for config registry index
25      *
26      */
27     const CHECKDB = 'checkDB';    
28
29     /**
30      * init setup framework
31      */
32     public static function initFramework()
33     {
34         Setup_Core::setupConfig();
35         
36         Setup_Core::setupTempDir();
37                 
38         // Server Timezone must be setup before logger, as logger has timehandling!
39         Setup_Core::setupServerTimezone();
40
41         Setup_Core::setupLogger();
42
43         //Database Connection must be setup before cache because setupCache uses constant "SQL_TABLE_PREFIX"
44         Setup_Core::setupDatabaseConnection();
45
46         Setup_Core::setupStreamWrapper();
47         
48         //Cache must be setup before User Locale because otherwise Zend_Locale tries to setup 
49         //its own cache handler which might result in a open_basedir restriction depending on the php.ini settings 
50         Setup_Core::setupCache();
51
52         Setup_Core::setupSession();
53         
54         // setup a temporary user locale/timezone. This will be overwritten later but we 
55         // need to handle exceptions during initialisation process such as seesion timeout
56         Setup_Core::set('locale', new Zend_Locale('en_US'));
57         Setup_Core::set('userTimeZone', 'UTC');
58         
59         Setup_Core::setupUserLocale();
60         
61         header('X-API: http://www.tine20.org/apidocs/tine20/');
62     }
63     
64     /**
65      * dispatch request
66      *
67      */
68     public static function dispatchRequest()
69     {
70         // disable magic_quotes_runtime
71         ini_set('magic_quotes_runtime', 0);
72         
73         // display errors we can't handle ourselves
74         error_reporting(E_COMPILE_ERROR | E_CORE_ERROR | E_ERROR | E_PARSE);
75         ini_set('display_errors', 1);
76         
77         ini_set('log_errors', 1);
78         set_error_handler('Tinebase_Core::errorHandler', E_ALL);
79         
80         // set default internal encoding
81         ini_set('iconv.internal_encoding', 'utf-8');
82         
83         $server = NULL;
84         
85         /**************************** JSON API *****************************/
86
87         if ( (isset($_SERVER['HTTP_X_TINE20_REQUEST_TYPE']) && $_SERVER['HTTP_X_TINE20_REQUEST_TYPE'] == 'JSON')  || 
88              (isset($_POST['requestType']) && $_POST['requestType'] == 'JSON')
89            ) {
90             $server = new Setup_Server_Json();
91
92         /**************************** CLI API *****************************/
93         
94         } elseif (php_sapi_name() == 'cli') {
95             $server = new Setup_Server_Cli();
96             
97         /**************************** HTTP API ****************************/
98         
99         } else {
100             $server = new Setup_Server_Http();
101         }        
102         
103         $server->handle();
104     }
105     
106     /**
107      * setups global config
108      * 
109      * NOTE a config object will be intanciated regardless of the existance of 
110      *      the conffile!
111      *
112      * @return void
113      */
114     public static function setupConfig()
115     {
116         if(self::configFileExists()) {
117             $config = new Zend_Config(require self::getConfigFilePath());
118         } else {
119             $config = new Zend_Config(array());
120         }
121         self::set(self::CONFIG, $config);  
122     }
123     
124     /**
125      * checks if global config file exists
126      *
127      * @return bool
128      */
129     public static function configFileExists()
130     {
131         return (bool)self::getConfigFilePath();
132     }
133     
134     /**
135      * Searches for config.inc.php in include paths and returnes the first match
136      *
137      * @return String
138      */
139     public static function getConfigFilePath()
140     {
141         $includePaths = explode(PATH_SEPARATOR, get_include_path());
142         foreach ($includePaths as $includePath) {
143             $path = $includePath . '/config.inc.php';
144             if (file_exists($path)) {
145                 return $path;
146             }
147         }
148
149         return null;
150     }
151
152     /**
153      * checks if global config file or tine root is writable
154      *
155      * @return bool
156      */
157     public static function configFileWritable()
158     {        
159         if (self::configFileExists()) {
160             $configFilePath = self::getConfigFilePath();
161             return is_writable($configFilePath);
162         } else {
163             $path = dirname(dirname(__FILE__));
164             $testfilename = $path . DIRECTORY_SEPARATOR . uniqid(mt_rand()).'.tmp';
165             if (!($f = @fopen($testfilename, 'w'))) {
166                 error_log(__METHOD__ . '::' . __LINE__ . ' Your tine root dir ' . $path . ' is not writable for the webserver! Config file can\'t be created.');
167                 return false;
168             }
169             fclose($f);
170             unlink($testfilename);
171             return true;
172         }
173     }
174     
175     /**
176      * initializes the database connection
177      *
178      * @throws  Tinebase_Exception_UnexpectedValue
179      * 
180      * @todo try to write to db, if it fails: self::set(Setup_Core::CHECKDB, FALSE);
181      */
182     public static function setupDatabaseConnection()
183     {
184         self::set(Setup_Core::CHECKDB, FALSE);
185         
186         // check database first
187         if (self::configFileExists()) {
188             $dbConfig = Tinebase_Core::getConfig()->database;
189             
190             if ($dbConfig->adapter === self::PDO_MYSQL && (! defined(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY) || ! defined(PDO::MYSQL_ATTR_INIT_COMMAND))) {
191                 Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
192                     . ' MySQL PDO constants not defined.');
193
194                 return;
195             }
196             
197             try {
198                 parent::setupDatabaseConnection();
199                 
200                 $serverVersion = self::getDb()->getServerVersion();
201                 
202                 switch($dbConfig->adapter) {
203                     case self::PDO_MYSQL:
204                         if (version_compare(self::MYSQL_MINIMAL_VERSION, $serverVersion, '<')) {
205
206                             self::set(Setup_Core::CHECKDB, TRUE);
207                         } else {
208                             Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
209                                 . ' MySQL server version incompatible! ' . $serverVersion
210                                 . ' < ' . self::MYSQL_MINIMAL_VERSION
211                             );
212                         }
213                         break;
214                         
215                     case self::PDO_PGSQL:
216                         if (version_compare(self::PGSQL_MINIMAL_VERSION, $serverVersion, '<')) {
217                             self::set(Setup_Core::CHECKDB, TRUE);
218                         } else {
219                             Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
220                                 . ' PostgreSQL server version incompatible! ' . $serverVersion
221                                 . ' < ' . self::PGSQL_MINIMAL_VERSION
222                             );
223                         }
224                         break;
225                     
226                     default:
227                         //@todo check version requirements for other db adapters
228                         self::set(Setup_Core::CHECKDB, TRUE);
229                         break;
230                 }
231                 
232             } catch (Zend_Db_Adapter_Exception $zae) {
233                 Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $zae->getMessage());
234             }
235         }
236     }
237     
238     /**
239      * setups the logger
240      * 
241      * NOTE: if no logger is configured, we write to stderr in setup
242      *
243      * @param $_defaultWriter Zend_Log_Writer_Abstract default log writer
244      */
245     public static function setupLogger(Zend_Log_Writer_Abstract $_defaultWriter = NULL)
246     {
247         $writer = new Zend_Log_Writer_Stream('php://stderr');
248         parent::setupLogger($writer);
249     }
250     
251     /**
252      * initializes the session
253      */
254     public static function setupSession()
255     {
256         self::startSession(array(
257             'name'              => 'TINE20SETUPSESSID',
258         ), 'tinesetup');
259         
260         if (isset(self::get(self::SESSION)->setupuser)) {
261             self::set(self::USER, self::get(self::SESSION)->setupuser);
262         }
263
264         $config = self::getConfig();
265         define('TINE20_BUILDTYPE', strtoupper($config->get('buildtype', 'DEVELOPMENT')));
266         define('TINE20SETUP_CODENAME', getDevelopmentRevision());
267         define('TINE20SETUP_PACKAGESTRING', 'none');
268         define('TINE20SETUP_RELEASETIME', 'none');
269     }
270     
271     /**
272      * setup the cache and add it to zend registry
273      * 
274      * Ignores {@param $_enabled} and always sets it to false
275      *
276      */
277     public static function setupCache($_enabled = true)
278     {
279         // disable caching for setup
280         parent::setupCache(false);
281     }
282 }