Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Wed, Feb 5, 7:36 AM

in-portal

Index: branches/5.2.x/core/kernel/session/session.php
===================================================================
--- branches/5.2.x/core/kernel/session/session.php (revision 14994)
+++ branches/5.2.x/core/kernel/session/session.php (revision 14995)
@@ -1,1035 +1,1101 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/*
The session works the following way:
1. When a visitor loads a page from the site the script checks if cookies_on varibale has been passed to it as a cookie.
2. If it has been passed, the script tries to get Session ID (SID) from the request:
3. Depending on session mode the script is getting SID differently.
The following modes are available:
- Session::smAUTO
Automatic mode: if cookies are on at the client side, the script relays only on cookies and
ignore all other methods of passing SID. If cookies are off at the client side, the script relays on SID
passed through query string and referal passed by the client. THIS METHOD IS NOT 100% SECURE, as long as
attacker may get SID and substitude referal to gain access to user' session. One of the faults of this method
is that the session is only created when the visitor clicks the first link on the site, so there
is NO session at the first load of the page. (Actually there is a session, but it gets lost after
the first click because we do not use SID in query string while we are not sure if we need it)
- Session::smCOOKIES_ONLY
Cookies only: in this mode the script relays solely on cookies passed from the browser and ignores
all other methods. In this mode there is no way to use sessions for clients without cookies support
or cookies support disabled. The cookies are stored with the full domain name and path to base-directory
of script installation.
- Session::smGET_ONLY
GET only: the script will not set any cookies and will use only SID passed in query string using GET,
it will also check referal. The script will set SID at the first load of the page
- Session::smCOOKIES_AND_GET
Combined mode: the script will use both cookies and GET right from the start. If client has cookies enabled,
the script will check SID stored in cookie and passed in query string, and will use this SID only if both
cookie and query string matches. However if cookies are disabled on the client side, the script will work
the same way as in GET_ONLY mode.
4. After the script has the SID it tries to load it from the Storage (default is database)
5. If such SID is found in the database, the script checks its expiration time. If session is not expired,
it updates its expiration, and resend the cookie (if applicable to session mode)
6. Then the script loads all the data (session variables) pertaining to the SID.
Usage:
$session = new Session(Session::smAUTO); //Session::smAUTO is default, you could just leave the brackets empty, or provide another mode
$session->SetCookieDomain('my.domain.com');
$session->SetCookiePath('/myscript');
$session->SetCookieName('my_sid_cookie');
$session->SetGETName('sid');
$session->InitSession();
...
//link output:
echo "<a href='index.php?'". ( $session->NeedQueryString() ? 'sid='.$session->SID : '' ) .">My Link</a>";
*/
class Session extends kBase {
const smAUTO = 1;
const smCOOKIES_ONLY = 2;
const smGET_ONLY = 3;
const smCOOKIES_AND_GET = 4;
var $Checkers;
var $Mode;
var $OriginalMode = null;
var $GETName = 'sid';
var $CookiesEnabled = true;
var $CookieName = 'sid';
var $CookieDomain;
var $CookiePath;
var $CookieSecure = 0;
var $SessionTimeout = 3600;
var $Expiration;
var $SID;
var $CachedSID;
var $SessionSet = false;
/**
* Session ID is used from GET
*
* @var bool
*/
var $_fromGet = false;
/**
* Enter description here...
*
* @var SessionStorage
* @access protected
*/
protected $Storage;
var $CachedNeedQueryString = null;
/**
* Session Data array
*
* @var Params
*/
var $Data;
/**
* Names of optional session keys with their optional values (which does not need to be always stored)
*
* @var Array
*/
var $OptionalData = Array ();
/**
* Session expiration mark
*
* @var bool
*/
var $expired = false;
/**
* Creates session
*
* @param int $mode
* @access public
*/
public function __construct($mode = self::smAUTO)
{
parent::__construct();
$this->SetMode($mode);
}
function SetMode($mode)
{
$this->Mode = $mode;
$this->CachedNeedQueryString = null;
$this->CachedSID = null;
}
function SetCookiePath($path)
{
$this->CookiePath = str_replace(' ', '%20', $path);
}
/**
* Setting cookie domain. Set false for local domains, because they don't contain dots in their names.
*
* @param string $domain
*/
function SetCookieDomain($domain)
{
// 1. localhost or other like it without "." in domain name
if (!substr_count($domain, '.')) {
// don't use cookie domain at all
$this->CookieDomain = false;
return ;
}
// 2. match using predefined cookie domains from configuration
$cookie_domains = $this->Application->ConfigValue('SessionCookieDomains');
if ($cookie_domains) {
$cookie_domains = array_map('trim', explode("\n", $cookie_domains));
foreach ($cookie_domains as $cookie_domain) {
if (ltrim($cookie_domain, '.') == $domain) {
$this->CookieDomain = $cookie_domain; // as defined in configuration
return ;
}
}
}
// 3. only will execute, when none of domains were matched at previous step
$this->CookieDomain = $this->_autoGuessDomain($domain);
}
/**
* Auto-guess cookie domain based on $_SERVER['HTTP_HOST']
*
* @param $domain
* @return string
*/
function _autoGuessDomain($domain)
{
static $cache = Array ();
if (!array_key_exists($domain, $cache)) {
switch ( substr_count($domain, '.') ) {
case 2:
// 3rd level domain (3 parts)
$cache[$domain] = substr($domain, strpos($domain, '.')); // with leading "."
break;
case 1:
// 2rd level domain (2 parts)
$cache[$domain] = '.' . $domain; // with leading "."
break;
default:
// more then 3rd level
$cache[$domain] = ltrim($domain, '.'); // without leading "."
break;
}
}
return $cache[$domain];
}
function SetGETName($get_name)
{
$this->GETName = $get_name;
}
function SetCookieName($cookie_name)
{
$this->CookieName = $cookie_name;
}
function InitStorage($special)
{
$this->Storage =& $this->Application->recallObject('SessionStorage.'.$special);
$this->Storage->setSession($this);
}
public function Init($prefix, $special)
{
parent::Init($prefix, $special);
$this->CheckIfCookiesAreOn();
if ($this->CookiesEnabled) $_COOKIE['cookies_on'] = 1;
$this->Checkers = Array();
$this->InitStorage($special);
$this->Data = new Params();
$tmp_sid = $this->GetPassedSIDValue();
$check = $this->Check();
if ($this->Application->isAdmin) {
// 1. Front-End session may not be created (SID is present, but no data in database).
// Check expiration LATER from kApplication::Init, because template, used in session
// expiration redirect should be retrieved from mod-rewrite url first.
// 2. Admin sessions are always created, so case when SID is present,
// but session in database isn't is 100% session expired. Check expiration
// HERE because Session::SetSession will create missing session in database
// and when Session::ValidateExpired will be called later from kApplication::Init
// it won't consider such session as expired !!!
$this->ValidateExpired();
}
if ($check) {
$this->SID = $this->GetPassedSIDValue();
$this->Refresh();
$this->LoadData();
}
else {
$this->SetSession();
}
if (!is_null($this->OriginalMode)) $this->SetMode($this->OriginalMode);
}
function ValidateExpired()
{
if (defined('IS_INSTALL') && IS_INSTALL) {
return ;
}
// $this->DeleteExpired(); // called from u:OnDeleteExpiredSessions scheduled task now
if ($this->expired || ($this->CachedSID && !$this->_fromGet && !$this->SessionSet)) {
$this->RemoveSessionCookie();
// true was here to force new session creation, but I (kostja) used
// RemoveCookie a line above, to avoid redirect loop with expired sid
// not being removed setSession with true was used before, to set NEW
// session cookie
$this->SetSession();
// case #1: I've OR other site visitor expired my session
// case #2: I have no session in database, but SID is present
$this->expired = false;
$expire_event = new kEvent('u:OnSessionExpire');
$this->Application->HandleEvent($expire_event);
}
}
/**
* Helper method for detecting cookie availability
*
* @return bool
*/
function _checkCookieReferer()
{
// removing /admin for compatability with in-portal (in-link/admin/add_link.php)
$path = preg_replace('/admin[\/]{0,1}$/', '', $this->CookiePath);
$reg = '#^'.preg_quote(PROTOCOL.ltrim($this->CookieDomain, '.').$path).'#';
return preg_match($reg, getArrayValue($_SERVER, 'HTTP_REFERER') );
}
function CheckIfCookiesAreOn()
{
if ( $this->Mode == self::smGET_ONLY ) {
//we don't need to bother checking if we would not use it
$this->CookiesEnabled = false;
return false;
}
$http_query =& $this->Application->recallObject('HTTPQuery');
/* @var $http_query kHTTPQuery */
$cookies_on = array_key_exists('cookies_on', $http_query->Cookie); // not good here
$get_sid = getArrayValue($http_query->Get, $this->GETName);
if ( ($this->Application->HttpQuery->IsHTTPSRedirect() && $get_sid) || $this->getFlashSID() ) { // Redirect from http to https on different domain OR flash uploader
$this->OriginalMode = $this->Mode;
$this->SetMode(self::smGET_ONLY);
}
if ( !$cookies_on || $this->Application->HttpQuery->IsHTTPSRedirect() || $this->getFlashSID() ) {
//If referer is our server, but we don't have our cookies_on, it's definetly off
$is_install = defined('IS_INSTALL') && IS_INSTALL;
if ( !$is_install && $this->_checkCookieReferer() && !$this->Application->GetVar('admin') && !$this->Application->HttpQuery->IsHTTPSRedirect() ) {
$this->CookiesEnabled = false;
}
else {
//Otherwise we still suppose cookies are on, because may be it's the first time user visits the site
//So we send cookies on to get it next time (when referal will tell us if they are realy off
$this->SetCookie('cookies_on', 1, adodb_mktime() + 31104000); //one year should be enough
}
}
else {
$this->CookiesEnabled = true;
}
return $this->CookiesEnabled;
}
/**
* Sets cookie for current site using path and domain
*
* @param string $name
* @param mixed $value
* @param int $expires
*/
function SetCookie($name, $value, $expires = null)
{
if (isset($expires) && $expires < adodb_mktime()) {
unset($this->Application->HttpQuery->Cookie[$name]);
}
else {
$this->Application->HttpQuery->Cookie[$name] = $value;
}
$old_style_domains = Array (
// domain like in pre 5.1.0 versions
'.' . SERVER_NAME,
// auto-guessed domain (when user specified other domain in configuration variable)
$this->_autoGuessDomain(SERVER_NAME)
);
foreach ($old_style_domains as $old_style_domain) {
if ($this->CookieDomain != $old_style_domain) {
// new style cookie domain -> delete old style cookie to prevent infinite redirect
setcookie($name, $value, adodb_mktime() - 3600, $this->CookiePath, $old_style_domain, $this->CookieSecure);
}
}
setcookie($name, $value, $expires, $this->CookiePath, $this->CookieDomain, $this->CookieSecure);
}
function Check()
{
// don't check referer here, because it doesn't provide any security option and can be easily falsified
$sid = $this->GetPassedSIDValue();
if (empty($sid)) {
return false;
}
//try to load session by sid, if everything is fine
$result = $this->LoadSession($sid);
$this->SessionSet = $result; // fake front-end session will given "false" here
return $result;
}
function LoadSession($sid)
{
if( $this->Storage->LocateSession($sid) ) {
// if we have session with such SID - get its expiration
$this->Expiration = $this->Storage->GetExpiration();
// If session has expired
if ($this->Expiration < adodb_mktime()) {
// when expired session is loaded, then SID is
// not assigned, but used in Destroy method
$this->SID = $sid;
$this->Destroy();
$this->expired = true;
// when Destory methods calls SetSession inside and new session get created
return $this->SessionSet;
}
// Otherwise it's ok
return true;
}
else {
// fake or deleted due to expiration SID
if (!$this->_fromGet) {
$this->expired = true;
}
return false;
}
}
function getFlashSID()
{
$http_query =& $this->Application->recallObject('HTTPQuery');
/* @var $http_query kHTTPQuery */
return getArrayValue($http_query->Post, 'flashsid');
}
function GetPassedSIDValue($use_cache = 1)
{
if (!empty($this->CachedSID) && $use_cache) {
return $this->CachedSID;
}
// flash sid overrides regular sid
$get_sid = $this->getFlashSID();
if (!$get_sid) {
$http_query =& $this->Application->recallObject('HTTPQuery');
/* @var $http_query kHTTPQuery */
$get_sid = getArrayValue($http_query->Get, $this->GETName);
}
$sid_from_get = $get_sid ? true : false;
if ($this->Application->GetVar('admin') == 1 && $get_sid) {
$sid = $get_sid;
}
else {
switch ($this->Mode) {
case self::smAUTO:
//Cookies has the priority - we ignore everything else
$sid = $this->CookiesEnabled ? $this->GetSessionCookie() : $get_sid;
if ($this->CookiesEnabled) {
$sid_from_get = false;
}
break;
case self::smCOOKIES_ONLY:
$sid = $this->GetSessionCookie();
break;
case self::smGET_ONLY:
$sid = $get_sid;
break;
case self::smCOOKIES_AND_GET:
$cookie_sid = $this->GetSessionCookie();
//both sids should match if cookies are enabled
if (!$this->CookiesEnabled || ($cookie_sid == $get_sid)) {
$sid = $get_sid; //we use get here just in case cookies are disabled
}
else {
$sid = '';
$sid_from_get = false;
}
break;
}
}
$this->CachedSID = $sid;
$this->_fromGet = $sid_from_get;
return $this->CachedSID;
}
/**
* Returns session id
*
* @return int
* @access public
*/
function GetID()
{
return $this->SID;
}
/**
* Generates new session id
*
* @return int
* @access private
*/
function GenerateSID()
{
list ($usec, $sec) = explode(' ', microtime());
$sid_part_1 = substr($usec, 4, 4);
$sid_part_2 = mt_rand(1, 9);
$sid_part_3 = substr($sec, 6, 4);
$digit_one = substr($sid_part_1, 0, 1);
if ($digit_one == 0) {
$digit_one = mt_rand(1, 9);
$sid_part_1 = preg_replace('/^0/', '', $sid_part_1);
$sid_part_1 = $digit_one . $sid_part_1;
}
$this->setSID($sid_part_1 . $sid_part_2 . $sid_part_3);
return $this->SID;
}
/**
* Set's new session id
*
* @param int $new_sid
* @access private
*/
function setSID($new_sid)
{
$this->SID /*= $this->CachedSID*/ = $new_sid; // don't set cached sid here
$this->Application->SetVar($this->GETName,$new_sid);
}
function NeedSession()
{
$data = $this->Data->GetParams();
$data_keys = array_keys($data);
$optional_keys = array_keys($this->OptionalData);
$real_keys = array_diff($data_keys, $optional_keys);
return $real_keys ? true : false;
}
function SetSession($force = false)
{
if ( $this->SessionSet && !$force ) {
return true;
}
$this->Expiration = adodb_mktime() + $this->SessionTimeout;
if ( !$force && /*!$this->Application->isAdmin &&*/ !$this->Application->GetVar('admin') && !$this->NeedSession() ) {
// don't create session (in db) on Front-End, when sid is present (GPC), but data in db isn't
if ( $this->_fromGet ) {
// set sid, that was given in GET
$this->setSID($this->GetPassedSIDValue());
}
else {
// re-generate sid only, when cookies are used
$this->GenerateSID();
}
$this->Storage->StoreSession(false);
return false;
}
if ( !$this->SID || $force ) {
$this->GenerateSID();
}
switch ( $this->Mode ) {
case self::smAUTO:
if ( $this->CookiesEnabled ) {
$this->SetSessionCookie();
}
break;
case self::smGET_ONLY:
break;
case self::smCOOKIES_ONLY:
case self::smCOOKIES_AND_GET:
$this->SetSessionCookie();
break;
}
$this->Storage->StoreSession();
if ( $this->Application->isAdmin || $this->Special == 'admin' ) {
$this->StoreVar('admin', 1);
}
$this->SessionSet = true; // should be called before SaveData, because SaveData will try to SetSession again
if ( $this->Special != '' ) {
// front-session called from admin or otherwise, then save it's data
$this->SaveData();
}
$this->Application->resetCounters('UserSession');
return true;
}
/**
* Returns SID from cookie.
*
* Use 2 cookies to have 2 expiration:
* - 1. for normal expiration when browser is not closed (30 minutes by default), configurable
* - 2. for advanced expiration when browser is closed
*
* @return int
*/
function GetSessionCookie()
{
$keep_session_on_browser_close = $this->Application->ConfigValue('KeepSessionOnBrowserClose');
if (isset($this->Application->HttpQuery->Cookie[$this->CookieName]) &&
( $keep_session_on_browser_close ||
(
!$keep_session_on_browser_close &&
isset($this->Application->HttpQuery->Cookie[$this->CookieName.'_live'])
&&
$this->Application->HttpQuery->Cookie[$this->CookieName] == $this->Application->HttpQuery->Cookie[$this->CookieName.'_live']
)
)
) {
return $this->Application->HttpQuery->Cookie[$this->CookieName];
}
return false;
}
/**
* Updates SID in cookie with new value
*
*/
function SetSessionCookie()
{
$this->SetCookie($this->CookieName, $this->SID, $this->Expiration);
$this->SetCookie($this->CookieName.'_live', $this->SID);
$_COOKIE[$this->CookieName] = $this->SID; // for compatibility with in-portal
}
function RemoveSessionCookie()
{
$this->SetCookie($this->CookieName, '');
$this->SetCookie($this->CookieName.'_live', '');
$_COOKIE[$this->CookieName] = null; // for compatibility with in-portal
}
/**
* Refreshes session expiration time
*
* @access private
*/
function Refresh()
{
if ($this->Application->GetVar('skip_session_refresh')) {
return ;
}
if ($this->CookiesEnabled) {
// we need to refresh the cookie
$this->SetSessionCookie();
}
$this->Storage->UpdateSession();
}
function Destroy()
{
$this->Storage->DeleteSession();
$this->Data = new Params();
$this->SID = $this->CachedSID = '';
$this->SessionSet = false;
if ($this->CookiesEnabled) {
$this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty
}
$this->SetSession(true); //will create a new session, true to force
}
function NeedQueryString($use_cache = 1)
{
if ($this->CachedNeedQueryString != null && $use_cache) {
return $this->CachedNeedQueryString;
}
$result = false;
switch ($this->Mode) {
case self::smAUTO:
if (!$this->CookiesEnabled) {
$result = true;
}
break;
/*case self::smCOOKIES_ONLY:
break;*/
case self::smGET_ONLY:
case self::smCOOKIES_AND_GET:
$result = true;
break;
}
$this->CachedNeedQueryString = $result;
return $result;
}
function LoadData()
{
$this->Data->AddParams( $this->Storage->LoadData() );
}
function PrintSession($comment = '')
{
if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && kUtil::constOn('DBG_SHOW_SESSIONDATA')) {
// dump session data
$this->Application->Debugger->appendHTML('SessionStorage [' . ($this->RecallVar('admin') == 1 ? 'Admin' : 'Front-End') . '] ('.$comment.'):');
$session_data = $this->Data->GetParams();
ksort($session_data);
foreach ($session_data as $session_key => $session_value) {
if (kUtil::IsSerialized($session_value)) {
$session_data[$session_key] = unserialize($session_value);
}
}
$this->Application->Debugger->dumpVars($session_data);
if (!$this->RecallVar('admin')) {
// dump real keys (only for front-end)
$data_keys = array_keys($session_data);
$optional_keys = array_keys($this->OptionalData);
$real_keys = array_diff($data_keys, $optional_keys);
if ($real_keys) {
$ret = '';
foreach ($real_keys as $real_key) {
$ret .= '[' . $real_key . '] = [' . $session_data[$real_key] . ']<br/>';
}
$this->Application->Debugger->appendHTML('Real Keys:<br/> ' . $ret);
}
}
}
if (defined('DEBUG_MODE') && $this->Application->isDebugMode() && kUtil::constOn('DBG_SHOW_PERSISTENTDATA')) {
// dump persistent session data
if ($this->Storage->PersistentVars) {
$this->Application->Debugger->appendHTML('Persistant Session:');
$session_data = $this->Storage->PersistentVars;
ksort($session_data);
foreach ($session_data as $session_key => $session_value) {
if (kUtil::IsSerialized($session_value)) {
$session_data[$session_key] = unserialize($session_value);
}
}
$this->Application->Debugger->dumpVars($session_data);
}
}
}
function SaveData($params = Array ())
{
if (!$this->SetSession()) { // call it here - it may be not set before, because there was no need; if there is a need, it will be set here
return;
}
if (!$this->Application->GetVar('skip_last_template') && $this->Application->GetVar('ajax') != 'yes') {
$this->SaveLastTemplate( $this->Application->GetVar('t'), $params );
}
$this->PrintSession('after save');
$this->Storage->SaveData();
}
/**
* Save last template
*
* @param string $t
* @param Array $params
*/
function SaveLastTemplate($t, $params = Array ())
{
$wid = $this->Application->GetVar('m_wid');
$last_env = $this->getLastTemplateENV($t, Array ('m_opener' => 'u'));
$last_template = basename($_SERVER['PHP_SELF']) . '|' . $last_env;
$this->StoreVar(rtrim('last_template_' . $wid, '_'), $last_template);
// prepare last_template for opener stack, module & session could be added later
$last_env = $this->getLastTemplateENV($t, null, false);
$last_template = basename($_SERVER['PHP_SELF']) . '|' . $last_env;
// save last_template in persistent session
if (!$wid) {
if ($this->Application->isAdmin) {
// only for main window, not popups, not login template, not temp mode (used in adm:MainFrameLink tag)
$temp_mode = false;
$passed = explode(',', $this->Application->GetVar('passed'));
foreach ($passed as $passed_prefix) {
if ($this->Application->GetVar($passed_prefix.'_mode')) {
$temp_mode = true;
break;
}
}
if (!$temp_mode) {
if ( $this->Application->GetVarDirect('section', 'Get') !== false ) {
// check directly in GET, because LinkVar (session -> request) used on these vars
$last_template .= '&section='.$this->Application->GetVar('section').'&module='.$this->Application->GetVar('module');
}
$this->StorePersistentVar('last_template_popup', $last_template);
}
}
elseif ($this->Application->GetVar('admin')) {
// admin checking by session data to prevent recursive session save
static $admin_saved = null;
if (!$this->RecallVar('admin') && !isset($admin_saved)) {
// bug: we get recursion in this place, when cookies are disabled in browser and we are browsing
// front-end in admin's frame (front-end session is initialized using admin's sid and they are
// mixed together)
$admin_saved = true;
$admin_session =& $this->Application->recallObject('Session.admin');
/* @var $admin_session Session */
// save to admin last_template too, because when F5 is pressed in frameset Front-End frame should reload as well
$admin_session->StoreVar('last_template_popup', '../' . $last_template);
$admin_session->StorePersistentVar('last_template_popup', '../' . $last_template);
$admin_session->SaveData( Array ('save_last_template' => false) );
}
else {
// don't allow admin=1 & editing_mode=* to get in admin last_template
$last_template = preg_replace('/&(admin|editing_mode)=[\d]/', '', $last_template);
}
}
}
// save other last... variables for mystical purposes (customizations may be)
$this->StoreVar('last_url', $_SERVER['REQUEST_URI']); // needed by ord:StoreContinueShoppingLink
$this->StoreVar('last_env', $last_env);
$save_last_template = array_key_exists('save_last_template', $params) ? $params['save_last_template'] : true;
if ($save_last_template) {
// save last template here, because section & module could be added before
$this->StoreVar(rtrim('last_template_popup_'.$wid, '_'), $last_template);
}
}
function getLastTemplateENV($t, $params = null, $encode = true)
{
if (!isset($params)) {
$params = Array ();
}
$params['__URLENCODE__'] = 1; // uses "&" instead of "&amp;" for url part concatenation + replaces "\" to "%5C" (works in HTML)
if ($this->Application->GetVar('admin') && !array_key_exists('admin', $params) && !defined('EDITING_MODE')) {
$params['editing_mode'] = ''; // used in kApplication::Run
}
$params = array_merge($this->Application->getPassThroughVariables($params), $params);
$ret = $this->Application->BuildEnv($t, $params, 'all', false, false);
if (!$encode) {
// cancels 2nd part of replacements, that URLENCODE does
$ret = str_replace('%5C', '\\', $ret);
}
return $ret;
}
- function StoreVar($name, $value, $optional = false)
+ /**
+ * Stores variable $val in session under name $var
+ *
+ * Use this method to store variable in session. Later this variable could be recalled.
+ *
+ * @param string $name Variable name
+ * @param mixed $value Variable value
+ * @param bool $optional
+ * @return void
+ * @access public
+ * @see Session::RecallVar()
+ */
+ public function StoreVar($name, $value, $optional = false)
{
$this->Data->Set($name, $value);
- if ($optional) {
+ if ( $optional ) {
// make variable optional, also remember optional value
$this->OptionalData[$name] = $value;
}
- elseif (!$optional && array_key_exists($name, $this->OptionalData)) {
- if ($this->OptionalData[$name] == $value) {
+ elseif ( !$optional && array_key_exists($name, $this->OptionalData) ) {
+ if ( $this->OptionalData[$name] == $value ) {
// same value as optional -> don't remove optional mark
- return ;
+ return;
}
// make variable non-optional
unset($this->OptionalData[$name]);
}
}
- function StorePersistentVar($name, $value, $optional = false)
+ /**
+ * Stores variable to persistent session
+ *
+ * @param string $name
+ * @param mixed $value
+ * @param bool $optional
+ * @return void
+ * @access public
+ */
+ public function StorePersistentVar($name, $value, $optional = false)
{
$this->Storage->StorePersistentVar($name, $value, $optional);
}
function LoadPersistentVars()
{
$this->Storage->LoadPersistentVars();
}
- function StoreVarDefault($name, $value, $optional=false)
+ /**
+ * Stores default value for session variable
+ *
+ * @param string $name
+ * @param string $value
+ * @param bool $optional
+ * @return void
+ * @access public
+ * @see Session::RecallVar()
+ * @see Session::StoreVar()
+ */
+ public function StoreVarDefault($name, $value, $optional = false)
{
$tmp = $this->RecallVar($name);
- if($tmp === false || $tmp == '')
- {
+
+ if ( $tmp === false || $tmp == '' ) {
$this->StoreVar($name, $value, $optional);
}
}
- function RecallVar($name, $default = false)
+ /**
+ * Returns session variable value
+ *
+ * Return value of $var variable stored in Session. An optional default value could be passed as second parameter.
+ *
+ * @param string $name Variable name
+ * @param mixed $default Default value to return if no $var variable found in session
+ * @return mixed
+ * @access public
+ */
+ public function RecallVar($name, $default = false)
{
$ret = $this->Data->Get($name);
+
return ($ret === false) ? $default : $ret;
}
- function RecallPersistentVar($name, $default = false)
+ /**
+ * Returns variable value from persistent session
+ *
+ * @param string $name
+ * @param mixed $default
+ * @return mixed
+ * @access public
+ */
+ public function RecallPersistentVar($name, $default = false)
{
return $this->Storage->RecallPersistentVar($name, $default);
}
-
- function RemoveVar($name)
+ /**
+ * Deletes Session variable
+ *
+ * @param string $var
+ * @return void
+ * @access public
+ */
+ public function RemoveVar($name)
{
$this->Storage->RemoveFromData($name);
$this->Data->Remove($name);
}
- function RemovePersistentVar($name)
+ /**
+ * Removes variable from persistent session
+ *
+ * @param string $name
+ * @return void
+ * @access public
+ */
+ public function RemovePersistentVar($name)
{
- return $this->Storage->RemovePersistentVar($name);
+ $this->Storage->RemovePersistentVar($name);
}
/**
- * Ignores session varible value set before
+ * Ignores session variable value set before
*
* @param string $name
+ * @return void
+ * @access public
*/
- function RestoreVar($name)
+ public function RestoreVar($name)
{
$value = $this->Storage->GetFromData($name, '__missing__');
- if ($value === '__missing__') {
+ if ( $value === '__missing__' ) {
// there is nothing to restore (maybe session was not saved), look in optional variable values
$value = array_key_exists($name, $this->OptionalData) ? $this->OptionalData[$name] : false;
}
- return $this->StoreVar($name, $value);
+ $this->StoreVar($name, $value);
}
function GetField($var_name, $default = false)
{
return $this->Storage->GetField($var_name, $default);
}
function SetField($var_name, $value)
{
$this->Storage->SetField($var_name, $value);
}
/**
* Deletes expired sessions
*
* @return Array expired sids if any
* @access private
*/
function DeleteExpired()
{
return $this->Storage->DeleteExpired();
}
/**
* Deletes given sessions
*
* @param $session_ids
* @param int $delete_reason
* @return void
*/
function DeleteSessions($session_ids, $delete_reason = SESSION_LOG_EXPIRED)
{
$this->Storage->DeleteSessions($session_ids, $delete_reason);
}
/**
* Allows to check if user in this session is logged in or not
*
* @return bool
*/
function LoggedIn()
{
$user_id = $this->RecallVar('user_id');
$ret = $user_id > 0;
if (($this->RecallVar('admin') == 1 || defined('ADMIN')) && ($user_id == USER_ROOT)) {
$ret = true;
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/session/session_storage.php
===================================================================
--- branches/5.2.x/core/kernel/session/session_storage.php (revision 14994)
+++ branches/5.2.x/core/kernel/session/session_storage.php (revision 14995)
@@ -1,491 +1,505 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/**
* Implements Session Store in the Database
*
*/
class SessionStorage extends kDBBase {
/**
* Reference to session
*
* @var Session
* @access protected
*/
protected $Session = null;
var $Expiration;
var $SessionTimeout = 0;
var $DirectVars = Array ();
var $ChangedDirectVars = Array ();
var $PersistentVars = Array ();
var $OriginalData = Array ();
var $TimestampField;
var $SessionDataTable;
var $DataValueField;
var $DataVarField;
public function Init($prefix, $special)
{
parent::Init($prefix, $special);
$this->TableName = 'sessions';
$this->IDField = 'sid';
$this->TimestampField = 'expire';
$this->SessionDataTable = 'SessionData';
$this->DataValueField = 'value';
$this->DataVarField = 'var';
}
/**
* Sets reference to session
*
* @param Session $session
*/
public function setSession(&$session)
{
$this->Session =& $session;
$this->SessionTimeout = $session->SessionTimeout;
}
/**
* Calculates browser signature
*
* @return string
*/
function _getBrowserSignature()
{
$signature_parts = Array(
'HTTP_USER_AGENT', 'SERVER_PROTOCOL',
'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE'
);
$ret = '';
foreach ($signature_parts as $signature_part) {
if (array_key_exists($signature_part, $_SERVER)) {
$ret .= '&|&' . $_SERVER[$signature_part];
}
}
return md5( substr($ret, 3) );
}
function GetSessionDefaults()
{
$fields_hash = Array (
$this->IDField => $this->Session->SID,
$this->TimestampField => $this->Session->Expiration,
);
if (!defined('IS_INSTALL') || !IS_INSTALL) {
// this column was added only in 5.0.1 version,
// so accessing it while database is not upgraded
// will result in admin's inability to login inside
// installator
$fields_hash['BrowserSignature'] = $this->_getBrowserSignature();
}
// default values + values set during this script run
return array_merge($fields_hash, $this->DirectVars);
}
/**
* Stores session to database
*
* @param bool $to_database
*
* @return void
* @access public
*/
public function StoreSession($to_database = true)
{
if ( defined('IS_INSTALL') && IS_INSTALL && $to_database && !$this->Application->TableFound($this->TableName, true) ) {
return;
}
$fields_hash = $this->GetSessionDefaults();
if ( $to_database ) {
$this->Conn->doInsert($fields_hash, $this->TableName);
}
foreach ($fields_hash as $field_name => $field_value) {
$this->SetField($field_name, $field_value);
}
// ensure user groups are stored in a way, that kPermissionsHelper::CheckUserPermission can understand
$this->Session->StoreVar('UserGroups', $this->GetField('GroupList'), !$to_database);
}
function DeleteSession()
{
$this->DeleteSessions( Array ($this->Session->SID), SESSION_LOG_LOGGED_OUT );
$this->DirectVars = $this->ChangedDirectVars = $this->OriginalData = Array();
}
function UpdateSession($timeout = 0)
{
$this->SetField($this->TimestampField, $this->Session->Expiration);
$query = ' UPDATE '.$this->TableName.' SET '.$this->TimestampField.' = '.$this->Session->Expiration.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->SID);
$this->Conn->Query($query);
}
function LocateSession($sid)
{
$sql = 'SELECT *
FROM ' . $this->TableName . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($sid);
$result = $this->Conn->GetRow($sql);
if ($result === false) {
return false;
}
// perform security checks to ensure, that session is used by it's creator
if ($this->Application->ConfigValue('SessionBrowserSignatureCheck') && ($result['BrowserSignature'] != $this->_getBrowserSignature()) && $this->Application->GetVar('flashsid') === false) {
return false;
}
if ($this->Application->ConfigValue('SessionIPAddressCheck') && ($result['IpAddress'] != $_SERVER['REMOTE_ADDR'])) {
// most secure, except for cases where NAT (Network Address Translation)
// is used and two or more computers can have same IP address
return false;
}
$this->DirectVars = $result;
$this->Expiration = $result[$this->TimestampField];
return true;
}
function GetExpiration()
{
return $this->Expiration;
}
function LoadData()
{
$query = 'SELECT '.$this->DataValueField.','.$this->DataVarField.' FROM '.$this->SessionDataTable.' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->SID);
$this->OriginalData = $this->Conn->GetCol($query, $this->DataVarField);
return $this->OriginalData;
}
/**
* Enter description here...
*
* @param string $var_name
* @param mixed $default
* @return mixed
*/
function GetField($var_name, $default = false)
{
return isset($this->DirectVars[$var_name]) ? $this->DirectVars[$var_name] : $default;
//return $this->Conn->GetOne('SELECT '.$var_name.' FROM '.$this->TableName.' WHERE `'.$this->IDField.'` = '.$this->Conn->qstr($this->Session->GetID()) );
}
function SetField($var_name, $value)
{
$value_changed = !isset($this->DirectVars[$var_name]) || ($this->DirectVars[$var_name] != $value);
if ($value_changed) {
$this->DirectVars[$var_name] = $value;
$this->ChangedDirectVars[] = $var_name;
$this->ChangedDirectVars = array_unique($this->ChangedDirectVars);
}
//return $this->Conn->Query('UPDATE '.$this->TableName.' SET '.$var_name.' = '.$this->Conn->qstr($value).' WHERE '.$this->IDField.' = '.$this->Conn->qstr($this->Session->GetID()) );
}
/**
* Saves changes in session to database using single REPLACE query
*
* @return void
* @access public
*/
public function SaveData()
{
if ( !$this->Session->SID ) {
// can't save without sid
return ;
}
$replace = '';
$ses_data = $this->Session->Data->GetParams();
foreach ($ses_data as $key => $value) {
if ( isset($this->OriginalData[$key]) && $this->OriginalData[$key] == $value ) {
continue; //skip unchanged session data
}
else {
$replace .= sprintf("(%s, %s, %s),", $this->Conn->qstr($this->Session->SID), $this->Conn->qstr($key), $this->Conn->qstr($value));
}
}
$replace = rtrim($replace, ',');
if ( $replace != '' ) {
$query = ' REPLACE INTO ' . $this->SessionDataTable . ' (' . $this->IDField . ', ' . $this->DataVarField . ', ' . $this->DataValueField . ') VALUES ' . $replace;
$this->Conn->Query($query);
}
if ( $this->ChangedDirectVars ) {
$changes = Array ();
foreach ($this->ChangedDirectVars as $var) {
$changes[] = $var . ' = ' . $this->Conn->qstr($this->DirectVars[$var]);
}
$query = ' UPDATE ' . $this->TableName . '
SET ' . implode(',', $changes) . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($this->Session->GetID());
$this->Conn->Query($query);
}
}
function RemoveFromData($var)
{
if ($this->Session->SessionSet) {
// only, when session is stored in database
$sql = 'DELETE FROM ' . $this->SessionDataTable . '
WHERE ' . $this->IDField . ' = ' . $this->Conn->qstr($this->Session->SID) . ' AND ' . $this->DataVarField . ' = ' . $this->Conn->qstr($var);
$this->Conn->Query($sql);
}
unset($this->OriginalData[$var]);
}
function GetFromData($var, $default = false)
{
return array_key_exists($var, $this->OriginalData) ? $this->OriginalData[$var] : $default;
}
function GetExpiredSIDs()
{
$sql = 'SELECT ' . $this->IDField . '
FROM ' . $this->TableName . '
WHERE ' . $this->TimestampField . ' > ' . adodb_mktime();
return $this->Conn->GetCol($sql);
}
function DeleteExpired()
{
$expired_sids = $this->GetExpiredSIDs();
$this->DeleteSessions($expired_sids);
return $expired_sids;
}
function DeleteSessions($session_ids, $delete_reason = SESSION_LOG_EXPIRED)
{
if (!$session_ids) {
return ;
}
$log_table = $this->Application->getUnitOption('session-log', 'TableName');
if ($log_table) {
// mark session with proper status
$sub_sql = 'SELECT ' . $this->TimestampField . ' - ' . $this->SessionTimeout . '
FROM ' . $this->TableName . '
WHERE ' . $this->IDField . ' = ' . $log_table . '.SessionId';
$sql = 'UPDATE ' . $log_table . '
SET Status = ' . $delete_reason . ', SessionEnd = (' . $sub_sql . ')
WHERE Status = ' . SESSION_LOG_ACTIVE . ' AND SessionId IN (' . implode(',', $session_ids) . ')';
$this->Conn->Query($sql);
}
$where_clause = ' WHERE ' . $this->IDField . ' IN (' . implode(',', $session_ids) . ')';
$sql = 'DELETE FROM ' . $this->SessionDataTable . $where_clause;
$this->Conn->Query($sql);
$sql = 'DELETE FROM ' . $this->TableName . $where_clause;
$this->Conn->Query($sql);
// delete debugger ouputs left of deleted sessions
foreach ($session_ids as $session_id) {
$debug_file = (defined('RESTRICTED') ? RESTRICTED : WRITEABLE . '/cache') . '/debug_@' . $session_id . '@.txt';
if (file_exists($debug_file)) {
@unlink($debug_file);
}
}
}
function LoadPersistentVars()
{
$user_id = $this->Session->RecallVar('user_id');
if ($user_id != USER_GUEST) {
// root & normal users
$sql = 'SELECT VariableValue, VariableName
FROM '.TABLE_PREFIX.'PersistantSessionData
WHERE PortalUserId = '.$user_id;
$this->PersistentVars = $this->Conn->GetCol($sql, 'VariableName');
}
else {
$this->PersistentVars = Array ();
}
}
/**
* Stores variable to persistent session
*
* @param string $var_name
* @param mixed $var_value
* @param bool $optional
+ * @return void
+ * @access public
*/
- function StorePersistentVar($var_name, $var_value, $optional = false)
+ public function StorePersistentVar($var_name, $var_value, $optional = false)
{
$user_id = $this->Session->RecallVar('user_id');
- if ($user_id == USER_GUEST || $user_id === false) {
+ if ( $user_id == USER_GUEST || $user_id === false ) {
// -2 (when not logged in), false (when after u:OnLogout event)
$this->Session->StoreVar($var_name, $var_value, $optional);
- return ;
+ return;
}
$this->PersistentVars[$var_name] = $var_value;
- $key_clause = 'PortalUserId = '.$user_id.' AND VariableName = '.$this->Conn->qstr($var_name);
+ $key_clause = 'PortalUserId = ' . $user_id . ' AND VariableName = ' . $this->Conn->qstr($var_name);
$sql = 'SELECT VariableName
- FROM '.TABLE_PREFIX.'PersistantSessionData
- WHERE '.$key_clause;
+ FROM ' . TABLE_PREFIX . 'PersistantSessionData
+ WHERE ' . $key_clause;
$record_found = $this->Conn->GetOne($sql);
$fields_hash = Array (
'PortalUserId' => $user_id,
'VariableName' => $var_name,
'VariableValue' => $var_value,
);
- if ($record_found) {
- $this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'PersistantSessionData', $key_clause);
+ if ( $record_found ) {
+ $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'PersistantSessionData', $key_clause);
}
else {
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PersistantSessionData');
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'PersistantSessionData');
}
}
/**
* Gets persistent variable
*
* @param string $var_name
* @param mixed $default
* @return mixed
+ * @access public
*/
- function RecallPersistentVar($var_name, $default = false)
+ public function RecallPersistentVar($var_name, $default = false)
{
- if ($this->Session->RecallVar('user_id') == USER_GUEST) {
- if ($default == ALLOW_DEFAULT_SETTINGS) {
+ if ( $this->Session->RecallVar('user_id') == USER_GUEST ) {
+ if ( $default == ALLOW_DEFAULT_SETTINGS ) {
$default = null;
}
+
return $this->Session->RecallVar($var_name, $default);
}
- if (array_key_exists($var_name, $this->PersistentVars)) {
+ if ( array_key_exists($var_name, $this->PersistentVars) ) {
return $this->PersistentVars[$var_name];
}
- elseif ($default == ALLOW_DEFAULT_SETTINGS) {
+ elseif ( $default == ALLOW_DEFAULT_SETTINGS ) {
$default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
- if (!$default_user_id) {
+
+ if ( !$default_user_id ) {
$default_user_id = USER_ROOT;
}
+
$sql = 'SELECT VariableValue, VariableName
- FROM '.TABLE_PREFIX.'PersistantSessionData
- WHERE VariableName = '.$this->Conn->qstr($var_name).' AND PortalUserId = '.$default_user_id;
+ FROM ' . TABLE_PREFIX . 'PersistantSessionData
+ WHERE VariableName = ' . $this->Conn->qstr($var_name) . ' AND PortalUserId = ' . $default_user_id;
$value = $this->Conn->GetOne($sql);
$this->PersistentVars[$var_name] = $value;
- if ($value !== false) {
+
+ if ( $value !== false ) {
$this->StorePersistentVar($var_name, $value); //storing it, so next time we don't load default user setting
}
+
return $value;
}
- else {
- return $default;
- }
+
+ return $default;
}
+ /**
+ * Removes variable from persistent session
+ *
+ * @param string $var_name
+ * @return void
+ * @access public
+ */
function RemovePersistentVar($var_name)
{
unset($this->PersistentVars[$var_name]);
$user_id = $this->Session->RecallVar('user_id');
- if ($user_id == USER_GUEST || $user_id === false) {
+ if ( $user_id == USER_GUEST || $user_id === false ) {
// -2 (when not logged in), false (when after u:OnLogout event)
$this->Session->RemoveVar($var_name);
}
else {
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'PersistantSessionData
WHERE PortalUserId = ' . $user_id . ' AND VariableName = ' . $this->Conn->qstr($var_name);
$this->Conn->Query($sql);
}
}
/**
* Checks of object has given field
*
* @param string $name
* @return bool
* @access protected
*/
protected function HasField($name) { }
/**
* Returns field values
*
* @return Array
* @access protected
*/
protected function GetFieldValues() { }
/**
* Returns unformatted field value
*
* @param string $field
* @return string
* @access protected
*/
protected function GetDBField($field) { }
/**
* Returns true, when list/item was queried/loaded
*
* @return bool
* @access protected
*/
protected function isLoaded() { }
/**
* Returns specified field value from all selected rows.
* Don't affect current record index
*
* @param string $field
* @return Array
* @access protected
*/
protected function GetCol($field) { }
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/application.php
===================================================================
--- branches/5.2.x/core/kernel/application.php (revision 14994)
+++ branches/5.2.x/core/kernel/application.php (revision 14995)
@@ -1,2873 +1,3008 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/**
* Basic class for Kernel4-based Application
*
* This class is a Facade for any other class which needs to deal with Kernel4 framework.<br>
* The class incapsulates the main run-cycle of the script, provide access to all other objects in the framework.<br>
* <br>
* The class is a singleton, which means that there could be only one instance of kApplication in the script.<br>
* This could be guaranteed by NOT calling the class constructor directly, but rather calling kApplication::Instance() method,
* which returns an instance of the application. The method guarantees that it will return exactly the same instance for any call.<br>
* See singleton pattern by GOF.
*/
class kApplication implements kiCacheable {
/**
* Location of module helper class (used in installator too)
*/
const MODULE_HELPER_PATH = '/../units/helpers/modules_helper.php';
/**
* Is true, when Init method was called already, prevents double initialization
*
* @var bool
*/
var $InitDone = false;
/**
* Holds internal NParser object
* @access private
* @var NParser
*/
var $Parser;
/**
* Holds parser output buffer
* @access private
* @var string
*/
var $HTML;
/**
* The main Factory used to create
* almost any class of kernel and
* modules
*
* @access private
* @var kFactory
*/
var $Factory;
/**
* Template names, that will be used instead of regular templates
*
* @var Array
*/
var $ReplacementTemplates = Array ();
/**
* Mod-Rewrite listeners used during url building and parsing
*
* @var Array
*/
var $RewriteListeners = Array ();
/**
* Reference to debugger
*
* @var Debugger
*/
var $Debugger = null;
/**
* Holds all phrases used
* in code and template
*
* @var PhrasesCache
*/
var $Phrases;
/**
* Modules table content, key - module name
*
* @var Array
*/
var $ModuleInfo = Array();
/**
* Holds DBConnection
*
* @var kDBConnection
*/
var $Conn = null;
/**
* Maintains list of user-defined error handlers
*
* @var Array
*/
var $errorHandlers = Array();
/**
* Maintains list of user-defined exception handlers
*
* @var Array
*/
var $exceptionHandlers = Array();
// performance needs:
/**
* Holds a reference to httpquery
*
* @var kHttpQuery
*/
var $HttpQuery = null;
/**
* Holds a reference to UnitConfigReader
*
* @var kUnitConfigReader
*/
var $UnitConfigReader = null;
/**
* Holds a reference to Session
*
* @var Session
*/
var $Session = null;
/**
* Holds a ref to kEventManager
*
* @var kEventManager
*/
var $EventManager = null;
/**
* Holds a ref to kUrlManager
*
* @var kUrlManager
* @access public
*/
public $UrlManager = null;
/**
* Ref for TemplatesCache
*
* @var TemplatesCache
*/
var $TemplatesCache = null;
var $CompilationCache = array(); //used when compiling templates
var $CachedProcessors = array(); //used when running compiled templates
var $LambdaElements = 1; // for autonumbering unnamed RenderElements [any better place for this prop? KT]
/**
* Holds current NParser tag while parsing, can be used in error messages to display template file and line
*
* @var _BlockTag
*/
var $CurrentNTag = null;
/**
* Object of unit caching class
*
* @var kCacheManager
*/
var $cacheManager = null;
/**
* Tells, that administrator has authenticated in administrative console
* Should be used to manipulate data change OR data restrictions!
*
* @var bool
*/
var $isAdminUser = false;
/**
* Tells, that admin version of "index.php" was used, nothing more!
* Should be used to manipulate data display!
*
* @var bool
*/
var $isAdmin = false;
/**
* Instance of site domain object
*
* @var kDBItem
*/
var $siteDomain = null;
/**
* Prevent kApplication class to be created directly, only via Instance method
*
*/
protected function __construct()
{
}
/**
* Returns kApplication instance anywhere in the script.
*
* This method should be used to get single kApplication object instance anywhere in the
* Kernel-based application. The method is guaranteed to return the SAME instance of kApplication.
* Anywhere in the script you could write:
* <code>
* $application =& kApplication::Instance();
* </code>
* or in an object:
* <code>
* $this->Application =& kApplication::Instance();
* </code>
* to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class.
* To use descendant of standard kApplication class in your project you would need to define APPLICATION_CLASS constant
* BEFORE calling kApplication::Instance() for the first time. If APPLICATION_CLASS is not defined the method would
* create and return default KernelApplication instance.
*
* Pattern: Singleton
*
* @static
* @access public
* @return kApplication
*/
public static function &Instance()
{
static $instance = false;
if (!$instance) {
$class = defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication';
$instance = new $class();
$instance->Application =& $instance;
}
return $instance;
}
/**
* Initializes the Application
*
* @access public
* @see kHTTPQuery
* @see Session
* @see TemplatesCache
* @return bool Was Init actually made now or before
*/
public function Init()
{
if ( $this->InitDone ) {
return false;
}
$this->isAdmin = kUtil::constOn('ADMIN');
if ( !kUtil::constOn('SKIP_OUT_COMPRESSION') ) {
ob_start(); // collect any output from method (other then tags) into buffer
}
if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Init:');
}
if ( !$this->isDebugMode() && !kUtil::constOn('DBG_ZEND_PRESENT') ) {
error_reporting(0);
ini_set('display_errors', 0);
}
if ( !kUtil::constOn('DBG_ZEND_PRESENT') ) {
$error_handler = set_error_handler(Array (&$this, 'handleError'));
if ( $error_handler ) {
// wrap around previous error handler, if any was set
$this->errorHandlers[] = $error_handler;
}
$exception_handler = set_exception_handler(Array (&$this, 'handleException'));
if ( $exception_handler ) {
// wrap around previous exception handler, if any was set
$this->exceptionHandlers[] = $exception_handler;
}
}
$this->Factory = new kFactory();
$this->registerDefaultClasses();
$vars = kUtil::parseConfig(true);
$db_class = isset($vars['Databases']) ? 'kDBLoadBalancer' : 'kDBConnection';
$this->Conn =& $this->Factory->makeClass($db_class, Array (SQL_TYPE, Array (&$this, 'handleSQLError')));
$this->Conn->setup($vars);
$this->cacheManager =& $this->makeClass('kCacheManager');
$this->cacheManager->InitCache();
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Before UnitConfigReader');
}
// init config reader and all managers
$this->UnitConfigReader =& $this->makeClass('kUnitConfigReader');
$this->UnitConfigReader->scanModules(MODULES_PATH); // will also set RewriteListeners when existing cache is read
$this->registerModuleConstants();
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('After UnitConfigReader');
}
define('MOD_REWRITE', $this->ConfigValue('UseModRewrite') && !$this->isAdmin ? 1 : 0);
// start processing request
$this->HttpQuery =& $this->recallObject('HTTPQuery');
$this->HttpQuery->process();
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery initial');
}
$this->Session =& $this->recallObject('Session');
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed Session');
}
$this->UrlManager->LoadStructureTemplateMapping();
$this->Session->ValidateExpired(); // needs mod_rewrite url already parsed to keep user at proper template after session expiration
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit');
}
$this->cacheManager->LoadApplicationCache();
$site_timezone = $this->ConfigValue('Config_Site_Time');
if ( $site_timezone ) {
putenv('TZ=' . $site_timezone);
}
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Loaded cache and phrases');
}
$this->ValidateLogin(); // must be called before AfterConfigRead, because current user should be available there
$this->UnitConfigReader->AfterConfigRead(); // will set RewriteListeners when missing cache is built first time
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed AfterConfigRead');
}
if ( $this->GetVar('m_cat_id') === false ) {
$this->SetVar('m_cat_id', 0);
}
if ( !$this->RecallVar('curr_iso') ) {
$this->StoreVar('curr_iso', $this->GetPrimaryCurrency(), true); // true for optional
}
$visit_id = $this->RecallVar('visit_id');
if ( $visit_id !== false ) {
$this->SetVar('visits_id', $visit_id);
}
$language =& $this->recallObject('lang.current', null, Array ('live_table' => true));
/* @var $language LanguagesItem */
if ( preg_match('/utf-8/', $language->GetDBField('Charset')) ) {
setlocale(LC_ALL, 'en_US.UTF-8');
mb_internal_encoding('UTF-8');
}
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->profileFinish('kernel4_startup');
}
$this->InitDone = true;
$this->HandleEvent(new kEvent('adm:OnStartup'));
return true;
}
function InitManagers()
{
if ($this->InitDone) {
throw new Exception('Duplicate call of ' . __METHOD__, E_USER_ERROR);
return ;
}
$this->UrlManager =& $this->makeClass('kUrlManager');
$this->EventManager =& $this->makeClass('EventManager');
$this->Phrases =& $this->makeClass('kPhraseCache');
$this->RegisterDefaultBuildEvents();
}
/**
* Returns module information. Searches module by requested field
*
* @param string $field
* @param mixed $value
* @param string $return_field field value to returns, if not specified, then return all fields
* @return Array
*/
function findModule($field, $value, $return_field = null)
{
- $found = false;
- foreach ($this->ModuleInfo as $module_name => $module_info) {
+ $found = $module_info = false;
+
+ foreach ($this->ModuleInfo as $module_info) {
if ( strtolower($module_info[$field]) == strtolower($value) ) {
$found = true;
break;
}
}
if ( $found ) {
return isset($return_field) ? $module_info[$return_field] : $module_info;
}
return false;
}
/**
* Refreshes information about loaded modules
*
* @return void
* @access public
*/
public function refreshModuleInfo()
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules', true)) {
$this->registerModuleConstants();
return ;
}
// use makeClass over recallObject, since used before kApplication initialization during installation
$modules_helper =& $this->makeClass('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Modules
WHERE ' . $modules_helper->getWhereClause() . '
ORDER BY LoadOrder';
$this->ModuleInfo = $this->Conn->Query($sql, 'Name');
$this->registerModuleConstants();
}
/**
* Checks if passed language id if valid and sets it to primary otherwise
*
*/
function VerifyLanguageId()
{
$language_id = $this->GetVar('m_lang');
if (!$language_id) {
$language_id = 'default';
}
$this->SetVar('lang.current_id', $language_id);
$this->SetVar('m_lang', $language_id);
$lang_mode = $this->GetVar('lang_mode');
$this->SetVar('lang_mode', '');
$lang =& $this->recallObject('lang.current');
/* @var $lang kDBItem */
if (!$lang->isLoaded() || (!$this->isAdmin && !$lang->GetDBField('Enabled'))) {
if (!defined('IS_INSTALL')) {
$this->ApplicationDie('Unknown or disabled language');
}
}
$this->SetVar('lang_mode',$lang_mode);
}
/**
* Checks if passed theme id if valid and sets it to primary otherwise
*
*/
function VerifyThemeId()
{
if ($this->isAdmin) {
kUtil::safeDefine('THEMES_PATH', '/core/admin_templates');
return;
}
$path = $this->GetFrontThemePath();
if ($path === false) {
$this->ApplicationDie('No Primary Theme Selected or Current Theme is Unknown or Disabled');
}
kUtil::safeDefine('THEMES_PATH', $path);
}
- function GetFrontThemePath($force=0)
+ /**
+ * Returns relative path to current front-end theme
+ *
+ * @param bool $force
+ * @return string
+ * @access public
+ */
+ public function GetFrontThemePath($force = false)
{
static $path = null;
if ( !$force && isset($path) ) {
return $path;
}
$theme_id = $this->GetVar('m_theme');
if ( !$theme_id ) {
-// $theme_id = $this->GetDefaultThemeId(1); //1 to force front-end mode!
- $theme_id = 'default';
+ $theme_id = 'default'; // $this->GetDefaultThemeId(1); // 1 to force front-end mode!
}
$this->SetVar('m_theme', $theme_id);
$this->SetVar('theme.current_id', $theme_id); // KOSTJA: this is to fool theme' getPassedID
+
$theme =& $this->recallObject('theme.current');
/* @var $theme ThemeItem */
if ( !$theme->isLoaded() || !$theme->GetDBField('Enabled') ) {
return false;
}
// assign & then return, since it's static variable
$path = '/themes/' . $theme->GetDBField('Name');
return $path;
}
- function GetDefaultLanguageId($init = false)
+ /**
+ * Returns primary front/admin language id
+ *
+ * @param bool $init
+ * @return int
+ * @access public
+ */
+ public function GetDefaultLanguageId($init = false)
{
$cache_key = 'primary_language_info[%LangSerial%]';
$language_info = $this->getCache($cache_key);
- if ($language_info === false) {
+ if ( $language_info === false ) {
// cache primary language info first
$table = $this->getUnitOption('lang', 'TableName');
$id_field = $this->getUnitOption('lang', 'IDField');
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT ' . $id_field . ', IF(AdminInterfaceLang, "Admin", "Front") AS LanguageKey
FROM ' . $table . '
WHERE (AdminInterfaceLang = 1 OR PrimaryLang = 1) AND (Enabled = 1)';
$language_info = $this->Conn->GetCol($sql, 'LanguageKey');
- if ($language_info !== false) {
+ if ( $language_info !== false ) {
$this->setCache($cache_key, $language_info);
}
}
$language_key = ($this->isAdmin && $init) || count($language_info) == 1 ? 'Admin' : 'Front';
- if (array_key_exists($language_key, $language_info) && $language_info[$language_key] > 0) {
+ if ( array_key_exists($language_key, $language_info) && $language_info[$language_key] > 0 ) {
// get from cache
return $language_info[$language_key];
}
$language_id = $language_info && array_key_exists($language_key, $language_info) ? $language_info[$language_key] : false;
- if (!$language_id && defined('IS_INSTALL') && IS_INSTALL) {
+ if ( !$language_id && defined('IS_INSTALL') && IS_INSTALL ) {
$language_id = 1;
}
return $language_id;
}
- function GetDefaultThemeId($force_front=0)
+ /**
+ * Returns front-end primary theme id (even, when called from admin console)
+ *
+ * @param bool $force_front
+ * @return int
+ * @access public
+ */
+ public function GetDefaultThemeId($force_front = false)
{
static $theme_id = 0;
- if ($theme_id > 0) {
+ if ( $theme_id > 0 ) {
return $theme_id;
}
- if (kUtil::constOn('DBG_FORCE_THEME')) {
+ if ( kUtil::constOn('DBG_FORCE_THEME') ) {
$theme_id = DBG_FORCE_THEME;
}
- elseif (!$force_front && $this->isAdmin) {
+ elseif ( !$force_front && $this->isAdmin ) {
$theme_id = 999;
}
else {
$cache_key = 'primary_theme[%ThemeSerial%]';
$theme_id = $this->getCache($cache_key);
- if ($theme_id === false) {
+ if ( $theme_id === false ) {
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT ' . $this->getUnitOption('theme', 'IDField') . '
FROM ' . $this->getUnitOption('theme', 'TableName') . '
WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
$theme_id = $this->Conn->GetOne($sql);
- if ($theme_id !== false) {
+ if ( $theme_id !== false ) {
$this->setCache($cache_key, $theme_id);
}
}
}
return $theme_id;
}
/**
* Returns site primary currency ISO code
*
* @return string
+ * @access public
+ * @todo Move into In-Commerce
*/
- function GetPrimaryCurrency()
+ public function GetPrimaryCurrency()
{
$cache_key = 'primary_currency[%CurrSerial%][%SiteDomainSerial%]:' . $this->siteDomainField('DomainId');
$currency_iso = $this->getCache($cache_key);
- if ($currency_iso === false) {
- if ($this->isModuleEnabled('In-Commerce')) {
+ if ( $currency_iso === false ) {
+ if ( $this->isModuleEnabled('In-Commerce') ) {
$this->Conn->nextQueryCachable = true;
$currency_id = $this->siteDomainField('PrimaryCurrencyId');
$sql = 'SELECT ISO
FROM ' . $this->getUnitOption('curr', 'TableName') . '
WHERE ' . ($currency_id > 0 ? 'CurrencyId = ' . $currency_id : 'IsPrimary = 1');
$currency_iso = $this->Conn->GetOne($sql);
}
else {
$currency_iso = 'USD';
}
$this->setCache($cache_key, $currency_iso);
}
return $currency_iso;
}
/**
* Returns site domain field. When none of site domains are found false is returned.
*
* @param string $field
* @param bool $formatted
* @param string $format
+ * @return mixed
+ * @todo Move into separate module
*/
- function siteDomainField($field, $formatted = false, $format = null)
+ public function siteDomainField($field, $formatted = false, $format = null)
{
- if ($this->isAdmin) {
+ if ( $this->isAdmin ) {
// don't apply any filtering in administrative console
return false;
}
- if (!$this->siteDomain) {
+ if ( !$this->siteDomain ) {
$this->siteDomain =& $this->recallObject('site-domain.current');
/* @var $site_domain kDBItem */
}
- if ($this->siteDomain->isLoaded()) {
+ if ( $this->siteDomain->isLoaded() ) {
return $formatted ? $this->siteDomain->GetField($field, $format) : $this->siteDomain->GetDBField($field);
}
return false;
}
/**
- * Registers default classes such as ItemController, GridController and LoginController
- *
- * Called automatically while initializing Application
- * @access private
- * @return void
- */
- function RegisterDefaultClasses()
+ * Registers default classes such as kDBEventHandler, kUrlManager
+ *
+ * Called automatically while initializing kApplication
+ *
+ * @return void
+ * @access public
+ */
+ public function RegisterDefaultClasses()
{
$this->registerClass('kHelper', KERNEL_PATH . '/kbase.php');
$this->registerClass('kMultipleFilter', KERNEL_PATH . '/utility/filters.php');
$this->registerClass('kiCacheable', KERNEL_PATH . '/interfaces/cacheable.php');
$this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager', 'kiCacheable');
$this->registerClass('kHookManager', KERNEL_PATH . '/managers/hook_manager.php', null, 'kiCacheable');
$this->registerClass('kScheduledTaskManager', KERNEL_PATH . '/managers/scheduled_task_manager.php', null, 'kiCacheable');
$this->registerClass('kRequestManager', KERNEL_PATH . '/managers/request_manager.php');
$this->registerClass('kUrlManager', KERNEL_PATH . '/managers/url_manager.php');
$this->registerClass('kUrlProcessor', KERNEL_PATH . '/managers/url_processor.php');
$this->registerClass('kPlainUrlProcessor', KERNEL_PATH . '/managers/plain_url_processor.php', null, 'kUrlProcessor');
$this->registerClass('kRewriteUrlProcessor', KERNEL_PATH . '/managers/rewrite_url_processor.php', null, 'kUrlProcessor');
$this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php', null, 'kiCacheable');
$this->registerClass('PhrasesCache', KERNEL_PATH . '/languages/phrases_cache.php', 'kPhraseCache');
$this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php');
$this->registerClass('kValidator', KERNEL_PATH . '/utility/validator.php');
$this->registerClass('kOpenerStack', KERNEL_PATH . '/utility/opener_stack.php');
$this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php');
// Params class descendants
$this->registerClass('kArray', KERNEL_PATH . '/utility/params.php');
$this->registerClass('Params', KERNEL_PATH . '/utility/params.php');
$this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions');
$this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'kCache', 'Params');
$this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery', 'Params');
// session
$this->registerClass('Session', KERNEL_PATH . '/session/session.php');
$this->registerClass('SessionStorage', KERNEL_PATH . '/session/session_storage.php');
$this->registerClass('InpSession', KERNEL_PATH . '/session/inp_session.php', 'Session');
$this->registerClass('InpSessionStorage', KERNEL_PATH . '/session/inp_session_storage.php', 'SessionStorage');
// template parser
$this->registerClass('kTagProcessor', KERNEL_PATH . '/processors/tag_processor.php');
$this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php', 'm_TagProcessor', 'kTagProcessor');
$this->registerClass('kDBTagProcessor', KERNEL_PATH . '/db/db_tag_processor.php', null, 'kTagProcessor');
$this->registerClass('kCatDBTagProcessor', KERNEL_PATH . '/db/cat_tag_processor.php', null, 'kDBTagProcessor');
$this->registerClass('NParser', KERNEL_PATH . '/nparser/nparser.php');
$this->registerClass('TemplatesCache', KERNEL_PATH . '/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor'));
// database
$this->registerClass('kDBConnection', KERNEL_PATH . '/db/db_connection.php');
$this->registerClass('kDBLoadBalancer', KERNEL_PATH . '/db/db_load_balancer.php');
$this->registerClass('kDBItem', KERNEL_PATH . '/db/dbitem.php');
$this->registerClass('kCatDBItem', KERNEL_PATH . '/db/cat_dbitem.php', null, 'kDBItem');
$this->registerClass('kDBList', KERNEL_PATH . '/db/dblist.php');
$this->registerClass('kCatDBList', KERNEL_PATH . '/db/cat_dblist.php', null, 'kDBList');
$this->registerClass('kDBEventHandler', KERNEL_PATH . '/db/db_event_handler.php');
$this->registerClass('kCatDBEventHandler', KERNEL_PATH . '/db/cat_event_handler.php', null, 'kDBEventHandler');
// email sending
$this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender', 'kHelper');
$this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket');
// do not move to config - this helper is used before configs are read
$this->registerClass('kModulesHelper', KERNEL_PATH . self::MODULE_HELPER_PATH, 'ModulesHelper');
}
- function RegisterDefaultBuildEvents()
+ /**
+ * Registers default build events
+ *
+ * @return void
+ * @access protected
+ */
+ protected function RegisterDefaultBuildEvents()
{
$this->EventManager->registerBuildEvent('kTempTablesHandler', 'OnTempHandlerBuild');
}
/**
- * Returns cached category informaton by given cache name. All given category
+ * Returns cached category information by given cache name. All given category
* information is recached, when at least one of 4 caches is missing.
*
* @param int $category_id
* @param string $name cache name = {filenames, category_designs, category_tree}
* @return string
* @access public
*/
public function getCategoryCache($category_id, $name)
{
return $this->cacheManager->getCategoryCache($category_id, $name);
}
/**
* Returns caching type (none, memory, temporary)
*
* @param int $caching_type
* @return bool
* @access public
*/
public function isCachingType($caching_type)
{
return $this->cacheManager->isCachingType($caching_type);
}
/**
* Increments serial based on prefix and it's ID (optional)
*
* @param string $prefix
* @param int $id ID (value of IDField) or ForeignKeyField:ID
* @param bool $increment
+ * @return string
* @access public
*/
public function incrementCacheSerial($prefix, $id = null, $increment = true)
{
return $this->cacheManager->incrementCacheSerial($prefix, $id, $increment);
}
/**
* Returns cached $key value from cache named $cache_name
*
* @param int $key key name from cache
* @param bool $store_locally store data locally after retrieved
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getCache($key, $store_locally = true, $max_rebuild_seconds = 0)
{
return $this->cacheManager->getCache($key, $store_locally, $max_rebuild_seconds);
}
/**
* Adds new value to cache $cache_name and identified by key $key
*
* @param int $key key name to add to cache
- * @param mixed $value value of chached record
+ * @param mixed $value value of cached record
* @param int $expiration when value expires (0 - doesn't expire)
+ * @return bool
* @access public
*/
public function setCache($key, $value, $expiration = 0)
{
return $this->cacheManager->setCache($key, $value, $expiration);
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
+ * @return void
+ * @access public
*/
public function rebuildCache($name, $mode = null, $max_rebuilding_time = 0)
{
$this->cacheManager->rebuildCache($name, $mode, $max_rebuilding_time);
}
/**
* Deletes key from cache
*
* @param string $key
+ * @return void
* @access public
*/
public function deleteCache($key)
{
$this->cacheManager->deleteCache($key);
}
/**
* Reset's all memory cache at once
*
+ * @return void
* @access public
*/
public function resetCache()
{
$this->cacheManager->resetCache();
}
/**
* Returns value from database cache
*
* @param string $name key name
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getDBCache($name, $max_rebuild_seconds = 0)
{
return $this->cacheManager->getDBCache($name, $max_rebuild_seconds);
}
/**
* Sets value to database cache
*
* @param string $name
* @param mixed $value
* @param int|bool $expiration
+ * @return void
* @access public
*/
public function setDBCache($name, $value, $expiration = false)
{
$this->cacheManager->setDBCache($name, $value, $expiration);
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
+ * @return void
+ * @access public
*/
public function rebuildDBCache($name, $mode = null, $max_rebuilding_time = 0)
{
$this->cacheManager->rebuildDBCache($name, $mode, $max_rebuilding_time);
}
/**
* Deletes key from database cache
*
* @param string $name
+ * @return void
* @access public
*/
public function deleteDBCache($name)
{
$this->cacheManager->deleteDBCache($name);
}
/**
* Registers each module specific constants if any found
*
* @return bool
+ * @access protected
*/
- function registerModuleConstants()
+ protected function registerModuleConstants()
{
if ( file_exists(KERNEL_PATH . '/constants.php') ) {
kUtil::includeOnce(KERNEL_PATH . '/constants.php');
}
if ( !$this->ModuleInfo ) {
return false;
}
foreach ($this->ModuleInfo as $module_info) {
$constants_file = FULL_PATH . '/' . $module_info['Path'] . 'constants.php';
if ( file_exists($constants_file) ) {
kUtil::includeOnce($constants_file);
}
}
return true;
}
/**
* Performs redirect to hard maintenance template
*
+ * @return void
* @access public
*/
public function redirectToMaintenance()
{
$maintenance_page = WRITEBALE_BASE . '/maintenance.html';
$query_string = ''; // $this->isAdmin ? '' : '?next_template=' . urlencode($_SERVER['REQUEST_URI']);
if ( file_exists(FULL_PATH . $maintenance_page) ) {
header('Location: ' . BASE_PATH . $maintenance_page . $query_string);
exit;
}
}
/**
- * Actually runs the parser against current template and stores parsing result
- *
- * This method gets t variable passed to the script, loads the template given in t variable and
- * parses it. The result is store in {@link $this->HTML} property.
- * @access public
- * @return void
- */
- function Run()
+ * Actually runs the parser against current template and stores parsing result
+ *
+ * This method gets 't' variable passed to the script, loads the template given in 't' variable and
+ * parses it. The result is store in {@link $this->HTML} property.
+ *
+ * @return void
+ * @access public
+ */
+ public function Run()
{
// process maintenance mode redirect: begin
$maintenance_mode = $this->getMaintenanceMode();
if ( $maintenance_mode == MaintenanceMode::HARD ) {
$this->redirectToMaintenance();
}
elseif ( $maintenance_mode == MaintenanceMode::SOFT ) {
$maintenance_template = $this->isAdmin ? 'login' : $this->ConfigValue('SoftMaintenanceTemplate');
if ( $this->GetVar('t') != $maintenance_template ) {
$redirect_params = Array ();
if ( !$this->isAdmin ) {
$redirect_params['next_template'] = urlencode($_SERVER['REQUEST_URI']);
}
$this->Redirect($maintenance_template, $redirect_params);
}
}
// process maintenance mode redirect: end
if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Run:');
}
if ( $this->isAdminUser ) {
// for permission checking in events & templates
- $this->LinkVar('module'); // for common configuration templates
- $this->LinkVar('module_key'); // for common search templates
- $this->LinkVar('section'); // for common configuration templates
+ $this->LinkVar('module'); // for common configuration templates
+ $this->LinkVar('module_key'); // for common search templates
+ $this->LinkVar('section'); // for common configuration templates
- if ($this->GetVar('m_opener') == 'p') {
- $this->LinkVar('main_prefix'); // window prefix, that opened selector
- $this->LinkVar('dst_field'); // field to set value choosed in selector
+ if ( $this->GetVar('m_opener') == 'p' ) {
+ $this->LinkVar('main_prefix'); // window prefix, that opened selector
+ $this->LinkVar('dst_field'); // field to set value choosed in selector
}
- if ($this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax')) {
+ if ( $this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax') ) {
// hide debug output from ajax requests automatically
kUtil::safeDefine('DBG_SKIP_REPORTING', 1); // safeDefine, because debugger also defines it
}
}
elseif ( $this->GetVar('admin') ) {
$admin_session =& $this->recallObject('Session.admin');
/* @var $admin_session Session */
// store Admin Console User's ID to Front-End's session for cross-session permission checks
$this->StoreVar('admin_user_id', (int)$admin_session->RecallVar('user_id'));
if ( $this->CheckAdminPermission('CATEGORY.MODIFY', 0, $this->getBaseCategory()) ) {
// user can edit cms blocks (when viewing front-end through admin's frame)
$editing_mode = $this->GetVar('editing_mode');
define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_BROWSE);
}
}
kUtil::safeDefine('EDITING_MODE', ''); // user can't edit anything
$this->Phrases->setPhraseEditing();
$this->EventManager->ProcessRequest();
$this->InitParser();
$t = $this->GetVar('render_template', $this->GetVar('t'));
if ( !$this->TemplatesCache->TemplateExists($t) && !$this->isAdmin ) {
$cms_handler =& $this->recallObject('st_EventHandler');
/* @var $cms_handler CategoriesEventHandler */
$t = ltrim($cms_handler->GetDesignTemplate(), '/');
if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendHTML('<strong>Design Template</strong>: ' . $t . '; <strong>CategoryID</strong>: ' . $this->GetVar('m_cat_id'));
}
}
/*else {
$cms_handler->SetCatByTemplate();
}*/
if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Parsing:');
}
$this->HTML = $this->Parser->Run($t);
if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application after Parsing:');
}
}
- function InitParser($theme_name = false)
+ /**
+ * Performs template parser/cache initialization
+ *
+ * @param bool|string $theme_name
+ * @return void
+ * @access public
+ */
+ public function InitParser($theme_name = false)
{
- if( !is_object($this->Parser) ) {
+ if ( !is_object($this->Parser) ) {
$this->Parser =& $this->recallObject('NParser');
$this->TemplatesCache =& $this->recallObject('TemplatesCache');
}
$this->TemplatesCache->forceThemeName = $theme_name;
}
/**
- * Send the parser results to browser
- *
- * Actually send everything stored in {@link $this->HTML}, to the browser by echoing it.
- * @access public
- * @return void
- */
- function Done()
+ * Send the parser results to browser
+ *
+ * Actually send everything stored in {@link $this->HTML}, to the browser by echoing it.
+ *
+ * @return void
+ * @access public
+ */
+ public function Done()
{
$this->HandleEvent(new kEvent('adm:OnBeforeShutdown'));
$debug_mode = defined('DEBUG_MODE') && $this->isDebugMode();
if ( $debug_mode && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Done:');
}
if ( $debug_mode ) {
$this->EventManager->runScheduledTasks(reAFTER);
$this->Session->SaveData();
if ( kUtil::constOn('DBG_CACHE') ) {
$this->cacheManager->printStatistics();
}
$this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true);
}
else {
// send "Set-Cookie" header before any output is made
$this->Session->SetSession();
$this->HTML = ob_get_clean() . $this->HTML;
}
if ( $this->UseOutputCompression() ) {
$compression_level = $this->ConfigValue('OutputCompressionLevel');
if ( !$compression_level || $compression_level < 0 || $compression_level > 9 ) {
$compression_level = 7;
}
header('Content-Encoding: gzip');
echo gzencode($this->HTML, $compression_level);
}
else {
echo $this->HTML;
}
$this->cacheManager->UpdateApplicationCache();
flush();
if ( !$debug_mode ) {
$this->EventManager->runScheduledTasks(reAFTER);
$this->Session->SaveData();
}
if ( defined('DBG_CAPTURE_STATISTICS') && DBG_CAPTURE_STATISTICS && !$this->isAdmin ) {
$this->_storeStatistics();
}
}
/**
* Stores script execution statistics to database
*
+ * @return void
+ * @access protected
*/
- function _storeStatistics()
+ protected function _storeStatistics()
{
global $start;
$script_time = microtime(true) - $start;
$query_statistics = $this->Conn->getQueryStatistics(); // time & count
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'StatisticsCapture
- WHERE TemplateName = ' . $this->Conn->qstr( $this->GetVar('t') );
+ WHERE TemplateName = ' . $this->Conn->qstr($this->GetVar('t'));
$data = $this->Conn->GetRow($sql);
- if ($data) {
+ if ( $data ) {
$this->_updateAverageStatistics($data, 'ScriptTime', $script_time);
$this->_updateAverageStatistics($data, 'SqlTime', $query_statistics['time']);
$this->_updateAverageStatistics($data, 'SqlCount', $query_statistics['count']);
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'StatisticsCapture', 'StatisticsId = ' . $data['StatisticsId']);
}
else {
$data['ScriptTimeMin'] = $data['ScriptTimeAvg'] = $data['ScriptTimeMax'] = $script_time;
$data['SqlTimeMin'] = $data['SqlTimeAvg'] = $data['SqlTimeMax'] = $query_statistics['time'];
$data['SqlCountMin'] = $data['SqlCountAvg'] = $data['SqlCountMax'] = $query_statistics['count'];
$data['TemplateName'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'StatisticsCapture');
}
}
/**
* Calculates average time for statistics
*
* @param Array $data
* @param string $field_prefix
* @param float $current_value
+ * @return void
+ * @access protected
*/
- function _updateAverageStatistics(&$data, $field_prefix, $current_value)
+ protected function _updateAverageStatistics(&$data, $field_prefix, $current_value)
{
$data[$field_prefix . 'Avg'] = (($data['Hits'] * $data[$field_prefix . 'Avg']) + $current_value) / ($data['Hits'] + 1);
- if ($current_value < $data[$field_prefix . 'Min']) {
+ if ( $current_value < $data[$field_prefix . 'Min'] ) {
$data[$field_prefix . 'Min'] = $current_value;
}
- if ($current_value > $data[$field_prefix . 'Max']) {
+ if ( $current_value > $data[$field_prefix . 'Max'] ) {
$data[$field_prefix . 'Max'] = $current_value;
}
}
- function logSlowQuery($slow_sql, $time)
+ /**
+ * Remembers slow query SQL and execution time into log
+ *
+ * @param string $slow_sql
+ * @param int $time
+ * @return void
+ * @access public
+ */
+ public function logSlowQuery($slow_sql, $time)
{
$query_crc = crc32($slow_sql);
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'SlowSqlCapture
WHERE QueryCrc = ' . $query_crc;
$data = $this->Conn->Query($sql, null, true);
- if ($data) {
+ if ( $data ) {
$this->_updateAverageStatistics($data, 'Time', $time);
$template_names = explode(',', $data['TemplateNames']);
array_push($template_names, $this->GetVar('t'));
$data['TemplateNames'] = implode(',', array_unique($template_names));
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'SlowSqlCapture', 'CaptureId = ' . $data['CaptureId']);
}
else {
$data['TimeMin'] = $data['TimeAvg'] = $data['TimeMax'] = $time;
$data['SqlQuery'] = $slow_sql;
$data['QueryCrc'] = $query_crc;
$data['TemplateNames'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'SlowSqlCapture');
}
}
/**
* Checks if output compression options is available
*
- * @return string
+ * @return bool
+ * @access protected
*/
- function UseOutputCompression()
+ protected function UseOutputCompression()
{
- if (kUtil::constOn('IS_INSTALL') || kUtil::constOn('DBG_ZEND_PRESENT') || kUtil::constOn('SKIP_OUT_COMPRESSION')) {
+ if ( kUtil::constOn('IS_INSTALL') || kUtil::constOn('DBG_ZEND_PRESENT') || kUtil::constOn('SKIP_OUT_COMPRESSION') ) {
return false;
}
return $this->ConfigValue('UseOutputCompression') && function_exists('gzencode') && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
}
// Facade
/**
- * Returns current session id (SID)
- * @access public
- * @return int
- */
- function GetSID()
+ * Returns current session id (SID)
+ *
+ * @return int
+ * @access public
+ */
+ public function GetSID()
{
$session =& $this->recallObject('Session');
/* @var $session Session */
return $session->GetID();
}
- function DestroySession()
+ /**
+ * Destroys current session
+ *
+ * @return void
+ * @access public
+ * @see UserHelper::logoutUser()
+ */
+ public function DestroySession()
{
$session =& $this->recallObject('Session');
/* @var $session Session */
$session->Destroy();
}
/**
* Returns variable passed to the script as GET/POST/COOKIE
*
* @param string $name Name of variable to retrieve
* @param mixed $default default value returned in case if variable not present
- *
* @return mixed
* @access public
*/
public function GetVar($name, $default = false)
{
return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default;
}
/**
* Returns variable passed to the script as $type
*
* @param string $name Name of variable to retrieve
* @param string $type Get/Post/Cookie
* @param mixed $default default value returned in case if variable not present
- *
* @return mixed
* @access public
*/
public function GetVarDirect($name, $type, $default = false)
{
// $type = ucfirst($type);
$array = $this->HttpQuery->$type;
return isset($array[$name]) ? $array[$name] : $default;
}
/**
- * Returns ALL variables passed to the script as GET/POST/COOKIE
- *
- * @access public
- * @return array
- */
- function GetVars()
+ * Returns ALL variables passed to the script as GET/POST/COOKIE
+ *
+ * @return Array
+ * @access public
+ * @deprecated
+ */
+ public function GetVars()
{
return $this->HttpQuery->GetParams();
}
/**
- * Set the variable 'as it was passed to the script through GET/POST/COOKIE'
- *
- * This could be useful to set the variable when you know that
- * other objects would relay on variable passed from GET/POST/COOKIE
- * or you could use SetVar() / GetVar() pairs to pass the values between different objects.<br>
- *
- * This method is formerly known as $this->Session->SetProperty.
- * @param string $var Variable name to set
- * @param mixed $val Variable value
- * @access public
- * @return void
- */
+ * Set the variable 'as it was passed to the script through GET/POST/COOKIE'
+ *
+ * This could be useful to set the variable when you know that
+ * other objects would relay on variable passed from GET/POST/COOKIE
+ * or you could use SetVar() / GetVar() pairs to pass the values between different objects.<br>
+ *
+ * @param string $var Variable name to set
+ * @param mixed $val Variable value
+ * @return void
+ * @access public
+ */
public function SetVar($var,$val)
{
$this->HttpQuery->Set($var, $val);
}
/**
* Deletes kHTTPQuery variable
*
* @param string $var
- * @todo think about method name
+ * @return void
+ * @todo Think about method name
*/
- function DeleteVar($var)
+ public function DeleteVar($var)
{
- return $this->HttpQuery->Remove($var);
+ $this->HttpQuery->Remove($var);
}
/**
* Deletes Session variable
*
* @param string $var
+ * @return void
+ * @access public
*/
- function RemoveVar($var)
+ public function RemoveVar($var)
{
- return $this->Session->RemoveVar($var);
+ $this->Session->RemoveVar($var);
}
- function RemovePersistentVar($var)
+ /**
+ * Removes variable from persistent session
+ *
+ * @param string $var
+ * @return void
+ * @access public
+ */
+ public function RemovePersistentVar($var)
{
- return $this->Session->RemovePersistentVar($var);
+ $this->Session->RemovePersistentVar($var);
}
/**
* Restores Session variable to it's db version
*
* @param string $var
+ * @return void
+ * @access public
*/
- function RestoreVar($var)
+ public function RestoreVar($var)
{
- return $this->Session->RestoreVar($var);
+ $this->Session->RestoreVar($var);
}
/**
- * Returns session variable value
- *
- * Return value of $var variable stored in Session. An optional default value could be passed as second parameter.
- *
- * @see SimpleSession
- * @access public
- * @param string $var Variable name
- * @param mixed $default Default value to return if no $var variable found in session
- * @return mixed
- */
- function RecallVar($var,$default=false)
+ * Returns session variable value
+ *
+ * Return value of $var variable stored in Session. An optional default value could be passed as second parameter.
+ *
+ * @param string $var Variable name
+ * @param mixed $default Default value to return if no $var variable found in session
+ * @return mixed
+ * @access public
+ * @see Session::RecallVar()
+ */
+ public function RecallVar($var,$default=false)
{
return $this->Session->RecallVar($var,$default);
}
- function RecallPersistentVar($var, $default = false)
+ /**
+ * Returns variable value from persistent session
+ *
+ * @param string $var
+ * @param mixed $default
+ * @return mixed
+ * @access public
+ * @see Session::RecallPersistentVar()
+ */
+ public function RecallPersistentVar($var, $default = false)
{
return $this->Session->RecallPersistentVar($var, $default);
}
/**
* Stores variable $val in session under name $var
*
* Use this method to store variable in session. Later this variable could be recalled.
*
* @param string $var Variable name
* @param mixed $val Variable value
* @param bool $optional
- * @see kApplication::RecallVar()
+ * @return void
* @access public
+ * @see kApplication::RecallVar()
*/
- function StoreVar($var, $val, $optional = false)
+ public function StoreVar($var, $val, $optional = false)
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$this->Session->StoreVar($var, $val, $optional);
}
- function StorePersistentVar($var, $val, $optional = false)
+ /**
+ * Stores variable to persistent session
+ *
+ * @param string $var
+ * @param mixed $val
+ * @param bool $optional
+ * @return void
+ * @access public
+ */
+ public function StorePersistentVar($var, $val, $optional = false)
{
$this->Session->StorePersistentVar($var, $val, $optional);
}
- function StoreVarDefault($var, $val, $optional=false)
+ /**
+ * Stores default value for session variable
+ *
+ * @param string $var
+ * @param string $val
+ * @param bool $optional
+ * @return void
+ * @access public
+ * @see Session::RecallVar()
+ * @see Session::StoreVar()
+ */
+ public function StoreVarDefault($var, $val, $optional = false)
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$this->Session->StoreVarDefault($var, $val, $optional);
}
/**
- * Links HTTP Query variable with session variable
- *
- * If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session.
- * This method could be used for making sure that GetVar will return query or session value for given
- * variable, when query variable should overwrite session (and be stored there for later use).<br>
- * This could be used for passing item's ID into popup with multiple tab -
- * in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id').
- * After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session
- * @access public
- * @param string $var HTTP Query (GPC) variable name
- * @param mixed $ses_var Session variable name
- * @param mixed $default Default variable value
- * @param bool $optional
- */
- function LinkVar($var, $ses_var = null, $default = '', $optional = false)
+ * Links HTTP Query variable with session variable
+ *
+ * If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session.
+ * This method could be used for making sure that GetVar will return query or session value for given
+ * variable, when query variable should overwrite session (and be stored there for later use).<br>
+ * This could be used for passing item's ID into popup with multiple tab -
+ * in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id').
+ * After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session
+ *
+ * @param string $var HTTP Query (GPC) variable name
+ * @param mixed $ses_var Session variable name
+ * @param mixed $default Default variable value
+ * @param bool $optional
+ * @return void
+ * @access public
+ */
+ public function LinkVar($var, $ses_var = null, $default = '', $optional = false)
{
- if (!isset($ses_var)) $ses_var = $var;
- if ($this->GetVar($var) !== false) {
+ if ( !isset($ses_var) ) {
+ $ses_var = $var;
+ }
+
+ if ( $this->GetVar($var) !== false ) {
$this->StoreVar($ses_var, $this->GetVar($var), $optional);
}
else {
$this->SetVar($var, $this->RecallVar($ses_var, $default));
}
}
/**
- * Returns variable from HTTP Query, or from session if not passed in HTTP Query
- *
- * The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed.
- * Returns the default value if variable does not exist in session and was not passed in HTTP Query
- *
- * @see LinkVar
- * @access public
- * @param string $var HTTP Query (GPC) variable name
- * @param mixed $ses_var Session variable name
- * @param mixed $default Default variable value
- * @return mixed
- */
- function GetLinkedVar($var, $ses_var = null, $default = '')
+ * Returns variable from HTTP Query, or from session if not passed in HTTP Query
+ *
+ * The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed.
+ * Returns the default value if variable does not exist in session and was not passed in HTTP Query
+ *
+ * @param string $var HTTP Query (GPC) variable name
+ * @param mixed $ses_var Session variable name
+ * @param mixed $default Default variable value
+ * @return mixed
+ * @access public
+ * @see LinkVar
+ */
+ public function GetLinkedVar($var, $ses_var = null, $default = '')
{
$this->LinkVar($var, $ses_var, $default);
+
return $this->GetVar($var);
}
- function ProcessParsedTag($prefix, $tag, $params)
+ /**
+ * Renders given tag and returns it's output
+ *
+ * @param string $prefix
+ * @param string $tag
+ * @param Array $params
+ * @return mixed
+ * @access public
+ * @see kApplication::InitParser()
+ */
+ public function ProcessParsedTag($prefix, $tag, $params)
{
$processor = $this->Parser->GetProcessor($prefix);
/* @var $processor kDBTagProcessor */
return $processor->ProcessParsedTag($tag, $params, $prefix);
}
/**
* Return ADODB Connection object
*
* Returns ADODB Connection object already connected to the project database, configurable in config.php
* @access public
* @return kDBConnection
*/
function &GetADODBConnection()
{
return $this->Conn;
}
/**
* Allows to parse given block name or include template
*
* @param Array $params Parameters to pass to block. Reserved parameter "name" used to specify block name.
* @param bool $pass_params Forces to pass current parser params to this block/template. Use with caution, because you can accidentally pass "block_no_data" parameter.
* @param bool $as_template
* @return string
*/
function ParseBlock($params, $pass_params = false, $as_template = false)
{
if (substr($params['name'], 0, 5) == 'html:') {
return substr($params['name'], 5);
}
return $this->Parser->ParseBlock($params, $pass_params, $as_template);
}
/**
* Checks, that we have given block defined
*
* @param string $name
* @return bool
*/
function ParserBlockFound($name)
{
return $this->Parser->blockFound($name);
}
/**
* Allows to include template with a given name and given parameters
*
* @param Array $params Parameters to pass to template. Reserved parameter "name" used to specify template name.
* @return string
*/
function IncludeTemplate($params)
{
return $this->Parser->IncludeTemplate($params, isset($params['is_silent']) ? 1 : 0);
}
/**
* Return href for template
*
* @param string $t Template path
* @param string $prefix index.php prefix - could be blank, 'admin'
* @param Array $params
* @param string $index_file
* @return string
*/
public function HREF($t, $prefix = '', $params = Array (), $index_file = null)
{
return $this->UrlManager->HREF($t, $prefix, $params, $index_file);
}
/**
* Returns theme template filename and it's corresponding page_id based on given seo template
*
* @param string $seo_template
* @return string
* @access public
*/
public function getPhysicalTemplate($seo_template)
{
return $this->UrlManager->getPhysicalTemplate($seo_template);
}
/**
* Returns template name, that corresponds with given virtual (not physical) page id
*
* @param int $page_id
* @return string|bool
* @access public
*/
public function getVirtualPageTemplate($page_id)
{
return $this->UrlManager->getVirtualPageTemplate($page_id);
}
/**
* Returns variables with values that should be passed through with this link + variable list
*
* @param Array $params
* @return Array
*/
function getPassThroughVariables(&$params)
{
return $this->UrlManager->getPassThroughVariables($params);
}
public function BuildEnv($t, $params, $pass = 'all', $pass_events = false, $env_var = true)
{
return $this->UrlManager->plain->build($t, $params, $pass, $pass_events, $env_var);
}
/**
* Process QueryString only, create
* events, ids, based on config
* set template name and sid in
* desired application variables.
*
* @param string $env_var environment string value
* @param string $pass_name
* @return Array
* @access public
*/
public function processQueryString($env_var, $pass_name = 'passed')
{
return $this->UrlManager->plain->parse($env_var, $pass_name);
}
function BaseURL($prefix = '', $ssl = null, $add_port = true)
{
if ($ssl === null) {
// stay on same encryption level
return PROTOCOL . SERVER_NAME . ($add_port && defined('PORT') ? ':' . PORT : '') . BASE_PATH . $prefix . '/';
}
if ($ssl) {
// going from http:// to https://
$base_url = $this->isAdmin ? $this->ConfigValue('AdminSSL_URL') : false;
if (!$base_url) {
$ssl_url = $this->siteDomainField('SSLUrl');
$base_url = $ssl_url !== false ? $ssl_url : $this->ConfigValue('SSL_URL');
}
return rtrim($base_url, '/') . $prefix . '/';
}
// going from https:// to http://
$domain = $this->siteDomainField('DomainName');
if ($domain === false) {
$domain = DOMAIN;
}
return 'http://' . $domain . ($add_port && defined('PORT') ? ':' . PORT : '') . BASE_PATH . $prefix . '/';
}
function Redirect($t = '', $params = Array(), $prefix = '', $index_file = null)
{
$js_redirect = getArrayValue($params, 'js_redirect');
if ($t == '' || $t === true) {
$t = $this->GetVar('t');
}
// pass prefixes and special from previous url
if (array_key_exists('js_redirect', $params)) {
unset($params['js_redirect']);
}
// allows to send custom responce code along with redirect header
if (array_key_exists('response_code', $params)) {
$response_code = (int)$params['response_code'];
unset($params['response_code']);
}
else {
$response_code = 302; // Found
}
if (!array_key_exists('pass', $params)) {
$params['pass'] = 'all';
}
if ($this->GetVar('ajax') == 'yes' && $t == $this->GetVar('t')) {
// redirects to the same template as current
$params['ajax'] = 'yes';
}
$params['__URLENCODE__'] = 1;
$location = $this->HREF($t, $prefix, $params, $index_file);
if ($this->isDebugMode() && (kUtil::constOn('DBG_REDIRECT') || (kUtil::constOn('DBG_RAISE_ON_WARNINGS') && $this->Debugger->WarningCount))) {
$this->Debugger->appendTrace();
echo '<strong>Debug output above !!!</strong><br/>' . "\n";
if ( array_key_exists('HTTP_REFERER', $_SERVER) ) {
echo 'Referer: <strong>' . $_SERVER['HTTP_REFERER'] . '</strong><br/>' . "\n";
}
echo "Proceed to redirect: <a href=\"{$location}\">{$location}</a><br/>\n";
}
else {
if ($js_redirect) {
// show "redirect" template instead of redirecting,
// because "Set-Cookie" header won't work, when "Location"
// header is used later
$this->SetVar('t', 'redirect');
$this->SetVar('redirect_to', $location);
// make all additional parameters available on "redirect" template too
foreach ($params as $name => $value) {
$this->SetVar($name, $value);
}
return true;
}
else {
if ($this->GetVar('ajax') == 'yes' && $t != $this->GetVar('t')) {
// redirection to other then current template during ajax request
kUtil::safeDefine('DBG_SKIP_REPORTING', 1);
echo '#redirect#' . $location;
}
elseif (headers_sent() != '') {
// some output occured -> redirect using javascript
echo '<script type="text/javascript">window.location.href = \'' . $location . '\';</script>';
}
else {
// no output before -> redirect using HTTP header
// header('HTTP/1.1 302 Found');
header('Location: ' . $location, true, $response_code);
}
}
}
// session expiration is called from session initialization,
// that's why $this->Session may be not defined here
$session =& $this->recallObject('Session');
/* @var $session Session */
$this->HandleEvent( new kEvent('adm:OnBeforeShutdown') );
$session->SaveData();
ob_end_flush();
exit;
}
function Phrase($label, $allow_editing = true, $use_admin = false)
{
return $this->Phrases->GetPhrase($label, $allow_editing, $use_admin);
}
/**
* Replace language tags in exclamation marks found in text
*
* @param string $text
* @param bool $force_escape force escaping, not escaping of resulting string
* @return string
* @access public
*/
function ReplaceLanguageTags($text, $force_escape = null)
{
return $this->Phrases->ReplaceLanguageTags($text, $force_escape);
}
/**
* Checks if user is logged in, and creates
* user object if so. User object can be recalled
* later using "u.current" prefix_special. Also you may
* get user id by getting "u.current_id" variable.
*
* @access private
*/
function ValidateLogin()
{
$session =& $this->recallObject('Session');
/* @var $session Session */
$user_id = $session->GetField('PortalUserId');
if ( !$user_id && $user_id != USER_ROOT ) {
$user_id = USER_GUEST;
}
$this->SetVar('u.current_id', $user_id);
if ( !$this->isAdmin ) {
// needed for "profile edit", "registration" forms ON FRONT ONLY
$this->SetVar('u_id', $user_id);
}
$this->StoreVar('user_id', $user_id, $user_id == USER_GUEST); // storing Guest user_id (-2) is optional
$this->isAdminUser = $this->isAdmin && $this->LoggedIn();
if ( $this->GetVar('expired') == 1 ) {
// this parameter is set only from admin
$user =& $this->recallObject('u.login-admin', null, Array ('form_name' => 'login'));
/* @var $user UsersItem */
$user->SetError('UserLogin', 'session_expired', 'la_text_sess_expired');
}
if ( ($user_id != USER_GUEST) && defined('DBG_REQUREST_LOG') && DBG_REQUREST_LOG ) {
$this->HttpQuery->writeRequestLog(DBG_REQUREST_LOG);
}
if ( $user_id != USER_GUEST ) {
// normal users + root
$this->LoadPersistentVars();
}
$user_timezone = $this->Session->GetField('TimeZone');
if ( $user_timezone ) {
putenv('TZ=' . $user_timezone);
}
}
/**
* Loads current user persistent session data
*
*/
function LoadPersistentVars()
{
$this->Session->LoadPersistentVars();
}
/**
* Returns configuration option value by name
*
* @param string $name
* @return string
*/
function ConfigValue($name)
{
return $this->cacheManager->ConfigValue($name);
}
/**
* Changes value of individual configuration variable (+resets cache, when needed)
*
* @param string $name
* @param string $value
* @param bool $local_cache_only
* @return string
* @access public
*/
public function SetConfigValue($name, $value, $local_cache_only = false)
{
return $this->cacheManager->SetConfigValue($name, $value, $local_cache_only);
}
/**
* Allows to process any type of event
*
* @param kEvent $event
* @param Array $params
* @param Array $specific_params
* @access public
* @author Alex
*/
function HandleEvent(&$event, $params = null, $specific_params = null)
{
if ( isset($params) ) {
$event = new kEvent($params, $specific_params);
}
$this->EventManager->HandleEvent($event);
}
/**
* Registers new class in the factory
*
* @param string $real_class Real name of class as in class declaration
* @param string $file Filename in what $real_class is declared
* @param string $pseudo_class Name under this class object will be accessed using getObject method
* @param Array $dependecies List of classes required for this class functioning
* @access public
* @author Alex
*/
function registerClass($real_class, $file, $pseudo_class = null, $dependecies = Array() )
{
$this->Factory->registerClass($real_class, $file, $pseudo_class, $dependecies);
}
/**
* Unregisters existing class from factory
*
* @param string $real_class Real name of class as in class declaration
* @param string $pseudo_class Name under this class object is accessed using getObject method
*/
function unregisterClass($real_class, $pseudo_class = null)
{
$this->Factory->unregisterClass($real_class, $pseudo_class);
}
/**
* Add $class_name to required classes list for $depended_class class.
* All required class files are included before $depended_class file is included
*
* @param string $depended_class
* @param string $class_name
* @author Alex
*/
function registerDependency($depended_class, $class_name)
{
$this->Factory->registerDependency($depended_class, $class_name);
}
/**
* Add new scheduled task
*
* @param string $short_name name to be used to store last maintenance run info
* @param string $event_name
* @param int $run_interval run interval in seconds
* @param int $type before or after scheduled task
* @param int $status
* @access public
*/
public function registerScheduledTask($short_name, $event_name, $run_interval, $type = reBEFORE, $status = STATUS_ACTIVE)
{
$this->EventManager->registerScheduledTask($short_name, $event_name, $run_interval, $type, $status);
}
/**
* Registers Hook from subprefix event to master prefix event
*
* Pattern: Observer
*
* @param string $hook_event
* @param string $do_event
* @param int $mode
* @param bool $conditional
* @access public
*/
public function registerHook($hook_event, $do_event, $mode = hAFTER, $conditional = false)
{
$this->EventManager->registerHook($hook_event, $do_event, $mode, $conditional);
}
/**
* Registers build event for given pseudo class
*
* @param string $pseudo_class
* @param string $event_name
* @access public
*/
public function registerBuildEvent($pseudo_class, $event_name)
{
$this->EventManager->registerBuildEvent($pseudo_class, $event_name);
}
/**
* Allows one TagProcessor tag act as other TagProcessor tag
*
* @param Array $tag_info
* @author Kostja
*/
function registerAggregateTag($tag_info)
{
$aggregator =& $this->recallObject('TagsAggregator', 'kArray');
/* @var $aggregator kArray */
$tag_data = Array(
$tag_info['LocalPrefix'],
$tag_info['LocalTagName'],
getArrayValue($tag_info, 'LocalSpecial')
);
$aggregator->SetArrayValue($tag_info['AggregateTo'], $tag_info['AggregatedTagName'], $tag_data);
}
/**
* Returns object using params specified, creates it if is required
*
* @param string $name
* @param string $pseudo_class
* @param Array $event_params
* @param Array $arguments
* @return kBase
*/
public function &recallObject($name, $pseudo_class = null, $event_params = Array(), $arguments = Array ())
{
/*if ( !$this->hasObject($name) && $this->isDebugMode() && ($name == '_prefix_here_') ) {
// first time, when object with "_prefix_here_" prefix is accessed
$this->Debugger->appendTrace();
}*/
$result =& $this->Factory->getObject($name, $pseudo_class, $event_params, $arguments);
return $result;
}
/**
* Returns tag processor for prefix specified
*
* @param string $prefix
* @return kDBTagProcessor
*/
function &recallTagProcessor($prefix)
{
$this->InitParser(); // because kDBTagProcesor is in NParser dependencies
$result =& $this->recallObject($prefix . '_TagProcessor');
return $result;
}
/**
* Checks if object with prefix passes was already created in factory
*
* @param string $name object presudo_class, prefix
* @return bool
* @author Kostja
*/
function hasObject($name)
{
return isset($this->Factory->Storage[$name]);
}
/**
* Removes object from storage by given name
*
* @param string $name Object's name in the Storage
* @author Kostja
*/
public function removeObject($name)
{
$this->Factory->DestroyObject($name);
}
/**
* Get's real class name for pseudo class, includes class file and creates class instance
*
* Pattern: Factory Method
*
* @param string $pseudo_class
* @param Array $arguments
* @return kBase
* @access public
*/
public function &makeClass($pseudo_class, $arguments = Array ())
{
$result =& $this->Factory->makeClass($pseudo_class, $arguments);
return $result;
}
/**
* Checks if application is in debug mode
*
* @param bool $check_debugger check if kApplication debugger is initialized too, not only for defined DEBUG_MODE constant
* @return bool
* @author Alex
* @access public
*/
public function isDebugMode($check_debugger = true)
{
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
if ($check_debugger) {
$debug_mode = $debug_mode && is_object($this->Debugger);
}
return $debug_mode;
}
/**
* Apply url rewriting used by mod_rewrite or not
*
* @param bool|null $ssl Force ssl link to be build
* @return bool
*/
function RewriteURLs($ssl = false)
{
// case #1,#4:
// we want to create https link from http mode
// we want to create https link from https mode
// conditions: ($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')
// case #2,#3:
// we want to create http link from https mode
// we want to create http link from http mode
// conditions: !$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')
$allow_rewriting =
(!$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')) // always allow mod_rewrite for http
|| // or allow rewriting for redirect TO httpS or when already in httpS
(($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')); // but only if it's allowed in config!
return kUtil::constOn('MOD_REWRITE') && $allow_rewriting;
}
/**
* Reads unit (specified by $prefix)
* option specified by $option
*
* @param string $prefix
* @param string $option
* @param mixed $default
* @return string
* @access public
*/
public function getUnitOption($prefix, $option, $default = false)
{
return $this->UnitConfigReader->getUnitOption($prefix, $option, $default);
}
/**
* Set's new unit option value
*
* @param string $prefix
* @param string $option
* @param string $value
* @access public
*/
public function setUnitOption($prefix, $option, $value)
{
$this->UnitConfigReader->setUnitOption($prefix,$option,$value);
}
/**
* Read all unit with $prefix options
*
* @param string $prefix
* @return Array
* @access public
*/
public function getUnitOptions($prefix)
{
return $this->UnitConfigReader->getUnitOptions($prefix);
}
/**
* Returns true if config exists and is allowed for reading
*
* @param string $prefix
* @return bool
*/
public function prefixRegistred($prefix)
{
return $this->UnitConfigReader->prefixRegistred($prefix);
}
/**
* Splits any mixing of prefix and
* special into correct ones
*
* @param string $prefix_special
* @return Array
* @access public
*/
public function processPrefix($prefix_special)
{
return $this->Factory->processPrefix($prefix_special);
}
/**
* Set's new event for $prefix_special
* passed
*
* @param string $prefix_special
* @param string $event_name
* @access public
*/
function setEvent($prefix_special, $event_name)
{
$this->EventManager->setEvent($prefix_special,$event_name);
}
/**
* SQL Error Handler
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
* @author Alex
*/
function handleSQLError($code, $msg, $sql)
{
if ( isset($this->Debugger) ) {
$long_error_msg = '<span class="debug_error">' . $msg . ' (' . $code . ')</span><br/><a href="javascript:$Debugger.SetClipboard(\'' . htmlspecialchars($sql) . '\');"><strong>SQL</strong></a>: ' . $this->Debugger->formatSQL($sql);
$long_id = $this->Debugger->mapLongError($long_error_msg);
$error_msg = mb_substr($msg . ' (' . $code . ') [' . $sql . ']', 0, 1000) . ' #' . $long_id;
if ( kUtil::constOn('DBG_SQL_FAILURE') && !defined('IS_INSTALL') ) {
throw new Exception($error_msg);
}
else {
$this->Debugger->appendTrace();
}
}
else {
// when not debug mode, then fatal database query won't break anything
$error_msg = '<strong>SQL Error</strong> in sql: ' . $sql . ', code <strong>' . $code . '</strong> (' . $msg . ')';
}
trigger_error($error_msg, E_USER_WARNING);
return true;
}
/**
* Default error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array $errcontext
* @return bool
* @access public
*/
public function handleError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ())
{
$this->errorLogSilent($errno, $errstr, $errfile, $errline);
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
if ( !$this->errorHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
if ( $errno == E_USER_ERROR ) {
$this->errorDisplayFatal('<strong>Fatal Error: </strong>' . "{$errstr} in {$errfile} on line {$errline}");
}
if ( !$this->errorHandlers ) {
return true;
}
}
$res = false;
/* @var $handler Closure */
foreach ($this->errorHandlers as $handler) {
if ( is_array($handler) ) {
$object =& $handler[0];
$method = $handler[1];
$res = $object->$method($errno, $errstr, $errfile, $errline, $errcontext);
}
else {
$res = $handler($errno, $errstr, $errfile, $errline, $errcontext);
}
}
return $res;
}
/**
* Handles exception
*
* @param Exception $exception
* @return bool
* @access public
*/
public function handleException($exception)
{
// transform exception to regular error (no need to rewrite existing error handlers)
$errno = $exception->getCode();
$errstr = $exception->getMessage();
$errfile = $exception->getFile();
$errline = $exception->getLine();
$this->errorLogSilent($errno, $errstr, $errfile, $errline);
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
if ( !$this->exceptionHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
$this->errorDisplayFatal('<strong>' . get_class($exception) . ': </strong>' . "{$errstr} in {$errfile} on line {$errline}");
if ( !$this->exceptionHandlers ) {
return true;
}
}
$res = false;
/* @var $handler Closure */
foreach ($this->exceptionHandlers as $handler) {
if ( is_array($handler) ) {
$object =& $handler[0];
$method = $handler[1];
$res = $object->$method($exception);
}
else {
$res = $handler($exception);
}
}
return $res;
}
/**
* Silently saves each given error message to "silent_log.txt" file, when silent log mode is enabled
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @return void
* @access protected
*/
protected function errorLogSilent($errno, $errstr = '', $errfile = '', $errline = null)
{
if ( !defined('SILENT_LOG') || !SILENT_LOG ) {
return;
}
if ( !(defined('DBG_IGNORE_STRICT_ERRORS') && DBG_IGNORE_STRICT_ERRORS && defined('E_STRICT') && ($errno == E_STRICT)) ) {
$time = adodb_date('d/m/Y H:i:s');
$fp = fopen((defined('RESTRICTED') ? RESTRICTED : FULL_PATH) . '/silent_log.txt', 'a');
fwrite($fp, '[' . $time . '] #' . $errno . ': ' . strip_tags($errstr) . ' in [' . $errfile . '] on line ' . $errline . "\n");
fclose($fp);
}
}
/**
* Displays div with given error message
*
* @param string $msg
* @return void
* @access protected
*/
protected function errorDisplayFatal($msg)
{
$margin = $this->isAdmin ? '8px' : 'auto';
echo '<div style="background-color: #FEFFBF; margin: ' . $margin . '; padding: 10px; border: 2px solid red; text-align: center">' . $msg . '</div>';
exit;
}
/**
* Prints trace, when debug mode is not available
*
* @param bool $return_result
* @param int $skip_levels
* @return string
* @access public
*/
public function printTrace($return_result = false, $skip_levels = 1)
{
$ret = Array ();
$trace = debug_backtrace(false);
for ($i = 0; $i < $skip_levels; $i++) {
array_shift($trace);
}
foreach ($trace as $level => $trace_info) {
if ( isset($trace_info['class']) ) {
$object = $trace_info['class'];
}
elseif ( isset($trace_info['object']) ) {
$object = get_class($trace_info['object']);
}
else {
$object = '';
}
$args = '';
$type = isset($trace_info['type']) ? $trace_info['type'] : '';
if ( isset($trace_info['args']) ) {
foreach ($trace_info['args'] as $argument) {
if ( is_object($argument) ) {
$args .= get_class($argument) . ' instance, ';
}
else {
$args .= is_array($argument) ? 'Array' : substr($argument, 0, 10) . ' ..., ';
}
}
$args = substr($args, 0, -2);
}
$ret[] = '#' . $level . ' ' . $object . $type . $trace_info['function'] . '(' . $args . ') called at [' . $trace_info['file'] . ':' . $trace_info['line'] . ']';
}
if ( $return_result ) {
return implode("\n", $ret);
}
echo implode("\n", $ret);
return '';
}
/**
* Returns & blocks next ResourceId available in system
*
* @return int
* @access public
* @author Alex
*/
function NextResourceId()
{
$table_name = TABLE_PREFIX.'IdGenerator';
$this->Conn->Query('LOCK TABLES '.$table_name.' WRITE');
$this->Conn->Query('UPDATE '.$table_name.' SET lastid = lastid + 1');
$id = $this->Conn->GetOne('SELECT lastid FROM '.$table_name);
if($id === false)
{
$this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)');
$id = 2;
}
$this->Conn->Query('UNLOCK TABLES');
return $id - 1;
}
/**
* Returns genealogical main prefix for sub-table prefix passes
* OR prefix, that has been found in REQUEST and some how is parent of passed sub-table prefix
*
* @param string $current_prefix
* @param bool $real_top if set to true will return real topmost prefix, regardless of its id is passed or not
* @return string
* @access public
*/
function GetTopmostPrefix($current_prefix, $real_top = false)
{
// 1. get genealogical tree of $current_prefix
$prefixes = Array ($current_prefix);
while ( $parent_prefix = $this->getUnitOption($current_prefix, 'ParentPrefix') ) {
if (!$this->prefixRegistred($parent_prefix)) {
// stop searching, when parent prefix is not registered
break;
}
$current_prefix = $parent_prefix;
array_unshift($prefixes, $current_prefix);
}
if ($real_top) {
return $current_prefix;
}
// 2. find what if parent is passed
$passed = explode(',', $this->GetVar('all_passed'));
foreach ($prefixes as $a_prefix) {
if (in_array($a_prefix, $passed)) {
return $a_prefix;
}
}
return $current_prefix;
}
/**
* Triggers email event of type Admin
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEventAdmin($email_event_name, $to_user_id = null, $send_params = Array ())
{
$event =& $this->EmailEvent($email_event_name, EmailEvent::EVENT_TYPE_ADMIN, $to_user_id, $send_params);
return $event;
}
/**
* Triggers email event of type User
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEventUser($email_event_name, $to_user_id = null, $send_params = Array ())
{
$event =& $this->EmailEvent($email_event_name, EmailEvent::EVENT_TYPE_FRONTEND, $to_user_id, $send_params);
return $event;
}
/**
* Triggers general email event
*
* @param string $email_event_name
* @param int $email_event_type (0 for User, 1 for Admin)
* @param int $to_user_id
* @param array $send_params associative array of direct send params,
* possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return kEvent
*/
function &EmailEvent($email_event_name, $email_event_type, $to_user_id = null, $send_params = Array ())
{
$params = Array (
'EmailEventName' => $email_event_name,
'EmailEventToUserId' => $to_user_id,
'EmailEventType' => $email_event_type,
'DirectSendParams' => $send_params,
);
if (array_key_exists('use_special', $send_params)) {
$event_str = 'emailevents.' . $send_params['use_special'] . ':OnEmailEvent';
}
else {
$event_str = 'emailevents:OnEmailEvent';
}
$this->HandleEvent($event, $event_str, $params);
return $event;
}
/**
* Allows to check if user in this session is logged in or not
*
* @return bool
*/
function LoggedIn()
{
// no session during expiration process
return is_null($this->Session) ? false : $this->Session->LoggedIn();
}
/**
* Check current user permissions based on it's group permissions in specified category
*
* @param string $name permission name
* @param int $cat_id category id, current used if not specified
* @param int $type permission type {1 - system, 0 - per category}
* @return int
*/
function CheckPermission($name, $type = 1, $cat_id = null)
{
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
return $perm_helper->CheckPermission($name, $type, $cat_id);
}
/**
* Check current admin permissions based on it's group permissions in specified category
*
* @param string $name permission name
* @param int $cat_id category id, current used if not specified
* @param int $type permission type {1 - system, 0 - per category}
* @return int
*/
function CheckAdminPermission($name, $type = 1, $cat_id = null)
{
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
return $perm_helper->CheckAdminPermission($name, $type, $cat_id);
}
/**
* Set's any field of current visit
*
* @param string $field
* @param mixed $value
*/
function setVisitField($field, $value)
{
if ($this->isAdmin || !$this->ConfigValue('UseVisitorTracking')) {
// admin logins are not registred in visits list
return ;
}
$visit =& $this->recallObject('visits', null, Array ('raise_warnings' => 0));
/* @var $visit kDBItem */
if ($visit->isLoaded()) {
$visit->SetDBField($field, $value);
$visit->Update();
}
}
/**
* Allows to check if in-portal is installed
*
* @return bool
*/
function isInstalled()
{
return $this->InitDone && (count($this->ModuleInfo) > 0);
}
/**
* Allows to determine if module is installed & enabled
*
* @param string $module_name
* @return bool
*/
function isModuleEnabled($module_name)
{
return $this->findModule('Name', $module_name) !== false;
}
/**
* Returns Window ID of passed prefix main prefix (in edit mode)
*
* @param string $prefix
* @return mixed
*/
function GetTopmostWid($prefix)
{
$top_prefix = $this->GetTopmostPrefix($prefix);
$mode = $this->GetVar($top_prefix.'_mode');
return $mode != '' ? substr($mode, 1) : '';
}
/**
* Get temp table name
*
* @param string $table
* @param mixed $wid
* @return string
*/
function GetTempName($table, $wid = '')
{
return $this->GetTempTablePrefix($wid) . $table;
}
function GetTempTablePrefix($wid = '')
{
if (preg_match('/prefix:(.*)/', $wid, $regs)) {
$wid = $this->GetTopmostWid($regs[1]);
}
return TABLE_PREFIX . 'ses_' . $this->GetSID() . ($wid ? '_' . $wid : '') . '_edit_';
}
function IsTempTable($table)
{
static $cache = Array ();
if ( !array_key_exists($table, $cache) ) {
$cache[$table] = preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$table);
}
return (bool)$cache[$table];
}
/**
* Checks, that given prefix is in temp mode
*
* @param string $prefix
* @param string $special
* @return bool
*/
function IsTempMode($prefix, $special = '')
{
$top_prefix = $this->GetTopmostPrefix($prefix);
$var_names = Array (
$top_prefix,
rtrim($top_prefix . '_' . $special, '_'), // from post
rtrim($top_prefix . '.' . $special, '.'), // assembled locally
);
$var_names = array_unique($var_names);
$temp_mode = false;
foreach ($var_names as $var_name) {
$value = $this->GetVar($var_name . '_mode');
if ($value && (substr($value, 0, 1) == 't')) {
$temp_mode = true;
break;
}
}
return $temp_mode;
}
/**
* Return live table name based on temp table name
*
* @param string $temp_table
* @return string
*/
function GetLiveName($temp_table)
{
if( preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$temp_table, $rets) )
{
// cut wid from table end if any
return $rets[2];
}
else
{
return $temp_table;
}
}
function CheckProcessors($processors)
{
foreach ($processors as $a_processor)
{
if (!isset($this->CachedProcessors[$a_processor])) {
$this->CachedProcessors[$a_processor] =& $this->recallObject($a_processor.'_TagProcessor');
}
}
}
function ApplicationDie($message = '')
{
$message = ob_get_clean().$message;
if ($this->isDebugMode()) {
$message .= $this->Debugger->printReport(true);
}
echo $this->UseOutputCompression() ? gzencode($message, DBG_COMPRESSION_LEVEL) : $message;
exit;
}
/* moved from MyApplication */
function getUserGroups($user_id)
{
switch ($user_id) {
case USER_ROOT:
$user_groups = $this->ConfigValue('User_LoggedInGroup');
break;
case USER_GUEST:
$user_groups = $this->ConfigValue('User_LoggedInGroup') . ',' . $this->ConfigValue('User_GuestGroup');
break;
default:
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PortalUserId = ' . (int)$user_id;
$res = $this->Conn->GetCol($sql);
$user_groups = Array( $this->ConfigValue('User_LoggedInGroup') );
if ($res) {
$user_groups = array_merge($user_groups, $res);
}
$user_groups = implode(',', $user_groups);
}
return $user_groups;
}
/**
* Allows to detect if page is browsed by spider (293 scheduled_tasks supported)
*
* @return bool
*/
function IsSpider()
{
static $is_spider = null;
if (!isset($is_spider)) {
$user_agent = trim($_SERVER['HTTP_USER_AGENT']);
$robots = file(FULL_PATH.'/core/robots_list.txt');
foreach ($robots as $robot_info) {
$robot_info = explode("\t", $robot_info, 3);
if ($user_agent == trim($robot_info[2])) {
$is_spider = true;
break;
}
}
}
return $is_spider;
}
/**
* Allows to detect table's presense in database
*
* @param string $table_name
* @param bool $force
* @return bool
*/
function TableFound($table_name, $force = false)
{
return $this->Conn->TableFound($table_name, $force);
}
/**
* Returns counter value
*
* @param string $name counter name
* @param Array $params counter parameters
* @param string $query_name specify query name directly (don't generate from parmeters)
* @param bool $multiple_results
* @return mixed
*/
function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false)
{
$count_helper =& $this->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
return $count_helper->getCounter($name, $params, $query_name, $multiple_results);
}
/**
* Resets counter, which are affected by one of specified tables
*
* @param string $tables comma separated tables list used in counting sqls
* @return void
* @access public
*/
public function resetCounters($tables)
{
if ( kUtil::constOn('IS_INSTALL') ) {
return;
}
$count_helper =& $this->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
$count_helper->resetCounters($tables);
}
/**
* Sends XML header + optionally displays xml heading
*
* @param string|bool $xml_version
* @return string
* @access public
* @author Alex
*/
public function XMLHeader($xml_version = false)
{
$lang =& $this->recallObject('lang.current');
/* @var $lang LanguagesItem */
header('Content-type: text/xml; charset=' . $lang->GetDBField('Charset'));
return $xml_version ? '<?xml version="' . $xml_version . '" encoding="' . $lang->GetDBField('Charset') . '"?>' : '';
}
/**
* Returns category tree
*
* @param int $category_id
* @return Array
*/
function getTreeIndex($category_id)
{
$tree_index = $this->getCategoryCache($category_id, 'category_tree');
if ($tree_index) {
$ret = Array ();
list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index);
return $ret;
}
return false;
}
/**
* Base category of all categories
* Usually replaced category, with ID = 0 in category-related operations.
*
* @return int
*/
function getBaseCategory()
{
// same, what $this->findModule('Name', 'Core', 'RootCat') does
// don't cache while IS_INSTALL, because of kInstallToolkit::createModuleCategory and upgrade
return $this->ModuleInfo['Core']['RootCat'];
}
/**
* Deletes all data, that was cached during unit config parsing (excluding unit config locations)
*
* @param Array $config_variables
* @access public
*/
public function DeleteUnitCache($config_variables = null)
{
$this->cacheManager->DeleteUnitCache($config_variables);
}
/**
* Deletes cached section tree, used during permission checking and admin console tree display
*
* @return void
* @access public
*/
public function DeleteSectionCache()
{
$this->cacheManager->DeleteSectionCache();
}
/**
* Sets data from cache to object
*
* @param Array $data
* @access public
*/
public function setFromCache(&$data)
{
$this->ReplacementTemplates = $data['Application.ReplacementTemplates'];
$this->RewriteListeners = $data['Application.RewriteListeners'];
$this->ModuleInfo = $data['Application.ModuleInfo'];
}
/**
* Gets object data for caching
* The following caches should be reset based on admin interaction (adjusting config, enabling modules etc)
*
* @access public
* @return Array
*/
public function getToCache()
{
return Array (
'Application.ReplacementTemplates' => $this->ReplacementTemplates,
'Application.RewriteListeners' => $this->RewriteListeners,
'Application.ModuleInfo' => $this->ModuleInfo,
);
}
public function delayUnitProcessing($method, $params)
{
$this->cacheManager->delayUnitProcessing($method, $params);
}
/**
* Returns current maintenance mode state
*
* @param bool $check_ips
* @return int
* @access public
*/
public function getMaintenanceMode($check_ips = true)
{
$exception_ips = defined('MAINTENANCE_MODE_IPS') ? MAINTENANCE_MODE_IPS : '';
$setting_name = $this->isAdmin ? 'MAINTENANCE_MODE_ADMIN' : 'MAINTENANCE_MODE_FRONT';
if ( defined($setting_name) && constant($setting_name) > MaintenanceMode::NONE ) {
$exception_ip = $check_ips ? kUtil::ipMatch($exception_ips) : false;
if ( !$exception_ip ) {
return constant($setting_name);
}
}
return MaintenanceMode::NONE;
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/managers/cache_manager.php
===================================================================
--- branches/5.2.x/core/kernel/managers/cache_manager.php (revision 14994)
+++ branches/5.2.x/core/kernel/managers/cache_manager.php (revision 14995)
@@ -1,770 +1,779 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kCacheManager extends kBase implements kiCacheable {
/**
* Used variables from ConfigurationValues table
*
* @var Array
* @access protected
*/
protected $configVariables = Array();
/**
* Used variables from ConfigurationValues table retrieved from unit cache
*
* @var Array
* @access protected
*/
protected $originalConfigVariables = Array ();
/**
* IDs of config variables used in current run (for caching)
*
* @var Array
* @access protected
*/
protected $configIDs = Array ();
/**
* IDs of config variables retrieved from unit cache
*
* @var Array
* @access protected
*/
protected $originalConfigIDs = Array ();
/**
* Object of memory caching class
*
* @var kCache
* @access protected
*/
protected $cacheHandler = null;
protected $temporaryCache = Array (
'registerAggregateTag' => Array (),
'registerScheduledTask' => Array (),
'registerHook' => Array (),
'registerBuildEvent' => Array (),
'registerAggregateTag' => Array (),
);
/**
* Creates caching manager instance
*
* @access public
*/
public function InitCache()
{
$this->cacheHandler =& $this->Application->makeClass('kCache');
}
/**
* Returns cache key, used to cache phrase and configuration variable IDs used on current page
*
* @return string
* @access protected
*/
protected function getCacheKey()
{
// TODO: maybe language part isn't required, since same phrase from different languages have one ID now
return $this->Application->GetVar('t') . $this->Application->GetVar('m_theme') . $this->Application->GetVar('m_lang') . $this->Application->isAdmin;
}
/**
* Loads phrases and configuration variables, that were used on this template last time
*
* @access public
*/
public function LoadApplicationCache()
{
$phrase_ids = $config_ids = Array ();
$sql = 'SELECT PhraseList, ConfigVariables
FROM ' . TABLE_PREFIX . 'PhraseCache
WHERE Template = ' . $this->Conn->qstr( md5($this->getCacheKey()) );
$res = $this->Conn->GetRow($sql);
if ($res) {
if ( $res['PhraseList'] ) {
$phrase_ids = explode(',', $res['PhraseList']);
}
if ( $res['ConfigVariables'] ) {
$config_ids = array_diff( explode(',', $res['ConfigVariables']), $this->originalConfigIDs);
}
}
$this->Application->Phrases->Init('phrases', '', null, $phrase_ids);
$this->configIDs = $this->originalConfigIDs = $config_ids;
$this->InitConfig();
}
/**
* Updates phrases and configuration variables, that were used on this template
*
* @access public
*/
public function UpdateApplicationCache()
{
$update = false;
//something changed
$update = $update || $this->Application->Phrases->NeedsCacheUpdate();
$update = $update || (count($this->configIDs) && $this->configIDs != $this->originalConfigIDs);
if ($update) {
$fields_hash = Array (
'PhraseList' => implode(',', $this->Application->Phrases->Ids),
'CacheDate' => adodb_mktime(),
'Template' => md5( $this->getCacheKey() ),
'ConfigVariables' => implode(',', array_unique($this->configIDs)),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'PhraseCache', 'REPLACE');
}
}
/**
* Loads configuration variables, that were used on this template last time
*
* @access protected
*/
protected function InitConfig()
{
if (!$this->originalConfigIDs) {
return ;
}
$sql = 'SELECT VariableValue, VariableName
FROM ' . TABLE_PREFIX . 'ConfigurationValues
WHERE VariableId IN (' . implode(',', $this->originalConfigIDs) . ')';
$config_variables = $this->Conn->GetCol($sql, 'VariableName');
$this->configVariables = array_merge($this->configVariables, $config_variables);
}
/**
* Returns configuration option value by name
*
* @param string $name
* @return string
* @access public
*/
public function ConfigValue($name)
{
$site_domain_override = Array (
'DefaultEmailSender' => 'AdminEmail',
'DefaultEmailRecipients' => 'DefaultEmailRecipients',
);
if ( isset($site_domain_override[$name]) ) {
$res = $this->Application->siteDomainField($site_domain_override[$name]);
if ( $res ) {
return $res;
}
}
if ( array_key_exists($name, $this->configVariables) ) {
return $this->configVariables[$name];
}
if ( defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound('ConfigurationValues', true) ) {
return false;
}
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT VariableId, VariableValue
FROM ' . TABLE_PREFIX . 'ConfigurationValues
WHERE VariableName = ' . $this->Conn->qstr($name);
$res = $this->Conn->GetRow($sql);
if ( $res !== false ) {
$this->configIDs[] = $res['VariableId'];
$this->configVariables[$name] = $res['VariableValue'];
return $res['VariableValue'];
}
trigger_error('Usage of undefined configuration variable "<strong>' . $name . '</strong>"', E_USER_NOTICE);
return false;
}
/**
* Changes value of individual configuration variable (+resets cache, when needed)
*
* @param string $name
* @param string $value
* @param bool $local_cache_only
* @return string
* @access public
*/
public function SetConfigValue($name, $value, $local_cache_only = false)
{
$this->configVariables[$name] = $value;
if ( $local_cache_only ) {
return;
}
$fields_hash = Array ('VariableValue' => $value);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'ConfigurationValues', 'VariableName = ' . $this->Conn->qstr($name));
if ( array_key_exists($name, $this->originalConfigVariables) && $value != $this->originalConfigVariables[$name] ) {
$this->DeleteUnitCache();
}
}
/**
* Loads data, that was cached during unit config parsing
*
* @return bool
* @access public
*/
public function LoadUnitCache()
{
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$data = $this->Application->getCache('master:configs_parsed', false, CacheSettings::$unitCacheRebuildTime);
}
else {
$data = $this->Application->getDBCache('configs_parsed', CacheSettings::$unitCacheRebuildTime);
}
if ( $data ) {
$cache = unserialize($data); // 126 KB all modules
unset($data);
$this->Application->InitManagers();
$this->Application->Factory->setFromCache($cache);
$this->Application->UnitConfigReader->setFromCache($cache);
$this->Application->EventManager->setFromCache($cache);
$aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray');
/* @var $aggregator kArray */
$aggregator->setFromCache($cache);
$this->setFromCache($cache);
$this->Application->setFromCache($cache);
unset($cache);
return true;
}
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$this->Application->rebuildCache('master:configs_parsed', kCache::REBUILD_NOW, CacheSettings::$unitCacheRebuildTime);
}
else {
$this->Application->rebuildDBCache('configs_parsed', kCache::REBUILD_NOW, CacheSettings::$unitCacheRebuildTime);
}
return false;
}
/**
* Empties factory and event manager cache (without storing changes)
*/
public function EmptyUnitCache()
{
$cache_keys = Array (
'Factory.Files', 'Factory.realClasses', 'Factory.Dependencies',
'EventManager.buildEvents', 'EventManager.beforeHooks',
'EventManager.afterHooks', 'EventManager.beforeRegularEvents',
'EventManager.afterRegularEvents'
);
$empty_cache = Array ();
foreach ($cache_keys as $cache_key) {
$empty_cache[$cache_key] = Array ();
}
$this->Application->Factory->setFromCache($empty_cache);
$this->Application->EventManager->setFromCache($empty_cache);
// otherwise ModulesHelper indirectly used from includeConfigFiles won't work
$this->Application->RegisterDefaultClasses();
}
/**
* Updates data, that was parsed from unit configs this time
*
* @access public
*/
public function UpdateUnitCache()
{
$aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray');
/* @var $aggregator kArray */
$this->preloadConfigVars(); // preloading will put to cache
$cache = array_merge(
$this->Application->Factory->getToCache(),
$this->Application->UnitConfigReader->getToCache(),
$this->Application->EventManager->getToCache(),
$aggregator->getToCache(),
$this->getToCache(),
$this->Application->getToCache()
);
$cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s');
if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) {
$this->Application->setCache('master:configs_parsed', serialize($cache));
$this->Application->setCache('master:last_cache_rebuild', $cache_rebuild_by);
}
else {
$this->Application->setDBCache('configs_parsed', serialize($cache));
$this->Application->setDBCache('last_cache_rebuild', $cache_rebuild_by);
}
}
public function delayUnitProcessing($method, $params)
{
if ($this->Application->InitDone) {
// init already done -> call immediately (happens during installation)
$function = Array (&$this->Application, $method);
call_user_func_array($function, $params);
return ;
}
$this->temporaryCache[$method][] = $params;
}
public function applyDelayedUnitProcessing()
{
foreach ($this->temporaryCache as $method => $method_calls) {
$function = Array (&$this->Application, $method);
foreach ($method_calls as $method_call) {
call_user_func_array($function, $method_call);
}
$this->temporaryCache[$method] = Array ();
}
}
/**
* Deletes all data, that was cached during unit config parsing (excluding unit config locations)
*
* @param Array $config_variables
* @access public
*/
public function DeleteUnitCache($config_variables = null)
{
if ( isset($config_variables) && !array_intersect(array_keys($this->originalConfigVariables), $config_variables) ) {
// prevent cache reset, when given config variables are not in unit cache
return;
}
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$this->Application->rebuildCache('master:configs_parsed', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime);
}
else {
$this->Application->rebuildDBCache('configs_parsed', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime);
}
}
/**
* Deletes cached section tree, used during permission checking and admin console tree display
*
* @return void
* @access public
*/
public function DeleteSectionCache()
{
if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
$this->Application->rebuildCache('master:sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime);
}
else {
$this->Application->rebuildDBCache('sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime);
}
}
/**
* Preloads 21 widely used configuration variables, so they will get to cache for sure
*
* @access protected
*/
protected function preloadConfigVars()
{
$config_vars = Array (
// session related
'SessionTimeout', 'SessionCookieName', 'SessionCookieDomains', 'SessionBrowserSignatureCheck',
'SessionIPAddressCheck', 'CookieSessions', 'KeepSessionOnBrowserClose', 'User_GuestGroup',
'User_LoggedInGroup', 'RegistrationUsernameRequired',
// output related
'UseModRewrite', 'UseContentLanguageNegotiation', 'UseOutputCompression', 'OutputCompressionLevel',
'Config_Site_Time', 'SystemTagCache',
// tracking related
'UseChangeLog', 'UseVisitorTracking', 'ModRewriteUrlEnding', 'ForceModRewriteUrlEnding',
'RunScheduledTasksFromCron',
);
$escaped_config_vars = $this->Conn->qstrArray($config_vars);
$sql = 'SELECT VariableId, VariableName, VariableValue
FROM ' . TABLE_PREFIX . 'ConfigurationValues
WHERE VariableName IN (' . implode(',', $escaped_config_vars) . ')';
$data = $this->Conn->Query($sql, 'VariableId');
foreach ($data as $variable_id => $variable_info) {
$this->configIDs[] = $variable_id;
$this->configVariables[ $variable_info['VariableName'] ] = $variable_info['VariableValue'];
}
}
/**
* Sets data from cache to object
*
* Used for cases, when ConfigValue is called before LoadApplicationCache method (e.g. session init, url engine init)
*
* @param Array $data
* @access public
*/
public function setFromCache(&$data)
{
$this->configVariables = $this->originalConfigVariables = $data['Application.ConfigHash'];
$this->configIDs = $this->originalConfigIDs = $data['Application.ConfigCacheIds'];
}
/**
* Gets object data for caching
* The following caches should be reset based on admin interaction (adjusting config, enabling modules etc)
*
* @access public
* @return Array
*/
public function getToCache()
{
return Array (
'Application.ConfigHash' => $this->configVariables,
'Application.ConfigCacheIds' => $this->configIDs,
// not in use, since it only represents template specific values, not global ones
// 'Application.Caches.ConfigVariables' => $this->originalConfigIDs,
);
}
/**
* Returns caching type (none, memory, temporary)
*
* @param int $caching_type
* @return bool
* @access public
*/
public function isCachingType($caching_type)
{
return $this->cacheHandler->getCachingType() == $caching_type;
}
/**
* Prints caching statistics
*
* @access public
*/
public function printStatistics()
{
$this->cacheHandler->printStatistics();
}
/**
* Returns cached $key value from cache named $cache_name
*
* @param int $key key name from cache
* @param bool $store_locally store data locally after retrieved
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getCache($key, $store_locally = true, $max_rebuild_seconds = 0)
{
return $this->cacheHandler->getCache($key, $store_locally, $max_rebuild_seconds);
}
/**
* Adds new value to cache $cache_name and identified by key $key
*
* @param int $key key name to add to cache
- * @param mixed $value value of chached record
+ * @param mixed $value value of cached record
* @param int $expiration when value expires (0 - doesn't expire)
* @return bool
* @access public
*/
public function setCache($key, $value, $expiration = 0)
{
return $this->cacheHandler->setCache($key, $value, $expiration);
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
+ * @return void
+ * @access public
*/
public function rebuildCache($name, $mode = null, $max_rebuilding_time = 0)
{
$this->cacheHandler->rebuildCache($name, $mode, $max_rebuilding_time);
}
/**
* Deletes key from cache
*
* @param string $key
+ * @return void
* @access public
*/
public function deleteCache($key)
{
$this->cacheHandler->delete($key);
}
/**
* Reset's all memory cache at once
*
+ * @return void
* @access public
*/
public function resetCache()
{
$this->cacheHandler->reset();
}
/**
* Returns value from database cache
*
* @param string $name key name
* @param int $max_rebuild_seconds
* @return mixed
* @access public
*/
public function getDBCache($name, $max_rebuild_seconds = 0)
{
if ( $this->_getDBCache($name . '_rebuild') ) {
// cache rebuild requested -> rebuild now
$this->deleteDBCache($name . '_rebuild');
return false;
}
// no serials in cache key OR cache is outdated
$wait_seconds = $max_rebuild_seconds;
while (true) {
$cache = $this->_getDBCache($name);
$rebuilding = $this->_getDBCache($name . '_rebuilding');
if ( ($cache === false) && (!$rebuilding || $wait_seconds == 0) ) {
// cache missing and nobody rebuilding it -> rebuild; enough waiting for cache to be ready
return false;
}
elseif ( $cache !== false ) {
// cache present -> return it
return $cache;
}
$wait_seconds -= kCache::WAIT_STEP;
sleep(kCache::WAIT_STEP);
}
return false;
}
/**
* Returns value from database cache
*
* @param string $name key name
* @return mixed
* @access protected
*/
protected function _getDBCache($name)
{
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT Data, Cached, LifeTime
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = ' . $this->Conn->qstr($name);
$data = $this->Conn->GetRow($sql);
if ($data) {
$lifetime = (int)$data['LifeTime']; // in seconds
if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) {
// delete expired
$this->Conn->nextQueryCachable = true;
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = ' . $this->Conn->qstr($name);
$this->Conn->Query($sql);
return false;
}
return $data['Data'];
}
return false;
}
/**
* Sets value to database cache
*
* @param string $name
* @param mixed $value
* @param int|bool $expiration
+ * @return void
* @access public
*/
public function setDBCache($name, $value, $expiration = false)
{
$this->deleteDBCache($name . '_rebuilding');
$this->_setDBCache($name, $value, $expiration);
}
/**
* Sets value to database cache
*
* @param string $name
* @param mixed $value
* @param int|bool $expiration
* @access protected
*/
protected function _setDBCache($name, $value, $expiration = false)
{
if ((int)$expiration <= 0) {
$expiration = -1;
}
$fields_hash = Array (
'VarName' => $name,
'Data' => &$value,
'Cached' => adodb_mktime(),
'LifeTime' => (int)$expiration,
);
$this->Conn->nextQueryCachable = true;
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
}
/**
* Sets rebuilding mode for given cache
*
* @param string $name
* @param int $mode
* @param int $max_rebuilding_time
+ * @return void
+ * @access public
*/
public function rebuildDBCache($name, $mode = null, $max_rebuilding_time = 0)
{
if ( !isset($mode) || $mode == kCache::REBUILD_NOW ) {
$this->_setDBCache($name . '_rebuilding', 1, $max_rebuilding_time);
$this->deleteDBCache($name . '_rebuild');
}
elseif ( $mode == kCache::REBUILD_LATER ) {
$this->_setDBCache($name . '_rebuild', 1, 0);
$this->deleteDBCache($name . '_rebuilding');
}
}
/**
* Deletes key from database cache
*
* @param string $name
+ * @return void
* @access public
*/
public function deleteDBCache($name)
{
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = ' . $this->Conn->qstr($name);
$this->Conn->Query($sql);
}
/**
* Increments serial based on prefix and it's ID (optional)
*
* @param string $prefix
* @param int $id ID (value of IDField) or ForeignKeyField:ID
* @param bool $increment
+ * @return string
* @access public
*/
public function incrementCacheSerial($prefix, $id = null, $increment = true)
{
$pascal_case_prefix = implode('', array_map('ucfirst', explode('-', $prefix)));
$serial_name = $pascal_case_prefix . (isset($id) ? 'IDSerial:' . $id : 'Serial');
if ($increment) {
if (defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Incrementing serial: <strong>' . $serial_name . '</strong>.');
}
$this->setCache($serial_name, (int)$this->getCache($serial_name) + 1);
if (!defined('IS_INSTALL') || !IS_INSTALL) {
// delete cached mod-rewrite urls related to given prefix and id
$delete_clause = isset($id) ? $prefix . ':' . $id : $prefix;
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls
WHERE Prefixes LIKE ' . $this->Conn->qstr('%|' . $delete_clause . '|%');
$this->Conn->Query($sql);
}
}
return $serial_name;
}
/**
* Returns cached category informaton by given cache name. All given category
* information is recached, when at least one of 4 caches is missing.
*
* @param int $category_id
* @param string $name cache name = {filenames, category_designs, category_tree}
* @return string
* @access public
*/
public function getCategoryCache($category_id, $name)
{
$serial_name = '[%CIDSerial:' . $category_id . '%]';
$cache_key = $name . $serial_name;
$ret = $this->getCache($cache_key);
if ($ret === false) {
if (!$category_id) {
// don't query database for "Home" category (ID = 0), because it doesn't exist in database
return false;
}
// this allows to save 2 sql queries for each category
$this->Conn->nextQueryCachable = true;
$sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight
FROM ' . TABLE_PREFIX . 'Category
WHERE CategoryId = ' . (int)$category_id;
$category_data = $this->Conn->GetRow($sql);
if ($category_data !== false) {
// only direct links to category pages work (symlinks, container pages and so on won't work)
$this->setCache('filenames' . $serial_name, $category_data['NamedParentPath']);
$this->setCache('category_designs' . $serial_name, ltrim($category_data['CachedTemplate'], '/'));
$this->setCache('category_tree' . $serial_name, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']);
}
}
return $this->getCache($cache_key);
}
}
\ No newline at end of file
Index: branches/5.2.x/core/kernel/processors/tag_processor.php
===================================================================
--- branches/5.2.x/core/kernel/processors/tag_processor.php (revision 14994)
+++ branches/5.2.x/core/kernel/processors/tag_processor.php (revision 14995)
@@ -1,350 +1,350 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kTagProcessor extends kBase {
/**
* Returns joined prefix and special if any
*
* @param bool $from_submit if true, then joins prefix & special by "_", uses "." otherwise
* @return string
* @access public
*/
public function getPrefixSpecial($from_submit = false)
{
if (!$from_submit) {
return parent::getPrefixSpecial();
}
return rtrim($this->Prefix . '_' . $this->Special, '_');
}
/**
* Processes tag
*
* @param _BlockTag $tag
* @return string
* @access public
*/
function ProcessTag(&$tag)
{
return $this->ProcessParsedTag($tag->Tag, $tag->NP, $tag->getPrefixSpecial());
}
/**
* Checks, that tag is implemented in this tag processor
*
* @param string $tag
* @param string $prefix
- *
+ *
* @return bool
* @access public
*/
public function CheckTag($tag, $prefix)
{
$method = $tag;
if ( method_exists($this, $method) ) {
return true;
}
if ( $this->Application->hasObject('TagsAggregator') ) {
$aggregator =& $this->Application->recallObject('TagsAggregator');
/* @var $aggregator kArray */
$tmp = $this->Application->processPrefix($prefix);
$tag_mapping = $aggregator->GetArrayValue($tmp['prefix'], $method);
if ( $tag_mapping ) {
return true;
}
}
return false;
}
function FormCacheKey($tag, $params, $prefix)
{
// link tag to it's template
$reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
$template_path = preg_replace($reg_exp, '', $this->Application->Parser->TempalteFullPath, 1);
$element = 'file=' . $template_path . ':' . $prefix . '_' . $tag . '_' . crc32( serialize($params) );
return $this->Application->Parser->FormCacheKey($element);
}
function ProcessParsedTag($tag, $params, $prefix, $file='unknown', $line=0)
{
$Method = $tag;
- if (method_exists($this, $Method)) {
- if (defined('DEBUG_MODE') && defined('DBG_SHOW_TAGS') && DBG_SHOW_TAGS && $this->Application->isDebugMode()) {
- $this->Application->Debugger->appendHTML('Processing PreParsed Tag '.$Method.' in '.$this->Prefix);
+ if ( method_exists($this, $Method) ) {
+ if ( defined('DEBUG_MODE') && defined('DBG_SHOW_TAGS') && DBG_SHOW_TAGS && $this->Application->isDebugMode() ) {
+ $this->Application->Debugger->appendHTML('Processing PreParsed Tag ' . $Method . ' in ' . $this->Prefix);
}
- list ($prefix_only, ) = explode('.', $prefix);
+ list ($prefix_only,) = explode('.', $prefix);
$this->Application->Parser->PrefixesInUse[$prefix_only] = 1;
$cache_key = '';
$backup_prefix = $this->Prefix;
$backup_special = $this->Special;
- if ($this->Application->Parser->CachingEnabled && array_key_exists('cache_timeout', $params)) {
+ if ( $this->Application->Parser->CachingEnabled && array_key_exists('cache_timeout', $params) ) {
// individual tag caching
$cache_key = $this->FormCacheKey($tag, $params, $prefix);
$res = $this->Application->Parser->getCache($cache_key);
- if ($res !== false) {
+ if ( $res !== false ) {
return $res;
}
}
$original_params = $params;
$flag_values = $this->PreparePostProcess($params);
// pass_params for non ParseBlock tags :)
- if ($flag_values['pass_params']) {
+ if ( $flag_values['pass_params'] ) {
$params = array_merge($this->Application->Parser->Params, $params);
}
$ret = $this->$Method($params);
$this->Init($backup_prefix, $backup_special);
$ret = $this->PostProcess($ret, $flag_values);
- if ($this->Application->Parser->CachingEnabled && $flag_values['cache_timeout']) {
+ if ( $this->Application->Parser->CachingEnabled && $flag_values['cache_timeout'] ) {
$this->Application->Parser->setCache($cache_key, $ret, (int)$flag_values['cache_timeout']);
}
return $ret;
}
else {
list ($ret, $tag_found) = $this->processAggregatedTag($tag, $params, $prefix, $file, $line);
- if ($tag_found) {
+ if ( $tag_found ) {
return $ret;
}
$error_tag = Array ('file' => $file, 'line' => $line);
throw new ParserException('Undefined tag: <strong>' . $prefix . ':' . $tag . '</strong>', 0, null, $error_tag);
return false;
}
}
function processAggregatedTag($tag, $params, $prefix, $file = 'unknown', $line = 0)
{
if ( $this->Application->hasObject('TagsAggregator') ) {
$Method = $tag;
$aggregator =& $this->Application->recallObject('TagsAggregator');
/* @var $aggregator kArray */
$tmp = $this->Application->processPrefix($prefix);
$tag_mapping = $aggregator->GetArrayValue($tmp['prefix'], $Method);
if ( $tag_mapping ) {
// aggregated tag defined
$tmp = $this->Application->processPrefix($tag_mapping[0]);
$__tag_processor = $tmp['prefix'] . '_TagProcessor';
$processor =& $this->Application->recallObject($__tag_processor);
/* @var $processor kTagProcessor */
$processor->Init($tmp['prefix'], getArrayValue($tag_mapping, 2) ? $tag_mapping[2] : $tmp['special']);
$params['original_tag'] = $Method; // allows to define same method for different aggregated tags in same tag processor
$params['PrefixSpecial'] = $this->getPrefixSpecial(); // $prefix;
$ret = $processor->ProcessParsedTag($tag_mapping[1], $params, $prefix);
if ( isset($params['result_to_var']) ) {
$this->Application->Parser->SetParam($params['result_to_var'], $ret);
$ret = '';
}
return Array ($ret, true);
}
else {
// aggregated tag not defined
$error_tag = Array ('file' => $file, 'line' => $line);
throw new ParserException('Undefined aggregated tag <strong>' . $prefix . ':' . $Method . '</strong> (in ' . get_class($this) . ' tag processor)', 0, null, $error_tag);
}
}
return Array ('', false);
}
function PreparePostProcess(&$params)
{
$flags = Array('js_escape', 'equals_to', 'result_to_var', 'pass_params', 'html_escape', 'strip_nl', 'trim', 'cache_timeout');
$flag_values = Array();
foreach ($flags as $flag_name) {
$flag_values[$flag_name] = false;
if (isset($params[$flag_name])) {
$flag_values[$flag_name] = $params[$flag_name];
unset($params[$flag_name]);
}
}
return $flag_values;
}
function PostProcess($ret, $flag_values)
{
if ($flag_values['html_escape']) {
$ret = htmlspecialchars($ret);
}
if ($flag_values['js_escape']) {
$ret = addslashes($ret);
$ret = str_replace(Array("\r", "\n"), Array('\r', '\n'), $ret);
$ret = str_replace('</script>', "</'+'script>", $ret);
}
if ($flag_values['strip_nl']) {
// 1 - strip \r,\n; 2 - strip tabs too
$ret = preg_replace($flag_values['strip_nl'] == 2 ? "/[\r\n\t]/" : "/[\r\n]/", '', $ret);
}
if ($flag_values['trim']) {
$ret = trim($ret);
}
// TODO: in new parser implement this parameter in compiled code (by Alex)
if ($flag_values['equals_to'] !== false) {
$equals_to = explode('|', $flag_values['equals_to']);
$ret = in_array($ret, $equals_to);
}
if ($flag_values['result_to_var']) {
$this->Application->Parser->SetParam($flag_values['result_to_var'], $ret);
$ret = '';
}
return $ret;
}
/**
* Not tag, method for parameter
* selection from list in this TagProcessor
*
* @param Array $params
* @param string $possible_names
* @return string|bool
* @access protected
*/
protected function SelectParam($params, $possible_names = null)
{
if ( !isset($possible_names) ) {
// select 1st parameter non-empty parameter value
$possible_names = explode(',', $params['possible_names']);
foreach ($possible_names as $param_name) {
$value = $this->Application->Parser->GetParam($param_name);
$string_value = (string)$value;
if ( ($string_value != '') && ($string_value != '0') ) {
return $value;
}
}
return false;
}
if ( !is_array($possible_names) ) {
$possible_names = explode(',', $possible_names);
}
foreach ($possible_names as $name) {
if ( isset($params[$name]) ) {
return $params[$name];
}
}
return false;
}
/**
* Returns templates path for module, which is gathered from prefix module
*
* @param Array $params
* @return string
* @author Alex
*/
function ModulePath($params)
{
$force_module = getArrayValue($params, 'module');
if ($force_module) {
if ($force_module == '#session#') {
$force_module = preg_replace('/([^:]*):.*/', '\1', $this->Application->RecallVar('module'));
if (!$force_module) $force_module = 'core';
}
else {
$force_module = mb_strtolower($force_module);
}
if ($force_module == 'core') {
$module_folder = 'core';
}
else {
$module_folder = trim( $this->Application->findModule('Name', $force_module, 'Path'), '/');
}
}
else {
$module_folder = $this->Application->getUnitOption($this->Prefix, 'ModuleFolder');
}
return '../../'.$module_folder.'/admin_templates/';
}
}
/*class ProcessorsPool {
var $Processors = Array();
var $Application;
var $Prefixes = Array();
var $S;
function ProcessorsPool()
{
$this->Application =& KernelApplication::Instance();
$this->S =& $this->Application->Session;
}
function RegisterPrefix($prefix, $path, $class)
{
// echo " RegisterPrefix $prefix, $path, $class <br>";
$prefix_item = Array(
'path' => $path,
'class' => $class
);
$this->Prefixes[$prefix] = $prefix_item;
}
function CreateProcessor($prefix, &$tag)
{
// echo " prefix : $prefix <br>";
if (!isset($this->Prefixes[$prefix]))
$this->Application->ApplicationDie ("<b>Filepath and ClassName for prefix $prefix not defined while processing ".htmlspecialchars($tag->GetFullTag())."!</b>");
include_once($this->Prefixes[$prefix]['path']);
$ClassName = $this->Prefixes[$prefix]['class'];
$a_processor = new $ClassName($prefix);
$this->SetProcessor($prefix, $a_processor);
}
function SetProcessor($prefix, &$a_processor)
{
$this->Processors[$prefix] =& $a_processor;
}
function &GetProcessor($prefix, &$tag)
{
if (!isset($this->Processors[$prefix]))
$this->CreateProcessor($prefix, $tag);
return $this->Processors[$prefix];
}
}*/
\ No newline at end of file
Index: branches/5.2.x/core/kernel/utility/params.php
===================================================================
--- branches/5.2.x/core/kernel/utility/params.php (revision 14994)
+++ branches/5.2.x/core/kernel/utility/params.php (revision 14995)
@@ -1,179 +1,180 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class Params extends kBase {
var $_Params = Array();
/**
* Creates class instance
*
* @param string $params_str
* @access public
*/
public function __construct($params_str = null)
{
parent::__construct();
if($params_str != '') {
$this->SplitParamsStr($params_str);
}
}
/**
* Splits tag params into associative array
*
* @param string $params_str
* @access private
*/
function SplitParamsStr($params_str)
{
// $re = preg_quote('([\${}a-zA-Z0-9_.-#\[\]]+)=(["\']{1,1})(.*?)(?<!\\)\2','/');
// preg_match_all('/'.$re.'/s', $params_str, $rets, PREG_SET_ORDER);
preg_match_all('/([\${}a-zA-Z0-9_.\\-\\\\#\\[\\]]+)=(["\']{1,1})(.*?)(?<!\\\)\\2/s', $params_str, $rets, PREG_SET_ORDER);
$values = Array();
foreach ($rets AS $key => $val){
$values[$val[1]] = str_replace('\\' . $val[2], $val[2], $val[3]);
}
$this->AddParams($values);
}
/**
* Sets new parameter value
*
* @param string $name
* @param string $val
* @return void
* @access public
*/
public function Set($name, $val)
{
$this->_Params[$name] = $val;
}
/**
* Removes parameter
*
* @param string $name
+ * @return void
* @access public
*/
- function Remove($name)
+ public function Remove($name)
{
unset($this->_Params[$name]);
}
/**
* Gets parameter value by parameter name
*
* @param string $name Name of variable to retrieve
* @param mixed $default default value returned in case if variable not present
* @return string
* @access public
*/
public function Get($name, $default = false)
{
return isset($this->_Params[$name]) ? $this->_Params[$name] : $default;
}
/**
* Mass parameter setting from hash
*
* @param Array $params
* @access public
*/
function AddParams($params)
{
if (!is_array($params)) return;
/*if (count($this->_Params) == 0) {
$this->_Params = $params;
}
else {*/
foreach ($params as $name => $val)
// $this->Set(strtolower($name), $val);
$this->Set($name, $val);
//}
}
/**
* Return all paramters as hash
*
* @return Array
* @access public
*/
function GetParams()
{
return $this->_Params;
}
}
class kArray extends kBase implements kiCacheable {
var $_Array;
/**
* Returns array value with any deep key
*
* @return mixed
* @todo array_unshift doesn't accept parameters by reference, fix it's usage in this method
*/
function GetArrayValue()
{
$args = func_get_args();
kUtil::array_unshift_ref($args, $this->_Array);
return call_user_func_array('getArrayValue', $args);
}
function SetArrayValue()
{
$args = func_get_args();
$value = array_pop($args);
$arr =& $this->_Array;
for ($i=0; $i<count($args); $i++) {
$key = $args[$i];
if ( !isset($arr[$key]) || !is_array($arr[$key]) ) {
$arr[$key] = Array();
}
$arr =& $arr[$key];
}
$arr = $value;
}
/**
* Sets data from cache to object
*
* @param Array $data
* @access public
*/
public function setFromCache(&$data)
{
$this->_Array = $data['TagsAggregator.data'];
}
/**
* Gets object data for caching
*
* @access public
* @return Array
*/
public function getToCache()
{
return Array (
'TagsAggregator.data' => $this->_Array,
);
}
}
\ No newline at end of file

Event Timeline