Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Jul 3, 7:35 AM

in-portal

This document is not UTF8. It was detected as Shift JIS and converted to UTF8 for display.
Index: branches/5.0.x/core/kernel/utility/debugger/debugger_responce.php
===================================================================
--- branches/5.0.x/core/kernel/utility/debugger/debugger_responce.php (revision 12848)
+++ branches/5.0.x/core/kernel/utility/debugger/debugger_responce.php (revision 12849)
@@ -1,76 +1,75 @@
<?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.
*/
ini_set('memory_limit', -1);
set_time_limit(0);
define('FULL_PATH', realpath(dirname(__FILE__).'/../../../..') );
$sid = $_GET['sid'];
$path = isset($_GET['path']) ? $_GET['path'] : '/system/cache';
if ((strpos($path, '../') !== false) || (trim($path) !== $path)) {
// when relative paths or special chars are found template names from url, then it's hacking attempt
exit;
}
if (!preg_match('/^@([\d]+)@$/', $sid)) exit;
$debug_file = FULL_PATH.$path.'/debug_'.$sid.'.txt';
if (file_exists($debug_file)) {
$ret = file_get_contents($debug_file);
$ret = str_replace('#DBG_FILESIZE#', formatSize( filesize($debug_file) ), $ret);
unlink($debug_file);
}
else {
$ret = 'file not found';
}
if (function_exists('gzencode') && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
header('Content-Encoding: gzip');
echo gzencode($ret);
}
else {
echo $ret;
}
/**
* Formats file/memory size in nice way
*
* @param int $bytes
* @return string
* @access public
*/
function formatSize($bytes)
{
if ($bytes >= 1099511627776) {
$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
$suffix = "TB";
} elseif ($bytes >= 1073741824) {
$return = round($bytes / 1024 / 1024 / 1024, 2);
$suffix = "GB";
} elseif ($bytes >= 1048576) {
$return = round($bytes / 1024 / 1024, 2);
$suffix = "MB";
} elseif ($bytes >= 1024) {
$return = round($bytes / 1024, 2);
$suffix = "KB";
} else {
$return = $bytes;
$suffix = "Byte";
}
$return .= ' '.$suffix;
return $return;
}
-?>
\ No newline at end of file
Index: branches/5.0.x/core/kernel/utility/formatters/customfield_formatter.php
===================================================================
--- branches/5.0.x/core/kernel/utility/formatters/customfield_formatter.php (revision 12848)
+++ branches/5.0.x/core/kernel/utility/formatters/customfield_formatter.php (revision 12849)
@@ -1,44 +1,42 @@
<?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.
*/
/**
* Like kMultiLanguage formatter for LEFT JOINed custom fields
*
*/
class kCustomFieldFormatter extends kFormatter
{
function Format($value, $field_name, &$object, $format=null)
{
$options = $object->GetFieldOptions($field_name);
$master_field = isset($options['master_field']) ? $options['master_field'] : false;
if (!$master_field) {
return $value;
}
$format = isset($format) ? $format : ( isset($options['format']) ? $options['format'] : null);
if ($value == '' && $format != 'no_default') { // try to get default language value
$def_lang_value = $object->GetDBField($master_field);
if ($def_lang_value == '') return NULL;
return $def_lang_value; //return value from default language
}
return $value;
}
- }
-
-?>
\ No newline at end of file
+ }
\ No newline at end of file
Index: branches/5.0.x/core/units/users/users_event_handler.php
===================================================================
--- branches/5.0.x/core/units/users/users_event_handler.php (revision 12848)
+++ branches/5.0.x/core/units/users/users_event_handler.php (revision 12849)
@@ -1,1886 +1,1884 @@
<?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 UsersEventHandler extends kDBEventHandler
{
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array (
// admin
'OnSetPersistantVariable' => Array('self' => 'view'), // because setting to logged in user only
'OnUpdateRootPassword' => Array('self' => true),
'OnUpdatePassword' => Array('self' => true),
// front
'OnRefreshForm' => Array('self' => true),
'OnForgotPassword' => Array('self' => true),
'OnResetPassword' => Array('self' => true),
'OnResetPasswordConfirmed' => Array('self' => true),
'OnSubscribeQuery' => Array('self' => true),
'OnSubscribeUser' => Array('self' => true),
'OnRecommend' => Array('self' => true),
'OnItemBuild' => Array('self' => true),
'OnMassResetSettings' => Array('self' => 'edit'),
'OnMassCloneUsers' => Array('self' => 'add'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Shows only admins when required
*
* @param kEvent $event
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
if ($event->Special == 'admins') {
$object->addFilter('primary_filter', 'ug.GroupId = 11');
}
if ($event->Special == 'regular') {
$object->addFilter('primary_filter', 'ug.GroupId <> 11');
}
if (!$this->Application->isAdminUser) {
$object->addFilter('status_filter', '%1$s.Status = '.STATUS_ACTIVE);
}
if ($event->Special == 'online') {
$object->addFilter('online_users_filter', 's.PortalUserId IS NOT NULL');
}
if ($event->Special == 'group') {
$group_id = $this->Application->GetVar('g_id');
if ($group_id !== false) {
// show only users, that user doesn't belong to current group
$table_name = $this->Application->GetTempName(TABLE_PREFIX.'UserGroup', 'prefix:g');
$sql = 'SELECT PortalUserId
FROM ' . $table_name . '
WHERE GroupId = ' . (int)$group_id;
$user_ids = $this->Conn->GetCol($sql);
// array_push($user_ids); // Guest & Everyone groups are set dynamically
if ($user_ids) {
$object->addFilter('already_member_filter', '%1$s.PortalUserId NOT IN ('.implode(',', $user_ids).')');
}
}
}
}
/**
* Checks permissions of user
*
* @param kEvent $event
*/
function CheckPermission(&$event)
{
if ($event->Name == 'OnLogin' || $event->Name == 'OnLogout') {
// permission is checked in OnLogin event directly
return true;
}
if (!$this->Application->isAdminUser) {
$user_id = $this->Application->RecallVar('user_id');
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($event->Name == 'OnCreate' && $user_id == -2) {
// "Guest" can create new users
return true;
}
if ($event->Name == 'OnUpdate' && $user_id > 0) {
$user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
foreach ($items_info as $id => $field_values) {
if ($id != $user_id) {
// registered users can update their record only
return false;
}
$user_dummy->Load($id);
$status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
// not active user is not allowed to update his record (he could not activate himself manually)
return false;
}
if (isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field]) {
// user can't change status by himself
return false;
}
}
return true;
}
if ($event->Name == 'OnUpdate' && $user_id <= 0) {
// guests are not allowed to update their record, because they don't have it :)
return false;
}
}
return parent::CheckPermission($event);
}
/**
* Handles session expiration (redirects to valid template)
*
* @param kEvent $event
*/
function OnSessionExpire(&$event)
{
$this->Application->resetCounters('UserSession');
// place 2 of 2 (also in kHTTPQuery::getRedirectParams)
$admin_url_params = Array (
'm_cat_id' => 0, // category means nothing on admin login screen
'm_wid' => '', // remove wid, otherwise parent window may add wid to its name breaking all the frameset (for <a> targets)
'pass' => 'm', // don't pass any other (except "m") prefixes to admin session expiration template
'expired' => 1, // expiration mark to show special error on login screen
'no_pass_through' => 1, // this way kApplication::HREF won't add them again
);
if ($this->Application->isAdmin) {
$this->Application->Redirect('index', $admin_url_params, '', 'index.php');
}
if ($this->Application->GetVar('admin') == 1) {
// Front-End showed in admin's right frame
$session_admin =& $this->Application->recallObject('Session.admin');
/* @var $session_admin Session */
if (!$session_admin->LoggedIn()) {
// front-end session created from admin session & both expired
$this->Application->DeleteVar('admin');
$this->Application->Redirect('index', $admin_url_params, '', 'admin/index.php');
}
}
// Front-End session expiration
$get = $this->Application->HttpQuery->getRedirectParams();
$t = $this->Application->GetVar('t');
$get['js_redirect'] = $this->Application->ConfigValue('UseJSRedirect');
$this->Application->Redirect($t ? $t : 'index', $get);
}
/**
* Checks user data and logs it in if allowed
*
* OnLogin is called from u:autoLoginUser and password is supplied
* OnLogin is called from u:OnAutoLoginUser supplying cookie with encoded username & password
*
* @param kEvent $event
*/
function OnLogin(&$event)
{
// persistent session data after login is not refreshed, because redirect will follow in any case
$prefix_special = $this->Application->isAdmin ? 'u.current' : 'u'; // "u" used on front not to change theme
$object =& $this->Application->recallObject($prefix_special, null, Array('skip_autoload' => true));
$password = $this->Application->GetVar('password');
$invalid_pseudo = $this->Application->isAdmin ? 'la_invalid_password' : 'lu_invalid_password';
$remember_login_cookie = $this->Application->GetVar('remember_login');
if (!$password && !$remember_login_cookie) {
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
return false;
}
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
list ($login_field, $submit_field) = $email_as_login && !$this->Application->isAdmin ? Array('Email', 'email') : Array('Login', 'login');
$login_value = $this->Application->GetVar($submit_field);
// process "Save Username" checkbox
if ($this->Application->isAdmin) {
$save_username = $this->Application->GetVar('cb_save_username') ? $login_value : '';
$this->Application->Session->SetCookie('save_username', $save_username, adodb_mktime() + 31104000); // 1 year expiration
$this->Application->SetVar('save_username', $save_username); // cookie will be set on next refresh, but refresh won't occur if login error present, so duplicate cookie in HTTPQuery
}
$super_admin = ($login_value == 'super-root') && $this->verifySuperAdmin();
if ($this->Application->isAdmin && ($login_value == 'root') || ($super_admin && $login_value == 'super-root')) {
// logging in "root" (admin only)
$login_value = 'root';
$root_password = $this->Application->ConfigValue('RootPass');
$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
$test = $password_formatter->EncryptPassword($password, 'b38');
if ($root_password != $test) {
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
return false;
}
elseif ($this->checkLoginPermission($login_value)) {
$user_id = -1;
$object->Load($user_id);
$object->SetDBField('Login', $login_value);
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
// $session->SetField('GroupList', implode(',', $groups) );
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
$this->Application->LoadPersistentVars();
if ($super_admin) {
$this->Application->StoreVar('super_admin', 1);
}
$this->Application->HandleEvent($dummy, 'session-log:OnStartSession');
$this->processLoginRedirect($event, $password);
return true;
}
else {
$object->SetError('ValidateLogin', 'invalid_license', 'la_invalid_license');
$event->status = erFAIL;
return false;
}
}
/*$sql = 'SELECT PortalUserId FROM '.$object->TableName.' WHERE (%s = %s) AND (Password = MD5(%s))';
$user_id = $this->Conn->GetOne( sprintf($sql, $login_field, $this->Conn->qstr($login_value), $this->Conn->qstr($password) ) );*/
if ($remember_login_cookie) {
$user_info = explode('|', $remember_login_cookie); // 0 - username, 1 - md5(password)
$sql = 'SELECT PortalUserId
FROM '.$object->TableName.'
WHERE (Email = %1$s OR Login = %1$s) AND (Password = %2$s)';
$user_id = $this->Conn->GetOne( sprintf($sql, $this->Conn->qstr($user_info[0]), $this->Conn->qstr($user_info[1]) ) );
} else {
$sql = 'SELECT PortalUserId
FROM '.$object->TableName.'
WHERE (Email = %1$s OR Login = %1$s) AND (Password = MD5(%2$s))';
$user_id = $this->Conn->GetOne( sprintf($sql, $this->Conn->qstr($login_value), $this->Conn->qstr($password) ) );
}
if ($user_id) {
$object->Load($user_id);
if (!$this->checkBanRules($object)) {
$event->status = erFAIL;
return false;
}
if ($object->GetDBField('Status') == STATUS_ACTIVE) {
$groups = $object->getMembershipGroups(true);
if(!$groups) $groups = Array();
array_push($groups, $this->Application->ConfigValue('User_LoggedInGroup') );
$this->Application->StoreVar( 'UserGroups', implode(',', $groups) );
if ($this->checkLoginPermission($login_value)) {
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
$session->SetField('GroupList', implode(',', $groups) );
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
$this->Application->LoadPersistentVars();
if (!$remember_login_cookie) {
// don't change last login time when auto-login is used
$this_login = (int)$this->Application->RecallPersistentVar('ThisLogin');
$this->Application->StorePersistentVar('LastLogin', $this_login);
$this->Application->StorePersistentVar('ThisLogin', adodb_mktime());
}
if ($this->Application->GetVar('cb_remember_login') == 1) {
// remember username & password when "Remember Login" checkbox us checked (when user is using login form on Front-End)
$remember_login_cookie = $login_value . '|' . md5($password);
$this->Application->Session->SetCookie('remember_login', $remember_login_cookie, adodb_mktime() + 2592000); // 30 days
}
$this->Application->HandleEvent($dummy, 'session-log:OnStartSession');
}
else {
$object->Load(-2);
$object->SetError('ValidateLogin', 'no_permission', 'lu_no_permissions');
$event->status = erFAIL;
}
if (!$remember_login_cookie) {
$this->processLoginRedirect($event, $password);
}
}
else {
$event->redirect = $this->Application->GetVar('pending_disabled_template');
}
}
else
{
$object->SetID(-2);
$object->SetError('ValidateLogin', 'invalid_password', $invalid_pseudo);
$event->status = erFAIL;
}
$event->SetRedirectParam('pass', 'all');
// $event->SetRedirectParam('pass_category', 1); // to test
}
/**
* [HOOK] Auto-Logins Front-End user when "Remember Login" cookie is found
*
* @param kEvent $event
*/
function OnAutoLoginUser(&$event)
{
$remember_login_cookie = $this->Application->GetVar('remember_login');
if (!$remember_login_cookie || $this->Application->isAdmin || $this->Application->LoggedIn()) {
return ;
}
$event->CallSubEvent('OnLogin');
}
/**
* Checks that user is allowed to use super admin mode
*
* @return bool
*/
function verifySuperAdmin()
{
$sa_mode = ipMatch(defined('SA_IP') ? SA_IP : '');
return $sa_mode || $this->Application->isDebugMode();
}
/**
* Enter description here...
*
* @param string $user_name
* @return bool
*/
function checkLoginPermission($user_name)
{
$ret = true;
if ($this->Application->isAdmin) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
if ($user_name != 'root') {
// root is virtual user, so allow him to login to admin in any case
$ret = $this->Application->CheckPermission('ADMIN', 1);
}
}
else {
$ret = $this->Application->CheckPermission('LOGIN', 1);
}
return $ret;
}
/**
* Process all required data and redirect logged-in user
*
* @param kEvent $event
*/
function processLoginRedirect(&$event, $password)
{
$prefix_special = $this->Application->isAdmin ? 'u.current' : 'u'; // "u" used on front not to change theme
$object =& $this->Application->recallObject($prefix_special, null, Array('skip_autoload' => true));
$next_template = $this->Application->GetVar('next_template');
if ($next_template == '_ses_redirect') {
$location = $this->Application->BaseURL().$this->Application->RecallVar($next_template);
if( $this->Application->isDebugMode() && constOn('DBG_REDIRECT') )
{
$this->Application->Debugger->appendTrace();
echo "<b>Debug output above!!!</b> Proceed to redirect: <a href=\"$location\">$location</a><br>";
}
else {
header('Location: '.$location);
}
$session =& $this->Application->recallObject('Session');
$session->SaveData();
exit;
}
if ($next_template) {
$event->redirect = $next_template;
}
if ($this->Application->ConfigValue('UseJSRedirect')) {
$event->SetRedirectParam('js_redirect', 1);
}
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LoginUser', $object->GetDBField('Login'), $password);
$this->Application->resetCounters('UserSession');
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogin(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LoginUser', $event->getEventParam('user'), $event->getEventParam('pass') );
if ($event->redirect && is_string($event->redirect)) {
// some real template specified instead of true
$this->Application->Redirect($event->redirect, $event->redirect_params);
}
}
/**
* Called when user logs in using old in-portal
*
* @param kEvent $event
*/
function OnInpLogout(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LogoutUser');
}
function OnLogout(&$event)
{
$sync_manager =& $this->Application->recallObjectP('UsersSyncronizeManager', null, Array(), 'InPortalSyncronize');
$sync_manager->performAction('LogoutUser');
$this->Application->HandleEvent($dummy, 'session-log:OnEndSession');
$this->Application->SetVar('u.current_id', -2);
$object =& $this->Application->recallObject('u.current', null, Array('skip_autoload' => true));
$object->Load(-2);
$this->Application->DestroySession();
$session =& $this->Application->recallObject('Session');
/* @var $session Session */
$group_list = $this->Application->ConfigValue('User_GuestGroup') . ',' . $this->Application->ConfigValue('User_LoggedInGroup');
$session->SetField('PortalUserId', -2);
$session->SetField('GroupList', $group_list);
$this->Application->StoreVar('user_id', -2, true);
$this->Application->StoreVar('UserGroups', $group_list, true);
if ($this->Application->ConfigValue('UseJSRedirect')) {
$event->SetRedirectParam('js_redirect', 1);
}
$this->Application->resetCounters('UserSession');
$this->Application->Session->SetCookie('remember_login', '', adodb_mktime() - 3600);
$event->SetRedirectParam('pass', 'all');
}
/**
* Prefill states dropdown with correct values
*
* @param kEvent $event
* @access public
*/
function OnPrepareStates(&$event)
{
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->PopulateStates($event, 'State', 'Country');
$object =& $event->getObject();
if( $object->isRequired('Country') && $cs_helper->CountryHasStates( $object->GetDBField('Country') ) ) $object->setRequired('State', true);
$object->setLogin();
}
/**
* Redirects user after succesfull registration to confirmation template (on Front only)
*
* @param kEvent $event
*/
function OnAfterItemCreate(&$event)
{
$this->saveUserImages($event);
if ($this->Application->GetVar('skip_set_primary')) return;
$is_subscriber = $this->Application->GetVar('IsSubscriber');
if(!$is_subscriber)
{
$object =& $event->getObject();
$ug_table = TABLE_PREFIX.'UserGroup';
if ($object->mode == 't') {
$ug_table = $this->Application->GetTempName($ug_table, 'prefix:'.$event->Prefix);
}
$sql = 'UPDATE '.$ug_table.'
SET PrimaryGroup = 0
WHERE PortalUserId = '.$object->GetDBField('PortalUserId');
$this->Conn->Query($sql);
// set primary group to user
if ($this->Application->isAdminUser && $this->Application->GetVar('user_group')) {
// while in admin you can set any group for new users
$group_id = $this->Application->GetVar('user_group');
}
else {
$group_id = $object->GetDBField('UserGroup');
if ($group_id) {
// check, that group is allowed for Front-End
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'PortalGroup
WHERE GroupId = ' . (int)$group_id . ' AND FrontRegistration = 1';
$group_id = $this->Conn->GetOne($sql);
}
if (!$group_id) {
// when group not selected -> use default group
$group_id = $this->Application->ConfigValue('User_NewGroup');
}
}
$sql = 'REPLACE INTO '.$ug_table.'(PortalUserId,GroupId,PrimaryGroup) VALUES (%s,%s,1)';
$this->Conn->Query( sprintf($sql, $object->GetID(), $group_id) );
}
}
/**
* Login user if possible, if not then redirect to corresponding template
*
* @param kEvent $event
*/
function autoLoginUser(&$event)
{
$object =& $event->getObject();
$this->Application->SetVar('u.current_id', $object->GetID() );
if($object->GetDBField('Status') == STATUS_ACTIVE && !$this->Application->ConfigValue('User_Password_Auto'))
{
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
list($login_field, $submit_field) = $email_as_login ? Array('Email', 'email') : Array('Login', 'login');
$this->Application->SetVar($submit_field, $object->GetDBField($login_field) );
$this->Application->SetVar('password', $object->GetDBField('Password_plain') );
$event->CallSubEvent('OnLogin');
}
}
/**
* When creating user & user with such email exists then force to use OnUpdate insted of ?
*
* @param kEvent $event
*/
function OnSubstituteSubscriber(&$event)
{
$ret = false;
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
list($id, $field_values) = each($items_info);
$user_email = isset($field_values['Email']) ? $field_values['Email'] : false;
if($user_email)
{
// check if is subscriber
$verify_user =& $this->Application->recallObject('u.verify', null, Array('skip_autoload' => true) );
$verify_user->Load($user_email, 'Email');
if( $verify_user->isLoaded() && $verify_user->isSubscriberOnly() )
{
$items_info = Array( $verify_user->GetDBField('PortalUserId') => $field_values );
$this->Application->SetVar($event->getPrefixSpecial(true), $items_info);
$ret = true;
}
}
}
if( isset($event->MasterEvent) )
{
$event->MasterEvent->setEventParam('is_subscriber_only', $ret);
}
else
{
$event->setEventParam('is_subscriber_only', $ret);
}
}
/**
* Enter description here...
*
* @param kEvent $event
* @return bool
*/
function isSubscriberOnly(&$event)
{
$event->CallSubEvent('OnSubstituteSubscriber');
$is_subscriber = false;
if( $event->getEventParam('is_subscriber_only') )
{
$is_subscriber = true;
$object =& $event->getObject( Array('skip_autoload' => true) );
$this->OnUpdate($event);
if($event->status == erSUCCESS)
{
$this->OnAfterItemCreate($event);
$object->SendEmailEvents();
if (!$this->Application->isAdmin && ($event->status == erSUCCESS) && $event->redirect) {
$this->autoLoginUser($event);
}
}
}
return $is_subscriber;
}
/**
* Creates new user
*
* @param kEvent $event
*/
function OnCreate(&$event)
{
if (!$this->Application->isAdminUser) {
$this->setUserStatus($event);
}
if (!$this->isSubscriberOnly($event)) {
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->CheckStateField($event, 'State', 'Country');
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
if ($this->Application->ConfigValue('User_Password_Auto')) {
$pass = makepassword4(rand(5,8));
$object->SetField('Password', $pass);
$object->SetField('VerifyPassword', $pass);
$this->Application->SetVar('user_password',$pass);
}
parent::OnCreate($event);
$this->Application->SetVar('u.current_id', $object->getID() ); // for affil:OnRegisterAffiliate after hook
$this->setNextTemplate($event);
if (!$this->Application->isAdmin && ($event->status == erSUCCESS) && $event->redirect) {
$object->SendEmailEvents();
$this->autoLoginUser($event);
}
}
}
/**
* Set's new user status based on config options
*
* @param kEvent $event
*/
function setUserStatus(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$new_users_allowed = $this->Application->ConfigValue('User_Allow_New');
switch ($new_users_allowed) {
case 1: // Immediate
$object->SetDBField('Status', STATUS_ACTIVE);
$next_template = $this->Application->GetVar('registration_confirm_template');
if ($next_template) {
$event->redirect = $next_template;
}
break;
case 3: // Upon Approval
case 4: // Email Activation
$next_template = $this->Application->GetVar('registration_confirm_pending_template');
if ($next_template) {
$event->redirect = $next_template;
}
$object->SetDBField('Status', STATUS_PENDING);
break;
case 2: // Not Allowed
$object->SetDBField('Status', STATUS_DISABLED);
break;
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$this->_makePasswordRequired($event);
$email_as_login = $this->Application->ConfigValue('Email_As_Login');
$object =& $event->getObject();
if (!$this->checkBanRules($object)) {
$event->status = erFAIL;
return false;
}
if ($email_as_login) {
$object->Fields['Email']['error_msgs']['unique'] = $this->Application->Phrase('lu_user_and_email_already_exist');
}
}
/**
* Set's new unique resource id to user
*
* @param kEvent $event
*/
function OnAfterItemValidate(&$event)
{
$object =& $event->getObject();
$resource_id = $object->GetDBField('ResourceId');
if (!$resource_id)
{
$object->SetDBField('ResourceId', $this->Application->NextResourceId() );
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnRecommend(&$event)
{
$friend_email = $this->Application->GetVar('friend_email');
$friend_name = $this->Application->GetVar('friend_email');
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $object UsersItem */
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $friend_email))
{
/*$cutoff = adodb_mktime() + (int)$this->Application->ConfigValue('Suggest_MinInterval');
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'SuggestMail
WHERE email = ' . $this->Conn->qstr($friend_email) . ' AND sent < ' . $cutoff;
if ($this->Conn->GetRow($sql) !== false) {
$object->SetError('Email', 'send_error', 'lu_email_already_suggested');
$event->status = erFAIL;
return ;
}*/
$send_params = Array ();
$send_params['to_email'] = $friend_email;
$send_params['to_name'] = $friend_name;
$user_id = $this->Application->RecallVar('user_id');
$email_event =& $this->Application->EmailEventUser('USER.SUGGEST', $user_id, $send_params);
$email_event =& $this->Application->EmailEventAdmin('USER.SUGGEST');
if ($email_event->status == erSUCCESS){
/*$fields_hash = Array (
'email' => $friend_email,
'sent' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'SuggestMail');*/
$event->redirect_params = array('opener' => 's', 'pass' => 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
else {
// $event->redirect_params = array('opener' => 's', 'pass' => 'all');
// $event->redirect = $this->Application->GetVar('template_fail');
$object->SetError('Email', 'send_error', 'lu_email_send_error');
$event->status = erFAIL;
}
}
else {
$object->SetError('Email', 'invalid_email', 'lu_InvalidEmail');
$event->status = erFAIL;
}
}
/**
* Saves address changes and mades no redirect
*
* @param kEvent $event
*/
function OnUpdateAddress(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
list($id,$field_values) = each($items_info);
if($id > 0) $object->Load($id);
$object->SetFieldsFromHash($field_values);
$object->setID($id);
$object->Validate();
}
$event->redirect = false;
}
/**
* Validate subscriber's email & store it to session -> redirect to confirmation template
*
* @param kEvent $event
*/
function OnSubscribeQuery(&$event)
{
$user_email = $this->Application->GetVar('subscriber_email');
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email)) {
$object =& $this->Application->recallObject($this->Prefix.'.subscriber', null, Array('skip_autoload' => true));
/* @var $object UsersItem */
$this->Application->StoreVar('SubscriberEmail', $user_email);
$object->Load($user_email, 'Email');
if ($object->isLoaded()) {
$group_info = $this->GetGroupInfo($object->GetID());
$event->redirect = $this->Application->GetVar($group_info ? 'unsubscribe_template' : 'subscribe_template');
}
else {
$event->redirect = $this->Application->GetVar('subscribe_template');
$this->Application->StoreVar('SubscriberEmail', $user_email);
}
}
else {
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $object UsersItem */
$object->SetError('SubscribeEmail', 'invalid_email', 'lu_InvalidEmail');
$event->status = erFAIL;
}
}
/**
* Subscribe/Unsubscribe user based on email stored in previous step
*
* @param kEvent $event
*/
function OnSubscribeUser(&$event)
{
$object = &$this->Application->recallObject($this->Prefix.'.subscriber', null, Array('skip_autoload' => true));
/* @var $object UsersItem */
$user_email = $this->Application->RecallVar('SubscriberEmail');
if (preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email)) {
$this->RemoveRequiredFields($object);
$object->Load($user_email, 'Email');
if ($object->isLoaded()) {
$group_info = $this->GetGroupInfo($object->GetID());
if ($group_info){
if ($event->getEventParam('no_unsubscribe')) return;
if ($group_info['PrimaryGroup']){
// delete user
$object->Delete();
}
else {
$this->RemoveSubscriberGroup($object->GetID());
}
$event->redirect = $this->Application->GetVar('unsubscribe_ok_template');
}
else {
$this->AddSubscriberGroup($object->GetID(), 0);
$event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
}
else {
$object->SetField('Email', $user_email);
$object->SetField('Login', $user_email);
$object->SetDBField('dob', 1);
$object->SetDBField('dob_date', 1);
$object->SetDBField('dob_time', 1);
$object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default
$ip = getenv('HTTP_X_FORWARDED_FOR')?getenv('HTTP_X_FORWARDED_FOR'):getenv('REMOTE_ADDR');
$object->SetDBField('ip', $ip);
$this->Application->SetVar('IsSubscriber', 1);
if ($object->Create()) {
$this->AddSubscriberGroup($object->GetID(), 1);
$event->redirect = $this->Application->GetVar('subscribe_ok_template');
}
$this->Application->SetVar('IsSubscriber', 0);
}
}
}
function AddSubscriberGroup($user_id, $is_primary)
{
$group_id = $this->Application->ConfigValue('User_SubscriberGroup');
$sql = 'INSERT INTO ' . TABLE_PREFIX . 'UserGroup
(PortalUserId, GroupId, PrimaryGroup) VALUES (%s, %s, ' . $is_primary . ')';
$this->Conn->Query( sprintf($sql, $user_id, $group_id) );
$this->Application->EmailEventAdmin('USER.SUBSCRIBE');
$this->Application->EmailEventUser('USER.SUBSCRIBE', $user_id);
}
function RemoveSubscriberGroup($user_id)
{
$group_id = $this->Application->ConfigValue('User_SubscriberGroup');
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PortalUserId = ' . $user_id . '
AND GroupId = ' . $this->Application->ConfigValue('User_SubscriberGroup');
$this->Conn->Query($sql);
$this->Application->EmailEventAdmin('USER.UNSUBSCRIBE');
$this->Application->EmailEventUser('USER.UNSUBSCRIBE', $user_id);
}
/**
* Allows to detect user subscription status (subscribed or not)
*
* @param int $user_id
* @return bool
*/
function GetGroupInfo($user_id)
{
$sql = 'SELECT * FROM ' . TABLE_PREFIX . 'UserGroup
WHERE (PortalUserId = ' . $user_id . ')
AND (GroupId = ' . $this->Application->ConfigValue('User_SubscriberGroup') . ')';
return $this->Conn->GetRow($sql);
}
function OnForgotPassword(&$event)
{
$user_object =& $this->Application->recallObject('u.forgot', null, Array('skip_autoload' => true));
/* @var $user_object UsersItem */
// used for error reporting only -> rewrite code + theme (by Alex)
$user_current_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
/* @var $user_current_object UsersItem */
$username = $this->Application->GetVar('username');
$email = $this->Application->GetVar('email');
$found = false;
$allow_reset = true;
if (strlen($username)) {
$user_object->Load($username, 'Login');
if ($user_object->isLoaded()) {
$found = ($user_object->GetDBField("Login")==$username && $user_object->GetDBField("Status")==1) && strlen($user_object->GetDBField("Password"));
}
}
else if(strlen($email)) {
$user_object->Load($email, 'Email');
if ($user_object->isLoaded()) {
$found = ($user_object->GetDBField("Email")==$email && $user_object->GetDBField("Status")==1) && strlen($user_object->GetDBField("Password"));
}
}
if ($user_object->isLoaded()) {
$PwResetConfirm = $user_object->GetDBField('PwResetConfirm');
$PwRequestTime = $user_object->GetDBField('PwRequestTime');
$PassResetTime = $user_object->GetDBField('PassResetTime');
//$MinPwResetDelay = $user_object->GetDBField('MinPwResetDelay');
$MinPwResetDelay = $this->Application->ConfigValue('Users_AllowReset');
$allow_reset = (strlen($PwResetConfirm) ?
adodb_mktime() > $PwRequestTime + $MinPwResetDelay :
adodb_mktime() > $PassResetTime + $MinPwResetDelay);
}
if ($found && $allow_reset) {
$this->Application->StoreVar('tmp_user_id', $user_object->GetDBField("PortalUserId"));
$this->Application->StoreVar('tmp_email', $user_object->GetDBField("Email"));
$confirm_template = $this->Application->GetVar('reset_confirm_template');
if (!$confirm_template) {
$this->Application->SetVar('reset_confirm_template', 'platform/login/forgotpass_reset');
}
$this->Application->EmailEventUser('USER.PSWDC', $user_object->GetDBField('PortalUserId'));
$event->redirect = $this->Application->GetVar('template_success');
}
else {
if (!strlen($username) && !strlen($email)) {
$user_current_object->SetError('Login', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata');
$user_current_object->SetError('Email', 'forgotpw_nodata', 'lu_ferror_forgotpw_nodata');
}
else {
if ($allow_reset) {
if (strlen($username)) {
$user_current_object->SetError('Login', 'unknown_username', 'lu_ferror_unknown_username');
}
if (strlen($email)) {
$user_current_object->SetError('Email', 'unknown_email', 'lu_ferror_unknown_email');
}
}
else {
if (strlen($username)) {
$user_current_object->SetError('Login', 'reset_denied', 'lu_ferror_reset_denied');
}
if (strlen($email)) {
$user_current_object->SetError('Email', 'reset_denied', 'lu_ferror_reset_denied');
}
}
}
if($user_current_object->FieldErrors){
$event->redirect = false;
}
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnResetPassword(&$event)
{
$user_object =& $this->Application->recallObject('u.forgot');
if($user_object->Load($this->Application->RecallVar('tmp_user_id'))){
$this->Application->EmailEventUser('USER.PSWDC', $user_object->GetDBField("PortalUserId"));
$event->redirect = $this->Application->GetVar('template_success');
$m_cat_id = $this->Application->findModule('Name', 'In-Commerce', 'RootCat');
$this->Application->SetVar('m_cat_id', $m_cat_id);
$event->SetRedirectParam('pass', 'm');
}
}
function OnResetPasswordConfirmed(&$event)
{
// used for error reporting only -> rewrite code + theme (by Alex)
$user_current_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true));// TODO: change theme too
/* @var $user_current_object UsersItem */
$passed_key = trim($this->Application->GetVar('user_key'));
if (!$passed_key) {
$event->redirect_params = Array('opener' => 's', 'pass' => 'all');
$event->redirect = false;
$user_current_object->SetError('PwResetConfirm', 'code_is_not_valid', 'lu_code_is_not_valid');
}
$user_object =& $this->Application->recallObject('u.forgot', null, Array('skip_autoload' => true));
/* @var $user_object UsersItem */
$user_object->Load($passed_key, 'PwResetConfirm');
if ($user_object->isLoaded()) {
$exp_time = $user_object->GetDBField('PwRequestTime') + 3600;
$user_object->SetDBField('PwResetConfirm', '');
$user_object->SetDBField('PwRequestTime', 0);
if ($exp_time > adodb_mktime()) {
$newpw = makepassword4();
$this->Application->StoreVar('password', $newpw);
$user_object->SetField('Password', $newpw);
$user_object->SetField('VerifyPassword', $newpw);
$user_object->SetDBField('PassResetTime', adodb_mktime());
$user_object->SetDBField('PwResetConfirm', '');
$user_object->SetDBField('PwRequestTime', 0);
$user_object->Update();
$this->Application->SetVar('ForgottenPassword', $newpw);
$email_event_user =& $this->Application->EmailEventUser('USER.PSWD', $user_object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('USER.PSWD');
$this->Application->DeleteVar('ForgottenPassword');
if ($email_event_user->status == erSUCCESS) {
$event->redirect_params = array('opener' => 's', 'pass' => 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
} else {
$user_current_object->SetError('PwResetConfirm', 'code_expired', 'lu_code_expired');
$event->redirect = false;
}
} else {
$user_current_object->SetError('PwResetConfirm', 'code_is_not_valid', 'lu_code_is_not_valid');
$event->redirect = false;
}
}
function OnUpdate(&$event)
{
$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
$cs_helper->CheckStateField($event, 'State', 'Country');
parent::OnUpdate($event);
$this->setNextTemplate($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function setNextTemplate(&$event)
{
if ($this->Application->isAdmin) {
return ;
}
$event->redirect_params['opener'] = 's';
$object =& $event->getObject();
if ($object->GetDBField('Status') == STATUS_ACTIVE) {
$next_template = $this->Application->GetVar('next_template');
if ($next_template) {
$event->redirect = $next_template;
}
}
}
/**
* Delete users from groups if their membership is expired
*
* @param kEvent $event
*/
function OnCheckExpiredMembership(&$event)
{
// send pre-expiration reminders: begin
$pre_expiration = adodb_mktime() + $this->Application->ConfigValue('User_MembershipExpirationReminder') * 3600 * 24;
$sql = 'SELECT PortalUserId, GroupId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (ExpirationReminderSent = 0) AND (MembershipExpires < '.$pre_expiration.')';
$skip_clause = $event->getEventParam('skip_clause');
if ($skip_clause) {
$sql .= ' AND !('.implode(') AND !(', $skip_clause).')';
}
$records = $this->Conn->Query($sql);
if ($records) {
$conditions = Array();
foreach ($records as $record) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRATION.NOTICE', $record['PortalUserId']);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRATION.NOTICE');
$conditions[] = '(PortalUserId = '.$record['PortalUserId'].' AND GroupId = '.$record['GroupId'].')';
}
$sql = 'UPDATE '.TABLE_PREFIX.'UserGroup
SET ExpirationReminderSent = 1
WHERE '.implode(' OR ', $conditions);
$this->Conn->Query($sql);
}
// send pre-expiration reminders: end
// remove users from groups with expired membership: begin
$sql = 'SELECT PortalUserId
FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$user_ids = $this->Conn->GetCol($sql);
if ($user_ids) {
foreach ($user_ids as $id) {
$email_event_user =& $this->Application->EmailEventUser('USER.MEMBERSHIP.EXPIRED', $id);
$email_event_admin =& $this->Application->EmailEventAdmin('USER.MEMBERSHIP.EXPIRED');
}
}
$sql = 'DELETE FROM '.TABLE_PREFIX.'UserGroup
WHERE (MembershipExpires IS NOT NULL) AND (MembershipExpires < '.adodb_mktime().')';
$this->Conn->Query($sql);
// remove users from groups with expired membership: end
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnRefreshForm(&$event)
{
$event->redirect = false;
$item_info = $this->Application->GetVar($event->Prefix_Special);
list($id, $fields) = each($item_info);
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->setID($id);
$object->IgnoreValidation = true;
$object->SetFieldsFromHash($fields);
}
/**
* Sets persistant variable
*
* @param kEvent $event
*/
function OnSetPersistantVariable(&$event)
{
$field = $this->Application->GetVar('field');
$value = $this->Application->GetVar('value');
$this->Application->StorePersistentVar($field, $value);
$force_tab = $this->Application->GetVar('SetTab');
if ($force_tab) {
$this->Application->StoreVar('force_tab', $force_tab);
}
}
/**
* Overwritten to return user from order by special .ord
*
* @param kEvent $event
*/
function getPassedID(&$event)
{
switch ($event->Special) {
case 'ord':
$order =& $this->Application->recallObject('ord');
/* @var $order OrdersItem */
$id = $order->GetDBField('PortalUserId');
break;
case 'profile':
$id = $this->Application->GetVar('user_id');
if (!$id) {
// if none user_id given use current user id
$id = $this->Application->RecallVar('user_id');
}
break;
default:
$id = parent::getPassedID($event);
break;
}
return $id;
}
/**
* Allows to change root password
*
* @param kEvent $event
*/
function OnUpdateRootPassword(&$event)
{
return $this->OnUpdatePassword($event);
}
/**
* Allows to change root password
*
* @param kEvent $event
*/
function OnUpdatePassword(&$event)
{
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if (!$items_info) return ;
list ($id, $field_values) = each($items_info);
$user_id = $this->Application->RecallVar('user_id');
if ($id == $user_id && ($user_id > 0 || $user_id == -1)) {
$user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true));
/* @var $user_dummy kDBItem */
$user_dummy->Load($id);
$status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField'));
if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) {
// not active user is not allowed to update his record (he could not activate himself manually)
return false;
}
}
if ($user_id == -1) {
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object UsersItem */
// put salt to user's config
$field_options = $object->GetFieldOptions('RootPassword');
$field_options['salt'] = 'b38';
$object->SetFieldOptions('RootPassword', $field_options);
$verify_options = $object->GetFieldOptions('VerifyRootPassword');
$verify_options['salt'] = 'b38';
$object->SetFieldOptions('VerifyRootPassword', $verify_options);
// this is internal hack to allow root/root passwords for dev
if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') {
$this->Application->ConfigHash['Min_Password'] = 4;
}
$this->RemoveRequiredFields($object);
$object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass'));
$object->SetFieldsFromHash($field_values);
$object->setID(-1);
$status = $object->Validate();
if ($status) {
// validation on, password match too
$fields_hash = Array (
'VariableValue' => $object->GetDBField('RootPassword')
);
$conf_table = $this->Application->getUnitOption('conf', 'TableName');
$this->Conn->doUpdate($fields_hash, $conf_table, 'VariableName = "RootPass"');
$event->SetRedirectParam('opener', 'u');
}
else {
$event->status = erFAIL;
$event->redirect = false;
return;
}
}
else {
$object =& $event->getObject();
$object->SetFieldsFromHash($field_values);
if (!$object->Update()) {
$event->status = erFAIL;
$event->redirect = false;
}
}
$event->SetRedirectParam('opener', 'u');
$event->redirect == true;
}
/**
* Apply custom processing to item
*
* @param kEvent $event
*/
function customProcessing(&$event, $type)
{
if ($event->Name == 'OnCreate' && $type == 'before') {
$object =& $event->getObject();
/* @var $object kDBItem */
// if auto password has not been set already - store real one - to be used in email events
if (!$this->Application->GetVar('user_password')) {
$this->Application->SetVar('user_password', $object->GetDirtyField('Password'));
$object->SetDBField('Password_plain', $object->GetDirtyField('Password'));
}
// validate here, because subscribing procedure should not validate captcha code
if ($this->Application->ConfigValue('RegistrationCaptcha')) {
$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
/* @var $captcha_helper kCaptchaHelper */
$captcha_helper->validateCode($event, false);
}
}
}
function OnMassResetSettings(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$event->status=erSUCCESS;
$ids = $this->StoreSelectedIDs($event);
$default_user_id = $this->Application->ConfigValue('DefaultSettingsUserId');
if (in_array($default_user_id, $ids)) {
array_splice($ids, array_search($default_user_id, $ids), 1);
}
if ($ids) {
$q = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData WHERE PortalUserId IN ('.join(',', $ids).') AND
(VariableName LIKE "%_columns_%"
OR
VariableName LIKE "%_filter%"
OR
VariableName LIKE "%_PerPage%")';
$this->Conn->Query($q);
}
$this->clearSelectedIDs($event);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
$virtual_users = Array (-1, -2); // root, Guest
return ($object->GetDBField('Status') == STATUS_ACTIVE) || in_array($object->GetID(), $virtual_users);
}
/**
* Sends approved/declined email event on user status change
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
$this->saveUserImages($event);
$object =& $event->getObject();
/* @var $object UsersItem */
if (!$this->Application->isAdmin || $object->IsTempTable()) {
return ;
}
$this->sendStatusChangeEvent($object->GetID(), $object->GetOriginalField('Status'), $object->GetDBField('Status'));
}
/**
* Stores user's original Status before overwriting with data from temp table
*
* @param kEvent $event
*/
function OnBeforeDeleteFromLive(&$event)
{
$user_status = $this->Application->GetVar('user_status');
if (!$user_status) {
$user_status = Array ();
}
$user_id = $event->getEventParam('id');
if ($user_id > 0) {
$user_status[$user_id] = $this->getUserStatus($user_id);
$this->Application->SetVar('user_status', $user_status);
}
}
/**
* Sends approved/declined email event on user status change (in temp tables during editing)
*
* @param kEvent $event
*/
function OnAfterCopyToLive(&$event)
{
$temp_id = $event->getEventParam('temp_id');
if ($temp_id == 0) {
// this is new user create, don't send email events
return ;
}
$new_status = $this->getUserStatus($temp_id);
$user_status = $this->Application->GetVar('user_status');
$this->sendStatusChangeEvent($temp_id, $user_status[$temp_id], $new_status);
}
/**
* Returns user status (active, pending, disabled) based on ID and temp mode setting
*
* @param int $user_id
* @return int
*/
function getUserStatus($user_id)
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField');
$table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
$sql = 'SELECT Status
FROM '.$table_name.'
WHERE '.$id_field.' = '.$user_id;
return $this->Conn->GetOne($sql);
}
/**
* Sends approved/declined email event on user status change
*
* @param int $user_id
* @param int $prev_status
* @param int $new_status
*/
function sendStatusChangeEvent($user_id, $prev_status, $new_status)
{
$status_events = Array (
STATUS_ACTIVE => 'USER.APPROVE',
STATUS_DISABLED => 'USER.DENY',
);
$email_event = isset($status_events[$new_status]) ? $status_events[$new_status] : false;
if (($prev_status != $new_status) && $email_event) {
$this->Application->EmailEventUser($email_event, $user_id);
$this->Application->EmailEventAdmin($email_event);
}
}
/**
* OnAfterConfigRead for users
*
* @param kEvent $event
*/
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
// 1. arrange user registration countries
$first_country = $this->Application->ConfigValue('User_Default_Registration_Country');
if ($first_country) {
// update user country dropdown sql
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (DestId = '.$first_country.', 1, 0) DESC, \\1', $fields['Country']['options_sql']);
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
}
// 2. set default user registration group
$virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
$virtual_fields['UserGroup']['default'] = $this->Application->ConfigValue('User_NewGroup');
$this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
// 3. allow avatar upload on Front-End
$file_helper =& $this->Application->recallObject('FileHelper');
/* @var $file_helper FileHelper */
$file_helper->createItemFiles($event->Prefix, true); // create image fields
if ($this->Application->isAdminUser) {
// 4. when in administrative console, then create all users with Active status
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
// $fields['Password']['required'] = 1; // set password required (will broke approve/decline buttons)
$fields['Status']['default'] = STATUS_ACTIVE;
$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
// 5. remove groups tab on editing forms when AdvancedUserManagement config variable not set
if (!$this->Application->ConfigValue('AdvancedUserManagement')) {
$edit_tab_presets = $this->Application->getUnitOption($event->Prefix, 'EditTabPresets');
foreach ($edit_tab_presets as $preset_name => $preset_tabs) {
if (array_key_exists('groups', $preset_tabs)) {
unset($edit_tab_presets[$preset_name]['groups']);
if (count($edit_tab_presets[$preset_name]) == 1) {
// only 1 tab left -> remove it too
$edit_tab_presets[$preset_name] = Array ();
}
}
}
$this->Application->setUnitOption($event->Prefix, 'EditTabPresets', $edit_tab_presets);
}
}
}
/**
* OnMassCloneUsers
*
* @param kEvent $event
*/
function OnMassCloneUsers(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$event->status=erSUCCESS;
$ids = $this->StoreSelectedIDs($event);
$this->Application->SetVar('skip_set_primary', 1); // otherwise it will default primary group, search for skip_set_primary above
$temp_handler =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$cloned_users = $temp_handler->CloneItems($event->Prefix, '', $ids);
$this->clearSelectedIDs($event);
}
/**
* When cloning users, reset password (set random)
*
* @param kEvent $event
*/
function OnBeforeClone(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$object->setRequired('Password', 0);
$object->setRequired('VerifyPassword', 0);
$object->SetDBField('Password', rand(100000000, 999999999));
$object->SetDBField('CreatedOn', adodb_mktime());
$object->SetDBField('ResourceId', false); // this will reset it
// change email cause it should be unique
$object->NameCopy(array(), $object->GetID(), 'Email', 'copy%1$s.%2$s');
$object->UpdateFormattersSubFields();
}
/**
* Copy user groups after copying user
*
* @param kEvent $event
*/
function OnAfterClone(&$event)
{
$id = $event->getEventParam('id');
$original_id = $event->getEventParam('original_id');
$sql = 'INSERT '.TABLE_PREFIX."UserGroup SELECT $id, GroupId, MembershipExpires, PrimaryGroup, 0 FROM ".TABLE_PREFIX."UserGroup WHERE PortalUserId = $original_id";
$this->Conn->Query($sql);
}
/**
* Saves selected ids to session
*
* @param kEvent $event
*/
function OnSaveSelected(&$event)
{
$this->StoreSelectedIDs($event);
// remove current ID, otherwise group selector will use it in filters
$this->Application->DeleteVar($event->getPrefixSpecial(true).'_id');
}
/**
* Adds selected link to listing
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$event->SetRedirectParam('opener', 'u');
$user_ids = $this->getSelectedIDs($event, true);
$this->clearSelectedIDs($event);
$dst_field = $this->Application->RecallVar('dst_field');
if ($dst_field != 'PrimaryGroupId') {
return ;
}
$group_ids = $this->Application->GetVar('g');
$primary_group_id = $group_ids ? array_shift( array_keys($group_ids) ) : false;
if (!$user_ids || !$primary_group_id) {
return ;
}
$table_name = $this->Application->getUnitOption('ug', 'TableName');
$sql = 'SELECT PortalUserId
FROM '.$table_name.'
WHERE (GroupId = '.$primary_group_id.') AND (PortalUserId IN ('.implode(',', $user_ids).'))';
$existing_members = $this->Conn->GetCol($sql);
// 1. reset primary group mark
$sql = 'UPDATE '.$table_name.'
SET PrimaryGroup = 0
WHERE PortalUserId IN ('.implode(',', $user_ids).')';
$this->Conn->Query($sql);
foreach ($user_ids as $user_id) {
if (in_array($user_id, $existing_members)) {
// 2. already member of that group -> just make primary
$sql = 'UPDATE '.$table_name.'
SET PrimaryGroup = 1
WHERE (PortalUserId = '.$user_id.') AND (GroupId = '.$primary_group_id.')';
$this->Conn->Query($sql);
}
else {
// 3. not member of that group -> make member & make primary
$fields_hash = Array (
'GroupId' => $primary_group_id,
'PortalUserId' => $user_id,
'PrimaryGroup' => 1,
);
$this->Conn->doInsert($fields_hash, $table_name);
}
}
}
/**
* Loads user images
*
* @param kEvent $event
*/
function OnAfterItemLoad(&$event)
{
parent::OnAfterItemLoad($event);
// linking existing images for item with virtual fields
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
$image_helper->LoadItemImages($object);
}
/**
* Save user images
*
* @param kEvent $event
*/
function saveUserImages(&$event)
{
if (!$this->Application->isAdmin) {
$image_helper =& $this->Application->recallObject('ImageHelper');
/* @var $image_helper ImageHelper */
$object =& $event->getObject();
/* @var $object kDBItem */
// process image upload in virtual fields
$image_helper->SaveItemImages($object);
}
}
/**
* Checks, if given user fields matches at least one of defined ban rules
*
* @param kDBItem $object
* @return bool
*/
function checkBanRules(&$object)
{
$table = $this->Application->getUnitOption('ban-rule', 'TableName');
if (!$this->Conn->TableFound($table)) {
// when ban table not found -> assume user is ok by default
return true;
}
$sql = 'SELECT *
FROM '.$table.'
WHERE ItemType = 6 AND Status = ' . STATUS_ACTIVE . '
ORDER BY Priority DESC';
$rules = $this->Conn->Query($sql);
$found = false;
foreach ($rules as $rule) {
$field = $rule['ItemField'];
$this_value = strtolower( $object->GetDBField($field) );
$test_value = strtolower( $rule['ItemValue'] );
switch ($rule['ItemVerb']) {
/*case 0: // any
$found = true;
break;*/
case 1: // is
if ($this_value == $test_value) {
$found = true;
}
break;
/*case 2: // is not
if ($this_value != $test_value) {
$found = true;
}
break;*/
case 3: // contains
if (strstr($this_value, $test_value)) {
$found = true;
}
break;
/*case 4: // not contains
if (!strstr($this_value, $test_value)) {
$found = true;
}
break;
case 5: // Greater Than
if ($test_value > $this_value) {
$found = true;
}
break;
case 6: // Less Than
if ($test_value < $this_value) {
$found = true;
}
break;
case 7: // exists
if (strlen($this_value) > 0) {
$found = true;
}
break;
case 8: // unique
if ($this->ValueExists($field, $this_value)) {
$found = true;
}
break;*/
}
if ($found) {
break;
}
}
return !$found;
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function OnPreCreate(&$event)
{
parent::OnPreCreate($event);
if ($event->status == erSUCCESS) {
$this->_makePasswordRequired($event);
}
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function OnNew(&$event)
{
parent::OnNew($event);
if ($event->status == erSUCCESS) {
$this->_makePasswordRequired($event);
}
}
/**
* Makes password required for new users
*
* @param kEvent $event
*/
function _makePasswordRequired(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$required_fields = Array ('Password', 'Password_plain', 'VerifyPassword', 'VerifyPassword_plain');
foreach ($required_fields as $required_field) {
$object->setRequired($required_field);
}
}
}
-
-?>
\ No newline at end of file
Index: branches/5.0.x/core/units/helpers/mod_rewrite_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (revision 12848)
+++ branches/5.0.x/core/units/helpers/mod_rewrite_helper.php (revision 12849)
@@ -1,985 +1,984 @@
<?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 kModRewriteHelper extends kHelper {
/**
* Holds a refererence to httpquery
*
* @var kHttpQuery
*/
var $HTTPQuery = null;
/**
* Parts found during url parsing
*
* @var Array
*/
var $_partsFound = Array ();
/**
* Category item prefix, that was found
*
* @var string
*/
var $_modulePrefix = false;
/**
* Template aliases for current theme
*
* @var Array
*/
var $_templateAliases = null;
/**
* Constructor of kModRewriteHelper class
*
* @return kModRewriteHelper
*/
function kModRewriteHelper()
{
parent::kHelper();
$this->HTTPQuery =& $this->Application->recallObject('HTTPQuery');
}
function processRewriteURL()
{
$passed = Array ();
$url = $this->HTTPQuery->Get('_mod_rw_url_');
if (substr($url, -5) == '.html') {
$url = substr($url, 0, strlen($url) - 5);
}
$restored = false;
$sql = 'SELECT Data, Cached
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "mod_rw_' . md5($url) . '"';
$cache = $this->Conn->GetRow($sql);
if (false && $cache && $cache['Cached'] > 0) {
// not used for now
$cache = unserialize($cache['Data']);
$vars = $cache['vars'];
$passed = $cache['passed'];
$restored = true;
}
else {
$vars = $this->parseRewriteURL($url);
$passed = $vars['pass']; // also used in bottom of this method
unset($vars['pass']);
$cache = Array ('vars' => $vars, 'passed' => $passed);
$fields_hash = Array (
'VarName' => 'mod_rw_' . md5($url),
'Data' => serialize($cache),
'Cached' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
if (array_key_exists('t', $this->HTTPQuery->Post) && $this->HTTPQuery->Post['t']) {
// template from POST overrides template from URL.
$vars['t'] = $this->HTTPQuery->Post['t'];
if (isset($vars['is_virtual']) && $vars['is_virtual']) {
$vars['m_cat_id'] = 0; // this is virtual template category (for Proj-CMS)
}
}
unset($vars['is_virtual']);
}
foreach ($vars as $name => $value) {
$this->HTTPQuery->Set($name,$value);
}
// if ($restored) {
$this->InitAll();
// }
$this->HTTPQuery->finalizeParsing($passed);
}
function parseRewriteURL($url)
{
$sql = 'SELECT Data, Cached
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "mod_rw_' . md5($url) . '"';
$vars = $this->Conn->GetRow($sql);
if (false && $vars && $vars['Cached'] > 0) {
// not used for now
$vars = unserialize($menu['Data']);
return $vars;
}
$vars = Array ('pass' => Array ('m'));
$url_parts = $url ? explode('/', trim(mb_strtolower($url, 'UTF-8'), '/')) : Array ();
if (($this->HTTPQuery->Get('rewrite') == 'on') || !$url_parts) {
$this->_setDefaultValues($vars);
}
if (!$url_parts) {
$this->InitAll();
$vars['t'] = $this->HTTPQuery->getDefaultTemplate('');
return $vars;
}
else {
$vars['t'] = '';
}
$this->_parseLanguage($url_parts, $vars);
$this->_parseTheme($url_parts, $vars);
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_page>
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_page> (category-based section template)
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<template>/<module_item>
// http://site-url/<language>/<theme>/<category>[_<category_page>]/<module_item> (category-based detail template)
// http://site-url/<language>/<theme>/<rl_injections>/<category>[_<category_page>]/<rl_part> (customized url)
if ( $this->processRewriteListeners($url_parts, $vars) ) {
return $vars;
}
if ($this->_parsePhisycalTemplate($url_parts, $vars)) {
$this->_partsFound[] = 'parsePhisycalTemplate';
}
if (($this->_modulePrefix === false) && in_array('parseCategory', $this->_partsFound)) {
// no item found, but category found -> module index page
foreach ($this->Application->RewriteListeners as $prefix => $listener) {
// no idea what module we are talking about, so pass info form all modules
$vars['pass'][] = $prefix;
}
return $vars;
}
if (!$this->_partsFound) {
$not_found = $this->Application->ConfigValue('ErrorTemplate');
$vars['t'] = $not_found ? $not_found : 'error_notfound';
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$vars['m_cat_id'] = $themes_helper->getPageByTemplate($vars['t'], $vars['m_theme']);
header('HTTP/1.0 404 Not Found');
}
return $vars;
}
function InitAll()
{
$this->Application->VerifyLanguageId();
$this->Application->Phrases->Init('phrases');
$this->Application->VerifyThemeId();
}
/**
* Processes url using rewrite listeners
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function processRewriteListeners(&$url_parts, &$vars)
{
$this->initRewriteListeners();
$page_number = $this->_parsePage($url_parts, $vars);
if ($page_number) {
$this->_partsFound[] = 'parsePage';
}
foreach ($this->Application->RewriteListeners as $prefix => $listener) {
// set default page
$vars[$prefix . '_Page'] = 1; // will override page in session in case, when none is given in url
if ($page_number) {
// page given in url - use it
$vars[$prefix . '_id'] = 0;
$vars[$prefix . '_Page'] = $page_number;
}
$listener_result = $listener[0]->$listener[1](REWRITE_MODE_PARSE, $prefix, $vars, $url_parts);
if ($listener_result === false) {
// will not proceed to other methods
return true;
}
}
// will proceed to other methods
return false;
}
/**
* Parses real template name from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function _parsePhisycalTemplate($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
do {
$template_path = implode('/', $url_parts);
$t_parts['path'] = dirname($template_path) == '.' ? '' : '/' . dirname($template_path);
$t_parts['file'] = basename($template_path);
$sql = 'SELECT FileId
FROM ' . TABLE_PREFIX . 'ThemeFiles
WHERE (ThemeId = ' . $vars['m_theme'] . ') AND (FilePath = ' . $this->Conn->qstr($t_parts['path']) . ') AND (FileName = ' . $this->Conn->qstr($t_parts['file'] . '.tpl') . ')';
$template_found = $this->Conn->GetOne($sql);
if (!$template_found) {
array_shift($url_parts);
}
} while (!$template_found && $url_parts);
if ($template_found) {
$vars['t'] = $template_path;
// 1. will damage actual category during category item review add process
// 2. will use "use_section" parameter of "m_Link" tag to gain same effect
// $themes_helper =& $this->Application->recallObject('ThemesHelper');
// /* @var $themes_helper kThemesHelper */
//
// $vars['m_cat_id'] = $themes_helper->getPageByTemplate($template_path, $vars['m_theme']);
return true;
}
return false;
}
/**
* Parses category part of url, build main part of url
*
* @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE.
* @param string $prefix Prefix, that listener uses for system integration
* @param Array $params Params, that are used for url building or created during url parsing.
* @param Array $url_parts Url parts to parse (only for parsing).
* @param bool $keep_events Keep event names in resulting url (only for building).
* @return bool|string|Array Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener.
*/
function MainRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false)
{
if ($rewrite_mode == REWRITE_MODE_BUILD) {
return $this->_buildMainUrl($prefix, $params, $keep_events);
}
if ( $this->_parseFriendlyUrl($url_parts, $params) ) {
// friendly urls work like exact match only!
return false;
}
if ($this->_parseCategory($url_parts, $params)) {
$this->_partsFound[] = 'parseCategory';
}
return true;
}
/**
* Build main part of every url
*
* @param string $prefix_special
* @param Array $params
* @param bool $keep_events
* @return string
*/
function _buildMainUrl($prefix_special, &$params, $keep_events)
{
$ret = '';
list ($prefix) = explode('.', $prefix_special);
$processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events);
if ($processed_params === false) {
return '';
}
// add language
$default_language_id = $this->Application->GetDefaultLanguageId();
if ($processed_params['m_lang'] && ($processed_params['m_lang'] != $default_language_id)) {
$language_name = $this->Application->getCache('language_names', $processed_params['m_lang']);
if ($language_name === false) {
$sql = 'SELECT PackName
FROM ' . TABLE_PREFIX . 'Language
WHERE LanguageId = ' . $processed_params['m_lang'];
$language_name = $this->Conn->GetOne($sql);
$this->Application->setCache('language_names', $processed_params['m_lang'], $language_name);
}
$ret .= $language_name . '/';
}
// add theme
$default_theme_id = $this->Application->GetDefaultThemeId();
if ($processed_params['m_theme'] && ($processed_params['m_theme'] != $default_theme_id)) {
$theme_name = $this->Application->getCache('theme_names', $processed_params['m_theme']);
if ($theme_name === false) {
$sql = 'SELECT Name
FROM ' . TABLE_PREFIX . 'Theme
WHERE ThemeId = ' . $processed_params['m_theme'];
$theme_name = $this->Conn->GetOne($sql);
$this->Application->setCache('theme_names', $processed_params['m_theme'], $theme_name);
}
$ret .= $theme_name . '/';
}
// inject custom url parts made by other rewrite listeners just after language/theme url parts
if ($params['inject_parts']) {
$ret .= implode('/', $params['inject_parts']) . '/';
}
// add category
if ($processed_params['m_cat_id'] > 0 && $params['pass_category']) {
$category_filename = $this->Application->getFilename('c', $processed_params['m_cat_id']);
preg_match('/^Content\/(.*)/i', $category_filename, $regs);
if ($regs) {
$template = array_key_exists('t', $params) ? $params['t'] : false;
if (strtolower($regs[1]) == strtolower($template)) {
// we could have category path like "Content/<template_path>" in this case remove template
$params['pass_template'] = false;
}
$ret .= $regs[1] . '/';
}
$params['category_processed'] = true;
}
// reset category page
$force_page_adding = false;
if (array_key_exists('reset', $params) && $params['reset']) {
unset($params['reset']);
if ($processed_params['m_cat_id']) {
$processed_params['m_cat_page'] = 1;
$force_page_adding = true;
}
}
if ((array_key_exists('category_processed', $params) && $params['category_processed'] && ($processed_params['m_cat_page'] > 1)) || $force_page_adding) {
// category name was added before AND category page number found
$ret = rtrim($ret, '/') . '_' . $processed_params['m_cat_page'] . '/';
}
$template = array_key_exists('t', $params) ? $params['t'] : false;
$category_template = ($processed_params['m_cat_id'] > 0) && $params['pass_category'] ? $this->Application->getCache('category_designs', $processed_params['m_cat_id']) : '';
if ((strtolower($template) == '__default__') && ($processed_params['m_cat_id'] == 0)) {
// for "Home" category set template to index when not set
$template = 'index';
}
// remove template from url if it is category index cached template
if (($template == $category_template) || (mb_strtolower($template) == '__default__')) {
// given template is also default template for this category or '__default__' given
$params['pass_template'] = false;
}
if ($template && $params['pass_template']) {
$ret .= $template . '/';
}
return mb_strtolower( rtrim($ret, '/') );
}
/**
* Gets language part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function _parseLanguage(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$url_part = reset($url_parts);
$sql = 'SELECT LanguageId, IF(LOWER(PackName) = ' . $this->Conn->qstr($url_part) . ', 2, PrimaryLang) AS SortKey
FROM ' . TABLE_PREFIX . 'Language
WHERE Enabled = 1
ORDER BY SortKey DESC';
$language_info = $this->Conn->GetRow($sql);
$this->Application->Phrases = new PhrasesCache();
if ($language_info && $language_info['LanguageId'] && $language_info['SortKey']) {
// primary language will be selected in case, when $url_part doesn't match to other's language pack name
// don't use next enabled language, when primary language is disabled
$vars['m_lang'] = $language_info['LanguageId'];
if ($language_info['SortKey'] == 2) {
// language was found by pack name
array_shift($url_parts);
}
return true;
}
return false;
}
/**
* Gets theme part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function _parseTheme(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$url_part = reset($url_parts);
$sql = 'SELECT ThemeId, IF(LOWER(Name) = ' . $this->Conn->qstr($url_part) . ', 2, PrimaryTheme) AS SortKey, TemplateAliases
FROM ' . TABLE_PREFIX . 'Theme
WHERE Enabled = 1
ORDER BY SortKey DESC';
$theme_info = $this->Conn->GetRow($sql);
if ($theme_info && $theme_info['ThemeId'] && $theme_info['SortKey']) {
// primary theme will be selected in case, when $url_part doesn't match to other's theme name
// don't use next enabled theme, when primary theme is disabled
$vars['m_theme'] = $theme_info['ThemeId'];
if ($theme_info['TemplateAliases']) {
$this->_templateAliases = unserialize($theme_info['TemplateAliases']);
}
else {
$this->_templateAliases = Array ();
}
if ($theme_info['SortKey'] == 2) {
// theme was found by name
array_shift($url_parts);
}
return true;
}
$vars['m_theme'] = 0; // required, because used later for category/template detection
return false;
}
/**
* Checks if whole url_parts matches a whole In-CMS page
*
* @param array $url_parts
* @return boolean
*/
function _parseFriendlyUrl($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE FriendlyURL = ' . $this->Conn->qstr(implode('/', $url_parts));
$friendly = $this->Conn->GetRow($sql);
if ($friendly) {
$vars['m_cat_id'] = $friendly['CategoryId'];
$vars['t'] = preg_replace('/^Content\//i', '', $friendly['NamedParentPath']);
return true;
}
return false;
}
/**
* Set's page (when found) to all modules
*
* @param Array $url_parts
* @param Array $vars
* @return string
*
* @todo Should find a way, how to determine what rewrite listerner page is it
*/
function _parsePage(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$page_number = end($url_parts);
if (!is_numeric($page_number)) {
return false;
}
array_pop($url_parts);
return $page_number;
}
/**
* Remove page numbers for all rewrite listeners
*
* @todo Should find a way, how to determine what rewrite listerner page is it
*/
function removePages()
{
foreach ($this->Application->RewriteListeners as $prefix => $listener) {
$this->Application->DeleteVar($prefix . '_Page');
}
}
/**
* Extracts category part from url
*
* @param Array $url_parts
* @param Array $vars
* @return bool
*/
function _parseCategory($url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$res = false;
$url_part = array_shift($url_parts);
$category_id = 0;
$last_category_info = false;
$category_path = $url_part == 'content' ? '' : 'content';
do {
$category_path = trim($category_path . '/' . $url_part, '/');
// bb_<topic_id> -> forums/bb_2
if ( !preg_match('/^bb_[\d]+$/', $url_part) && preg_match('/(.*)_([\d]+)$/', $category_path, $rets) ) {
$category_path = $rets[1];
$vars['m_cat_page'] = $rets[2];
}
$sql = 'SELECT CategoryId, IsIndex, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE Status IN (1,4) AND (LOWER(NamedParentPath) = ' . $this->Conn->qstr($category_path) . ') AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
$category_info = $this->Conn->GetRow($sql);
if ($category_info !== false) {
$last_category_info = $category_info;
$url_part = array_shift($url_parts);
$res = true;
}
} while ($category_info !== false && $url_part);
if ($last_category_info) {
// IsIndex = 2 is a Container-only page, meaning it should go to index-page child
if ($last_category_info['IsIndex'] == 2) {
$sql = 'SELECT CategoryId, NamedParentPath
FROM ' . TABLE_PREFIX . 'Category
WHERE (ParentId = ' . $last_category_info['CategoryId'] . ') AND (IsIndex = 1) AND (ThemeId = ' . $vars['m_theme'] . ' OR ThemeId = 0)';
$category_info = $this->Conn->GetRow($sql);
if ($category_info) {
// when index sub-page is found use it, otherwise use container page
$last_category_info = $category_info;
}
}
// 1. Set virtual page as template, this will be replaced to physical template later in kApplication::Run.
// 2. Don't set CachedTemplate field as template here, because we will loose original page associated with it's cms blocks!
$vars['t'] = mb_strtolower( preg_replace('/^Content\//i', '', $last_category_info['NamedParentPath']), 'UTF-8' );
$vars['m_cat_id'] = $last_category_info['CategoryId'];
$vars['is_virtual'] = true; // for template from POST, strange code there!
}
else {
$vars['m_cat_id'] = 0;
}
return $res;
}
/**
* Builds/parses category item part of url
*
* @param int $rewrite_mode Mode in what rewrite listener was called. Possbile two modes: REWRITE_MODE_BUILD, REWRITE_MODE_PARSE.
* @param string $prefix Prefix, that listener uses for system integration
* @param Array $params Params, that are used for url building or created during url parsing.
* @param Array $url_parts Url parts to parse (only for parsing).
* @param bool $keep_events Keep event names in resulting url (only for building).
* @return bool Return true to continue to next listener; return false (when building) not to rewrite given prefix; return false (when parsing) to stop processing at this listener.
*/
function CategoryItemRewriteListener($rewrite_mode = REWRITE_MODE_BUILD, $prefix, &$params, &$url_parts, $keep_events = false)
{
static $parsed = false;
if ($rewrite_mode == REWRITE_MODE_BUILD) {
return $this->_buildCategoryItemUrl($prefix, $params, $keep_events);
}
if (!$parsed) {
$this->_modulePrefix = $this->_parseCategoryItemUrl($url_parts, $params);
if ($this->_modulePrefix !== false) {
$params['pass'][] = $this->_modulePrefix;
$this->_partsFound[] = 'parseCategoryItemUrl';
}
$parsed = true;
}
return true;
}
/**
* Build category teim part of url
*
* @param string $prefix_special
* @param Array $params
* @param bool $keep_events
* @return string
*/
function _buildCategoryItemUrl($prefix_special, &$params, $keep_events)
{
$ret = '';
list ($prefix) = explode('.', $prefix_special);
$processed_params = $this->getProcessedParams($prefix_special, $params, $keep_events);
if ($processed_params === false) {
return '';
}
if ($processed_params[$prefix_special . '_id']) {
// this allows to fill 3 cache records with one query (see this method for details)
$category_id = array_key_exists('m_cat_id', $params) ? $params['m_cat_id'] : $this->Application->GetVar('m_cat_id');
$category_filename = $this->Application->getFilename('c', $category_id);
// if template is also item template of category, then remove template
$template = array_key_exists('t', $params) ? $params['t'] : false;
$item_template = $this->GetItemTemplate($category_id, $prefix);
if ($template == $item_template || strtolower($template) == '__default__') {
// given template is also default template for this category item or '__default__' given
$params['pass_template'] = false;
}
// get item's filename
if ($prefix == 'bb') {
$ret .= 'bb_' . $processed_params[$prefix_special . '_id'] . '/';
}
else {
$filename = $this->Application->getFilename($prefix, $processed_params[$prefix_special . '_id'], $category_id);
if ($filename !== false) {
$ret .= $filename . '/';
}
}
} else {
if ($processed_params[$prefix_special . '_Page'] == 1) {
// when printing category items and we are on the 1st page -> there is no information about
// category item prefix and $params['pass_category'] will not be added automatically
$params['pass_category'] = true;
}
else {
$ret .= $processed_params[$prefix_special . '_Page'] . '/';
}
}
return mb_strtolower( rtrim($ret, '/') );
}
/**
* Sets template and id, corresponding to category item given in url
*
* @param Array $url_parts
* @param Array $vars
* @return bool|string
*/
function _parseCategoryItemUrl(&$url_parts, &$vars)
{
if (!$url_parts) {
return false;
}
$item_filename = end($url_parts);
if (is_numeric($item_filename)) {
// this page, don't process here
return false;
}
if (preg_match('/^bb_([\d]+)/', $item_filename, $regs)) {
// process topics separatly, because they don't use item filenames
array_pop($url_parts);
return $this->_parseTopicUrl($regs[1], $vars);
}
// locating the item in CategoryItems by filename to detect its ItemPrefix and its category ParentPath
$sql = 'SELECT ci.ItemResourceId, ci.ItemPrefix, c.ParentPath, ci.CategoryId
FROM ' . TABLE_PREFIX . 'CategoryItems AS ci
LEFT JOIN ' . TABLE_PREFIX . 'Category AS c ON c.CategoryId = ci.CategoryId
WHERE (ci.CategoryId = ' . (int)$vars['m_cat_id'] . ') AND (ci.Filename = ' . $this->Conn->qstr($item_filename) . ')';
$cat_item = $this->Conn->GetRow($sql);
if ($cat_item !== false) {
// item found
$module_prefix = $cat_item['ItemPrefix'];
$item_template = $this->GetItemTemplate($cat_item, $module_prefix);
// converting ResourceId to correpsonding Item id
$module_config = $this->Application->getUnitOptions($module_prefix);
$sql = 'SELECT ' . $module_config['IDField'] . '
FROM ' . $module_config['TableName'] . '
WHERE ResourceId = ' . $cat_item['ItemResourceId'];
$item_id = $this->Conn->GetOne($sql);
array_pop($url_parts);
if ($item_id) {
if ($item_template) {
// when template is found in category -> set it
$vars['t'] = $item_template;
}
// we have category item id
$vars[$module_prefix . '_id'] = $item_id;
return $module_prefix;
}
}
return false;
}
/**
* Set's template and topic id corresponding to topic given in url
*
* @param int $topic_id
* @param Array $vars
* @return string
*/
function _parseTopicUrl($topic_id, &$vars)
{
$sql = 'SELECT c.ParentPath, c.CategoryId
FROM ' . TABLE_PREFIX . 'Category AS c
WHERE c.CategoryId = ' . (int)$vars['m_cat_id'];
$cat_item = $this->Conn->GetRow($sql);
$item_template = $this->GetItemTemplate($cat_item, 'bb');
if ($item_template) {
$vars['t'] = $item_template;
}
$vars['bb_id'] = $topic_id;
return 'bb';
}
/**
* Returns enviroment variable values for given prefix (uses directly given params, when available)
*
* @param string $prefix_special
* @param Array $params
* @param bool $keep_events
* @return Array
*/
function getProcessedParams($prefix_special, &$params, $keep_events)
{
list ($prefix) = explode('.', $prefix_special);
$query_vars = $this->Application->getUnitOption($prefix, 'QueryString');
if (!$query_vars) {
// given prefix doesn't use "env" variable to pass it's data
return false;
}
$event_key = array_search('event', $query_vars);
if ($event_key) {
// pass through event of this prefix
unset($query_vars[$event_key]);
}
if (array_key_exists($prefix_special . '_event', $params) && !$params[$prefix_special . '_event']) {
// if empty event, then remove it from url
unset( $params[$prefix_special . '_event'] );
}
// if pass events is off and event is not implicity passed
if (!$keep_events && !array_key_exists($prefix_special . '_event', $params)) {
unset($params[$prefix_special . '_event']); // remove event from url if requested
//otherwise it will use value from get_var
}
$processed_params = Array ();
foreach ($query_vars as $index => $var_name) {
// if value passed in params use it, otherwise use current from application
$var_name = $prefix_special . '_' . $var_name;
$processed_params[$var_name] = array_key_exists($var_name, $params) ? $params[$var_name] : $this->Application->GetVar($var_name);
if (array_key_exists($var_name, $params)) {
unset($params[$var_name]);
}
}
return $processed_params;
}
/**
* Returns module item details template specified in given category custom field for given module prefix
*
* @param int|Array $category
* @param string $module_prefix
* @return string
*/
function GetItemTemplate($category, $module_prefix)
{
$cache_key = serialize($category) . '_' . $module_prefix;
$cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $cache_key);
if ($cached_value !== false) {
return $cached_value;
}
if (!is_array($category)) {
if ($category == 0) {
$category = $this->Application->findModule('Var', $module_prefix, 'RootCat');
}
$sql = 'SELECT c.ParentPath, c.CategoryId
FROM ' . TABLE_PREFIX . 'Category AS c
WHERE c.CategoryId = ' . $category;
$category = $this->Conn->GetRow($sql);
}
$parent_path = implode(',',explode('|', substr($category['ParentPath'], 1, -1)));
// item template is stored in module' system custom field - need to get that field Id
$item_template_field_id = $this->getItemTemplateCustomField($module_prefix);
// looking for item template through cats hierarchy sorted by parent path
$query = ' SELECT ccd.l1_cust_' . $item_template_field_id . ',
FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') AS Ord1,
c.CategoryId, c.Name, ccd.l1_cust_' . $item_template_field_id . '
FROM ' . TABLE_PREFIX . 'Category AS c
LEFT JOIN ' . TABLE_PREFIX . 'CategoryCustomData AS ccd
ON ccd.ResourceId = c.ResourceId
WHERE c.CategoryId IN (' . $parent_path . ') AND ccd.l1_cust_' . $item_template_field_id . ' != \'\'
ORDER BY FIND_IN_SET(c.CategoryId, ' . $this->Conn->qstr($parent_path) . ') DESC';
$item_template = $this->Conn->GetOne($query);
if (!isset($this->_templateAliases)) {
// when empty url OR mod-rewrite disabled
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$sql = 'SELECT TemplateAliases
FROM ' . TABLE_PREFIX . 'Theme
WHERE ThemeId = ' . (int)$themes_helper->getCurrentThemeId();
$template_aliases = $this->Conn->GetOne($sql);
$this->_templateAliases = $template_aliases ? unserialize($template_aliases) : Array ();
}
if ($item_template && array_key_exists($item_template, $this->_templateAliases)) {
$item_template = $this->_templateAliases[$item_template];
}
$this->Application->setCache(__CLASS__ . __FUNCTION__, $cache_key, $item_template);
return $item_template;
}
/**
* Loads all registered rewrite listeners, so they could be quickly accessed later
*
*/
function initRewriteListeners()
{
static $init_done = false;
if ($init_done) {
return ;
}
foreach ($this->Application->RewriteListeners as $prefix => $listener_data) {
list ($listener_prefix, $listener_method) = explode(':', $listener_data['listener']);
$listener =& $this->Application->recallObject($listener_prefix);
$this->Application->RewriteListeners[$prefix] = Array (&$listener, $listener_method);
}
$init_done = true;
}
/**
* Returns category custom field id, where given module prefix item template name is stored
*
* @param string $module_prefix
* @return int
*/
function getItemTemplateCustomField($module_prefix)
{
$cached_value = $this->Application->getCache(__CLASS__ . __FUNCTION__, $module_prefix);
if ($cached_value !== false) {
return $cached_value;
}
$sql = 'SELECT CustomFieldId
FROM ' . TABLE_PREFIX . 'CustomField
WHERE FieldName = ' . $this->Conn->qstr($module_prefix . '_ItemTemplate');
$item_template_field_id = $this->Conn->GetOne($sql);
$this->Application->setCache(__CLASS__ . __FUNCTION__, $module_prefix, $item_template_field_id);
return $item_template_field_id;
}
/**
* Sets default parsed values before actual url parsing
*
* @param Array $vars
*/
function _setDefaultValues(&$vars)
{
$defaults = Array ('m_cat_id' => 0, 'm_cat_page' => 1, 'm_opener' => 's', 't' => 'index');
foreach ($defaults as $default_key => $default_value) {
// bug: null is never returned
if ($this->HTTPQuery->Get($default_key) == null) {
$vars[$default_key] = $default_value;
}
}
}
}
-?>
\ No newline at end of file
Index: branches/5.0.x/core/units/helpers/multilanguage_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/multilanguage_helper.php (revision 12848)
+++ branches/5.0.x/core/units/helpers/multilanguage_helper.php (revision 12849)
@@ -1,307 +1,304 @@
<?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!');
/**
* Performs action on multilingual fields
*
*/
class kMultiLanguageHelper extends kHelper {
/**
* Maximal language id
*
* @var int
*/
var $languageCount = 0;
/**
* Languages created in system
*
* @var Array
*/
var $languagesIDs = Array ();
/**
* Structure of table, that is currently processed
*
* @var Array
*/
var $curStructure = Array();
/**
* Field, to get structure information from
*
* @var string
*/
var $curSourceField = false;
/**
* Indexes used in table of 32
*
* @var int
*/
var $curIndexCount = 0;
/**
* Fields from config, that are currently used
*
* @var Array
*/
var $curFields = Array();
function kMultiLanguageHelper()
{
parent::kHelper();
$this->languageCount = $this->getLanguageCount();
}
/**
* Checks if language with specified id is created
*
* @param int $language_id
* @return bool
*/
function LanguageFound($language_id)
{
return in_array($language_id, $this->languagesIDs) || $language_id <= 5;
}
/**
* Returns language count in system (always is divisible by 5)
*
*/
function getLanguageCount()
{
$id_field = $this->Application->getUnitOption('lang', 'IDField');
$table_name = $this->Application->getUnitOption('lang', 'TableName');
$this->languagesIDs = $this->Conn->GetCol('SELECT '.$id_field.' FROM '.$table_name);
$languages_count = $this->Conn->GetOne('SELECT MAX('.$id_field.') FROM '.$table_name);
return max($languages_count, 5);
}
function scanTable($mask)
{
$i = 0;
$fields_found = 0;
$fields = array_keys($this->curStructure);
foreach ($fields as $field_name) {
if (preg_match($mask, $field_name)) {
$fields_found++;
}
}
return $fields_found;
}
function readTableStructure($table_name, $refresh = false)
{
// if ($refresh || !getArrayValue($structure_status, $prefix.'.'.$table_name)) {
$this->curStructure = $this->Conn->Query('DESCRIBE '.$table_name, 'Field');
$this->curIndexCount = count($this->Conn->Query('SHOW INDEXES FROM '.$table_name));
// }
}
/**
* Creates missing multilanguage fields in table by specified prefix
*
* @param string $prefix
* @param bool $refresh Forces config field structure to be re-read from database
*/
function createFields($prefix, $refresh = false)
{
if ($refresh && preg_match('/(.*)-cdata$/', $prefix, $regs)) {
// call main item config to clone cdata table
$this->Application->UnitConfigReader->loadConfig($regs[1]);
$this->Application->HandleEvent( new kEvent($prefix.':OnAfterConfigRead') );
}
$table_name = $this->Application->getUnitOption($prefix, 'TableName');
$this->curFields = $this->Application->getUnitOption($prefix, 'Fields');
if (!($table_name && $this->curFields) || ($table_name && !$this->Conn->TableFound($table_name))) {
// invalid config found or prefix not found
return true;
}
$sqls = Array();
$this->readTableStructure($table_name, $refresh);
foreach($this->curFields as $field_name => $field_options)
{
if (getArrayValue($field_options, 'formatter') == 'kMultiLanguage') {
if (isset($field_options['master_field'])) {
unset($this->curFields[$field_name]);
continue;
}
$this->setSourceField($field_name);
if ($this->languageCount > 0) {
// `l77_Name` VARCHAR( 255 ) NULL DEFAULT '0';
$field_mask = Array();
$field_mask['name'] = 'l%s_'.$field_name;
$field_mask['null'] = getArrayValue($field_options, 'not_null') ? 'NOT NULL' : 'NULL';
if ($this->curSourceField) {
$default_value = $this->getFieldParam('Default') != 'NULL' ? $this->Conn->qstr($this->getFieldParam('Default')) : $this->getFieldParam('Default');
$field_mask['type'] = $this->getFieldParam('Type');
}
else {
$default_value = is_null($field_options['default']) ? 'NULL' : $this->Conn->qstr($field_options['default']);
$field_mask['type'] = $field_options['db_type'];
}
$field_mask['default'] = 'DEFAULT '.$default_value;
if (strtoupper($field_mask['type']) == 'TEXT') {
// text fields in mysql doesn't have default value
$field_mask = $field_mask['name'].' '.$field_mask['type'].' '.$field_mask['null'];
}
else {
$field_mask = $field_mask['name'].' '.$field_mask['type'].' '.$field_mask['null'].' '.$field_mask['default'];
}
$alter_sqls = $this->generateAlterSQL($field_mask, 1, $this->languageCount);
if ($alter_sqls) {
$sqls[] = 'ALTER TABLE '.$table_name.' '.$alter_sqls;
}
}
}
}
foreach ($sqls as $sql_query) {
$this->Conn->Query($sql_query);
}
}
function deleteField($prefix, $custom_id)
{
$table_name = $this->Application->getUnitOption($prefix, 'TableName');
$sql = 'DESCRIBE '.$table_name.' "l%_cust_'.$custom_id.'"';
$fields = $this->Conn->GetCol($sql);
$sql = 'ALTER TABLE '.$table_name.' ';
$sql_template = 'DROP COLUMN %s, ';
foreach ($fields as $field_name) {
$sql .= sprintf($sql_template, $field_name);
}
$this->Conn->Query( substr($sql, 0, -2) );
}
/**
* Returns parameter requested of current source field
*
* @param string $param_name
* @return string
*/
function getFieldParam($param_name)
{
return $this->curStructure[$this->curSourceField][$param_name];
}
/**
* Detects field name to create other fields from
*
* @param string $field_name
*/
function setSourceField($field_name)
{
$ret = $this->scanTable('/^l[\d]+_'.preg_quote($field_name, '/').'$/');
if (!$ret) {
// no multilingual fields at all (but we have such field without language prefix)
$original_found = $this->scanTable('/'.preg_quote($field_name, '/').'/');
$this->curSourceField = $original_found ? $field_name : false;
}
else {
$this->curSourceField = 'l1_'.$field_name;
}
}
/**
* Returns ALTER statement part for adding required fields to table
*
* @param string $field_mask sql mask for creating field with correct definition (type & size)
* @param int $start_index add new fields starting from this index
* @param int $create_count create this much new multilingual field translations
* @return string
*/
function generateAlterSQL($field_mask, $start_index, $create_count)
{
static $single_lang = null;
if (!isset($single_lang)) {
// if single language mode, then create indexes only on primary columns
$table_name = $this->Application->getUnitOption('lang', 'TableName');
$sql = 'SELECT COUNT(*)
FROM '.$table_name.'
WHERE Enabled = 1';
// if language count = 0, then assume it's multi language mode
$single_lang = $this->Conn->GetOne($sql) == 1;
}
$ret = '';
$ml_field = preg_replace('/l(.*?)_(.*?) (.*)/', '\\2', $field_mask);
$i_count = $start_index + $create_count;
while ($start_index < $i_count) {
if (isset($this->curStructure['l'.$start_index.'_'.$ml_field]) || (!$this->LanguageFound($start_index)) ) {
$start_index++;
continue;
}
$prev_index = $start_index - 1;
do {
list($prev_field,$type) = explode(' ', sprintf($field_mask, $prev_index) );
} while ($prev_index > 0 && !$this->LanguageFound($prev_index--));
if (substr($prev_field, 0, 3) == 'l0_') {
$prev_field = substr($prev_field, 3, strlen($prev_field));
if (!$this->curSourceField) {
// get field name before this one
$fields = array_keys($this->curFields);
// $prev_field = key(end($this->curStructure));
$prev_field = $fields[array_search($prev_field, $fields) - 1];
if (getArrayValue($this->curFields[$prev_field], 'formatter') == 'kMultiLanguage') {
$prev_field = 'l'.$this->languageCount.'_'.$prev_field;
}
}
}
$field_expression = sprintf($field_mask, $start_index);
$ret .= 'ADD COLUMN '.$field_expression.' AFTER `'.$prev_field.'`, ';
if ($this->curIndexCount < 32 && ($start_index == $this->Application->GetDefaultLanguageId() || !$single_lang)) {
// create index for primary language column + for all others (if multiple languages installed)
list($field_name, $field_params) = explode(' ', $field_expression, 2);
$index_type = isset($this->curFields[$ml_field]['index_type']) ? $this->curFields[$prev_field]['index_type'] : 'string';
$ret .= $index_type == 'string' ? 'ADD INDEX (`'.$field_name.'` (5) ), ' : 'ADD INDEX (`'.$field_name.'`), ';
$this->curIndexCount++;
}
$start_index++;
}
return preg_replace('/, $/', ';', $ret);
}
}
-
-
-?>
\ No newline at end of file
Index: branches/5.0.x/core/units/general/libchart/classes/view/chart/HorizontalBarChart.php
===================================================================
--- branches/5.0.x/core/units/general/libchart/classes/view/chart/HorizontalBarChart.php (revision 12848)
+++ branches/5.0.x/core/units/general/libchart/classes/view/chart/HorizontalBarChart.php (revision 12849)
@@ -1,213 +1,212 @@
<?php
/* Libchart - PHP chart library
* Copyright (C) 2005-2007 Jean-Marc Tr?スmeaux (jm.tremeaux at gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Horizontal bar chart
*
* @author Jean-Marc Tr?スmeaux (jm.tremeaux at gmail.com)
*/
class LibchartHorizontalBarChart extends LibchartBarChart {
/**
* Ratio of empty space beside the bars.
*/
private $emptyToFullRatio;
/**
* Creates a new horizontal bar chart.
*
* @param integer width of the image
* @param integer height of the image
*/
public function LibchartHorizontalBarChart($width = 600, $height = 250) {
parent::BarChart($width, $height);
$this->emptyToFullRatio = 1 / 5;
$this->plot->setGraphPadding(new Padding(5, 30, 30, 50));
}
/**
* Computes the layout.
*/
protected function computeLayout() {
if ($this->hasSeveralSerie) {
$this->plot->setHasCaption(true);
}
$this->plot->computeLayout();
}
/**
* Print the axis.
*/
protected function printAxis() {
$minValue = $this->axis->getLowerBoundary();
$maxValue = $this->axis->getUpperBoundary();
$stepValue = $this->axis->getTics();
// Get graphical obects
$img = $this->plot->getImg();
$palette = $this->plot->getPalette();
$text = $this->plot->getText();
// Get the graph area
$graphArea = $this->plot->getGraphArea();
// Horizontal axis
for ($value = $minValue; $value <= $maxValue; $value += $stepValue) {
$x = $graphArea->x1 + ($value - $minValue) * ($graphArea->x2 - $graphArea->x1) / ($this->axis->displayDelta);
imagerectangle($img, $x - 1, $graphArea->y2 + 2, $x, $graphArea->y2 + 3, $palette->axisColor[0]->getColor($img));
imagerectangle($img, $x - 1, $graphArea->y2, $x, $graphArea->y2 + 1, $palette->axisColor[1]->getColor($img));
$text->printText($img, $x, $graphArea->y2 + 5, $this->plot->getTextColor(), $value, $text->fontCondensed, $text->HORIZONTAL_CENTER_ALIGN);
}
// Get first serie of a list
$pointList = $this->getFirstSerieOfList();
// Vertical Axis
$pointCount = count($pointList);
reset($pointList);
$rowHeight = ($graphArea->y2 - $graphArea->y1) / $pointCount;
reset($pointList);
for ($i = 0; $i <= $pointCount; $i++) {
$y = $graphArea->y2 - $i * $rowHeight;
imagerectangle($img, $graphArea->x1 - 3, $y, $graphArea->x1 - 2, $y + 1, $palette->axisColor[0]->getColor($img));
imagerectangle($img, $graphArea->x1 - 1, $y, $graphArea->x1, $y + 1, $palette->axisColor[1]->getColor($img));
if ($i < $pointCount) {
$point = current($pointList);
next($pointList);
$label = $point->getX();
$text->printText($img, $graphArea->x1 - 5, $y - $rowHeight / 2, $this->plot->getTextColor(), $label, $text->fontCondensed, $text->HORIZONTAL_RIGHT_ALIGN | $text->VERTICAL_CENTER_ALIGN);
}
}
}
/**
* Print the bars.
*/
protected function printBar() {
// Get the data as a list of series for consistency
$serieList = $this->getDataAsSerieList();
// Get graphical obects
$img = $this->plot->getImg();
$palette = $this->plot->getPalette();
$text = $this->plot->getText();
// Get the graph area
$graphArea = $this->plot->getGraphArea();
$minValue = $this->axis->getLowerBoundary();
$maxValue = $this->axis->getUpperBoundary();
$stepValue = $this->axis->getTics();
$barColorSet = $palette->barColorSet;
$barColorSet->reset();
$serieCount = count($serieList);
for ($j = 0; $j < $serieCount; $j++) {
$serie = $serieList[$j];
$pointList = $serie->getPointList();
$pointCount = count($pointList);
reset($pointList);
// Get the next color
$color = $barColorSet->currentColor();
$shadowColor = $barColorSet->currentShadowColor();
$barColorSet->next();
$rowHeight = ($graphArea->y2 - $graphArea->y1) / $pointCount;
for ($i = 0; $i < $pointCount; $i++) {
$y = $graphArea->y2 - $i * $rowHeight;
$point = current($pointList);
next($pointList);
$value = $point->getY();
$xmax = $graphArea->x1 + ($value - $minValue) * ($graphArea->x2 - $graphArea->x1) / ($this->axis->displayDelta);
// Bar dimensions
$yWithMargin = $y - $rowHeight * $this->emptyToFullRatio;
$rowWidthWithMargin = $rowHeight * (1 - $this->emptyToFullRatio * 2);
$barWidth = $rowWidthWithMargin / $serieCount;
$barOffset = $barWidth * $j;
$y1 = $yWithMargin - $barWidth - $barOffset;
$y2 = $yWithMargin - $barOffset - 1;
// Text
$text->printText($img, $xmax + 5, $y2 - $barWidth / 2, $this->plot->getTextColor(), $value, $text->fontCondensed, $text->VERTICAL_CENTER_ALIGN);
imagefilledrectangle($img, $graphArea->x1 + 1, $y1, $xmax, $y2, $shadowColor->getColor($img));
imagefilledrectangle($img, $graphArea->x1 + 2, $y1 + 1, $xmax - 4, $y2, $color->getColor($img));
}
}
}
/**
* Renders the caption.
*/
protected function printCaption() {
// Get the list of labels
$labelList = $this->dataSet->getTitleList();
// Create the caption
$caption = new LibchartCaption();
$caption->setPlot($this->plot);
$caption->setLabelList($labelList);
$palette = $this->plot->getPalette();
$barColorSet = $palette->barColorSet;
$caption->setColorSet($barColorSet);
// Render the caption
$caption->render();
}
/**
* Render the chart image.
*
* @param string name of the file to render the image to (optional)
*/
public function render($fileName = null) {
// Check the data model
$this->checkDataModel();
$this->bound->computeBound($this->dataSet);
$this->computeAxis();
$this->computeLayout();
$this->createImage();
$this->plot->printLogo();
$this->plot->printTitle();
if (!$this->isEmptyDataSet(1)) {
$this->printAxis();
$this->printBar();
if ($this->hasSeveralSerie) {
$this->printCaption();
}
}
$this->plot->render($fileName);
}
- }
-?>
\ No newline at end of file
+ }
\ No newline at end of file
Index: branches/5.0.x/core/units/general/libchart/classes/libchart.php
===================================================================
--- branches/5.0.x/core/units/general/libchart/classes/libchart.php (revision 12848)
+++ branches/5.0.x/core/units/general/libchart/classes/libchart.php (revision 12849)
@@ -1,44 +1,43 @@
<?php
/* Libchart - PHP chart library
* Copyright (C) 2005-2007 Jean-Marc Tr駑eaux (jm.tremeaux at gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
exit;
require_once 'model/Point.php';
require_once 'model/DataSet.php';
require_once 'model/XYDataSet.php';
require_once 'model/XYSeriesDataSet.php';
require_once 'view/primitive/Padding.php';
require_once 'view/primitive/Rectangle.php';
require_once 'view/primitive/Primitive.php';
require_once 'view/text/Text.php';
require_once 'view/color/Color.php';
require_once 'view/color/ColorSet.php';
require_once 'view/color/Palette.php';
require_once 'view/axis/Bound.php';
require_once 'view/axis/Axis.php';
require_once 'view/plot/Plot.php';
require_once 'view/caption/Caption.php';
require_once 'view/chart/Chart.php';
require_once 'view/chart/BarChart.php';
require_once 'view/chart/VerticalBarChart.php';
require_once 'view/chart/HorizontalBarChart.php';
require_once 'view/chart/LineChart.php';
- require_once 'view/chart/PieChart.php';
-?>
\ No newline at end of file
+ require_once 'view/chart/PieChart.php';
\ No newline at end of file
Index: branches/5.0.x/core/install/utf.php
===================================================================
--- branches/5.0.x/core/install/utf.php (revision 12848)
+++ branches/5.0.x/core/install/utf.php (revision 12849)
@@ -1,156 +1,155 @@
<?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.
*/
// comment out this line to run the script
die(' Should be enabled by the administrator! ');
$start = getmicrotime();
define('FULL_PATH', realpath(dirname(__FILE__)).'/../../');
define('REL_PATH', '/core/install');
include_once(FULL_PATH.'/core/kernel/startup.php');
$application =& kApplication::Instance();
$application->Init();
header('Content-type: text/html; charset: utf-8');
if (!defined('DEBUG_MODE') || !DEBUG_MODE) exit;
$target_charset = 'utf8';
$target_collation = 'utf8_general_ci';
//$target_charset = 'latin1';
//$target_collation = 'latin1_swedish_ci';
ini_set('max_execution_time', 0);
// Convert language translation
$langs = $application->Conn->Query('SELECT * FROM '.TABLE_PREFIX.'Language', 'LanguageId');
foreach ($langs as $lang_id => $a_lang) {
switch ( strtoupper($a_lang['Charset']) ) {
case 'WINDOWS-1251':
$langs[$lang_id]['mysql_charset'] = 'cp1251';
break;
case 'WINDOWS-1257':
$langs[$lang_id]['mysql_charset'] = 'cp1257';
break;
case 'UTF-8':
// when column have latin1 collation, but it's data is encoded to utf8 (from web browser)
$langs[$lang_id]['mysql_charset'] = 'utf8';
break;
default:
$langs[$lang_id]['mysql_charset'] = 'latin1';
}
}
print_pre($langs);
//die();
$query = 'ALTER DATABASE `'.SQL_DB.'` DEFAULT CHARACTER SET '.$target_charset.' COLLATE '.$target_collation;
$application->Conn->Query($query);
$query = 'SHOW TABLE STATUS';
$tables = $application->Conn->Query($query);
foreach ($tables as $table_status)
{
$table = $table_status['Name'];
if (!preg_match('/^'.preg_quote(TABLE_PREFIX, '/').'/', $table)) {
continue;
}
if ($table_status['Collation'] != $target_collation) {
$sql = 'ALTER TABLE '.$table.' COLLATE '.$application->Conn->qstr($target_collation);
echo "$sql<br>\n";
$application->Conn->Query($sql);
}
echo "scanning $table<br>";
$columns = $application->Conn->Query('SHOW FULL COLUMNS FROM '.$table);
foreach ($columns as $a_column) {
if ($a_column['Collation'] && $a_column['Collation'] != 'NULL') {
if ($a_column['Collation'] == $target_collation) {
echo "skipping ".$a_column['Field'].'<br>';
continue;
}
echo 'processing column '.$a_column['Field'].' ('.$a_column['Collation'].')<br>';
// ALTER TABLE `inp_Addresses` ADD `utf_To` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `To` ;
// adding temporary UTF column
$new_def = $a_column['Type'].' CHARACTER SET '.$target_charset.' COLLATE '.$target_collation.' '.($a_column['Null'] == 'YES' ? 'NULL':'NOT NULL');
$q = 'ALTER TABLE `'.$table.'` ADD `utf_'.$a_column['Field'].'` '.$new_def.' AFTER `'.$a_column['Field'].'`;';
echo "$q<br>";
$application->Conn->Query($q);
// copying value to utf
if ($table == TABLE_PREFIX.'Phrase' && $a_column['Field'] == 'Translation') {
foreach ($langs as $lang_id => $a_lang) {
$cast = $a_lang['mysql_charset'];
if (!$cast) $cast = 'latin1';
$copy_def = 'CONVERT( CAST(BINARY('.$a_column['Field'].') AS CHAR CHARACTER SET '.$cast.') USING '.$target_charset.')';
$q = 'UPDATE `'.$table.'` SET `utf_'.$a_column['Field'].'` = '.$copy_def.' WHERE LanguageId = '.$lang_id;
echo "$q<br>";
$application->Conn->Query($q);
}
}
elseif (preg_match('/l([0-9]+)_.*/', $a_column['Field'], $matches)) {
$cast = $langs[$matches[1]]['mysql_charset'];
if (!$cast) $cast = 'latin1';
$copy_def = 'CONVERT( CAST(BINARY('.$a_column['Field'].') AS CHAR CHARACTER SET '.$cast.') USING '.$target_charset.')';
$q = 'UPDATE `'.$table.'` SET `utf_'.$a_column['Field'].'` = '.$copy_def;
echo "$q<br>";
$application->Conn->Query($q);
}
else {
$copy_def = 'BINARY(`'.$a_column['Field'].'`);';
$q = 'UPDATE `'.$table.'` SET `utf_'.$a_column['Field'].'` = '.$copy_def;
echo "$q<br>";
$application->Conn->Query($q);
}
// altering orignal field to utf
$q = 'ALTER TABLE `'.$table.'` CHANGE `'.$a_column['Field'].'` `'.$a_column['Field'].'` '.$new_def.';';
echo "$q<br>";
$application->Conn->Query($q);
// copying utf value back
$q = 'UPDATE `'.$table.'` SET `'.$a_column['Field'].'` = `utf_'.$a_column['Field'].'`;';
echo "$q<br>";
$application->Conn->Query($q);
// removing temporary UTF column
$q = 'ALTER TABLE `'.$table.'` DROP `utf_'.$a_column['Field'].'`;';
echo "$q<br>";
$application->Conn->Query($q);
}
}
}
$application->Conn->Query('UPDATE '.TABLE_PREFIX.'Language SET Charset = \''.$target_charset.'\'');
function getmicrotime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
-}
-?>
\ No newline at end of file
+}
\ No newline at end of file
Index: branches/5.0.x/core/install.php
===================================================================
--- branches/5.0.x/core/install.php (revision 12848)
+++ branches/5.0.x/core/install.php (revision 12849)
@@ -1,1453 +1,1452 @@
<?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.
*/
ini_set('display_errors', 1);
error_reporting(E_ALL);
define('IS_INSTALL', 1);
define('ADMIN', 1);
define('FULL_PATH', realpath(dirname(__FILE__).'/..') );
define('REL_PATH', '/core');
// run installator
$install_engine = new kInstallator();
$install_engine->Init();
$install_engine->Run();
$install_engine->Done();
class kInstallator {
/**
* Reference to kApplication class object
*
* @var kApplication
*/
var $Application = null;
/**
* Connection to database
*
* @var kDBConnection
*/
var $Conn = null;
/**
* XML file containing steps information
*
* @var string
*/
var $StepDBFile = '';
/**
* Step name, that currently being processed
*
* @var string
*/
var $currentStep = '';
/**
* Steps list (preset) to use for current installation
*
* @var string
*/
var $stepsPreset = '';
/**
* Installtion steps to be done
*
* @var Array
*/
var $steps = Array (
'fresh_install' => Array ('check_paths', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish'),
'clean_reinstall' => Array ('check_paths', 'clean_db', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish'),
'already_installed' => Array ('check_paths', 'install_setup'),
'upgrade' => Array ('check_paths', 'install_setup', 'upgrade_modules', 'security', 'finish'),
'update_license' => Array ('check_paths', 'install_setup', 'select_license', /*'download_license',*/ 'select_domain', 'security', 'finish'),
'db_reconfig' => Array ('check_paths', 'install_setup', 'db_reconfig', 'security', 'finish'),
'fix_paths' => Array ('check_paths', 'install_setup', 'fix_paths', 'security', 'finish'),
);
/**
* Steps, that doesn't required admin to be logged-in to proceed
*
* @var Array
*/
var $skipLoginSteps = Array ('check_paths', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish', -1);
/**
* Steps, on which kApplication should not be initialized, because of missing correct db table structure
*
* @var Array
*/
var $skipApplicationSteps = Array ('check_paths', 'clean_db', 'db_config', 'db_reconfig' /*, 'install_setup'*/); // remove install_setup when application will work separately from install
/**
* Folders that should be writeable to continue installation. $1 - main writeable folder from config.php ("/system" by default)
*
* @var Array
*/
var $writeableFolders = Array (
'$1',
'$1/images',
'$1/images/resized',
'$1/images/pending',
'$1/images/pending/resized',
'$1/images/emoticons', // for "In-Bulletin"
'$1/images/manufacturers', // for "In-Commerce"
'$1/images/manufacturers/resized', // for "In-Commerce"
'$1/images/polls', // for "In-Bulletin"
'$1/images/polls/resized', // for "In-Bulletin"
'$1/backupdata',
'$1/export',
'$1/stylesheets',
'$1/user_files',
'$1/cache',
'/themes',
);
/**
* Contains last error message text
*
* @var string
*/
var $errorMessage = '';
/**
* Base path for includes in templates
*
* @var string
*/
var $baseURL = '';
/**
* Holds number of last executed query in the SQL
*
* @var int
*/
var $LastQueryNum = 0;
/**
* Common tools required for installation process
*
* @var kInstallToolkit
*/
var $toolkit = null;
function Init()
{
include_once(FULL_PATH . REL_PATH . '/kernel/utility/multibyte.php'); // emulating multi-byte php extension
require_once(FULL_PATH . REL_PATH . '/install/install_toolkit.php'); // toolkit required for module installations to installator
$this->toolkit = new kInstallToolkit();
$this->toolkit->setInstallator($this);
$this->StepDBFile = FULL_PATH.'/'.REL_PATH.'/install/steps_db.xml';
$base_path = rtrim(preg_replace('/'.preg_quote(rtrim(REL_PATH, '/'), '/').'$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/');
$this->baseURL = 'http://'.$_SERVER['HTTP_HOST'].$base_path.'/core/install/';
set_error_handler( Array(&$this, 'ErrorHandler') );
if (file_exists($this->toolkit->INIFile)) {
// if config.php found, then check his write permission too
$this->writeableFolders[] = '/config.php';
}
else {
$this->writeableFolders[] = '/';
}
if (!$this->toolkit->getSystemConfig('Misc', 'WriteablePath')) {
// set global writable folder when such setting is missing
$this->toolkit->setSystemConfig('Misc', 'WriteablePath', DIRECTORY_SEPARATOR . 'system');
$this->toolkit->SaveConfig(true); // immediately save, because this path will be used in Application later
}
$this->currentStep = $this->GetVar('step');
// can't check login on steps where no application present anyways :)
$this->skipLoginSteps = array_unique(array_merge($this->skipLoginSteps, $this->skipApplicationSteps));
$this->SelectPreset();
if (!$this->currentStep) {
$this->SetFirstStep(); // sets first step of current preset
}
$this->InitStep();
}
function SetFirstStep()
{
reset($this->steps[$this->stepsPreset]);
$this->currentStep = current($this->steps[$this->stepsPreset]);
}
/**
* Selects preset to proceed based on various criteria
*
*/
function SelectPreset()
{
$preset = $this->GetVar('preset');
if ($this->toolkit->systemConfigFound()) {
// only at installation first step
$status = $this->CheckDatabase(false);
if ($status && $this->AlreadyInstalled()) {
// if already installed, then all future actions need login to work
$this->skipLoginSteps = Array ('check_paths', -1);
if (!$preset) {
$preset = 'already_installed';
$this->currentStep = '';
}
}
}
if ($preset === false) {
$preset = 'fresh_install'; // default preset
}
$this->stepsPreset = $preset;
}
function GetVar($name)
{
return array_key_exists($name, $_REQUEST) ? $_REQUEST[$name] : false;
}
function SetVar($name, $value)
{
$_REQUEST[$name] = $value;
}
/**
* Performs needed intialization of data, that step requires
*
*/
function InitStep()
{
$require_login = !in_array($this->currentStep, $this->skipLoginSteps);
$this->InitApplication($require_login);
if ($require_login) {
// step require login to proceed
if (!$this->Application->LoggedIn()) {
$this->stepsPreset = 'already_installed';
$this->currentStep = 'install_setup'; // manually set 2nd step, because 'check_paths' step doesn't contain login form
// $this->SetFirstStep();
}
}
switch ($this->currentStep) {
case 'check_paths':
$writeable_base = $this->toolkit->getSystemConfig('Misc', 'WriteablePath');
foreach ($this->writeableFolders as $folder_path) {
$file_path = FULL_PATH . str_replace('$1', $writeable_base, $folder_path);
if (file_exists($file_path) && !is_writable($file_path)) {
$this->errorMessage = '<br/>Installation can not continue until all required permissions are set correctly';
break;
}
}
break;
case 'clean_db':
// don't use Application, because all tables will be erased and it will crash
$sql = 'SELECT Path
FROM ' . TABLE_PREFIX . 'Modules';
$modules = $this->Conn->GetCol($sql);
foreach ($modules as $module_folder) {
$remove_file = '/' . $module_folder . 'install/remove_schema.sql';
if (file_exists(FULL_PATH . $remove_file)) {
$this->toolkit->RunSQL($remove_file);
}
}
$this->currentStep = $this->GetNextStep();
break;
case 'db_config':
case 'db_reconfig':
$fields = Array (
'DBType', 'DBHost', 'DBName', 'DBUser',
'DBUserPassword', 'DBCollation', 'TablePrefix'
);
// set fields
foreach ($fields as $field_name) {
$submit_value = $this->GetVar($field_name);
if ($submit_value !== false) {
$this->toolkit->setSystemConfig('Database', $field_name, $submit_value);
}
/*else {
$this->toolkit->setSystemConfig('Database', $field_name, '');
}*/
}
break;
case 'download_license':
$license_source = $this->GetVar('license_source');
if ($license_source !== false && $license_source != 1) {
// previous step was "Select License" and not "Download from Intechnic" option was selected
$this->currentStep = $this->GetNextStep();
}
break;
case 'choose_modules':
// if no modules found, then proceed to next step
$modules = $this->ScanModules();
if (!$modules) {
$this->currentStep = $this->GetNextStep();
}
break;
case 'select_theme':
// put available theme list in database
$this->toolkit->rebuildThemes();
break;
case 'upgrade_modules':
// get installed modules from db and compare their versions to upgrade script
$modules = $this->GetUpgradableModules();
if (!$modules) {
$this->currentStep = $this->GetNextStep();
}
break;
case 'install_setup':
$next_preset = $this->Application->GetVar('next_preset');
if ($next_preset !== false) {
if ($this->Application->GetVar('login') == 'root') {
// verify "root" user using configuration settings
$login_event = new kEvent('u.current:OnLogin');
$this->Application->HandleEvent($login_event);
if ($login_event->status != erSUCCESS) {
$user =& $this->Application->recallObject('u.current');
/* @var $user UsersItem */
$this->errorMessage = $user->GetErrorMsg('ValidateLogin') . '. If you don\'t know your username or password, contact Intechnic Support';
}
}
else {
// non "root" user -> verify using licensing server
$url_params = Array (
'login=' . md5( $this->GetVar('login') ),
'password=' . md5( $this->GetVar('password') ),
'action=check',
'license_code=' . base64_encode( $this->toolkit->getSystemConfig('Intechnic', 'LicenseCode') ),
'version=' . '4.3.0',//$this->toolkit->GetMaxModuleVersion('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
if (substr($file_data, 0, 5) == 'Error') {
$this->errorMessage = substr($file_data, 6) . ' If you don\'t know your username or password, contact Intechnic Support';
}
if ($this->errorMessage == '') {
$user_id = -1;
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
}
}
if ($this->errorMessage == '') {
// processed with redirect to selected step preset
if (!isset($this->steps[$next_preset])) {
$this->errorMessage = 'Preset "'.$next_preset.'" not yet implemented';
}
else {
$this->stepsPreset = $next_preset;
}
}
}
else {
// if preset was not choosen, then raise error
$this->errorMessage = 'Please select action to perform';
}
break;
case 'security':
// perform write check
if ($this->Application->GetVar('skip_security_check')) {
// administrator intensionally skips security checks
break;
}
$write_check = true;
$check_paths = Array ('/', '/index.php', '/config.php', ADMIN_DIRECTORY . '/index.php');
foreach ($check_paths as $check_path) {
$path_check_status = $this->toolkit->checkWritePermissions(FULL_PATH . $check_path);
if (is_bool($path_check_status) && $path_check_status) {
$write_check = false;
break;
}
}
// script execute check
if (file_exists(WRITEABLE . '/install_check.php')) {
unlink(WRITEABLE . '/install_check.php');
}
$fp = fopen(WRITEABLE . '/install_check.php', 'w');
fwrite($fp, "<?php\n\techo 'OK';\n");
fclose($fp);
$curl_helper =& $this->Application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
$output = $curl_helper->Send($this->Application->BaseURL(WRITEBALE_BASE) . 'install_check.php');
unlink(WRITEABLE . '/install_check.php');
$execute_check = ($output !== 'OK');
$directive_check = true;
$ini_vars = Array ('register_globals' => false, 'open_basedir' => true, 'allow_url_fopen' => false);
foreach ($ini_vars as $var_name => $var_value) {
$current_value = ini_get($var_name);
if (($var_value && !$current_value) || (!$var_value && $current_value)) {
$directive_check = false;
break;
}
}
if (!$write_check || !$execute_check || !$directive_check) {
$this->errorMessage = true;
}
/*else {
$this->currentStep = $this->GetNextStep();
}*/
break;
}
$this->PerformValidation(); // returns validation status (just in case)
}
/**
* Validates data entered by user
*
* @return bool
*/
function PerformValidation()
{
if ($this->GetVar('step') != $this->currentStep) {
// just redirect from previous step, don't validate
return true;
}
$status = true;
switch ($this->currentStep) {
case 'db_config':
case 'db_reconfig':
// 1. check if required fields are filled
$section_name = 'Database';
$required_fields = Array ('DBType', 'DBHost', 'DBName', 'DBUser', 'DBCollation');
foreach ($required_fields as $required_field) {
if (!$this->toolkit->getSystemConfig($section_name, $required_field)) {
$status = false;
$this->errorMessage = 'Please fill all required fields';
break;
}
}
if (!$status) break;
// 2. check permissions, that use have in this database
$status = $this->CheckDatabase(($this->currentStep == 'db_config') && !$this->GetVar('UseExistingSetup'));
break;
case 'select_license':
$license_source = $this->GetVar('license_source');
if ($license_source == 2) {
// license from file -> file must be uploaded
$upload_error = $_FILES['license_file']['error'];
if ($upload_error != UPLOAD_ERR_OK) {
$this->errorMessage = 'Missing License File';
}
}
elseif (!is_numeric($license_source)) {
$this->errorMessage = 'Please select license';
}
$status = $this->errorMessage == '';
break;
case 'root_password':
// check, that password & verify password match
$password = $this->Application->GetVar('root_password');
$password_verify = $this->Application->GetVar('root_password_verify');
if ($password != $password_verify) {
$this->errorMessage = 'Passwords does not match';
}
elseif (mb_strlen($password) < 4) {
$this->errorMessage = 'Root Password must be at least 4 characters';
}
$status = $this->errorMessage == '';
break;
case 'choose_modules':
break;
case 'upgrade_modules':
$modules = $this->Application->GetVar('modules');
if (!$modules) {
$modules = Array ();
$this->errorMessage = 'Please select module(-s) to ' . ($this->currentStep == 'choose_modules' ? 'install' : 'upgrade');
}
// check interface module
$upgrade_data = $this->GetUpgradableModules();
if (array_key_exists('core', $upgrade_data) && !in_array('core', $modules)) {
// core can be upgraded, but isn't selected
$this->errorMessage = 'Please select "Core" as interface module';
}
$status = $this->errorMessage == '';
break;
}
return $status;
}
/**
* Perform installation step actions
*
*/
function Run()
{
if ($this->errorMessage) {
// was error during data validation stage
return ;
}
switch ($this->currentStep) {
case 'db_config':
case 'db_reconfig':
// store db configuration
$sql = 'SHOW COLLATION
LIKE \''.$this->toolkit->getSystemConfig('Database', 'DBCollation').'\'';
$collation_info = $this->Conn->Query($sql);
if ($collation_info) {
$this->toolkit->setSystemConfig('Database', 'DBCharset', $collation_info[0]['Charset']);
// database is already connected, that's why set collation on the fly
$this->Conn->Query('SET NAMES \''.$this->toolkit->getSystemConfig('Database', 'DBCharset').'\' COLLATE \''.$this->toolkit->getSystemConfig('Database', 'DBCollation').'\'');
}
$this->toolkit->SaveConfig();
if ($this->currentStep == 'db_config') {
if ($this->GetVar('UseExistingSetup')) {
// abort clean install and redirect to already_installed
$this->stepsPreset = 'already_installed';
break;
}
// import base data into new database, not for db_reconfig
$this->toolkit->RunSQL('/core/install/install_schema.sql');
$this->toolkit->RunSQL('/core/install/install_data.sql');
// create category using sql, because Application is not available here
$table_name = $this->toolkit->getSystemConfig('Database', 'TablePrefix') . 'IdGenerator';
$this->Conn->Query('UPDATE ' . $table_name . ' SET lastid = lastid + 1');
$resource_id = $this->Conn->GetOne('SELECT lastid FROM ' . $table_name);
if ($resource_id === false) {
$this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)');
$resource_id = 2;
}
$fields_hash = Array (
'l1_Name' => 'Content', 'Filename' => 'Content', 'AutomaticFilename' => 0,
'CreatedById' => -1, 'CreatedOn' => time(), 'ResourceId' => $resource_id - 1,
'l1_Description' => 'Content', 'Status' => 4,
);
$this->Conn->doInsert($fields_hash, $this->toolkit->getSystemConfig('Database', 'TablePrefix') . 'Category');
$this->toolkit->SetModuleRootCategory('Core', $this->Conn->getInsertID());
// set module "Core" version after install (based on upgrade scripts)
$this->toolkit->SetModuleVersion('Core');
// for now we set "In-Portal" module version to "Core" module version (during clean install)
$this->toolkit->SetModuleVersion('In-Portal', $this->toolkit->GetMaxModuleVersion('Core'));
}
break;
case 'select_license':
$license_source = $this->GetVar('license_source');
switch ($license_source) {
case 1: // Download from Intechnic
break;
case 2: // Upload License File
$file_data = array_map('trim', file($_FILES['license_file']['tmp_name']));
if ((count($file_data) == 3) && $file_data[1]) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
if ($modules_helper->verifyLicense($file_data[1])) {
$this->toolkit->setSystemConfig('Intechnic', 'License', $file_data[1]);
$this->toolkit->setSystemConfig('Intechnic', 'LicenseCode', $file_data[2]);
$this->toolkit->SaveConfig();
}
else {
$this->errorMessage = 'Invalid License File';
}
}
else {
$this->errorMessage = 'Invalid License File';
}
break;
case 3: // Use Existing License
$license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License');
if ($license_hash) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
if (!$modules_helper->verifyLicense($license_hash)) {
$this->errorMessage = 'Invalid or corrupt license detected';
}
}
else {
// happens, when browser's "Back" button is used
$this->errorMessage = 'Missing License File';
}
break;
case 4: // Skip License (Local Domain Installation)
if ($this->toolkit->sectionFound('Intechnic')) {
// remove any previous license information
$this->toolkit->setSystemConfig('Intechnic', 'License');
$this->toolkit->setSystemConfig('Intechnic', 'LicenseCode');
$this->toolkit->SaveConfig();
}
break;
}
break;
case 'download_license':
$license_login = $this->GetVar('login');
$license_password = $this->GetVar('password');
$license_id = $this->GetVar('licenses');
if (strlen($license_login) && strlen($license_password) && !$license_id) {
// Here we determine weather login is ok & check available licenses
$url_params = Array (
'login=' . md5($license_login),
'password=' . md5($license_password),
'version=' . $this->toolkit->GetMaxModuleVersion('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
if (!$file_data) {
// error connecting to licensing server
$this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!';
}
else {
if (substr($file_data, 0, 5) == 'Error') {
// after processing data server returned error
$this->errorMessage = substr($file_data, 6);
}
else {
// license received
if (substr($file_data, 0, 3) == 'SEL') {
// we have more, then one license -> let user choose
$this->SetVar('license_selection', base64_encode( substr($file_data, 4) )); // we received html with radio buttons with names "licenses"
$this->errorMessage = 'Please select which license to use';
}
else {
// we have one license
$this->toolkit->processLicense($file_data);
}
}
}
}
else if (!$license_id) {
// licenses were not queried AND user/password missing
$this->errorMessage = 'Incorrect Username or Password. If you don\'t know your username or password, contact Intechnic Support';
}
else {
// Here we download license
$url_params = Array (
'license_id=' . md5($license_id),
'dlog=' . md5($license_login),
'dpass=' . md5($license_password),
'version=' . $this->toolkit->GetMaxModuleVersion('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
if (!$file_data) {
// error connecting to licensing server
$this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!';
}
else {
if (substr($file_data, 0, 5) == 'Error') {
// after processing data server returned error
$this->errorMessage = substr($file_data, 6);
}
else {
$this->toolkit->processLicense($file_data);
}
}
}
break;
case 'select_domain':
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License');
if ($license_hash) {
// when license present, then extract domain from it
$license_hash = base64_decode($license_hash);
list ( , , $license_keys) = $modules_helper->_ParseLicense($license_hash);
$license_domain = $license_keys[0]['domain'];
}
else {
// when license missing, then use current domain
$license_domain = $_SERVER['HTTP_HOST'];
}
$domain = $this->GetVar('domain') == 1 ? $_SERVER['HTTP_HOST'] : str_replace(' ', '', $this->GetVar('other'));
if ($domain != '') {
if (strstr($domain, $license_domain) || $modules_helper->_IsLocalSite($domain)) {
$this->toolkit->setSystemConfig('Misc', 'Domain', $domain);
$this->toolkit->SaveConfig();
}
else {
$this->errorMessage = 'Domain name entered does not match domain name in the license!';
}
}
else {
$this->errorMessage = 'Please enter valid domain!';
}
break;
case 'root_password':
// update root password in database
$password = md5( md5($this->Application->GetVar('root_password')) . 'b38');
$config_values = Array (
'RootPass' => $password,
'Site_Path' => BASE_PATH.'/', // set Site_Path (for SSL & old in-portal code)
'Backup_Path' => FULL_PATH . $this->toolkit->getSystemConfig('Misc', 'WriteablePath') . DIRECTORY_SEPARATOR . 'backupdata',
'Smtp_AdminMailFrom' => 'portal@' . $this->toolkit->getSystemConfig('Misc', 'Domain')
);
$this->toolkit->saveConfigValues($config_values);
// login as "root", when no errors on password screen
$this->Application->SetVar('login', 'root');
$this->Application->SetVar('password', $this->Application->GetVar('root_password'));
$login_event = new kEvent('u.current:OnLogin');
$this->Application->HandleEvent($login_event);
// import base language for core (english)
$this->toolkit->ImportLanguage('/core/install/english');
// set imported language as primary
$lang =& $this->Application->recallObject('lang.-item', null, Array('skip_autoload' => true));
/* @var $lang LanguagesItem */
$lang->Load(1); // fresh install => ID=1
$lang->setPrimary(true); // for Front-End
break;
case 'choose_modules':
// run module install scripts
$modules = $this->Application->GetVar('modules');
if ($modules) {
foreach ($modules as $module) {
$install_file = MODULES_PATH.'/'.$module.'/install.php';
if (file_exists($install_file)) {
include_once($install_file);
// set module version after install (based on upgrade scripts)
$this->toolkit->SetModuleVersion($module);
}
}
}
// update category cache
$updater =& $this->Application->recallObject('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
break;
case 'post_config':
$this->toolkit->saveConfigValues( $this->GetVar('config') );
break;
case 'select_theme':
// 1. mark theme, that user is selected
$theme_id = $this->GetVar('theme');
$theme_table = $this->Application->getUnitOption('theme', 'TableName');
$theme_idfield = $this->Application->getUnitOption('theme', 'IDField');
$sql = 'UPDATE ' . $theme_table . '
SET Enabled = 1, PrimaryTheme = 1
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$this->Conn->Query($sql);
$this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!!
if ($this->Application->isModuleEnabled('In-Portal')) {
// 2. compile theme stylesheets (only In-Portal uses them)
$css_table = $this->Application->getUnitOption('css', 'TableName');
$css_idfield = $this->Application->getUnitOption('css', 'IDField');
$sql = 'SELECT LOWER(Name) AS Name, ' . $css_idfield . '
FROM ' . $css_table;
$css_hash = $this->Conn->GetCol($sql, $css_idfield);
$css_item =& $this->Application->recallObject('css', null, Array('skip_autoload' => true));
/* @var $css_item StyleshetsItem */
foreach ($css_hash as $stylesheet_id => $theme_name) {
$css_item->Load($stylesheet_id);
$css_item->Compile();
$sql = 'UPDATE ' . $theme_table . '
SET StylesheetId = ' . $stylesheet_id . '
WHERE LOWER(Name) = ' . $this->Conn->qstr($theme_name);
$this->Conn->Query($sql);
}
}
// install theme dependent demo data
if ($this->Application->GetVar('install_demo_data')) {
$sql = 'SELECT Name
FROM ' . $theme_table . '
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$theme_name = $this->Conn->GetOne($sql);
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
continue;
}
$this->toolkit->RunSQL('/themes' . '/' . $theme_name . '/' . $module_info['TemplatePath'] . '_install/install_data.sql');
}
}
break;
case 'upgrade_modules':
// get installed modules from db and compare their versions to upgrade script
$modules = $this->Application->GetVar('modules');
if ($modules) {
$upgrade_data = $this->GetUpgradableModules();
$start_from_module = $this->GetVar('continue_from_module');
$start_from_query = $this->GetVar('continue_from_query');
if (!$start_from_query) $start_from_query = 0;
foreach ($modules as $module_name) {
if ($start_from_module && $module_name != $start_from_module) {
continue;
}
else {
$start_from_module = false; //otherwise it will skip all modules after the one we start with!
}
$module_info = $upgrade_data[$module_name];
$upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql');
$sqls = file_get_contents($upgrades_file);
$version_mark = preg_replace('/(\(.*?\))/', $module_info['FromVersion'], VERSION_MARK);
// get only sqls from next (relative to current) version to end of file
$start_pos = strpos($sqls, $version_mark);
$sqls = substr($sqls, $start_pos);
preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs);
if (!$start_from_module) {
$this->RunUpgrades($module_info['Path'], $regs[1], 'before');
}
if (!$this->toolkit->RunSQLText($sqls, null, null, $start_from_query)) {
$this->errorMessage .= '<input type="hidden" name="continue_from_module" value="'.$module_name.'">';
$this->errorMessage .= '<input type="hidden" name="continue_from_query" value="'.$this->LastQueryNum.'">';
$this->errorMessage .= '<br/>Click Continue button below to skip this query and go further<br/>';
$this->Done();
}
$start_from_query = 0; // so that next module start from the beggining
$this->toolkit->ImportLanguage('/' . $module_info['Path'] . 'install/english', true);
$this->RunUpgrades($module_info['Path'], $regs[1], 'after'); // upgrade script could operate resulting language pack
// after upgrade sqls are executed update version and upgrade language pack
$this->toolkit->SetModuleVersion($module_name, $module_info['ToVersion']);
}
// for now we set "In-Portal" module version to "Core" module version (during upgrade)
if (in_array('core', $modules)) {
$this->toolkit->SetModuleVersion('In-Portal', $upgrade_data['core']['ToVersion']);
}
}
break;
case 'fix_paths':
$this->toolkit->saveConfigValues( $this->Application->GetVar('config') );
break;
case 'finish':
// delete cache
$this->toolkit->deleteCache();
// set installation finished mark
if ($this->Application->ConfigValue('InstallFinished') === false) {
$fields_hash = Array (
'VariableName' => 'InstallFinished',
'VariableValue' => 1,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ConfigurationValues');
}
break;
}
if ($this->errorMessage) {
// was error during run stage
return ;
}
$this->currentStep = $this->GetNextStep();
$this->InitStep(); // init next step (that will be shown now)
$this->InitApplication();
if ($this->currentStep == -1) {
// step after last step -> redirect to admin
$this->Application->Redirect('index', null, '', 'index.php');
}
}
/**
* Run upgrade PHP scripts for module with specified path
*
* @param string $module_path
* @param Array $versions
* @param string $mode upgrade mode = {before,after}
*/
function RunUpgrades($module_path, $versions, $mode)
{
static $upgrade_classes = Array ();
$upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'php');
if (!file_exists($upgrades_file) || !$versions) {
return ;
}
if (!isset($upgrade_classes[$module_path])) {
// save class name, because 2nd time
// (in after call $upgrade_class variable will not be present)
include_once $upgrades_file;
$upgrade_classes[$module_path] = $upgrade_class;
}
$upgrade_object = new $upgrade_classes[$module_path]();
if (method_exists($upgrade_object, 'setToolkit')) {
$upgrade_object->setToolkit($this->toolkit);
}
foreach ($versions as $version) {
$upgrade_method = 'Upgrade_'.str_replace(Array ('.', '-'), '_', $version);
if (method_exists($upgrade_object, $upgrade_method)) {
$upgrade_object->$upgrade_method($mode);
}
}
}
/**
* Initialize kApplication
*
* @param bool $force initialize in any case
*/
function InitApplication($force = false)
{
if (($force || !in_array($this->currentStep, $this->skipApplicationSteps)) && !isset($this->Application)) {
// step is allowed for application usage & it was not initialized in previous step
global $start, $debugger, $dbg_options;
include_once(FULL_PATH.'/core/kernel/startup.php');
$this->Application =& kApplication::Instance();
$this->toolkit->Application =& kApplication::Instance();
$this->Application->Init();
$this->Conn =& $this->Application->GetADODBConnection();
$this->toolkit->Conn =& $this->Application->GetADODBConnection();
}
}
/**
* Show next step screen
*
*/
function Done($error_message = null)
{
if (isset($error_message)) {
$this->errorMessage = $error_message;
}
include_once (FULL_PATH.'/'.REL_PATH.'/install/incs/install.tpl');
if (isset($this->Application)) {
$this->Application->Done();
}
exit;
}
function ConnectToDatabase()
{
include_once FULL_PATH . '/core/kernel/db/db_connection.php';
$required_keys = Array ('DBType', 'DBUser', 'DBName');
foreach ($required_keys as $required_key) {
if (!$this->toolkit->getSystemConfig('Database', $required_key)) {
// one of required db connection settings missing -> abort connection
return false;
}
}
$this->Conn = new kDBConnection($this->toolkit->getSystemConfig('Database', 'DBType'), Array(&$this, 'DBErrorHandler'));
$this->Conn->Connect(
$this->toolkit->getSystemConfig('Database', 'DBHost'),
$this->toolkit->getSystemConfig('Database', 'DBUser'),
$this->toolkit->getSystemConfig('Database', 'DBUserPassword'),
$this->toolkit->getSystemConfig('Database', 'DBName')
);
// setup toolkit too
$this->toolkit->Conn =& $this->Conn;
return $this->Conn->errorCode == 0;
}
/**
* Checks if core is already installed
*
* @return bool
*/
function AlreadyInstalled()
{
$table_prefix = $this->toolkit->getSystemConfig('Database', 'TablePrefix');
$sql = 'SELECT VariableValue
FROM ' . $table_prefix . 'ConfigurationValues
WHERE VariableName = "InstallFinished"';
return $this->TableExists('ConfigurationValues') && $this->Conn->GetOne($sql);
}
function CheckDatabase($check_installed = true)
{
// perform various check type to database specified
// 1. user is allowed to connect to database
// 2. user has all types of permissions in database
if (mb_strlen($this->toolkit->getSystemConfig('Database', 'TablePrefix')) > 7) {
$this->errorMessage = 'Table prefix should not be longer than 7 characters';
return false;
}
// connect to database
$status = $this->ConnectToDatabase();
if ($status) {
// if connected, then check if all sql statements work
$sql_tests[] = 'DROP TABLE IF EXISTS test_table';
$sql_tests[] = 'CREATE TABLE test_table(test_col mediumint(6))';
$sql_tests[] = 'LOCK TABLES test_table WRITE';
$sql_tests[] = 'INSERT INTO test_table(test_col) VALUES (5)';
$sql_tests[] = 'UPDATE test_table SET test_col = 12';
$sql_tests[] = 'UNLOCK TABLES';
$sql_tests[] = 'ALTER TABLE test_table ADD COLUMN new_col varchar(10)';
$sql_tests[] = 'SELECT * FROM test_table';
$sql_tests[] = 'DELETE FROM test_table';
$sql_tests[] = 'DROP TABLE IF EXISTS test_table';
foreach ($sql_tests as $sql_test) {
$this->Conn->Query($sql_test);
if ($this->Conn->getErrorCode() != 0) {
$status = false;
break;
}
}
if ($status) {
// if statements work & connection made, then check table existance
if ($check_installed && $this->AlreadyInstalled()) {
$this->errorMessage = 'An In-Portal Database already exists at this location';
return false;
}
}
else {
// user has insufficient permissions in database specified
$this->errorMessage = 'Permission Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg();
return false;
}
}
else {
// was error while connecting
if (!$this->Conn) return false;
$this->errorMessage = 'Connection Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg();
return false;
}
return true;
}
/**
* Checks if all passed tables exists
*
* @param string $tables comma separated tables list
* @return bool
*/
function TableExists($tables)
{
$prefix = $this->toolkit->getSystemConfig('Database', 'TablePrefix');
$all_found = true;
$tables = explode(',', $tables);
foreach ($tables as $table_name) {
$sql = 'SHOW TABLES LIKE "'.$prefix.$table_name.'"';
if (count($this->Conn->Query($sql)) == 0) {
$all_found = false;
break;
}
}
return $all_found;
}
/**
* Returns modules list found in modules folder
*
* @return Array
*/
function ScanModules()
{
static $modules = null;
if (!isset($modules)) {
$modules = Array();
$fh = opendir(MODULES_PATH);
while ( ($sub_folder = readdir($fh)) ) {
$folder_path = MODULES_PATH . '/'.$sub_folder;
if ($sub_folder != '.' && $sub_folder != '..' && is_dir($folder_path)) {
if ($sub_folder == 'core') {
// skip modules here
continue;
}
// this is folder in MODULES_PATH directory
if (file_exists($folder_path.'/install.php') && file_exists($folder_path.'/install/install_schema.sql')) {
$install_order = trim( file_get_contents($folder_path . '/install/install_order.txt') );
$modules[$install_order] = $sub_folder;
}
}
}
}
// allows to control module install order
ksort($modules, SORT_NUMERIC);
return $modules;
}
/**
* Returns list of modules, that can be upgraded
*
*/
function GetUpgradableModules()
{
$ret = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
// don't show In-Portal, because it shares upgrade scripts with Core module
continue;
}
$upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql');
if (!file_exists($upgrades_file)) {
// no upgrade file
continue;
}
$sqls = file_get_contents($upgrades_file);
$versions_found = preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs);
if (!$versions_found) {
// upgrades file doesn't contain version definitions
continue;
}
$to_version = end($regs[1]);
$this_version = $this->toolkit->ConvertModuleVersion($module_info['Version']);
if ($this->toolkit->ConvertModuleVersion($to_version) > $this_version) {
// destination version is greather then current
foreach ($regs[1] as $version) {
if ($this->toolkit->ConvertModuleVersion($version) > $this_version) {
$from_version = $version;
break;
}
}
$version_info = Array (
'FromVersion' => $from_version,
'ToVersion' => $to_version,
);
$ret[ strtolower($module_name) ] = array_merge_recursive2($module_info, $version_info);
}
}
return $ret;
}
/**
* Returns content to show for current step
*
* @return string
*/
function GetStepBody()
{
$step_template = FULL_PATH.'/core/install/step_templates/'.$this->currentStep.'.tpl';
if (file_exists($step_template)) {
ob_start();
include_once ($step_template);
return ob_get_clean();
}
return '{step template "'.$this->currentStep.'" missing}';
}
/**
* Parses step information file, cache result for current step ONLY & return it
*
* @return Array
*/
function &_getStepInfo()
{
static $info = Array('help_title' => null, 'step_title' => null, 'help_body' => null, 'queried' => false);
if (!$info['queried']) {
$fdata = file_get_contents($this->StepDBFile);
$parser = xml_parser_create();
xml_parse_into_struct($parser, $fdata, $values, $index);
xml_parser_free($parser);
foreach ($index['STEP'] as $section_index) {
$step_data =& $values[$section_index];
if ($step_data['attributes']['NAME'] == $this->currentStep) {
$info['step_title'] = $step_data['attributes']['TITLE'];
if (isset($step_data['attributes']['HELP_TITLE'])) {
$info['help_title'] = $step_data['attributes']['HELP_TITLE'];
}
else {
// if help title not set, then use step title
$info['help_title'] = $step_data['attributes']['TITLE'];
}
$info['help_body'] = trim($step_data['value']);
break;
}
}
$info['queried'] = true;
}
return $info;
}
/**
* Returns particular information abou current step
*
* @param string $info_type
* @return string
*/
function GetStepInfo($info_type)
{
$step_info =& $this->_getStepInfo();
if (isset($step_info[$info_type])) {
return $step_info[$info_type];
}
return '{step "'.$this->currentStep.'"; param "'.$info_type.'" missing}';
}
/**
* Returns passed steps titles
*
* @param Array $steps
* @return Array
* @see kInstaller:PrintSteps
*/
function _getStepTitles($steps)
{
$fdata = file_get_contents($this->StepDBFile);
$parser = xml_parser_create();
xml_parse_into_struct($parser, $fdata, $values, $index);
xml_parser_free($parser);
$ret = Array ();
foreach ($index['STEP'] as $section_index) {
$step_data =& $values[$section_index];
if (in_array($step_data['attributes']['NAME'], $steps)) {
$ret[ $step_data['attributes']['NAME'] ] = $step_data['attributes']['TITLE'];
}
}
return $ret;
}
/**
* Returns current step number in active steps_preset.
* Value can't be cached, because same step can have different number in different presets
*
* @return int
*/
function GetStepNumber()
{
return array_search($this->currentStep, $this->steps[$this->stepsPreset]) + 1;
}
/**
* Returns step name to process next
*
* @return string
*/
function GetNextStep()
{
$next_index = $this->GetStepNumber();
if ($next_index > count($this->steps[$this->stepsPreset]) - 1) {
return -1;
}
return $this->steps[$this->stepsPreset][$next_index];
}
/**
* Returns step name, that was processed before this step
*
* @return string
*/
function GetPreviousStep()
{
$next_index = $this->GetStepNumber() - 1;
if ($next_index < 0) {
$next_index = 0;
}
return $this->steps[$this->stepsPreset][$next_index];
}
/**
* Prints all steps from active steps preset and highlights current step
*
* @param string $active_tpl
* @param string $passive_tpl
* @return string
*/
function PrintSteps($active_tpl, $passive_tpl)
{
$ret = '';
$step_titles = $this->_getStepTitles($this->steps[$this->stepsPreset]);
foreach ($this->steps[$this->stepsPreset] as $step_name) {
$template = $step_name == $this->currentStep ? $active_tpl : $passive_tpl;
$ret .= sprintf($template, $step_titles[$step_name]);
}
return $ret;
}
/**
* Installation error handler for sql errors
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
*/
function DBErrorHandler($code, $msg, $sql)
{
$this->errorMessage = 'Query: <br />'.htmlspecialchars($sql).'<br />execution result is error:<br />['.$code.'] '.$msg;
return true;
}
/**
* Installation error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array $errcontext
*/
function ErrorHandler($errno, $errstr, $errfile = '', $errline = '', $errcontext = '')
{
if ($errno == E_USER_ERROR) {
// only react on user fatal errors
$this->Done($errstr);
}
}
/**
* Checks, that given button should be visible on current installation step
*
* @param string $name
* @return bool
*/
function buttonVisible($name)
{
$button_visibility = Array (
'continue' => $this->GetNextStep() != -1 || ($this->stepsPreset == 'already_installed'),
'refresh' => in_array($this->currentStep, Array ('check_paths', 'security')),
'back' => in_array($this->currentStep, Array (/*'select_license',*/ 'download_license', 'select_domain')),
);
if ($name == 'any') {
foreach ($button_visibility as $button_name => $button_visible) {
if ($button_visible) {
return true;
}
}
return false;
}
return array_key_exists($name, $button_visibility) ? $button_visibility[$name] : true;
}
}
-?>
\ No newline at end of file

Event Timeline