806745d77d05490922cb260d168bfbc85fda8c5f
[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-2016 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         //Database Connection must be setup before cache because setupCache uses constant "SQL_TABLE_PREFIX"
39         Setup_Core::setupDatabaseConnection();
40         
41         Setup_Core::setupStreamWrapper();
42         
43         //Cache must be setup before User Locale because otherwise Zend_Locale tries to setup 
44         //its own cache handler which might result in a open_basedir restriction depending on the php.ini settings 
45         Setup_Core::setupCache();
46         
47         Setup_Core::setupBuildConstants();
48         
49         // setup a temporary user locale/timezone. This will be overwritten later but we 
50         // need to handle exceptions during initialisation process such as seesion timeout
51         Setup_Core::set('locale', new Zend_Locale('en_US'));
52         Setup_Core::set(Tinebase_Core::USERTIMEZONE, 'UTC');
53         
54         Setup_Core::setupUserLocale();
55         
56         header('X-API: http://www.tine20.org/apidocs/tine20/');
57     }
58     
59     /**
60      * startSetupSession
61      * 
62      * TODO remove redundancy with Tinebase_Core::startCoreSession()
63      */
64     public static function startSetupSession ()
65     {
66         Tinebase_Session::setSessionBackend();
67         
68         Zend_Session::start();
69         
70         $setupSession = Setup_Session::getSessionNamespace();
71         
72         if (isset($setupSession->setupuser)) {
73             self::set(self::USER, $setupSession->setupuser);
74         }
75         
76         if (!isset($setupSession->jsonKey)) {
77             $setupSession->jsonKey = Tinebase_Record_Abstract::generateUID();
78         }
79         self::set('jsonKey', $setupSession->jsonKey);
80     }
81     
82     /**
83      * dispatch request
84      *
85      * @see Tinebase_Core::dispatchRequest()
86      */
87     public static function dispatchRequest()
88     {
89         $request = new \Zend\Http\PhpEnvironment\Request();
90         self::set(self::REQUEST, $request);
91         
92         $server = NULL;
93         
94         /**************************** JSON API *****************************/
95         if ( (isset($_SERVER['HTTP_X_TINE20_REQUEST_TYPE']) && $_SERVER['HTTP_X_TINE20_REQUEST_TYPE'] == 'JSON')  || 
96              (isset($_POST['requestType']) && $_POST['requestType'] == 'JSON')
97            ) {
98             $server = new Setup_Server_Json();
99         
100         /**************************** CLI API *****************************/
101         } elseif (php_sapi_name() == 'cli') {
102             $server = new Setup_Server_Cli();
103         
104         /**************************** HTTP API ****************************/
105         } else {
106             $server = new Setup_Server_Http();
107         }
108         
109         $server->handle();
110     }
111     
112     /**
113      * setups global config
114      * 
115      * NOTE a config object will be instantiated regardless of the existance of 
116      *      the config file!
117      *
118      * @return void
119      */
120     public static function setupConfig()
121     {
122         if(self::configFileExists()) {
123             $config = new Zend_Config(require self::getConfigFilePath());
124         } else {
125             $config = new Zend_Config(array());
126         }
127         self::set(self::CONFIG, $config);
128     }
129     
130     /**
131      * checks if global config file exists
132      *
133      * @return bool
134      */
135     public static function configFileExists()
136     {
137         return (bool)self::getConfigFilePath();
138     }
139     
140     /**
141      * Searches for config.inc.php in include paths and returnes the first match
142      *
143      * @return String
144      */
145     public static function getConfigFilePath()
146     {
147         $includePaths = explode(PATH_SEPARATOR, get_include_path());
148         foreach ($includePaths as $includePath) {
149             $path = $includePath . '/config.inc.php';
150             if (file_exists($path)) {
151                 return $path;
152             }
153         }
154
155         return null;
156     }
157
158     /**
159      * checks if global config file or tine root is writable
160      *
161      * @return bool
162      */
163     public static function configFileWritable()
164     {
165         if (self::configFileExists()) {
166             $configFilePath = self::getConfigFilePath();
167             return is_writable($configFilePath);
168         } else {
169             $path = dirname(dirname(__FILE__));
170             $testfilename = $path . DIRECTORY_SEPARATOR . uniqid(mt_rand()).'.tmp';
171             if (!($f = @fopen($testfilename, 'w'))) {
172                 error_log(__METHOD__ . '::' . __LINE__ . ' Your tine root dir ' . $path . ' is not writable for the webserver! Config file can\'t be created.');
173                 return false;
174             }
175             fclose($f);
176             unlink($testfilename);
177             return true;
178         }
179     }
180     
181     /**
182      * initializes the database connection
183      * 
184      * @return boolean
185      * 
186      * @todo try to write to db, if it fails: self::set(Setup_Core::CHECKDB, FALSE);
187      */
188     public static function setupDatabaseConnection()
189     {
190         $dbcheck = FALSE;
191         
192         // check database first
193         if (self::configFileExists()) {
194             $dbConfig = Tinebase_Core::getConfig()->database;
195             
196             if ($dbConfig->adapter === self::PDO_MYSQL && (! defined(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY) || ! defined(PDO::MYSQL_ATTR_INIT_COMMAND))) {
197                 Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
198                     . ' MySQL PDO constants not defined.');
199                 return FALSE;
200             }
201             
202             try {
203                 parent::setupDatabaseConnection();
204                 
205                 $serverVersion = self::getDb()->getServerVersion();
206                 
207                 switch ($dbConfig->adapter) {
208                     case self::PDO_MYSQL:
209                         if (version_compare(self::MYSQL_MINIMAL_VERSION, $serverVersion, '<')) {
210                             $dbcheck = TRUE;
211                         } else {
212                             Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
213                                 . ' MySQL server version incompatible! ' . $serverVersion
214                                 . ' < ' . self::MYSQL_MINIMAL_VERSION
215                             );
216                         }
217                         break;
218                         
219                     case self::ORACLE:
220
221                         if (version_compare(self::ORACLE_MINIMAL_VERSION, $serverVersion, '<')) {
222                             self::set(Setup_Core::CHECKDB, TRUE);
223                         } else {
224                             Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
225                                 . ' Oracle server version incompatible! ' . $serverVersion
226                                 . ' < ' . self::ORACLE_MINIMAL_VERSION
227                             );
228                         }
229
230                         $dbcheck = TRUE;
231                         break;
232
233                     case self::PDO_PGSQL:
234                         if (version_compare(self::PGSQL_MINIMAL_VERSION, $serverVersion, '<')) {
235                             $dbcheck = TRUE;
236                         } else {
237                             Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ 
238                                 . ' PostgreSQL server version incompatible! ' . $serverVersion
239                                 . ' < ' . self::PGSQL_MINIMAL_VERSION
240                             );
241                         }
242                         break;
243                     
244                     default:
245                         // @todo check version requirements for other db adapters
246                         $dbcheck = TRUE;
247                         break;
248                 }
249                 
250             } catch (Zend_Db_Adapter_Exception $zae) {
251                 Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $zae->getMessage());
252             } catch (Zend_Db_Exception $zde) {
253                 Setup_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $zde->getMessage());
254             }
255         }
256         
257         self::set(Setup_Core::CHECKDB, $dbcheck);
258         return $dbcheck;
259     }
260     
261     /**
262      * setups the logger
263      * 
264      * NOTE: if no logger is configured, we write to stderr in setup
265      *
266      * @param $_defaultWriter Zend_Log_Writer_Abstract default log writer
267      */
268     public static function setupLogger(Zend_Log_Writer_Abstract $_defaultWriter = NULL)
269     {
270         $writer = new Zend_Log_Writer_Stream('php://stderr');
271         parent::setupLogger($writer);
272     }
273     
274     /**
275      * initializes the build constants like buildtype, package information, ...
276      */
277     public static function setupBuildConstants()
278     {
279         $config = self::getConfig();
280         define('TINE20_BUILDTYPE',           strtoupper($config->get('buildtype', 'DEVELOPMENT')));
281         define('TINE20SETUP_CODENAME',       Tinebase_Helper::getDevelopmentRevision());
282         define('TINE20SETUP_PACKAGESTRING', 'none');
283         define('TINE20SETUP_RELEASETIME',   'none');
284     }
285     
286     /**
287      * setup the cache and add it to zend registry
288      * 
289      * Ignores {@param $_enabled} and always sets it to false
290      *
291      */
292     public static function setupCache($_enabled = true)
293     {
294         // disable caching for setup
295         parent::setupCache(false);
296     }
297 }