eGroupWare PHP Cross Reference Groupware Applications

Source: /phpgwapi/inc/class.egw.inc.php - 722 lines - 23794 bytes - Summary - Text - Print

Description: eGroupWare API - Applications

   1  <?php
   2  /**
   3   * eGroupWare API - Applications
   4   *
   5   * @link http://www.egroupware.org
   6   * This file was originaly written by Dan Kuykendall and Joseph Engo
   7   * Copyright (C) 2000, 2001 Dan Kuykendall
   8   * Parts Copyright (C) 2003 Free Software Foundation
   9   * @author    RalfBecker@outdoor-training.de
  10   * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
  11   * @package api
  12   * @version $Id$
  13   */
  14  
  15  /**
  16   * New written class to create the eGW enviroment AND restore it from a php-session
  17   *
  18   * Rewritten by RalfBecker@outdoor-training.de to store the eGW enviroment
  19   * (egw-object and egw_info-array) in a php-session and restore it from
  20   * there instead of creating it completly new on each page-request.
  21   * The enviroment gets now created by the egw-class
  22   *
  23   * Use now a php5 getter method to create the usuall subobject on demand, to allow a quicker
  24   * header include on sites not useing php4-restore.
  25   * This also makes a lot of application code, like the following, unnecessary:
  26   * if (!is_object($GLOBALS['egw']->datetime)
  27   * {
  28   *         $GLOBALS['egw']->datetime = CreateObject('phpgwapi.datetime');
  29   * }
  30   * You can now simply use $GLOBALS['egw']->datetime, and the egw class instanciates it for you on demand.
  31   */
  32  class egw extends egw_minimal
  33  {
  34      /**
  35       * Turn on debug mode. Will output additional data for debugging purposes.
  36       * @var    string
  37       * @access    public
  38       */
  39      var $debug = 0;        // This will turn on debugging information.
  40      /**
  41       * Instance of the account object
  42       *
  43       * @var accounts
  44       */
  45      var $accounts;
  46      /**
  47       * Instace of the common object
  48       *
  49       * @var common
  50       */
  51      var $common;
  52      /**
  53       * Instace of the hooks object
  54       *
  55       * @var hooks
  56       */
  57      var $hooks;
  58  
  59      /**
  60       * Constructor: Instantiates the sub-classes
  61       *
  62       * @author RalfBecker@outdoor-training.de
  63       * @param array $domain_names array with valid egw-domain names
  64       */
  65  	function __construct($domain_names=null)
  66      {
  67          $GLOBALS['egw'] =& $this;    // we need to be immediately available there for the other classes we instantiate
  68          // for the migration: reference us to the old phpgw object
  69          $GLOBALS['phpgw'] =& $this;
  70          $this->setup($domain_names,True);
  71      }
  72  
  73      /**
  74       * Called every time the constructor is called.  Also called by sessions to ensure the correct db,
  75       *  in which case we do not recreate the session object.
  76       * @author RalfBecker@outdoor-training.de (moved to setup() by milos@groupwhere.org
  77       * @param array $domain_names array with valid egw-domain names
  78       * @param boolean $createsessionobject True to create the session object (default=True)
  79       */
  80  	function setup($domain_names,$createsessionobject=True)
  81      {
  82          // create the DB-object
  83          $this->db = new egw_db($GLOBALS['egw_info']['server']);
  84          if ($this->debug)
  85          {
  86              $this->db->Debug = 1;
  87          }
  88          $this->db->set_app('phpgwapi');
  89  
  90          // check if eGW is already setup, if not redirect to setup/
  91          try {
  92              $this->db->connect();
  93              $num_config = $this->db->select(config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
  94          }
  95          catch(egw_exception_db_connection $e) {
  96              // ignore exception, get handled below
  97          }
  98          catch(egw_exception_db_invalid_sql $e1) {
  99              unset($e1);    // not used
 100              try {
 101                  $phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
 102              }
 103              catch (egw_exception_db_invalid_sql $e2) {
 104                  unset($e2);    // not used
 105                  // ignor error, get handled below
 106              }
 107          }
 108          if (!$num_config)
 109          {
 110              // we check for the old table too, to not scare updating users ;-)
 111              if ($phpgw_config)
 112              {
 113                  throw new Exception('You need to update EGroupware before you can continue using it.',999);
 114              }
 115              if ($e)
 116              {
 117                  throw new egw_exception_db_setup('Connection with '.$e->getMessage()."\n\n".
 118                      'Maybe you not created a database for EGroupware yet.',999);
 119              }
 120              throw new egw_exception_db_setup('It appears that you have not created the database tables for EGroupware.',999);
 121          }
 122          // Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in config::read)
 123          foreach($this->db->select(config::TABLE,'config_name,config_value',array(
 124              'config_app'  => 'phpgwapi',
 125              'config_name' => array('system_charset','install_id','temp_dir'),
 126          ),__LINE__,__FILE__) as $row)
 127          {
 128              $GLOBALS['egw_info']['server'][$row['config_name']] = $row['config_value'];
 129          }
 130          if ($GLOBALS['egw_info']['server']['system_charset'] && $GLOBALS['egw_info']['server']['system_charset'] != 'utf-8')
 131          {
 132              $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
 133          }
 134          // load up the $GLOBALS['egw_info']['server'] array
 135          $GLOBALS['egw_info']['server'] += config::read('phpgwapi');
 136  
 137          // if no server timezone set, use date_default_timezone_get() to determine it once
 138          // it fills to log with deprecated warnings under 5.3 otherwise
 139          if (empty($GLOBALS['egw_info']['server']['server_timezone']) ||
 140              $GLOBALS['egw_info']['server']['server_timezone'] == 'System/Localtime')    // treat invalid tz like empty!
 141          {
 142              try
 143              {
 144                  $tz = new DateTimeZone(date_default_timezone_get());
 145                  config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
 146                  error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']);
 147              }
 148              catch(Exception $e)
 149              {
 150                  // do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
 151                  error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
 152              }
 153          }
 154          date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
 155  
 156          // setup the other subclasses
 157          // translation class is here only for backward compatibility, as all it's methods can be called static now
 158          $this->translation    = new translation();
 159          $this->common         = new common();
 160          $this->accounts       = accounts::getInstance();
 161          $this->acl            = new acl();
 162          // we instanciate the hooks object here manually, to cache it's hooks in the session
 163          $this->hooks          = new hooks();
 164          /* Do not create the session object if called by the sessions class.  This way
 165           * we ensure the correct db based on the user domain.
 166           */
 167          if($createsessionobject)
 168          {
 169              $this->session    = new egw_session($domain_names);
 170          }
 171          $this->preferences    = new preferences();
 172          $this->applications   = new applications();
 173  
 174          if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
 175          {
 176              $this->verify_session();
 177              $this->applications->read_installed_apps();    // to get translated app-titles, has to be after verify_session
 178  
 179              $this->define_egw_constants();
 180  
 181              $this->check_app_rights();
 182  
 183              $this->load_optional_classes();
 184          }
 185          else    // set the defines for login, in case it's more then just login
 186          {
 187              $this->define_egw_constants();
 188          }
 189      }
 190  
 191      /**
 192       * __wakeup function gets called by php while unserializing the egw-object, eg. reconnects to the DB
 193       *
 194       * @author RalfBecker@outdoor-training.de
 195       */
 196  	function __wakeup()
 197      {
 198          $GLOBALS['egw'] =& $this;    // we need to be immediately available there for the other classes we instantiate
 199          // for the migration: reference us to the old phpgw object
 200          $GLOBALS['phpgw'] =& $this;
 201  
 202          if ($GLOBALS['egw_info']['server']['system_charset'])
 203          {
 204              $this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
 205          }
 206          // restoring server timezone, to avoid warnings under php5.3
 207          if (!empty($GLOBALS['egw_info']['server']['server_timezone']))
 208          {
 209              date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
 210          }
 211  
 212          $this->define_egw_constants();
 213      }
 214  
 215      /**
 216       * wakeup2 function needs to be called after unserializing the egw-object
 217       *
 218       * It adapts the restored object/enviroment to the changed (current) application / page-request
 219       *
 220       * @author RalfBecker@outdoor-training.de
 221       */
 222  	function wakeup2()
 223      {
 224          // do some application specific stuff, need to be done as we are different (current) app now
 225          if (isset($this->template))
 226          {
 227              $this->template->set_root(EGW_APP_TPL);
 228          }
 229          // init the translation class, necessary as own wakeup would run before our's
 230          translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
 231  
 232          $this->unset_datetime();
 233  
 234          // verify the session
 235          $GLOBALS['egw']->verify_session();
 236          $GLOBALS['egw']->check_app_rights();
 237  
 238          $this->load_optional_classes();
 239      }
 240  
 241      /**
 242       * Unsetting datetime object, so time gets updated
 243       */
 244  	function unset_datetime()
 245      {
 246          unset($this->datetime);
 247      }
 248  
 249      /**
 250       * load optional classes by mentioning them in egw_info[flags][enable_CLASS_class] => true
 251       *
 252       * Also loads the template-class if not egw_info[flags][disable_Template_class] is set
 253       *
 254       * Maybe the whole thing should be depricated ;-)
 255       */
 256  	function load_optional_classes()
 257      {
 258          // output the header unless the developer turned it off
 259          if (!@$GLOBALS['egw_info']['flags']['noheader'])
 260          {
 261              common::egw_header();
 262          }
 263  
 264          // Load the (depricated) app include files if they exists
 265          if (EGW_APP_INC != "" && ! preg_match ('/phpgwapi/i', EGW_APP_INC) &&
 266          file_exists(EGW_APP_INC . '/functions.inc.php') && !isset($_GET['menuaction']))
 267          {
 268              include (EGW_APP_INC . '/functions.inc.php');
 269          }
 270          if (!@$GLOBALS['egw_info']['flags']['noheader'] && !@$GLOBALS['egw_info']['flags']['noappheader'] &&
 271          file_exists(EGW_APP_INC . '/header.inc.php') && !isset($_GET['menuaction']))
 272          {
 273              include(EGW_APP_INC . '/header.inc.php');
 274          }
 275      }
 276  
 277      /**
 278       * Verfiy there is a valid session
 279       *
 280       * One can specify a callback, which gets called if there's no valid session. If the callback returns true, the parameter
 281       * containst account-details (in keys login, passwd and passwd_type) to automatic create an (anonymous session)
 282       *
 283       * It also checks if enforce_ssl is set in the DB and redirects to the https:// version of the site.
 284       *
 285       * If there is no valid session and none could be automatic created, the function will redirect to login and NOT return
 286       */
 287  	function verify_session()
 288      {
 289          if($GLOBALS['egw_info']['server']['enforce_ssl'] === 'redirect' && !$_SERVER['HTTPS'])
 290          {
 291              Header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
 292              exit;
 293          }
 294          // check if we have a session, if not try to automatic create one
 295          if ($this->session->verify()) return true;
 296  
 297          $account = null;
 298          if (($account_callback = $GLOBALS['egw_info']['flags']['autocreate_session_callback']) && is_callable($account_callback) &&
 299              ($sessionid = call_user_func_array($account_callback,array(&$account))) === true)    // $account_call_back returns true, false or a session-id
 300          {
 301              $sessionid = $this->session->create($account);
 302          }
 303          if (!$sessionid)
 304          {
 305              //echo "<p>account_callback='$account_callback', account=".print_r($account,true).", sessionid=$sessionid</p>\n"; exit;
 306              // we forward to the same place after the re-login
 307              if ($GLOBALS['egw_info']['server']['webserver_url'] && $GLOBALS['egw_info']['server']['webserver_url'] != '/' &&
 308                  ($webserver_path = parse_url($GLOBALS['egw_info']['server']['webserver_url'],PHP_URL_PATH)) && $webserver_path != '/')
 309              {
 310                  // we have to use only path component, to cope with domains like http://egroupware.domain.com and /egroupware
 311                  list(,$relpath) = explode($webserver_path,parse_url($_SERVER['PHP_SELF'],PHP_URL_PATH),2);
 312              }
 313              else    // the webserver-url is empty or just a slash '/' (eGW is installed in the docroot and no domain given)
 314              {
 315                  $matches = null;
 316                  if (preg_match('/^https?:\/\/[^\/]*\/(.*)$/',$relpath=$_SERVER['PHP_SELF'],$matches))
 317                  {
 318                      $relpath = $matches[1];
 319                  }
 320              }
 321              // this removes the sessiondata if its saved in the URL
 322              $query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']);
 323              if ($GLOBALS['egw_info']['server']['http_auth_types'])
 324              {
 325                  $redirect = '/phpgwapi/ntlm/index.php?';
 326              }
 327              else
 328              {
 329                  $redirect = '/login.php?';
 330                  // only add "your session could not be verified", if a sessionid is given (cookie or on url)
 331                  if (egw_session::get_sessionid()) $redirect .= 'cd=10&';
 332              }
 333              if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : ''));
 334              self::redirect_link($redirect);
 335          }
 336      }
 337  
 338      /**
 339       * Verify the user has rights for the requested app
 340       *
 341       * If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return)
 342       *
 343       * @throws egw_exception_redirect for anonymous user accessing something he has no rights to
 344       * @throws egw_exception_no_permission_admin
 345       * @throws egw_exception_no_permission_app
 346       */
 347  	function check_app_rights()
 348      {
 349          $this->currentapp = $GLOBALS['egw_info']['flags']['currentapp'];    // some apps change it later
 350  
 351          if ($GLOBALS['egw_info']['flags']['currentapp'] != 'home')    // give everyone implicit home rights
 352          {
 353              // This will need to use ACL in the future
 354              if (!$GLOBALS['egw_info']['user']['apps'][$currentapp = $GLOBALS['egw_info']['flags']['currentapp']] ||
 355                  ($GLOBALS['egw_info']['flags']['admin_only'] && !$GLOBALS['egw_info']['user']['apps']['admin']))
 356              {
 357                  // present a login page, if anon user has no right for an application
 358                  if ($this->session->session_flags == 'A')
 359                  {
 360                      // need to destroy a basic auth session here, because it will only be available on current url
 361                      if (($sessionid = egw_session::get_sessionid(true)))
 362                      {
 363                          $GLOBALS['egw']->session->destroy($sessionid);
 364                      }
 365                      throw new egw_exception_redirect(egw::link('/logout.php'));
 366                  }
 367                  if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only'])
 368                  {
 369                      throw new egw_exception_no_permission_admin();
 370                  }
 371                  throw new egw_exception_no_permission_app($currentapp);
 372              }
 373          }
 374      }
 375  
 376      /**
 377       * create all the defines / constants of the eGW-environment (plus the deprecated phpgw ones)
 378       */
 379  	function define_egw_constants()
 380      {
 381          define('EGW_ACL_READ',1);
 382          define('EGW_ACL_ADD',2);
 383          define('EGW_ACL_EDIT',4);
 384          define('EGW_ACL_DELETE',8);
 385          define('EGW_ACL_PRIVATE',16);
 386          define('EGW_ACL_GROUP_MANAGERS',32);
 387          define('EGW_ACL_CUSTOM_1',64);
 388          define('EGW_ACL_CUSTOM_2',128);
 389          define('EGW_ACL_CUSTOM_3',256);
 390          // and the old ones
 391          define('PHPGW_ACL_READ',1);
 392          define('PHPGW_ACL_ADD',2);
 393          define('PHPGW_ACL_EDIT',4);
 394          define('PHPGW_ACL_DELETE',8);
 395          define('PHPGW_ACL_PRIVATE',16);
 396          define('PHPGW_ACL_GROUP_MANAGERS',32);
 397          define('PHPGW_ACL_CUSTOM_1',64);
 398          define('PHPGW_ACL_CUSTOM_2',128);
 399          define('PHPGW_ACL_CUSTOM_3',256);
 400          // A few hacker resistant constants that will be used throught the program
 401          define('EGW_TEMPLATE_DIR', $this->common->get_tpl_dir('phpgwapi'));
 402          define('EGW_IMAGES_DIR', $this->common->get_image_path('phpgwapi'));
 403          define('EGW_IMAGES_FILEDIR', $this->common->get_image_dir('phpgwapi'));
 404          define('EGW_APP_ROOT', $this->common->get_app_dir());
 405          define('EGW_APP_INC', $this->common->get_inc_dir());
 406          define('EGW_APP_TPL', $this->common->get_tpl_dir());
 407          define('EGW_IMAGES', $this->common->get_image_path());
 408          define('EGW_APP_IMAGES_DIR', $this->common->get_image_dir());
 409          // and the old ones
 410          define('PHPGW_TEMPLATE_DIR',EGW_TEMPLATE_DIR);
 411          define('PHPGW_IMAGES_DIR',EGW_IMAGES_DIR);
 412          define('PHPGW_IMAGES_FILEDIR',EGW_IMAGES_FILEDIR);
 413          define('PHPGW_APP_ROOT',EGW_APP_ROOT);
 414          define('PHPGW_APP_INC',EGW_APP_INC);
 415          define('PHPGW_APP_TPL',EGW_APP_TPL);
 416          define('PHPGW_IMAGES',EGW_IMAGES);
 417          define('PHPGW_APP_IMAGES_DIR',EGW_APP_IMAGES_DIR);
 418      }
 419  
 420      /**
 421       * force the session cache to be re-created, because some of it's data changed
 422       *
 423       * Needs to be called if user-preferences, system-config or enabled apps of the current user have been changed and
 424       * the change should have immediate effect
 425       */
 426  	static function invalidate_session_cache()
 427      {
 428          unset($_SESSION['egw_info_cache']);
 429          unset($_SESSION['egw_object_cache']);
 430      }
 431  
 432      /**
 433       * run string through htmlspecialchars and stripslashes
 434       *
 435       * @param string $s
 436       * @return string The string with html special characters replaced with entities
 437       */
 438  	static function strip_html($s)
 439      {
 440          return htmlspecialchars(stripslashes($s));
 441      }
 442  
 443      /**
 444       * Link url generator
 445       *
 446       * @param string $url url link is for
 447       * @param string|array $extravars ='' extra params to be added to url
 448       * @param string $link_app =null if appname or true, some templates generate a special link-handler url
 449       * @return string    The full url after processing
 450       */
 451  	static function link($url, $extravars = '', $link_app=null)
 452      {
 453          return $GLOBALS['egw']->framework->link($url, $extravars, $link_app);
 454      }
 455  
 456      /**
 457       * Redirects direct to a generated link
 458       *
 459       * @param string $url url link is for
 460       * @param string|array $extravars ='' extra params to be added to url
 461       * @param string $link_app =null if appname or true, some templates generate a special link-handler url
 462       * @return string    The full url after processing
 463       */
 464  	static function redirect_link($url, $extravars='', $link_app=null)
 465      {
 466          return $GLOBALS['egw']->framework->redirect_link($url, $extravars, $link_app);
 467      }
 468  
 469      /**
 470       * Handles redirects under iis and apache, it does NOT return (calls exit)
 471       *
 472       * This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called
 473       *
 474       * @param string $url url to redirect to
 475       * @param string $link_app =null appname to redirect for, default currentapp
 476       */
 477  	static function redirect($url, $link_app=null)
 478      {
 479          // Determines whether the current output buffer should be flushed
 480          $do_flush = true;
 481  
 482          if (egw_json_response::isJSONResponse() || egw_json_request::isJSONRequest())
 483          {
 484              $response = egw_json_response::get();
 485              $response->redirect($url, false, $link_app);
 486  
 487              // If we are in a json request, we should not flush the current output!
 488              $do_flush = false;
 489          }
 490          else
 491          {
 492              $file = $line = null;
 493              if (headers_sent($file,$line))
 494              {
 495                  throw new egw_exception_assertion_failed(__METHOD__."('".htmlspecialchars($url)."') can NOT redirect, output already started at $file line $line!");
 496              }
 497              if ($GLOBALS['egw']->framework instanceof jdots_framework && !empty($link_app))
 498              {
 499                  egw_framework::set_extra('egw', 'redirect', array($url, $link_app));
 500                  $GLOBALS['egw']->framework->render('');
 501              }
 502              else
 503              {
 504                  Header("Location: $url");
 505                  print("\n\n");
 506              }
 507          }
 508  
 509          if ($do_flush)
 510          {
 511              @ob_flush(); flush();
 512          }
 513  
 514          // commit session (if existing), to fix timing problems sometimes preventing session creation ("Your session can not be verified")
 515          if (isset($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
 516  
 517          exit;
 518      }
 519  
 520      /**
 521       * Shortcut to translation class
 522       *
 523       * This function is a basic wrapper to translation::translate()
 524       *
 525       * @deprecated only used in the old timetracker
 526       * @param  string    The key for the phrase
 527       * @see    translation::translate()
 528       */
 529  	static function lang($key,$args=null)
 530      {
 531          if (!is_array($args))
 532          {
 533              $args = func_get_args();
 534              array_shift($args);
 535          }
 536          return translation::translate($key,$args);
 537      }
 538  
 539      /**
 540       * registered shutdown callbacks and optional arguments
 541       *
 542       * @var array
 543       */
 544      private static $shutdown_callbacks = array();
 545  
 546      /**
 547       * Register a callback to run on shutdown AFTER output send to user
 548       *
 549       * Allows eg. static classes (no destructor) to run on shutdown AND
 550       * garanties to run AFTER output send to user.
 551       *
 552       * @param callable $callback use array($classname, $method) for static methods
 553       * @param array $args =array()
 554       */
 555  	public static function on_shutdown($callback, array $args=array())
 556      {
 557          array_unshift($args, $callback);
 558  
 559          // prepend new callback, to run them in oposite order they are registered
 560          array_unshift(self::$shutdown_callbacks, $args);
 561      }
 562  
 563      /**
 564       * Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db
 565       */
 566  	function __destruct()
 567      {
 568          if (!defined('EGW_SHUTDOWN'))
 569          {
 570              define('EGW_SHUTDOWN',True);
 571  
 572              // send json response BEFORE flushing output
 573              if (egw_json_request::isJSONRequest())
 574              {
 575                  egw_json_response::sendResult();
 576              }
 577  
 578              // run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions
 579              foreach(self::$shutdown_callbacks as $n => $data)
 580              {
 581                  try {
 582                      //error_log(__METHOD__."() running ".array2string($data));
 583                      $callback = array_shift($data);
 584                      if (!is_array($callback) || strpos($callback[1], 'session') === false) continue;
 585                      call_user_func_array($callback, $data);
 586                  }
 587                  catch (Exception $ex) {
 588                      _egw_log_exception($ex);
 589                  }
 590                  unset(self::$shutdown_callbacks[$n]);
 591              }
 592              // now we can close the session
 593              // without closing the session fastcgi_finish_request() will NOT send output to user
 594              if (isset($GLOBALS['egw']->session) && is_object($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
 595  
 596              // flush all output to user
 597              /* does NOT work on Apache :-(
 598              for($i = 0; ob_get_level() && $i < 10; ++$i)
 599              {
 600                  ob_end_flush();
 601              }
 602              flush();*/
 603              // working for fastCGI :-)
 604              if (function_exists('fastcgi_finish_request') && substr($_SERVER['PHP_SELF'], -32) != '/phpgwapi/cron/asyncservices.php')
 605              {
 606                  fastcgi_finish_request();
 607              }
 608  
 609              // run all on_shutdown, do NOT stop on exceptions
 610              foreach(self::$shutdown_callbacks as $data)
 611              {
 612                  try {
 613                      //error_log(__METHOD__."() running ".array2string($data));
 614                      $callback = array_shift($data);
 615                      call_user_func_array($callback, $data);
 616                  }
 617                  catch (Exception $ex) {
 618                      _egw_log_exception($ex);
 619                  }
 620              }
 621              // call the asyncservice check_run function if it is not explicitly set to cron-only
 622              if (!$GLOBALS['egw_info']['server']['asyncservice'])    // is default
 623              {
 624                  ExecMethod('phpgwapi.asyncservice.check_run','fallback');
 625              }
 626              $this->db->disconnect();
 627          }
 628      }
 629  }
 630  
 631  /**
 632   * Minimal eGW object used in setup, does not instanciate anything by default
 633   *
 634   */
 635  class egw_minimal
 636  {
 637      /**
 638       * Instance of the db-object
 639       *
 640       * @var egw_db
 641       */
 642      var $db;
 643      /**
 644       * Current app at the instancation of the class
 645       *
 646       * @var string
 647       */
 648      var $currentapp;
 649      /**
 650       * Global ADOdb object, need to be defined here, to not call magic __get method
 651       *
 652       * @var ADOConnection
 653       */
 654      var $ADOdb;
 655  
 656      /**
 657       * Classes which get instanciated in a different name
 658       *
 659       * @var array
 660       */
 661      static $sub_objects = array(
 662          'log' => 'errorlog',
 663  //        'js'  => 'javascript',
 664          'link' => 'bolink',        // depricated use static egw_link methods
 665          'datetime' => 'egw_datetime',
 666  //        'session' => 'sessions',
 667          'session' => 'egw_session',
 668          'framework' => true,    // special handling in __get()
 669          'template' => 'Template',
 670      );
 671  
 672      /**
 673       * Magic function to check if a sub-object is set
 674       *
 675       * @param string $name
 676       * @return boolean
 677       */
 678  	function __isset($name)
 679      {
 680          //error_log(__METHOD__."($name)");
 681          return isset($this->$name);
 682      }
 683  
 684      /**
 685       * Magic function to return a sub-object
 686       *
 687       * @param string $name
 688       * @return mixed
 689       */
 690  	function __get($name)
 691      {
 692          //error_log(__METHOD__."($name)".function_backtrace());
 693  
 694          if ($name == 'js') $name = 'framework';    // javascript class is integrated now into framework
 695  
 696          if (isset($this->$name))
 697          {
 698              return $this->$name;
 699          }
 700  
 701          if (!isset(self::$sub_objects[$name]) && !class_exists($name))
 702          {
 703              if ($name != 'ADOdb') error_log(__METHOD__.": There's NO $name object! ".function_backtrace());
 704              return null;
 705          }
 706          switch($name)
 707          {
 708              case 'framework':
 709                  return $this->framework = egw_framework::factory();
 710              case 'template':    // need to be instancated for the current app
 711                  if (!($tpl_dir = common::get_tpl_dir($this->currentapp)))
 712                  {
 713                      return null;
 714                  }
 715                  return $this->template = new Template($tpl_dir);
 716              default:
 717                  $class = isset(self::$sub_objects[$name]) ? self::$sub_objects[$name] : $name;
 718                  break;
 719          }
 720          return $this->$name = new $class();
 721      }
 722  }

title

Description

title

Description

title

Description

title

title

Body