* @copyright Copyright © 2006 Peter Adams * @license http://www.gnu.org/copyleft/gpl.html GPL v2.0 * @category owa * @package owa * @version $Revision$ * @since owa 1.0.0 */ class owa_settings { /** * Configuration Entity * * @var object configuration entity */ var $config; var $default_config; var $db_settings = array(); var $fetched_from_db; var $is_dirty; var $config_id; var $config_from_db; /** * Constructor * * @param string id the id of the configuration array to load */ function __construct() { // create configuration object $this->config = owa_coreAPI::entityFactory('base.configuration'); // load the default settings $this->getDefaultConfig(); // include/load config file $this->loadConfigFile(); // apply config constants $this->applyConfigConstants(); // setup directory paths $this->setupPaths(); // set default timezone if not set already. Needed to avoid an E_WARNING. if (!ini_get('date.timezone')) { if (function_exists('date_default_timezone_set')) { date_default_timezone_set($this->get('base', 'timezone')); } } // Todo: must remove config object dependancy from all classes generated by $this->load // before we can uncomment this and remove it from owa_caller constructor or else there // is a race condition. //if ($this->isConfigFilePresent()) { // $this->load($this->get('base', 'configuration_id')); //} // include storage engine class so that DTD constants get loaded owa_coreAPI::setupStorageEngine($this->get('base','db_type')); } function isConfigFilePresent() { $file = OWA_DIR.'owa-config.php'; $oldfile = OWA_BASE_DIR.'/conf/owa-config.php'; if (file_exists($file)) { return true; } elseif (file_exists($oldfile)) { return true; } else { return false; } } function loadConfigFile() { /* LOAD CONFIG FILE */ $file = OWA_DIR.'owa-config.php'; $oldfile = OWA_BASE_DIR.'/conf/owa-config.php'; if (file_exists($file)) { include_once($file); $config_file_exists = true; } elseif (file_exists($oldfile)) { include_once($oldfile); $config_file_exists = true; } else { $config_file_exists = false; } } function applyConfigConstants() { if(!defined('OWA_DATA_DIR')){ define('OWA_DATA_DIR', OWA_DIR.'owa-data/'); } if (defined('OWA_DATA_DIR')) { $this->set('base', 'data_dir', OWA_DATA_DIR); } if(!defined('OWA_CACHE_DIR')){ define('OWA_CACHE_DIR', OWA_DATA_DIR.'caches/'); } if (defined('OWA_CACHE_DIR')) { $this->set('base', 'cache_dir', OWA_CACHE_DIR); } // Looks for log level constant if (defined('OWA_ERROR_LOG_LEVEL')) { $this->set('base', 'error_log_level', OWA_ERROR_LOG_LEVEL); } /* CONFIGURATION ID */ if (defined('OWA_CONFIGURATION_ID')) { $this->set('base', 'configuration_id', OWA_CONFIGURATION_ID); } /* OBJECT CACHING */ // Looks for object cache config constant // must comebefore user db values are fetched from db if (defined('OWA_CACHE_OBJECTS')) { $this->set('base', 'cache_objects', OWA_CACHE_OBJECTS); } /* DATABASE CONFIGURATION */ // This needs to come before the fetch of user overrides from the DB // Constants defined in the config file have the final word // values passed from calling application must be applied prior // to the rest of the caller's overrides if (defined('OWA_DB_TYPE')) { $this->set('base', 'db_type', OWA_DB_TYPE); } if (defined('OWA_DB_NAME')) { $this->set('base', 'db_name', OWA_DB_NAME); } if (defined('OWA_DB_HOST')) { $this->set('base', 'db_host', OWA_DB_HOST); } if (defined('OWA_DB_USER')) { $this->set('base', 'db_user', OWA_DB_USER); } if (defined('OWA_DB_PASSWORD')) { $this->set('base', 'db_password', OWA_DB_PASSWORD); } /* SET ERROR HANDLER */ if (defined('OWA_ERROR_HANDLER')) { $this->set('base', 'error_handler', OWA_ERROR_HANDLER); } if (defined('OWA_CONFIG_DO_NOT_FETCH_FROM_DB')) { $this->set('base', 'do_not_fetch_config_from_db', OWA_CONFIG_DO_NOT_FETCH_FROM_DB); } if (defined('OWA_PUBLIC_URL')) { $this->set('base', 'public_url', OWA_PUBLIC_URL); } if (defined('OWA_PUBLIC_PATH')) { $this->set('base', 'public_path', OWA_PUBLIC_PATH); } if (defined('OWA_QUEUE_EVENTS')) { $this->set('base', 'queue_events', OWA_QUEUE_EVENTS); } if (defined('OWA_EVENT_QUEUE_TYPE')) { $this->set('base', 'event_queue_type', OWA_EVENT_QUEUE_TYPE); } if (defined('OWA_EVENT_SECONDARY_QUEUE_TYPE')) { $this->set('base', 'event_secondary_queue_type', OWA_EVENT_SECONDARY_QUEUE_TYPE); } if (defined('OWA_USE_REMOTE_EVENT_QUEUE')) { $this->set('base', 'use_remote_event_queue', OWA_USE_REMOTE_EVENT_QUEUE); } if (defined('OWA_REMOTE_EVENT_QUEUE_TYPE')) { $this->set('base', 'remote_event_queue_type', OWA_REMOTE_EVENT_QUEUE_TYPE); } if (defined('OWA_REMOTE_EVENT_QUEUE_ENDPOINT')) { $this->set('base', 'remote_event_queue_endpoint', OWA_REMOTE_EVENT_QUEUE_ENDPOINT); } } function applyModuleOverrides($module, $config) { // merge default config with overrides if (!empty($config)) { $in_place_config = $this->config->get('settings'); $old_array = $in_place_config[$module]; $new_array = array_merge($old_array, $config); $in_place_config[$module] = $new_array; $this->config->set('settings', $in_place_config); //print_r($this->config->get('settings')); } } /** * Loads configuration from data store * * @param string id the id of the configuration array to load */ function load($id = 1) { $this->config_id = $id; $db_config = owa_coreAPI::entityFactory('base.configuration'); $db_config->getByPk('id', $id); $db_settings = unserialize($db_config->get('settings')); //print $db_settings; // store copy of config for use with updates and set a flag if (!empty($db_settings)): // needed to get rid of legacy setting that used to be stored in the DB. if (array_key_exists('error_handler', $db_settings['base'])) { unset($db_settings['base']['error_handler']); } $this->db_settings = $db_settings; $this->config_from_db = true; endif; if (!empty($db_settings)): //print_r($db_settings); //$db_settings = unserialize($db_settings); $default = $this->config->get('settings'); // merge default config with overrides fetched from data store $new_config = array(); foreach ($db_settings as $k => $v) { if (isset($default[$k]) && is_array($default[$k])): $new_config[$k] = array_merge($default[$k], $db_settings[$k]); else: $new_config[$k] = $db_settings[$k]; endif; } $this->config->set('settings', $new_config); endif; $db_id = $db_config->get('id'); $this->config->set('id', $db_id); return; } /** * Fetches a modules entire configuration array * * @param string $module The name of module whose configuration values you want to fetch * @return array Config values */ function fetch($module = '') { $v = $this->config->get('settings'); if (!empty($module)): return $v[$module]; else: return $v['base']; endif; } /** * updates or creates configuration values * * @return boolean */ function save() { // serialize array of values prior to update $config = owa_coreAPI::entityFactory('base.configuration'); // if fetch from db flag is not true, try to fetch the config just in // case if was cached or something wen wrong. // Then merge the new values into it. if ($this->config_from_db != true): $config->getByPk('id', $this->get('base', 'configuration_id')); $settings = $config->get('settings'); if (!empty($settings)): $settings = unserialize($settings); $new_config = array(); foreach ($this->db_settings as $k => $v) { if (!is_array($settings[$k])): $settings[$k] = array(); endif; $new_config[$k] = array_merge($settings[$k], $this->db_settings[$k]); } $config->set('settings', serialize($new_config)); //$config->set('settings', serialize(array_merge($settings, $this->db_settings))); else: $config->set('settings', serialize($this->db_settings)); endif; // test to see if object exists $id = $config->get('id'); // if it does just update if (!empty($id)): $status = $config->update(); // else create the object else: $config->set('id', $this->get('base', 'configuration_id')); $status = $config->create(); endif; // update the config else: $config->set('settings', serialize($this->db_settings)); $config->set('id', $this->get('base', 'configuration_id')); $status = $config->update(); endif; $this->is_dirty = false; return $status; } /** * Accessor Method * * @param string $module the name of the module * @param string $key the configuration key * @return unknown */ function get($module, $key) { $values = $this->config->get('settings'); if ( isset( $values[$module] ) && array_key_exists($key, $values[$module])) { return $values[$module][$key]; } else { return false; } } /** * Sets configuration value. will not be persisted. * * @param string $module the name of the module * @param string $key the configuration key * @param string $value the configuration value * @return boolean */ function set($module, $key, $value) { $values = $this->config->get('settings'); $values[$module][$key] = $value; $this->config->set('settings', $values); } /** * Adds Setting value to be configuration and persistant data store * * @param string $module the name of the module * @param string $key the configuration key * @param string $value the configuration value * @depricated */ function setSetting($module, $key, $value) { return $this->set($module, $key, $value); } /** * Adds Setting value to be configuration and persistant data store * * @param string $module the name of the module * @param string $key the configuration key * @param string $value the configuration value * @return */ function persistSetting($module, $key, $value) { $this->set($module, $key, $value); $this->db_settings[$module][$key] = $value; $this->is_dirty = true; } function defaultSetting($module, $key) { $defaults = $this->getDefaultSettingsArray(); if ( array_key_exists($module, $defaults) && array_key_exists($key, $defaults[$module]) ) { $this->set($module, $key, $defaults[$module][$key]); if ( array_key_exists($module, $this->db_settings) && array_key_exists($key, $this->db_settings[$module]) ) { unset($this->db_settings[$module][$key]); $this->is_dirty = true; } } } /** * Adds Setting value to be configuration but DOES NOT add to persistant data store * * @param string $module the name of the module * @param string $key the configuration key * @param string $value the configuration value * @return */ function setSettingTemporary($module, $key, $value) { $this->set($module, $key, $value); return; } /** * Replaces all values of a particular module's configuration * @todo: search to see where else this is used. If unused then make it for use in persist only. */ function replace($module, $values, $persist = false) { if ($persist) { $this->db_settings[$module] = $values; return; } $settings = $this->config->get('settings'); $settings[$module] = $values; $this->config->set('settings', $settings); } /** * Alternate Constructor for base module settings * Needed for backwards compatability with older classes * */ function &get_settings($id = 1) { static $config2; if (!isset($config2)): //print 'hello from alt constructor'; $config2 = &owa_coreAPI::configSingleton(); endif; return $config2->fetch('base'); } function getDefaultConfig() { $config = $this->getDefaultSettingsArray(); // set default values $this->config->set('settings', $config); } function getDefaultSettingsArray() { return array( 'base' => array( 'ns' => 'owa_', 'visitor_param' => 'v', 'session_param' => 's', 'site_session_param' => 'ss', 'last_request_param' => 'last_req', 'first_hit_param' => 'first_hit', 'feed_subscription_param' => 'sid', 'source_param' => 'source', 'graph_param' => 'graph', 'period_param' => 'period', 'document_param' => 'document', 'referer_param' => 'referer', 'site_id' => '', 'configuration_id' => '1', 'session_length' => 1800, 'requests_table' => 'request', 'sessions_table' => 'session', 'referers_table' => 'referer', 'ua_table' => 'ua', 'os_table' => 'os', 'documents_table' => 'document', 'sites_table' => 'site', 'hosts_table' => 'host', 'config_table' => 'configuration', 'version_table' => 'version', 'feed_requests_table' => 'feed_request', 'visitors_table' => 'visitor', 'impressions_table' => 'impression', 'clicks_table' => 'click', 'exits_table' => 'exit', 'users_table' => 'user', 'db_type' => '', 'db_name' => '', 'db_host' => '', 'db_user' => '', 'db_password' => '', 'db_force_new_connections' => true, 'db_make_persistant_connections' => false, 'resolve_hosts' => true, 'log_feedreaders' => true, 'log_robots' => false, 'log_sessions' => true, 'log_dom_clicks' => true, 'delay_first_hit' => false, 'async_db' => false, 'clean_query_string' => true, 'fetch_refering_page_info' => true, 'query_string_filters' => '', // move to site settings 'async_log_dir' => '', //OWA_DATA_DIR . 'logs/', 'async_log_file' => 'events.txt', 'async_lock_file' => 'owa.lock', 'async_error_log_file' => 'events_error.txt', 'notice_email' => '', 'log_php_errors' => false, 'error_handler' => 'production', 'error_log_level' => 0, 'error_log_file' => '', //OWA_DATA_DIR . 'logs/errors.txt', 'browscap.ini' => OWA_BASE_DIR . '/modules/base/data/php_browscap.ini', 'search_engines.ini' => OWA_BASE_DIR . '/conf/search_engines.ini', 'query_strings.ini' => OWA_BASE_DIR . '/conf/query_strings.ini', 'db_class_dir' => OWA_BASE_DIR . '/plugins/db/', 'templates_dir' => OWA_BASE_DIR . '/templates/', 'plugin_dir' => OWA_BASE_DIR . '/plugins/', 'module_dir' => OWA_BASE_DIR . '/modules', 'public_path' => '', 'geolocation_lookup' => true, 'geolocation_service' => 'hostip', 'report_wrapper' => 'wrapper_default.tpl', 'do_not_fetch_config_from_db' => false, 'announce_visitors' => false, 'public_url' => '', 'base_url' => '', 'action_url' => '', 'images_url' => '', 'reporting_url' => '', 'p3p_policy' => 'NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM', 'graph_link_template' => '%s?owa_action=graph&name=%s&%s', //action_url?... 'link_template' => '%s?%s', // main_url?key=value.... 'owa_user_agent' => 'Open Web Analytics Bot '.OWA_VERSION, 'fetch_owa_news' => true, 'owa_rss_url' => 'http://www.openwebanalytics.com/?feed=rss2', 'use_summary_tables' => false, 'summary_framework' => '', 'click_drawing_mode' => 'center_on_page', // remove 'log_clicks' => true, 'log_dom_streams' => true, 'timezone' => 'America/Los_Angeles', 'log_dom_stream_percentage' => 50, 'owa_wiki_link_template' => 'http://wiki.openwebanalytics.com/index.php?title=%s', 'wiki_url' => 'http://wiki.openwebanalytics.com', 'password_length' => 4, 'modules' => array('base'), 'mailer-from' => '', 'mailer-fromName' => 'OWA Mailer', 'mailer-host' => '', 'mailer-port' => '', 'mailer-smtpAuth' => '', 'mailer-username' => '', 'mailer-password' => '', 'queue_events' => false, 'event_queue_type' => '', 'event_secondary_queue_type' => '', 'use_remote_event_queue' => true, 'remote_event_queue_type' => 'http', 'remote_event_queue_endpoint' => '', 'cookie_domain' => false, 'ws_timeout' => 10, 'is_active' => true, 'per_site_visitors' => false, // remove 'cache_objects' => true, 'log_named_users' => true, 'log_visitor_pii' => true, 'do_not_log_ips' => '', // move to site settings 'track_feed_links' => true, 'theme' => '', 'reserved_words' => array('do' => 'action'), 'login_view' => 'base.login', 'not_capable_view' => 'base.error', 'start_page' => 'base.reportDashboard', 'default_action' => 'base.loginForm', 'default_page' => '', // move to site settings 'default_cache_expiration_period' => 604800, 'nonce_expiration_period' => 43200, 'max_prior_campaigns' => 5, 'campaign_params' => array( 'cn' => 'campaign', 'md' => 'medium', 'sr' => 'source', 'tr' => 'search_terms', 'ad' => 'ad', 'at' => 'ad_type'), 'trafficAttributionMode' => 'direct', 'campaignAttributionWindow' => 60, 'capabilities' => array( 'admin' => array( 'view_reports', 'edit_settings', 'edit_sites', 'edit_users', 'edit_modules' ), 'analyst' => array('view_reports'), 'viewer' => array('view_reports'), 'everyone' => array() ), 'numGoals' => 15, 'numGoalGroups' => 5, 'enableEcommerceReporting' => false, // move to site settings 'currencyLocal' => 'en_US', // move to site settings 'memcachedServers' => array(), 'memcachedPersisantConnections' => true, 'cacheType' => 'file', 'disabledEndpoints' => array(), 'disableAllEndpoints' => false, 'processQueuesJobSchedule' => '10 * * * *' ) ); } function setupPaths() { //build base url $base_url = ''; $proto = "http"; if(isset($_SERVER['HTTPS'])) { $proto .= 's'; } if(isset($_SERVER['SERVER_NAME'])) { $base_url .= $proto.'://'.$_SERVER['SERVER_NAME']; } if(isset($_SERVER['SERVER_PORT'])) { if($_SERVER['SERVER_PORT'] != 80) { $base_url .= ':'.$_SERVER['SERVER_PORT']; } } // there is some plugin use case where this is needed i think. if not get rid of it. if (!defined('OWA_PUBLIC_URL')) { define('OWA_PUBLIC_URL', ''); } // set base url $this->set('base', 'base_url', $base_url); //set public path if not defined in config file $public_path = $this->get('base', 'public_path'); if (empty($public_path)) { $public_path = OWA_PATH.'/public/'; $this->set('base','public_path', $public_path); } // set various paths $public_url = $this->get('base', 'public_url'); $main_url = $public_url.'index.php'; $this->set('base','main_url', $main_url); $this->set('base','main_absolute_url', $main_url); $modules_url = $public_url.'modules/'; $this->set('base','modules_url', $modules_url); $this->set('base','action_url',$public_url.'action.php'); $this->set('base','images_url', $modules_url); $this->set('base','images_absolute_url',$modules_url); $this->set('base','log_url',$public_url.'log.php'); $this->set('base','api_url',$public_url.'api.php'); $this->set('base', 'error_log_file', OWA_DATA_DIR . 'logs/errors_'. owa_coreAPI::generateInstanceSpecificHash() .'.txt'); $this->set('base', 'async_log_dir', OWA_DATA_DIR . 'logs/'); owa_coreAPI::debug('check for http host'); // Set cookie domain if (!empty($_SERVER['HTTP_HOST'])) { $this->setCookieDomain(); } } function createConfigFile($config_values) { if (file_exists(OWA_DIR.'owa-config.php')) { owa_coreAPI::error("Your config file already exists. If you need to change your configuration, edit that file at: ".OWA_DIR.'owa-config.php'); require_once(OWA_DIR . 'owa-config.php'); return true; } if (!file_exists(OWA_DIR.'owa-config-dist.php')) { owa_coreAPI::error("We can't find the configuration file template. Are you sure you installed OWA's files correctly? Exiting."); exit; } else { $configFileTemplate = file(OWA_DIR . 'owa-config-dist.php'); owa_coreAPI::debug('found sample config file.'); } $handle = fopen(OWA_DIR . 'owa-config.php', 'w'); foreach ($configFileTemplate as $line_num => $line) { switch (substr($line,0,20)) { case "define('OWA_DB_TYPE'": fwrite($handle, str_replace("yourdbtypegoeshere", $config_values['db_type'], $line)); break; case "define('OWA_DB_NAME'": fwrite($handle, str_replace("yourdbnamegoeshere", $config_values['db_name'], $line)); break; case "define('OWA_DB_USER'": fwrite($handle, str_replace("yourdbusergoeshere", $config_values['db_user'], $line)); break; case "define('OWA_DB_PASSW": fwrite($handle, str_replace("yourdbpasswordgoeshere", $config_values['db_password'], $line)); break; case "define('OWA_DB_HOST'": fwrite($handle, str_replace("yourdbhostgoeshere", $config_values['db_host'], $line)); break; case "define('OWA_PUBLIC_U": fwrite($handle, str_replace("http://domain/path/to/owa/", $config_values['public_url'], $line)); break; default: fwrite($handle, $line); } } fclose($handle); chmod(OWA_DIR . 'owa-config.php', 0750); owa_coreAPI::debug('Config file created'); require_once(OWA_DIR . 'owa-config.php'); return true; } function reset($module) { if ($module) { $defaults = array(); $defaults['install_complete'] = true; $defaults['schema_version'] = $this->get($module, 'schema_version'); $this->replace('base', $defaults, true); return $this->save(); } else { return false; } } function setCookieDomain ($domain = '') { $explicit = false; if ( ! $domain ) { $domain = $_SERVER['HTTP_HOST']; $explicit = true; } $domain = owa_lib::sanitizeCookieDomain($domain); $period = substr( $domain, 0, 1); if ( $period === '.' ) { $domain = substr( $domain, 1 ); } // unless www.domain.com is passed explicitly // strip the www from the domain. if ( ! $explicit ) { $part = substr( $domain, 0, 4 ); if ($part === 'www.') { $domain = substr( $domain, 4); } } $cookie_domain = '.'.$domain; $this->set('base','cookie_domain', $cookie_domain); owa_coreAPI::debug("Set cookie domain to $cookie_domain"); } function __destruct() { if ($this->is_dirty) { $this->save(); } } } ?>