Index: admin_templates/login.tpl =================================================================== --- admin_templates/login.tpl (revision 14590) +++ admin_templates/login.tpl (working copy) @@ -124,6 +124,8 @@
Index: kernel/application.php
===================================================================
--- kernel/application.php (revision 14590)
+++ kernel/application.php (working copy)
@@ -21,8 +21,8 @@
* The class incapsulates the main run-cycle of the script, provide access to all other objects in the framework. * * The class is a singleton, which means that there could be only one instance of kApplication in the script. -* This could be guranteed by NOT calling the class constuctor directly, but rather calling kApplication::Instance() method, -* which returns an instance of the application. The method gurantees that it will return exactly the same instance for any call. +* This could be guaranteed by NOT calling the class constructor directly, but rather calling kApplication::Instance() method, +* which returns an instance of the application. The method guarantees that it will return exactly the same instance for any call. * See singleton pattern by GOF. */ class kApplication implements kiCacheable { @@ -187,8 +187,8 @@ var $cacheManager = null; /** - * Tells, that administrator has authentificated in administrative console - * Should be used to manipulate data change OR data restrictioning! + * Tells, that administrator has authenticated in administrative console + * Should be used to manipulate data change OR data restrictions! * * @var bool */ @@ -222,7 +222,7 @@ * Returns kApplication instance anywhere in the script. * * This method should be used to get single kApplication object instance anywhere in the - * Kernel-based application. The method is guranteed to return the SAME instance of kApplication. + * Kernel-based application. The method is guaranteed to return the SAME instance of kApplication. * Anywhere in the script you could write: *
* $application =& kApplication::Instance();
@@ -232,7 +232,7 @@
* $this->Application =& kApplication::Instance();
*
* to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class.
- * To use descendand of standard kApplication class in your project you would need to define APPLICATION_CLASS constant
+ * To use descendant of standard kApplication class in your project you would need to define APPLICATION_CLASS constant
* BEFORE calling kApplication::Instance() for the first time. If APPLICATION_CLASS is not defined the method would
* create and return default KernelApplication instance.
*
@@ -266,7 +266,7 @@
*/
public function Init()
{
- if($this->InitDone) {
+ if ( $this->InitDone ) {
return false;
}
@@ -276,24 +276,24 @@
ob_start(); // collect any output from method (other then tags) into buffer
}
- if (defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY')) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) {
$this->Debugger->appendMemoryUsage('Application before Init:');
}
- if (!$this->isDebugMode() && !kUtil::constOn('DBG_ZEND_PRESENT')) {
+ if ( !$this->isDebugMode() && !kUtil::constOn('DBG_ZEND_PRESENT') ) {
error_reporting(0);
ini_set('display_errors', 0);
}
- if (!kUtil::constOn('DBG_ZEND_PRESENT')) {
- $error_handler = set_error_handler( Array (&$this, 'handleError') );
- if ($error_handler) {
+ if ( !kUtil::constOn('DBG_ZEND_PRESENT') ) {
+ $error_handler = set_error_handler(Array (&$this, 'handleError'));
+ if ( $error_handler ) {
// wrap around previous error handler, if any was set
$this->errorHandlers[] = $error_handler;
}
- $exception_handler = set_exception_handler( Array (&$this, 'handleException') );
- if ($exception_handler) {
+ $exception_handler = set_exception_handler(Array (&$this, 'handleException'));
+ if ( $exception_handler ) {
// wrap around previous exception handler, if any was set
$this->exceptionHandlers[] = $exception_handler;
}
@@ -302,14 +302,14 @@
$this->Factory = new kFactory();
$this->registerDefaultClasses();
- $this->Conn =& $this->Factory->makeClass( 'kDBConnection', Array (SQL_TYPE, Array (&$this, 'handleSQLError')) );
+ $this->Conn =& $this->Factory->makeClass('kDBConnection', Array (SQL_TYPE, Array (&$this, 'handleSQLError')));
$this->Conn->debugMode = $this->isDebugMode();
$this->Conn->Connect(SQL_SERVER, SQL_USER, SQL_PASS, SQL_DB);
$this->cacheManager =& $this->makeClass('kCacheManager');
$this->cacheManager->InitCache();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Before UnitConfigReader');
}
@@ -318,7 +318,7 @@
$this->registerModuleConstants();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('After UnitConfigReader');
}
@@ -326,19 +326,19 @@
$this->HttpQuery =& $this->recallObject('HTTPQuery');
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery initial');
}
$this->Session =& $this->recallObject('Session');
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed Session');
}
- if (!$this->RecallVar('UserGroups')) {
+ if ( !$this->RecallVar('UserGroups') ) {
$user_groups = trim($this->Session->GetField('GroupList'), ',');
- if (!$user_groups) {
+ if ( !$user_groups ) {
$user_groups = $this->ConfigValue('User_GuestGroup');
}
@@ -351,7 +351,7 @@
$this->Session->ValidateExpired();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit');
}
@@ -359,11 +359,11 @@
$site_timezone = $this->ConfigValue('Config_Site_Time');
- if ($site_timezone) {
+ if ( $site_timezone ) {
putenv('TZ=' . $site_timezone);
}
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Loaded cache and phrases');
}
@@ -371,37 +371,39 @@
$this->UnitConfigReader->AfterConfigRead();
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->appendTimestamp('Processed AfterConfigRead');
}
- if ($this->GetVar('m_cat_id') === false) {
+ if ( $this->GetVar('m_cat_id') === false ) {
$this->SetVar('m_cat_id', 0);
}
- if (!$this->RecallVar('curr_iso')) {
+ if ( !$this->RecallVar('curr_iso') ) {
$this->StoreVar('curr_iso', $this->GetPrimaryCurrency(), true); // true for optional
}
$visit_id = $this->RecallVar('visit_id');
- if ($visit_id !== false) {
+ if ( $visit_id !== false ) {
$this->SetVar('visits_id', $visit_id);
}
- $language =& $this->recallObject( 'lang.current', null, Array('live_table' => true) );
- if (preg_match('/utf-8/', $language->GetDBField('Charset'))) {
+ $language =& $this->recallObject('lang.current', null, Array ('live_table' => true));
+ /* @var $language LanguagesItem */
+
+ if ( preg_match('/utf-8/', $language->GetDBField('Charset')) ) {
setlocale(LC_ALL, 'en_US.UTF-8');
mb_internal_encoding('UTF-8');
}
- if (defined('DEBUG_MODE') && $this->isDebugMode()) {
+ if ( defined('DEBUG_MODE') && $this->isDebugMode() ) {
$this->Debugger->profileFinish('kernel4_startup');
}
$this->InitDone = true;
- $this->HandleEvent( new kEvent('adm:OnStartup') );
+ $this->HandleEvent(new kEvent('adm:OnStartup'));
return true;
}
@@ -446,11 +448,17 @@
return false;
}
- function refreshModuleInfo()
+ /**
+ * Refreshes information about loaded modules
+ *
+ * @return void
+ * @access public
+ */
+ public function refreshModuleInfo()
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules')) {
$this->registerModuleConstants();
- return false;
+ return ;
}
$modules_helper =& $this->makeClass('ModulesHelper');
@@ -519,21 +527,30 @@
function GetFrontThemePath($force=0)
{
- static $path=null;
- if (!$force && isset($path)) return $path;
+ static $path = null;
+ if ( !$force && isset($path) ) {
+ return $path;
+ }
+
$theme_id = $this->GetVar('m_theme');
- if (!$theme_id) {
+ if ( !$theme_id ) {
// $theme_id = $this->GetDefaultThemeId(1); //1 to force front-end mode!
$theme_id = 'default';
}
+
$this->SetVar('m_theme', $theme_id);
- $this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId
+ $this->SetVar('theme.current_id', $theme_id); // KOSTJA: this is to fool theme' getPassedId
$theme =& $this->recallObject('theme.current');
- if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) {
+ /* @var $theme ThemeItem */
+
+ if ( !$theme->isLoaded() || !$theme->GetDBField('Enabled') ) {
return false;
}
- $path = '/themes/'.$theme->GetDBField('Name');
+
+ // assign & then return, since it's static variable
+ $path = '/themes/' . $theme->GetDBField('Name');
+
return $path;
}
@@ -685,6 +702,7 @@
$this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php', null, 'kiCacheable');
$this->registerClass('PhrasesCache', KERNEL_PATH . '/languages/phrases_cache.php', 'kPhraseCache');
$this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php');
+ $this->registerClass('kValidator', KERNEL_PATH . '/utility/validator.php');
$this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php');
@@ -948,7 +966,10 @@
elseif ($this->GetVar('admin')) {
// viewing front-end through admin's frame
$admin_session =& $this->recallObject('Session.admin');
+ /* @var $admin_session Session */
+
$user = (int)$admin_session->RecallVar('user_id'); // in case, when no valid admin session found
+
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
@@ -1172,29 +1193,34 @@
/**
* Returns current session id (SID)
* @access public
- * @return longint
+ * @return int
*/
function GetSID()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
return $session->GetID();
}
function DestroySession()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$session->Destroy();
}
/**
- * Returns variable passed to the script as GET/POST/COOKIE
- *
- * @access public
- * @param string $name Name of variable to retrieve
- * @param int $default default value returned in case if varible not present
- * @return mixed
- */
- function GetVar($name, $default = false)
+ * Returns variable passed to the script as GET/POST/COOKIE
+ *
+ * @param string $name Name of variable to retrieve
+ * @param mixed $default default value returned in case if variable not present
+ *
+ * @return mixed
+ * @access public
+ */
+ public function GetVar($name, $default = false)
{
return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default;
}
@@ -1223,9 +1249,9 @@
* @access public
* @return void
*/
- function SetVar($var,$val)
+ public function SetVar($var,$val)
{
- return $this->HttpQuery->Set($var, $val);
+ $this->HttpQuery->Set($var, $val);
}
/**
@@ -1355,14 +1381,10 @@
return $this->GetVar($var);
}
- function AddBlock($name, $tpl)
- {
- $this->cache[$name] = $tpl;
- }
-
function ProcessParsedTag($prefix, $tag, $params)
{
$processor = $this->Parser->GetProcessor($prefix);
+ /* @var $processor kDBTagProcessor */
return $processor->ProcessParsedTag($tag, $params, $prefix);
}
@@ -1446,7 +1468,7 @@
return $this->UrlManager->getPassThroughVariables($params);
}
- function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true)
+ function BuildEnv($t, $params, $pass = 'all', $pass_events = false, $env_var = true)
{
return $this->UrlManager->BuildEnv($t, $params, $pass, $pass_events, $env_var);
}
@@ -1599,15 +1621,17 @@
function ValidateLogin()
{
$session =& $this->recallObject('Session');
+ /* @var $session Session */
+
$user_id = $session->GetField('PortalUserId');
- if (!$user_id && $user_id != USER_ROOT) {
+ if ( !$user_id && $user_id != USER_ROOT ) {
$user_id = USER_GUEST;
}
$this->SetVar('u.current_id', $user_id);
- if (!$this->isAdmin) {
+ if ( !$this->isAdmin ) {
// needed for "profile edit", "registration" forms ON FRONT ONLY
$this->SetVar('u_id', $user_id);
}
@@ -1616,18 +1640,19 @@
$this->isAdminUser = $this->isAdmin && $this->LoggedIn();
- if ($this->GetVar('expired') == 1) {
+ if ( $this->GetVar('expired') == 1 ) {
// this parameter is set only from admin
$user =& $this->recallObject('u.current');
+ /* @var $user UsersItem */
+
$user->SetError('ValidateLogin', 'session_expired', 'la_text_sess_expired');
}
- if (($user_id != USER_GUEST) && kUtil::constOn('DBG_REQUREST_LOG') ) {
- $http_query =& $this->recallObject('HTTPQuery');
- $http_query->writeRequestLog(DBG_REQUREST_LOG);
+ if ( ($user_id != USER_GUEST) && defined('DBG_REQUREST_LOG') && DBG_REQUREST_LOG ) {
+ $this->HttpQuery->writeRequestLog(DBG_REQUREST_LOG);
}
- if ($user_id != USER_GUEST) {
+ if ( $user_id != USER_GUEST ) {
// normal users + root
$this->LoadPersistentVars();
}
@@ -2009,21 +2034,23 @@
* @param string $errfile
* @param int $errline
* @param Array $errcontext
+ * @return bool
+ * @access public
*/
- function handleError($errno, $errstr = '', $errfile = '', $errline = '', $errcontext = '')
+ public function handleError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ())
{
$this->errorLogSilent($errno, $errstr, $errfile, $errline);
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
- if (!$this->errorHandlers || ($debug_mode && $skip_reporting)) {
+ if ( !$this->errorHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
- if ($errno == E_USER_ERROR) {
+ if ( $errno == E_USER_ERROR ) {
$this->errorDisplayFatal('Fatal Error: ' . "{$errstr} in {$errfile} on line {$errline}");
}
- if (!$this->errorHandlers) {
+ if ( !$this->errorHandlers ) {
return true;
}
}
@@ -2049,8 +2076,9 @@
*
* @param Exception $exception
* @return bool
+ * @access public
*/
- function handleException($exception)
+ public function handleException($exception)
{
// transform exception to regular error (no need to rewrite existing error handlers)
$errno = $exception->getCode();
@@ -2063,11 +2091,11 @@
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
- if (!$this->exceptionHandlers || ($debug_mode && $skip_reporting)) {
+ if ( !$this->exceptionHandlers || ($debug_mode && $skip_reporting) ) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
$this->errorDisplayFatal('' . get_class($exception) . ': ' . "{$errstr} in {$errfile} on line {$errline}");
- if (!$this->exceptionHandlers) {
+ if ( !$this->exceptionHandlers ) {
return true;
}
}
@@ -2088,10 +2116,19 @@
return $res;
}
- protected function errorLogSilent($errno, $errstr = '', $errfile = '', $errline = '')
+ /**
+ * Silently saves each given error message to "silent_log.txt" file, when silent log mode is enabled
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param int $errline
+ * @return void
+ * @access protected
+ */
+ protected function errorLogSilent($errno, $errstr = '', $errfile = '', $errline = null)
{
- if (!defined('SILENT_LOG') || !SILENT_LOG) {
- return ;
+ if ( !defined('SILENT_LOG') || !SILENT_LOG ) {
+ return;
}
if ( !(defined('DBG_IGNORE_STRICT_ERRORS') && DBG_IGNORE_STRICT_ERRORS && defined('E_STRICT') && ($errno == E_STRICT)) ) {
@@ -2103,6 +2140,13 @@
}
}
+ /**
+ * Displays div with given error message
+ *
+ * @param string $msg
+ * @return void
+ * @access protected
+ */
protected function errorDisplayFatal($msg)
{
$margin = $this->isAdmin ? '8px' : 'auto';
@@ -2116,8 +2160,9 @@
* @param bool $return_result
* @param int $skip_levels
* @return string
+ * @access public
*/
- function printTrace($return_result = false, $skip_levels = 1)
+ public function printTrace($return_result = false, $skip_levels = 1)
{
$ret = Array ();
$trace = debug_backtrace(false);
@@ -2127,11 +2172,11 @@
}
foreach ($trace as $level => $trace_info) {
- if ( isset($trace_info['class']) ) {
+ if ( isset($trace_info['class']) ) {
$object = $trace_info['class'];
}
elseif ( isset($trace_info['object']) ) {
- $object = get_class( $trace_info['object'] );
+ $object = get_class($trace_info['object']);
}
else {
$object = '';
@@ -2153,14 +2198,16 @@
$args = substr($args, 0, -2);
}
- $ret[] = '#' . $level . ' ' . $object . $type . $trace_info['function']. '(' . $args . ') called at [' . $trace_info['file'] . ':' . $trace_info['line'] . ']';
+ $ret[] = '#' . $level . ' ' . $object . $type . $trace_info['function'] . '(' . $args . ') called at [' . $trace_info['file'] . ':' . $trace_info['line'] . ']';
}
- if ($return_result) {
+ if ( $return_result ) {
return implode("\n", $ret);
}
echo implode("\n", $ret);
+
+ return '';
}
/**
@@ -2556,35 +2603,40 @@
}
/**
- * Resets counter, whitch are affected by one of specified tables
+ * Resets counter, which are affected by one of specified tables
*
* @param string $tables comma separated tables list used in counting sqls
+ * @return void
+ * @access public
*/
- function resetCounters($tables)
+ public function resetCounters($tables)
{
- if (kUtil::constOn('IS_INSTALL')) {
- return ;
+ if ( kUtil::constOn('IS_INSTALL') ) {
+ return;
}
$count_helper =& $this->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
- return $count_helper->resetCounters($tables);
+ $count_helper->resetCounters($tables);
}
/**
* Sends XML header + optionally displays xml heading
*
- * @param string $xml_version
+ * @param string|bool $xml_version
* @return string
+ * @access public
* @author Alex
*/
- function XMLHeader($xml_version = false)
+ public function XMLHeader($xml_version = false)
{
$lang =& $this->recallObject('lang.current');
- header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
+ /* @var $lang LanguagesItem */
- return $xml_version ? 'GetDBField('Charset').'"?>' : '';
+ header('Content-type: text/xml; charset=' . $lang->GetDBField('Charset'));
+
+ return $xml_version ? 'GetDBField('Charset') . '"?>' : '';
}
/**
Index: kernel/db/cat_dbitem.php
===================================================================
--- kernel/db/cat_dbitem.php (revision 14590)
+++ kernel/db/cat_dbitem.php (working copy)
@@ -57,7 +57,15 @@
$this->usePendingEditing = $this->Application->getUnitOption($this->Prefix, 'UsePendingEditing');
}
- function Create($force_id = false, $system_create = false)
+ /**
+ * Creates a record in the database table with current item' values
+ *
+ * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE!
+ * @param bool $system_create
+ * @return bool
+ * @access public
+ */
+ public function Create($force_id = false, $system_create = false)
{
$ret = parent::Create($force_id, $system_create);
@@ -84,33 +92,43 @@
$this->assignToCategory($this->GetDBField('CategoryId'), true);
}
- function Update($id=null, $system_update=false)
+ /**
+ * Updates previously loaded record with current item' values
+ *
+ * @access public
+ * @param int $id Primary Key Id to update
+ * @param bool $system_update
+ * @return bool
+ * @access public
+ */
+ public function Update($id = null, $system_update = false)
{
- $this->VirtualFields['ResourceId'] = Array();
+ $this->VirtualFields['ResourceId'] = Array ();
- if ($this->GetChangedFields()) {
+ if ( $this->GetChangedFields() ) {
$now = adodb_mktime();
$this->SetDBField('Modified_date', $now);
$this->SetDBField('Modified_time', $now);
$this->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
}
- if ($this->useFilenames) {
+ if ( $this->useFilenames ) {
$this->checkFilename();
$this->generateFilename();
}
$ret = parent::Update($id, $system_update);
- if ($ret) {
+ if ( $ret ) {
$filename = $this->useFilenames ? (string)$this->GetDBField('Filename') : '';
- $sql = 'UPDATE '.$this->CategoryItemsTable().'
- SET Filename = '.$this->Conn->qstr($filename).'
- WHERE ItemResourceId = '.$this->GetDBField('ResourceId');
+ $sql = 'UPDATE ' . $this->CategoryItemsTable() . '
+ SET Filename = ' . $this->Conn->qstr($filename) . '
+ WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
$this->Conn->Query($sql);
}
unset($this->VirtualFields['ResourceId']);
+
return $ret;
}
@@ -228,10 +246,11 @@
*
* @param int $id
* @return bool
+ * @access public
*/
- function Delete($id = null)
+ public function Delete($id = null)
{
- if( isset($id) ) {
+ if ( isset($id) ) {
$this->setID($id);
}
@@ -239,7 +258,7 @@
$ret = parent::Delete();
- if ($ret) {
+ if ( $ret ) {
// TODO: move to OnAfterItemDelete method
$query = ' DELETE FROM ' . $this->CategoryItemsTable() . '
WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
@@ -259,32 +278,43 @@
{
$id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); // because item was loaded before by ResourceId
- $ci_table = $this->Application->getUnitOption($this->Prefix.'-ci', 'TableName');
+ $ci_table = $this->Application->getUnitOption($this->Prefix . '-ci', 'TableName');
$resource_id = $this->GetDBField('ResourceId');
- $item_cats_sql = 'SELECT CategoryId FROM %s WHERE ItemResourceId = %s';
- $delete_category_items_sql = 'DELETE FROM %s WHERE ItemResourceId = %s AND CategoryId IN (%s)';
+ $item_cats_sql = ' SELECT CategoryId
+ FROM %s
+ WHERE ItemResourceId = %s';
+ $delete_category_items_sql = ' DELETE FROM %s
+ WHERE ItemResourceId = %s AND CategoryId IN (%s)';
+
$category_ids = $this->Conn->GetCol( sprintf($item_cats_sql, $ci_table, $resource_id) );
$cats_left = array_diff($category_ids, $delete_category_ids);
- if(!$cats_left)
- {
- $sql = 'SELECT %s FROM %s WHERE ResourceId = %s';
- $ids = $this->Conn->GetCol( sprintf($sql, $id_field, $this->TableName, $resource_id) );
- $temp =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp->DeleteItems($this->Prefix, $this->Special, $ids);
+ if ( !$cats_left ) {
+ $sql = 'SELECT %s
+ FROM %s
+ WHERE ResourceId = %s';
+ $ids = $this->Conn->GetCol(sprintf($sql, $id_field, $this->TableName, $resource_id));
+
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, $ids);
}
- else
- {
- $this->Conn->Query( sprintf($delete_category_items_sql, $ci_table, $resource_id, implode(',', $delete_category_ids) ) );
+ else {
+ $this->Conn->Query( sprintf($delete_category_items_sql, $ci_table, $resource_id, implode(',', $delete_category_ids)) );
- $sql = 'SELECT CategoryId FROM %s WHERE PrimaryCat = 1 AND ItemResourceId = %s';
- $primary_cat_id = $this->Conn->GetCol( sprintf($sql, $ci_table, $resource_id) );
- if( count($primary_cat_id) == 0 )
- {
- $sql = 'UPDATE %s SET PrimaryCat = 1 WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
- $this->Conn->Query( sprintf($sql, $ci_table, reset($cats_left), $resource_id ) );
+ $sql = 'SELECT CategoryId
+ FROM %s
+ WHERE PrimaryCat = 1 AND ItemResourceId = %s';
+ $primary_cat_id = $this->Conn->GetCol(sprintf($sql, $ci_table, $resource_id));
+
+ if ( count($primary_cat_id) == 0 ) {
+ $sql = 'UPDATE %s
+ SET PrimaryCat = 1
+ WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
+ $this->Conn->Query( sprintf($sql, $ci_table, reset($cats_left), $resource_id) );
}
}
}
@@ -298,6 +328,8 @@
function stripDisallowed($filename)
{
$filenames_helper =& $this->Application->recallObject('FilenamesHelper');
+ /* @var $filenames_helper kFilenamesHelper */
+
$table = $this->IsTempTable() ? $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems', 'prefix:'.$this->Prefix) : TABLE_PREFIX.'CategoryItems';
return $filenames_helper->stripDisallowed($table, 'ItemResourceId', $this->GetDBField('ResourceId'), $filename);
@@ -314,40 +346,27 @@
/**
* Generate item's filename based on it's title field value
*
- * @return string
+ * @return void
+ * @access protected
*/
- function generateFilename()
+ protected function generateFilename()
{
- if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) return false;
+ if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) {
+ return ;
+ }
$title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
- if (preg_match('/l([\d]+)_(.*)/', $title_field, $regs)) {
+
+ if ( preg_match('/l([\d]+)_(.*)/', $title_field, $regs) ) {
// if title field is multilingual, then use it's name from primary language
- $title_field = 'l'.$this->Application->GetDefaultLanguageId().'_'.$regs[2];
+ $title_field = 'l' . $this->Application->GetDefaultLanguageId() . '_' . $regs[2];
}
+
$name = $this->stripDisallowed( $this->GetDBField($title_field) );
- if ( $name != $this->GetDBField('Filename') ) $this->SetDBField('Filename', $name);
- }
-
- /**
- * Check if value is set for required field
- *
- * @param string $field field name
- * @param Array $params field options from config
- * @return bool
- * @access private
- */
- function ValidateRequired($field, $params)
- {
- $res = true;
- if (getArrayValue($params, 'required')) {
- $res = ( (string) $this->FieldValues[$field] != '');
+ if ( $name != $this->GetDBField('Filename') ) {
+ $this->SetDBField('Filename', $name);
}
- if (!$res) {
- $this->SetError($field, 'required');
- }
- return $res;
}
/**
@@ -355,44 +374,52 @@
*
* @param int $category_id
* @param bool $is_primary
+ * @return void
+ * @access public
*/
- function assignToCategory($category_id, $is_primary = false)
+ public function assignToCategory($category_id, $is_primary = false)
{
$table = $this->CategoryItemsTable();
- $key_clause = '(ItemResourceId = '.$this->GetDBField('ResourceId').')';
+ $key_clause = '(ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
- // get all cateories, where item is in
- $sql = 'SELECT PrimaryCat, CategoryId FROM '.$table.' WHERE '.$key_clause;
+ // get all categories, where item is in
+ $sql = 'SELECT PrimaryCat, CategoryId
+ FROM ' . $table . '
+ WHERE ' . $key_clause;
$item_categories = $this->Conn->GetCol($sql, 'CategoryId');
- if (!$item_categories) {
- $item_categories = Array();
- $primary_found = false;
- }
- // find primary category
- foreach ($item_categories as $item_category_id => $primary_found) {
- if ($primary_found) {
- break;
+ $primary_found = $item_category_id = false;
+
+ if ( $item_categories ) {
+ // find primary category
+ foreach ($item_categories as $item_category_id => $primary_found) {
+ if ( $primary_found ) {
+ break;
+ }
}
}
- if ($primary_found && ($item_category_id == $category_id) && !$is_primary) {
+ if ( $primary_found && ($item_category_id == $category_id) && !$is_primary ) {
// want to make primary category as non-primary :(
- return true;
+ return;
}
- else if (!$primary_found) {
+ elseif ( !$primary_found ) {
$is_primary = true;
}
- if ($is_primary && $item_categories) {
+ if ( $is_primary && $item_categories ) {
// reset primary mark from all other categories
- $sql = 'UPDATE '.$table.' SET PrimaryCat = 0 WHERE '.$key_clause;
+ $sql = 'UPDATE ' . $table . '
+ SET PrimaryCat = 0
+ WHERE ' . $key_clause;
$this->Conn->Query($sql);
}
// UPDATE & INSERT instead of REPLACE because CategoryItems table has no primary key defined in database
- if (isset($item_categories[$category_id])) {
- $sql = 'UPDATE '.$table.' SET PrimaryCat = '.($is_primary ? 1 : 0).' WHERE '.$key_clause.' AND (CategoryId = '.$category_id.')';
+ if ( isset($item_categories[$category_id]) ) {
+ $sql = 'UPDATE ' . $table . '
+ SET PrimaryCat = ' . ($is_primary ? 1 : 0) . '
+ WHERE ' . $key_clause . ' AND (CategoryId = ' . $category_id . ')';
$this->Conn->Query($sql);
}
else {
@@ -403,8 +430,10 @@
'ItemPrefix' => $this->Prefix,
'Filename' => $this->useFilenames ? (string)$this->GetDBField('Filename') : '', // because some prefixes does not use filenames,
);
+
$this->Conn->doInsert($fields_hash, $table);
}
+
// to ensure filename update after adding to another category
// this is critical since there may be an item with same filename in newly added category!
$this->Update();
@@ -493,16 +522,18 @@
{
$original_id = $this->GetDBField('OrgId');
- if (!($this->usePendingEditing && $original_id)) {
+ if ( !($this->usePendingEditing && $original_id) ) {
// non-pending copy of original link
return $this->ChangeStatus(STATUS_ACTIVE);
}
- if ($this->raiseEvent('OnBeforeDeleteOriginal', null, Array('original_id' => $original_id))) {
+ if ( $this->raiseEvent('OnBeforeDeleteOriginal', null, Array ('original_id' => $original_id)) ) {
// delete original item, because changes made in pending copy (this item) got to be approved in this method
- $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($original_id));
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, Array ($original_id));
+
$this->SetDBField('OrgId', 0);
return $this->ChangeStatus(STATUS_ACTIVE, true);
}
@@ -519,14 +550,16 @@
{
$original_id = $this->GetDBField('OrgId');
- if (!($this->usePendingEditing && $original_id)) {
+ if ( !($this->usePendingEditing && $original_id) ) {
// non-pending copy of original link
return $this->ChangeStatus(STATUS_DISABLED);
}
// delete this item, because changes made in pending copy (this item) will be declined in this method
- $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($this->GetID()));
+ $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems($this->Prefix, $this->Special, Array ($this->GetID()));
$this->sendEmailEvents(STATUS_DISABLED, true);
// original item is not changed here, because it is already enabled (thrus pending copy is visible to item's owner or admin with permission)
@@ -566,17 +599,17 @@
}
/**
- * Returns part of SQL WHERE clause identifing the record, ex. id = 25
- *
- * @access public
- * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
- * @param Array $keys_hash alternative, then item id, keys hash to load item by
- * @return void
- * @see kDBItem::Load()
- * @see kDBItem::Update()
- * @see kDBItem::Delete()
- */
- function GetKeyClause($method = null, $keys_hash = null)
+ * Returns part of SQL WHERE clause identifying the record, ex. id = 25
+ *
+ * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method
+ * @param Array $keys_hash alternative, then item id, keys hash to load item by
+ * @see kDBItem::Load()
+ * @see kDBItem::Update()
+ * @see kDBItem::Delete()
+ * @return string
+ * @access protected
+ */
+ protected function GetKeyClause($method = null, $keys_hash = null)
{
if ($method == 'load') {
// for item with many categories makes primary to load
Index: kernel/db/db_event_handler.php
===================================================================
--- kernel/db/db_event_handler.php (revision 14590)
+++ kernel/db/db_event_handler.php (working copy)
@@ -48,6 +48,8 @@
* Checks permissions of user
*
* @param kEvent $event
+ * @return bool
+ * @access public
*/
function CheckPermission(&$event)
{
@@ -398,7 +400,15 @@
// for permission checking inside item/list build events
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
- $object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields') );
+ if ( $event->getEventParam('form_name') !== false ) {
+ $form_name = $event->getEventParam('form_name');
+ }
+ else {
+ $request_forms = $this->Application->GetVar('forms', Array ());
+ $form_name = (string)getArrayValue( $request_forms, $object->getPrefixSpecial() );
+ }
+
+ $object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields'), $form_name );
$this->PrepareObject($object, $event);
// force live table if specified or is original item
@@ -492,8 +502,10 @@
function OnItemBuild(&$event)
{
$object =& $event->getObject();
- $this->dbBuild($object,$event);
+ /* @var $object kDBItem */
+ $this->dbBuild($object, $event);
+
$sql = $this->ItemPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
@@ -549,9 +561,11 @@
}
$actions =& $this->Application->recallObject('kActions');
+ /* @var $actions Params */
+
$actions->Set($event->getPrefixSpecial().'_GoTab', '');
-
$actions->Set($event->getPrefixSpecial().'_GoId', '');
+ $actions->Set('forms[' . $event->getPrefixSpecial() . ']', $object->getFormName());
}
/**
@@ -597,22 +611,26 @@
* Load item if id is available
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function LoadItem(&$event)
+ protected function LoadItem(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$id = $this->getPassedID($event);
- if ($object->isLoaded() && !is_array($id) && ($object->GetID() == $id)) {
+ if ( $object->isLoaded() && !is_array($id) && ($object->GetID() == $id) ) {
// object is already loaded by same id
return ;
}
- if ($object->Load($id)) {
+ if ( $object->Load($id) ) {
$actions =& $this->Application->recallObject('kActions');
- $actions->Set($event->getPrefixSpecial().'_id', $object->GetID() );
+ /* @var $actions Params */
+
+ $actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
}
else {
$object->setID($id);
@@ -632,9 +650,9 @@
$object =& $event->getObject();
/* @var $object kDBList */
- $this->dbBuild($object,$event);
+ $this->dbBuild($object, $event);
- if (!$object->isMainList() && $event->getEventParam('main_list')) {
+ if ( !$object->isMainList() && $event->getEventParam('main_list') ) {
// once list is set to main, then even "requery" parameter can't remove that
/*$passed = $this->Application->GetVar('passed');
$this->Application->SetVar('passed', $passed . ',' . $event->Prefix);*/
@@ -642,7 +660,7 @@
$object->becameMain();
}
- $object->setGridName( $event->getEventParam('grid') );
+ $object->setGridName($event->getEventParam('grid'));
$sql = $this->ListPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
@@ -653,13 +671,15 @@
$object->linkToParent( $this->getMainSpecial($event) );
$this->AddFilters($event);
- $this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex.
+ $this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex.
$this->SetPagination($event);
$this->SetSorting($event);
$actions =& $this->Application->recallObject('kActions');
- $actions->Set('remove_specials['.$event->getPrefixSpecial().']', '0');
- $actions->Set($event->getPrefixSpecial().'_GoTab', '');
+ /* @var $actions Params */
+
+ $actions->Set('remove_specials[' . $event->getPrefixSpecial() . ']', '0');
+ $actions->Set($event->getPrefixSpecial() . '_GoTab', '');
}
/**
@@ -691,10 +711,11 @@
* Apply any custom changes to list's sql query
*
* @param kEvent $event
+ * @return void
* @access protected
- * @see OnListBuild
+ * @see kDBEventHandler::OnListBuild()
*/
- function SetCustomQuery(&$event)
+ protected function SetCustomQuery(&$event)
{
}
@@ -1001,16 +1022,17 @@
}
}
- // always add forced sorting before any user sortings
+ // always add forced sorting before any user sorting fields
$forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting');
-
+ /* @var $forced_sorting Array */
+
if ($forced_sorting) {
foreach ($forced_sorting as $field => $dir) {
$object->AddOrderField($field, $dir);
}
}
- // add user sortings
+ // add user sorting fields
if ($cur_sort1 != '' && $cur_sort1_dir != '') {
$object->AddOrderField($cur_sort1, $cur_sort1_dir);
}
@@ -1071,13 +1093,16 @@
function AddFilters(&$event)
{
$object =& $event->getObject();
+ /* @var $object kDBList */
- $edit_mark = rtrim($this->Application->GetSID().'_'.$this->Application->GetTopmostWid($event->Prefix), '_');
+ $edit_mark = rtrim($this->Application->GetSID() . '_' . $this->Application->GetTopmostWid($event->Prefix), '_');
// add search filter
- $filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter');
- if ($filter_data) {
+ $filter_data = $this->Application->RecallVar($event->getPrefixSpecial() . '_search_filter');
+
+ if ( $filter_data ) {
$filter_data = unserialize($filter_data);
+
foreach ($filter_data as $filter_field => $filter_params) {
$filter_type = ($filter_params['type'] == 'having') ? kDBList::HAVING_FILTER : kDBList::WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $filter_params['value']);
@@ -1086,15 +1111,18 @@
}
// add custom filter
- $view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
- $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name);
- if ($custom_filters) {
+ $view_name = $this->Application->RecallVar($event->getPrefixSpecial() . '_current_view');
+ $custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial() . '_custom_filter.' . $view_name);
+
+ if ( $custom_filters ) {
$grid_name = $event->getEventParam('grid');
$custom_filters = unserialize($custom_filters);
- if (isset($custom_filters[$grid_name])) {
+
+ if ( isset($custom_filters[$grid_name]) ) {
foreach ($custom_filters[$grid_name] as $field_name => $field_options) {
list ($filter_type, $field_options) = each($field_options);
- if (isset($field_options['value']) && $field_options['value']) {
+
+ if ( isset($field_options['value']) && $field_options['value'] ) {
$filter_type = ($field_options['sql_filter_type'] == 'having') ? kDBList::HAVING_FILTER : kDBList::WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $field_options['value']);
$object->addFilter($field_name, $filter_value, $filter_type, kDBList::FLT_CUSTOM);
@@ -1103,29 +1131,34 @@
}
}
- $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
- if($view_filter)
- {
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial() . '_view_filter');
+
+ if ( $view_filter ) {
$view_filter = unserialize($view_filter);
+
$temp_filter =& $this->Application->makeClass('kMultipleFilter');
- $filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
+ /* @var $temp_filter kMultipleFilter */
+
+ $filter_menu = $this->Application->getUnitOption($event->Prefix, 'FilterMenu');
- $group_key = 0; $group_count = count($filter_menu['Groups']);
- while($group_key < $group_count)
- {
+ $group_key = 0;
+ $group_count = count($filter_menu['Groups']);
+
+ while ( $group_key < $group_count ) {
$group_info = $filter_menu['Groups'][$group_key];
- $temp_filter->setType( constant('kDBList::FLT_TYPE_'.$group_info['mode']) );
+ $temp_filter->setType(constant('kDBList::FLT_TYPE_' . $group_info['mode']));
$temp_filter->clearFilters();
- foreach ($group_info['filters'] as $flt_id)
- {
- $sql_key = getArrayValue($view_filter,$flt_id) ? 'on_sql' : 'off_sql';
- if ($filter_menu['Filters'][$flt_id][$sql_key] != '')
- {
- $temp_filter->addFilter('view_filter_'.$flt_id, $filter_menu['Filters'][$flt_id][$sql_key]);
+
+ foreach ($group_info['filters'] as $flt_id) {
+ $sql_key = getArrayValue($view_filter, $flt_id) ? 'on_sql' : 'off_sql';
+
+ if ( $filter_menu['Filters'][$flt_id][$sql_key] != '' ) {
+ $temp_filter->addFilter('view_filter_' . $flt_id, $filter_menu['Filters'][$flt_id][$sql_key]);
}
}
- $object->addFilter('view_group_'.$group_key, $temp_filter, $group_info['type'] , kDBList::FLT_VIEW);
+
+ $object->addFilter('view_group_' . $group_key, $temp_filter, $group_info['type'], kDBList::FLT_VIEW);
$group_key++;
}
}
@@ -1277,15 +1310,15 @@
*/
function ItemPrepareQuery(&$event)
{
- $sqls = $this->Application->getUnitOption($event->Prefix, 'ItemSQLs', Array ());
- $special = array_key_exists($event->Special, $sqls) ? $event->Special : '';
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
- if (!array_key_exists($special, $sqls)) {
- // preferred special not found in ItemSQLs -> use analog from ListSQLs
- return $this->ListPrepareQuery($event);
- }
+ $sqls = $object->getFormOption('ItemSQLs', Array ());
+ $special = isset($sqls[$event->Special]) ? $event->Special : '';
- return $sqls[$special];
+ // preferred special not found in ItemSQLs -> use analog from ListSQLs
+
+ return isset($sqls[$special]) ? $sqls[$special] : $this->ListPrepareQuery($event);
}
/**
@@ -1299,7 +1332,11 @@
*/
function ListPrepareQuery(&$event)
{
- $sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs', Array ());
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $sqls = $object->getFormOption('ListSQLs', Array ());
+
return $sqls[ array_key_exists($event->Special, $sqls) ? $event->Special : '' ];
}
@@ -1307,8 +1344,11 @@
* Apply custom processing to item
*
* @param kEvent $event
+ * @param string $type
+ * @return void
+ * @access protected
*/
- function customProcessing(&$event, $type)
+ protected function customProcessing(&$event, $type)
{
}
@@ -1356,19 +1396,21 @@
*/
function OnUpdate(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
return;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
+
+ if ( $items_info ) {
foreach ($items_info as $id => $field_values) {
$object->Load($id);
- $object->SetFieldsFromHash($field_values);
- $this->customProcessing($event, 'before');
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
if ( $object->Update($id) ) {
$this->customProcessing($event, 'after');
@@ -1451,64 +1493,70 @@
}
/**
- * Cancel's kDBItem Editing/Creation
+ * Cancels kDBItem Editing/Creation
*
* @param kEvent $event
+ * @return void
* @access protected
*/
- function OnCancel(&$event)
+ protected function OnCancel(&$event)
{
- $object =& $event->getObject(Array('skip_autoload' => true));
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- if ($items_info) {
- $delete_ids = Array();
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ if ( $items_info ) {
+ $delete_ids = Array ();
+
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
foreach ($items_info as $id => $field_values) {
$object->Load($id);
// record created for using with selector (e.g. Reviews->Select User), and not validated => Delete it
- if ($object->isLoaded() && !$object->Validate() && ($id <= 0) ) {
+ if ( $object->isLoaded() && !$object->Validate() && ($id <= 0) ) {
$delete_ids[] = $id;
}
}
- if ($delete_ids) {
- $temp->DeleteItems($event->Prefix, $event->Special, $delete_ids);
+ if ( $delete_ids ) {
+ $temp_handler->DeleteItems($event->Prefix, $event->Special, $delete_ids);
}
}
- $event->setRedirectParams(Array('opener'=>'u'), true);
+ $event->SetRedirectParam('opener', 'u');
}
-
/**
* Deletes all selected items.
* Automatically recurse into sub-items using temp handler, and deletes sub-items
* by calling its Delete method if sub-item has AutoDelete set to true in its config file
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnMassDelete(&$event)
+ protected function OnMassDelete(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $event->status=kEvent::erSUCCESS;
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
-
$ids = $this->StoreSelectedIDs($event);
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('ids');
- if($ids)
- {
- $temp->DeleteItems($event->Prefix, $event->Special, $ids);
+ if ( $ids ) {
+ $temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
}
+
$this->clearSelectedIDs($event);
}
@@ -1563,47 +1611,54 @@
* redirects to event' default redirect (normally grid template)
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnSave(&$event)
+ protected function OnSave(&$event)
{
$event->CallSubEvent('OnPreSave');
- if ($event->status == kEvent::erSUCCESS) {
- $skip_master = false;
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $changes_var_name = $this->Prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix);
+ if ($event->status != kEvent::erSUCCESS) {
+ return ;
+ }
- if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
- $live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array());
- if ($live_ids === false) {
- // coping from table failed, because we have another coping process to same table, that wasn't finished
- $event->status = kEvent::erFAIL;
- return ;
- }
+ $skip_master = false;
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
- if ($live_ids) {
- // ensure, that newly created item ids are avalable as if they were selected from grid
- // NOTE: only works if main item has subitems !!!
- $this->StoreSelectedIDs($event, $live_ids);
- }
+ $changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
- $object =& $event->getObject();
- /* @var $object kDBItem */
+ if ( !$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
+ $live_ids = $temp_handler->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array ());
- $this->SaveLoggedChanges($changes_var_name, $object->ShouldLogChanges());
- }
- else {
+ if ( $live_ids === false ) {
+ // coping from table failed, because we have another coping process to same table, that wasn't finished
$event->status = kEvent::erFAIL;
+ return ;
}
- $this->clearSelectedIDs($event);
+ if ( $live_ids ) {
+ // ensure, that newly created item ids are available as if they were selected from grid
+ // NOTE: only works if main item has sub-items !!!
+ $this->StoreSelectedIDs($event, $live_ids);
+ }
- $event->setRedirectParams(Array('opener' => 'u'), true);
- $this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
- // all temp tables are deleted here => all after hooks should think, that it's live mode now
- $this->Application->SetVar($event->Prefix.'_mode', '');
+ $this->SaveLoggedChanges($changes_var_name, $object->ShouldLogChanges());
}
+ else {
+ $event->status = kEvent::erFAIL;
+ }
+
+ $this->clearSelectedIDs($event);
+
+ $event->setRedirectParams(Array ('opener' => 'u'), true);
+ $this->Application->RemoveVar($event->getPrefixSpecial() . '_modified');
+
+ // all temp tables are deleted here => all after hooks should think, that it's live mode now
+ $this->Application->SetVar($event->Prefix . '_mode', '');
}
function SaveLoggedChanges($changes_var_name, $save = true)
@@ -1701,21 +1756,24 @@
* Removes all temp tables and clears selected ids
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnCancelEdit(&$event)
+ protected function OnCancelEdit(&$event)
{
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $temp->CancelEdit();
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+ $temp_handler->CancelEdit();
+
$this->clearSelectedIDs($event);
- $event->setRedirectParams(Array('opener'=>'u'), true);
- $this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
+ $event->setRedirectParams(Array ('opener' => 'u'), true);
+ $this->Application->RemoveVar($event->getPrefixSpecial() . '_modified');
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$this->Application->RemoveVar($changes_var_name);
}
-
/**
* Allows to determine if we are creating new item or editing already created item
*
@@ -1725,10 +1783,9 @@
function isNewItemCreate(&$event)
{
$object =& $event->getObject( Array ('raise_warnings' => 0) );
- return !$object->IsLoaded();
+ /* @var $object kDBItem */
-// $item_id = $this->getPassedID($event);
-// return ($item_id == '') ? true : false;
+ return !$object->isLoaded();
}
/**
@@ -1736,36 +1793,39 @@
* If there is no id, new item is created in temp table
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSave(&$event)
+ protected function OnPreSave(&$event)
{
- //$event->redirect = false;
// if there is no id - it means we need to create an item
- if (is_object($event->MasterEvent)) {
- $event->MasterEvent->setEventParam('IsNew',false);
+ if ( is_object($event->MasterEvent) ) {
+ $event->MasterEvent->setEventParam('IsNew', false);
}
- if ($this->isNewItemCreate($event)) {
+ if ( $this->isNewItemCreate($event) ) {
$event->CallSubEvent('OnPreSaveCreated');
- if (is_object($event->MasterEvent)) {
- $event->MasterEvent->setEventParam('IsNew',true);
+
+ if ( is_object($event->MasterEvent) ) {
+ $event->MasterEvent->setEventParam('IsNew', true);
}
- return;
+
+ return ;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
+ if ( $items_info ) {
foreach ($items_info as $id => $field_values) {
$object->Load($id);
- $object->SetFieldsFromHash($field_values);
- $this->customProcessing($event, 'before');
- if( $object->Update($id) )
- {
+ $object->SetFieldsFromHash($field_values);
+ $this->customProcessing($event, 'before');
+
+ if ( $object->Update($id) ) {
$this->customProcessing($event, 'after');
- $event->status=kEvent::erSUCCESS;
+ $event->status = kEvent::erSUCCESS;
}
else {
$event->status = kEvent::erFAIL;
@@ -1777,7 +1837,7 @@
}
/**
- * [HOOK] Saves subitem
+ * [HOOK] Saves sub-item
*
* @param kEvent $event
*/
@@ -1851,21 +1911,26 @@
* done in OnPreSaveCreated
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreCreate(&$event)
+ protected function OnPreCreate(&$event)
{
$this->setTempWindowID($event);
$this->clearSelectedIDs($event);
$this->Application->SetVar('m_lang', $this->Application->GetDefaultLanguageId());
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
- $temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
- $temp->PrepareEdit();
+ $temp_handler =& $this->Application->recallObject($event->Prefix . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+ $temp_handler->PrepareEdit();
+
$object->setID(0);
- $this->Application->SetVar($event->getPrefixSpecial().'_id', 0);
- $this->Application->SetVar($event->getPrefixSpecial().'_PreCreate', 1);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_PreCreate', 1);
$changes_var_name = $this->Prefix . '_changes_' . $this->Application->GetTopmostWid($this->Prefix);
$this->Application->RemoveVar($changes_var_name);
@@ -1875,74 +1940,83 @@
/**
* Creates a new item in temp table and
- * stores item id in App vars and Session on succsess
+ * stores item id in App vars and Session on success
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnPreSaveCreated(&$event)
+ protected function OnPreSaveCreated(&$event)
{
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if($items_info) $field_values = array_shift($items_info);
-
$object =& $event->getObject( Array('skip_autoload' => true) );
- $object->SetFieldsFromHash($field_values);
+ /* @var $object kDBItem */
+ $object->SetFieldsFromHash( $this->getSubmittedFields($event) );
+
$this->customProcessing($event, 'before');
- if( $object->Create() )
- {
+ if ( $object->Create() ) {
$this->customProcessing($event, 'after');
- $event->SetRedirectParam($event->getPrefixSpecial(true).'_id', $object->GetId());
- $event->status=kEvent::erSUCCESS;
+ $event->SetRedirectParam($event->getPrefixSpecial(true) . '_id', $object->GetID());
}
- else
- {
- $event->status=kEvent::erFAIL;
- $event->redirect=false;
+ else {
+ $event->status = kEvent::erFAIL;
+ $event->redirect = false;
$object->setID(0);
}
-
}
- function OnReset(&$event)
+ /**
+ * Reloads form to loose all changes made during item editing
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnReset(&$event)
{
//do nothing - should reset :)
- if ($this->isNewItemCreate($event)) {
+ if ( $this->isNewItemCreate($event) ) {
// just reset id to 0 in case it was create
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
$object->setID(0);
- $this->Application->SetVar($event->getPrefixSpecial().'_id',0);
+ $this->Application->SetVar($event->getPrefixSpecial() . '_id', 0);
}
}
/**
- * Apply same processing to each item beeing selected in grid
+ * Apply same processing to each item being selected in grid
*
* @param kEvent $event
- * @access private
+ * @return void
+ * @access protected
*/
- function iterateItems(&$event)
+ protected function iterateItems(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object =& $event->getObject(Array ('skip_autoload' => true));
+ /* @var $object kDBItem */
+
$ids = $this->StoreSelectedIDs($event);
- if ($ids) {
- $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') );
- $order_field = $this->Application->getUnitOption($event->Prefix,'OrderField');
+ if ( $ids ) {
+ $status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
+ $order_field = $this->Application->getUnitOption($event->Prefix, 'OrderField');
- if (!$order_field) {
+ if ( !$order_field ) {
$order_field = 'Priority';
}
foreach ($ids as $id) {
$object->Load($id);
- switch ($event->Name) {
+ switch ( $event->Name ) {
case 'OnMassApprove':
$object->SetDBField($status_field, 1);
break;
@@ -1960,7 +2034,7 @@
break;
}
- if ($object->Update()) {
+ if ( $object->Update() ) {
$event->status = kEvent::erSUCCESS;
}
else {
@@ -1981,19 +2055,18 @@
*/
function OnMassClone(&$event)
{
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) {
$event->status = kEvent::erFAIL;
- return;
+ return ;
}
- $event->status = kEvent::erSUCCESS;
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
-
$ids = $this->StoreSelectedIDs($event);
- if ($ids) {
- $temp->CloneItems($event->Prefix, $event->Special, $ids);
+ if ( $ids ) {
+ $temp_handler->CloneItems($event->Prefix, $event->Special, $ids);
}
$this->clearSelectedIDs($event);
@@ -2009,13 +2082,22 @@
return false;
}
- function OnPreSavePopup(&$event)
+ /**
+ * Saves data from editing form to database without checking required fields
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnPreSavePopup(&$event)
{
$object =& $event->getObject();
+ /* @var $object kDBItem */
+
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
- $this->finalizePopup($event);
+ $event->SetRedirectParam('opener', 'u');
}
@@ -2036,35 +2118,38 @@
}
/**
- * Occurse after loading item, 'id' parameter
+ * Occurs after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemLoad(&$event)
+ protected function OnAfterItemLoad(&$event)
{
}
/**
- * Occurse before creating item
+ * Occurs before creating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemCreate(&$event)
+ protected function OnBeforeItemCreate(&$event)
{
}
/**
- * Occurse after creating item
+ * Occurs after creating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnAfterItemCreate(&$event)
+ protected function OnAfterItemCreate(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
@@ -2075,18 +2160,19 @@
}
/**
- * Occurse before updating item
+ * Occurs before updating item
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
*/
- function OnBeforeItemUpdate(&$event)
+ protected function OnBeforeItemUpdate(&$event)
{
}
/**
- * Occurse after updating item
+ * Occurs after updating item
*
* @param kEvent $event
* @access public
@@ -2157,13 +2243,15 @@
}
/**
- * Occures before an item is deleted from live table when copying from temp
+ * Occurs before an item is deleted from live table when copying from temp
* (temp handler deleted all items from live and then copy over all items from temp)
* Id of item being deleted is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeDeleteFromLive(&$event)
+ protected function OnBeforeDeleteFromLive(&$event)
{
}
@@ -2227,13 +2315,14 @@
}
/**
- * Occures before an item is cloneded
- * Id of ORIGINAL item is passed as event' 'id' param
- * Do not call object' Update method in this event, just set needed fields!
+ * Occurs before an item has been cloned
+ * Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnBeforeClone(&$event)
+ protected function OnBeforeClone(&$event)
{
}
@@ -2265,9 +2354,11 @@
* passed
*
* @param kEvent $event
- * @access public
+ * @return void
+ * @access protected
+ * @deprecated
*/
- function finalizePopup(&$event)
+ protected function finalizePopup(&$event)
{
$event->SetRedirectParam('opener', 'u');
}
@@ -2320,20 +2411,31 @@
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
}
- function OnSetFilterPattern(&$event)
+ /**
+ * Sets view filter based on request
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnSetFilterPattern(&$event)
{
- $filters = $this->Application->GetVar($event->getPrefixSpecial(true).'_filters');
- if (!$filters) return ;
+ $filters = $this->Application->GetVar($event->getPrefixSpecial(true) . '_filters');
+ if ( !$filters ) {
+ return;
+ }
- $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
- $view_filter = $view_filter ? unserialize($view_filter) : Array();
+ $view_filter = $this->Application->RecallVar($event->getPrefixSpecial() . '_view_filter');
+ $view_filter = $view_filter ? unserialize($view_filter) : Array ();
$filters = explode(',', $filters);
+
foreach ($filters as $a_filter) {
list($id, $value) = explode('=', $a_filter);
$view_filter[$id] = $value;
}
- $this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
+
+ $this->Application->StoreVar($event->getPrefixSpecial() . '_view_filter', serialize($view_filter));
$event->redirect = false;
}
@@ -2369,31 +2471,40 @@
* Enter description here...
*
* @param kEvent $event
+ * @access protected
*/
- function OnPreSaveAndOpenTranslator(&$event)
+ protected function OnPreSaveAndOpenTranslator(&$event)
{
$this->Application->SetVar('allow_translation', true);
+
$object =& $event->getObject();
+ /* @var $object kDBItem */
+
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
- if ($event->status == kEvent::erSUCCESS) {
+ if ( $event->status == kEvent::erSUCCESS ) {
+ $resource_id = $this->Application->GetVar('translator_resource_id');
- $resource_id = $this->Application->GetVar('translator_resource_id');
- if ($resource_id) {
+ if ( $resource_id ) {
$t_prefixes = explode(',', $this->Application->GetVar('translator_prefixes'));
- $cdata =& $this->Application->recallObject($t_prefixes[1], null, Array('skip_autoload' => true));
+ $cdata =& $this->Application->recallObject($t_prefixes[1], null, Array ('skip_autoload' => true));
+ /* @var $cdata kDBItem */
+
$cdata->Load($resource_id, 'ResourceId');
- if (!$cdata->isLoaded()) {
+
+ if ( !$cdata->isLoaded() ) {
$cdata->SetDBField('ResourceId', $resource_id);
$cdata->Create();
}
- $this->Application->SetVar($cdata->getPrefixSpecial().'_id', $cdata->GetID());
+
+ $this->Application->SetVar($cdata->getPrefixSpecial() . '_id', $cdata->GetID());
}
$event->redirect = $this->Application->GetVar('translator_t');
- $event->setRedirectParams(Array (
+
+ $redirect_params = Array (
'pass' => 'all,trans,' . $this->Application->GetVar('translator_prefixes'),
'opener' => 's',
$event->getPrefixSpecial(true) . '_id' => $object->GetID(),
@@ -2401,11 +2512,13 @@
'trans_prefix' => $this->Application->GetVar('translator_prefixes'),
'trans_field' => $this->Application->GetVar('translator_field'),
'trans_multi_line' => $this->Application->GetVar('translator_multi_line'),
- ), true);
+ );
+ $event->setRedirectParams($redirect_params, true);
+
// 1. SAVE LAST TEMPLATE TO SESSION (really needed here, because of tweaky redirect)
$last_template = $this->Application->RecallVar('last_template');
- preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets);
+ preg_match('/index4\.php\|' . $this->Application->GetSID() . '-(.*):/U', $last_template, $rets);
$this->Application->StoreVar('return_template', $this->Application->GetVar('t'));
}
}
@@ -2418,9 +2531,9 @@
function RemoveRequiredFields(&$object)
{
// making all field non-required to achieve successful presave
- $fields = $object->getFields();
+ $fields = array_keys( $object->getFields() );
- foreach ($fields as $field => $options) {
+ foreach ($fields as $field) {
if ( $object->isRequired($field) ) {
$object->setRequired($field, false);
}
@@ -2434,17 +2547,20 @@
*/
function OnSelectUser(&$event)
{
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
$items_info = $this->Application->GetVar('u');
- if ($items_info) {
+
+ if ( $items_info ) {
$user_id = array_shift( array_keys($items_info) );
- $object =& $event->getObject();
$this->RemoveRequiredFields($object);
$is_new = !$object->isLoaded();
- $is_main = substr($this->Application->GetVar($event->Prefix.'_mode'), 0, 1) == 't';
+ $is_main = substr($this->Application->GetVar($event->Prefix . '_mode'), 0, 1) == 't';
- if ($is_new) {
+ if ( $is_new ) {
$new_event = $is_main ? 'OnPreCreate' : 'OnNew';
$event->CallSubEvent($new_event);
$event->redirect = true;
@@ -2452,7 +2568,7 @@
$object->SetDBField($this->Application->RecallVar('dst_field'), $user_id);
- if ($is_new) {
+ if ( $is_new ) {
$object->Create();
}
else {
@@ -2460,8 +2576,8 @@
}
}
- $event->SetRedirectParam($event->getPrefixSpecial().'_id', $object->GetID());
- $this->finalizePopup($event);
+ $event->SetRedirectParam($event->getPrefixSpecial() . '_id', $object->GetID());
+ $event->SetRedirectParam('opener', 'u');
}
@@ -2502,18 +2618,18 @@
}
/**
- * Apply some special processing to
- * object beeing recalled before using
- * it in other events that call prepareObject
+ * Apply some special processing to object being
+ * recalled before using it in other events that
+ * call prepareObject
*
- * @param Object $object
+ * @param kDBItem|kDBList $object
* @param kEvent $event
+ * @return void
* @access protected
*/
- function prepareObject(&$object, &$event)
+ protected function prepareObject(&$object, &$event)
{
- if ($event->Special == 'export' || $event->Special == 'import')
- {
+ if ( $event->Special == 'export' || $event->Special == 'import' ) {
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
@@ -2564,34 +2680,47 @@
}
- function OnDeleteExportPreset(&$event)
+ /**
+ * Deletes export preset
+ *
+ * @param kEvent $event
+ * @return void
+ * @access protected
+ */
+ protected function OnDeleteExportPreset(&$event)
{
- $object =& $event->GetObject();
+ $field_values = $this->getSubmittedFields($event);
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if($items_info)
- {
- list($id,$field_values) = each($items_info);
- $preset_key = $field_values['ExportPresets'];
+ if ( !$field_values ) {
+ return ;
+ }
- $export_settings = $this->Application->RecallPersistentVar('export_settings');
- if (!$export_settings) return ;
- $export_settings = unserialize($export_settings);
- if (!isset($export_settings[$event->Prefix])) return ;
+ $preset_key = $field_values['ExportPresets'];
+ $export_settings = $this->Application->RecallPersistentVar('export_settings');
- $to_delete = '';
- $export_presets = array(''=>'');
- foreach ($export_settings[$event->Prefix] as $key => $val) {
- if (implode('|', $val['ExportColumns']) == $preset_key) {
- $to_delete = $key;
- break;
- }
+ if ( !$export_settings ) {
+ return ;
+ }
+
+ $export_settings = unserialize($export_settings);
+
+ if ( !isset($export_settings[$event->Prefix]) ) {
+ return ;
+ }
+
+ $to_delete = '';
+
+ foreach ($export_settings[$event->Prefix] as $key => $val) {
+ if ( implode('|', $val['ExportColumns']) == $preset_key ) {
+ $to_delete = $key;
+ break;
}
- if ($to_delete) {
- unset($export_settings[$event->Prefix][$to_delete]);
- $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
- }
}
+
+ if ( $to_delete ) {
+ unset($export_settings[$event->Prefix][$to_delete]);
+ $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
+ }
}
/**
@@ -2620,8 +2749,10 @@
* Used to save files uploaded via swfuploader
*
* @param kEvent $event
+ * @return void
+ * @access protected
*/
- function OnUploadFile(&$event)
+ protected function OnUploadFile(&$event)
{
$event->status = kEvent::erSTOP;
// define('DBG_SKIP_REPORTING', 0);
@@ -2630,7 +2761,7 @@
if (!$this->Application->HttpQuery->Post) {
// Variables {field, id, flashsid} are always submitted through POST!
// When file size is larger, then "upload_max_filesize" (in php.ini),
- // then theese variables also are not submitted -> handle such case.
+ // then these variables also are not submitted -> handle such case.
header('HTTP/1.0 413 File size exceeds allowed limit');
echo $default_msg;
return ;
@@ -2902,13 +3033,13 @@
{
$event->status = kEvent::erSTOP;
- $lang =& $this->Application->recallObject('lang.current');
-// header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
+ /*$lang =& $this->Application->recallObject('lang.current');
+ header('Content-type: text/xml; charset=' . $lang->GetDBField('Charset'));*/
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
+
$picker_helper->PreparePicker($event->getPrefixSpecial(), $this->Application->GetVar('grid_name'));
-
$picker_helper->SaveWidths($event->getPrefixSpecial(), $this->Application->GetVar('widths'));
echo 'OK';
Index: kernel/db/db_tag_processor.php
===================================================================
--- kernel/db/db_tag_processor.php (revision 14590)
+++ kernel/db/db_tag_processor.php (working copy)
@@ -595,18 +595,27 @@
*
* @param kDBList $object
* @param Array $block_params
+ * @return void
+ * @access protected
*/
- function PrepareListElementParams(&$object, &$block_params)
+ protected function PrepareListElementParams(&$object, &$block_params)
{
// $fields_hash =& $object->getCurrentRecord();
}
- function MoreLink($params)
+ /**
+ * Renders given block name, when there there is more data in list, then are displayed right now
+ *
+ * @param Array $params
+ * @return string
+ * @access protected
+ */
+ protected function MoreLink($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
- if ($per_page !== false) {
+ if ( $per_page !== false ) {
$params['per_page'] = $per_page;
}
@@ -620,13 +629,13 @@
$has_next_page = $list->GetPerPage() < $list->GetRecordsCount();
}
- if ($has_next_page) {
- $block_params = Array (
- 'name' => $this->SelectParam($params, 'render_as,block'),
- );
+ if ( $has_next_page ) {
+ $block_params = Array ('name' => $this->SelectParam($params, 'render_as,block'));
return $this->Application->ParseBlock($block_params);
}
+
+ return '';
}
function PageLink($params)
@@ -755,12 +764,19 @@
return $iso;
}
+ /**
+ * Convert primary currency to selected (if they are the same, converter will just return)
+ *
+ * @param float $value
+ * @param string $iso
+ * @return float
+ */
function ConvertCurrency($value, $iso)
{
$converter =& $this->Application->recallObject('kCurrencyRates');
- // convery primary currency to selected (if they are the same, converter will just return)
- $value = $converter->Convert($value, 'PRIMARY', $iso);
- return $value;
+ /* @var $converter kCurrencyRates */
+
+ return $converter->Convert($value, 'PRIMARY', $iso);
}
function AddCurrencySymbol($value, $iso)
@@ -973,10 +989,14 @@
// - You may ignore this notice if submitted data really has a validation error'; - trigger_error(trim($error_msg), E_USER_NOTICE); - $this->Application->Debugger->dumpVars($this->FieldErrors); - } - - if ($global_res) { + if ( $this->validator->Validate() ) { // no validation errors $this->raiseEvent('OnAfterItemValidate'); + + return true; } - return $global_res; + return false; } /** - * Check field value by user-defined alghoritm - * - * @param string $field field name - * @param Array $params field options from config - * @return bool - */ - protected function CustomValidation($field, $params) - { - return true; - } - - /** * Check if item has errors * * @param Array $skip_fields fields to skip during error checking @@ -736,48 +681,11 @@ */ public function HasErrors($skip_fields = Array ()) { - $global_res = false; - - foreach ($this->Fields as $field => $field_params) { - // If Formatter has set some error messages during values parsing - if ( !( in_array($field, $skip_fields) ) && - isset($this->FieldErrors[$field]['pseudo']) && $this->FieldErrors[$field] != '') { - $global_res = true; - } + if ( !is_object($this->validator) ) { + return false; } - return $global_res; - } - /** - * Check if value in field matches field type specified in config - * - * @param string $field field name - * @param Array $params field options from config - * @return bool - */ - protected function ValidateType($field, $params) - { - $res = true; - $val = $this->FieldValues[$field]; - if ( $val != '' && - isset($params['type']) && - preg_match("#int|integer|double|float|real|numeric|string#", $params['type']) - ) { - if ($params['type'] == 'numeric') { - trigger_error('Invalid field type '.$params['type'].' (in ValidateType method), please use float instead', E_USER_NOTICE); - $params['type'] = 'float'; - } - $res = is_numeric($val); - if ($params['type']=='string' || $res) { - $f = 'is_'.$params['type']; - settype($val, $params['type']); - $res = $f($val) && ($val == $this->FieldValues[$field]); - } - if (!$res) { - $this->SetError($field, 'bad_type', null, Array ($params['type'])); - } - } - return $res; + return $this->validator->HasErrors($skip_fields); } /** @@ -787,125 +695,14 @@ * @param Array $params field options from config * @return bool * @access public + * @todo Find a way to get rid of direct call from kMultiLanguage::UpdateMasterFields method */ public function ValidateRequired($field, $params) { - $res = true; - if (isset($params['required']) && $params['required']) { - $check_value = $this->FieldValues[$field]; - if ($this->Application->ConfigValue('TrimRequiredFields')) { - $check_value = trim($check_value); - } - $res = ((string)$check_value != ''); - } - - if (!$res) { - $this->SetError($field, 'required'); - } - - return $res; + return $this->validator->ValidateRequired($field, $params); } /** - * Validates that current record has unique field combination among other table records - * - * @param string $field field name - * @param Array $params field options from config - * @return bool - * @access private - */ - protected function ValidateUnique($field, $params) - { - $res = true; - $unique_fields = getArrayValue($params,'unique'); - if($unique_fields !== false) - { - $where = Array(); - array_push($unique_fields,$field); - foreach($unique_fields as $unique_field) - { - // if field is not empty or if it is required - we add where condition - if ((string)$this->GetDBField($unique_field) != '' || (isset($this->Fields[$unique_field]['required']) && $this->Fields[$unique_field]['required'])) { - $where[] = '`'.$unique_field.'` = '.$this->Conn->qstr( $this->GetDBField($unique_field) ); - } - else { - // not good if we check by less fields than indicated - return true; - } - } - // This can ONLY happen if all unique fields are empty and not required. - // In such case we return true, because if unique field is not required there may be numerous empty values -// if (!$where) return true; - - $sql = 'SELECT COUNT(*) FROM %s WHERE ('.implode(') AND (',$where).') AND ('.$this->IDField.' <> '.(int)$this->ID.')'; - - $res_temp = $this->Conn->GetOne( str_replace('%s', $this->TableName, $sql) ); - - $current_table_only = getArrayValue($params, 'current_table_only'); // check unique record only in current table - $res_live = $current_table_only ? 0 : $this->Conn->GetOne( str_replace('%s', $this->Application->GetLiveName($this->TableName), $sql) ); - - $res = ($res_temp == 0) && ($res_live == 0); - - if (!$res) { - $this->SetError($field, 'unique'); - } - } - return $res; - } - - /** - * Check if field value is in range specified in config - * - * @param string $field field name - * @param Array $params field options from config - * @return bool - * @access private - */ - protected function ValidateRange($field, $params) - { - $res = true; - $val = $this->FieldValues[$field]; - - if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) { - if ( isset($params['max_value_inc'])) { - $res = $res && $val <= $params['max_value_inc']; - $max_val = $params['max_value_inc'].' (inclusive)'; - } - if ( isset($params['min_value_inc'])) { - $res = $res && $val >= $params['min_value_inc']; - $min_val = $params['min_value_inc'].' (inclusive)'; - } - if ( isset($params['max_value_exc'])) { - $res = $res && $val < $params['max_value_exc']; - $max_val = $params['max_value_exc'].' (exclusive)'; - } - if ( isset($params['min_value_exc'])) { - $res = $res && $val > $params['min_value_exc']; - $min_val = $params['min_value_exc'].' (exclusive)'; - } - } - if (!$res) { - if ( !isset($min_val) ) $min_val = '-∞'; - if ( !isset($max_val) ) $max_val = '∞'; - - $this->SetError($field, 'value_out_of_range', null, Array ($min_val, $max_val)); - return $res; - } - if ( isset($params['max_len'])) { - $res = $res && mb_strlen($val) <= $params['max_len']; - } - if ( isset($params['min_len'])) { - $res = $res && mb_strlen($val) >= $params['min_len']; - } - if (!$res) { - $error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len'), mb_strlen($val)); - $this->SetError($field, 'length_out_of_range', null, $error_params); - return $res; - } - return $res; - } - - /** * Return error message for field * * @param string $field @@ -914,33 +711,11 @@ */ public function GetErrorMsg($field, $force_escape = null) { - $err = $this->GetErrorPseudo($field); - - if (!$err) { + if ( !is_object($this->validator) ) { return ''; } - // if special error msg defined in config - if( isset($this->Fields[$field]['error_msgs'][$err]) ) - { - $msg = $this->Fields[$field]['error_msgs'][$err]; - } - else //fall back to defaults - { - if( !isset($this->ErrorMsgs[$err]) ) { - trigger_error('No user message is defined for pseudo error '.$err.' ', E_USER_WARNING); - return $err; //return the pseudo itself - } - $msg = $this->ErrorMsgs[$err]; - } - $msg = $this->Application->ReplaceLanguageTags($msg, $force_escape); - - if ( isset($this->FieldErrors[$field]['params']) ) - { - return vsprintf($msg, $this->FieldErrors[$field]['params']); - } - - return $msg; + return $this->validator->GetErrorMsg($field, $force_escape); } /** @@ -951,16 +726,21 @@ */ public function GetFieldErrors() { - return $this->FieldErrors; + if ( !is_object($this->validator) ) { + return Array (); + } + + return $this->validator->GetFieldErrors(); } /** - * Creates a record in the database table with current item' values - * - * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE! - * @access public - * @return bool - */ + * Creates a record in the database table with current item' values + * + * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE! + * @param bool $system_create + * @return bool + * @access public + */ public function Create($force_id = false, $system_create = false) { if (!$this->raiseEvent('OnBeforeItemCreate')) { @@ -989,7 +769,7 @@ if (is_null($field_value)) { if (array_key_exists('not_null', $this->Fields[$field_name]) && $this->Fields[$field_name]['not_null']) { // "kFormatter::Parse" methods converts empty values to NULL and for - // not-null fields they are replaced with default value here + // not-null fields they are replaced with default value here $values_sql .= $this->Conn->qstr($this->Fields[$field_name]['default']); } else { @@ -1048,18 +828,19 @@ } /** - * Deletes the record from databse - * - * @access public - * @return bool - */ + * Deletes the record from database + * + * @param int $id + * @return bool + * @access public + */ public function Delete($id = null) { - if (isset($id)) { + if ( isset($id) ) { $this->setID($id); } - if (!$this->raiseEvent('OnBeforeItemDelete')) { + if ( !$this->raiseEvent('OnBeforeItemDelete') ) { return false; } @@ -1069,14 +850,14 @@ $ret = $this->Conn->ChangeQuery($sql); $affected_rows = $this->Conn->getAffectedRows(); - if ($affected_rows > 0) { + if ( $affected_rows > 0 ) { $this->setModifiedFlag(ChangeLog::DELETE); // will change affected rows, so get it before this line // something was actually deleted $this->raiseEvent('OnAfterItemDelete'); } - if (!$this->IsTempTable()) { + if ( !$this->IsTempTable() ) { $this->Application->resetCounters($this->TableName); } @@ -1089,10 +870,10 @@ // master field is set only for CURRENT language $formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false; - if (($formatter == 'kMultiLanguage') && array_key_exists('master_field', $options) && array_key_exists('error_field', $options)) { + if ( ($formatter == 'kMultiLanguage') && isset($options['master_field']) && isset($options['error_field']) ) { // MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode, - // we display ML fields directly so we set it back to itself, otherwise error will not be displayed - unset($this->Fields[$field]['error_field']); + // we display ML fields directly so we set it back to itself, otherwise error won't be displayed + unset( $this->Fields[$field]['error_field'] ); } } } @@ -1279,7 +1060,7 @@ protected function LogChanges($main_prefix, $mode) { - if (!$mode) { + if ( !$mode ) { return ; } @@ -1295,7 +1076,7 @@ 'Action' => $mode, ); - if ($this->Prefix == $main_prefix) { + if ( $this->Prefix == $main_prefix ) { // main item $fields_hash['MasterId'] = $this->GetID(); $fields_hash['ParentPrefix'] = Array ($main_prefix); @@ -1304,10 +1085,11 @@ else { // sub item // collect foreign key values (for serial reset) - $foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey'); + $foreign_keys = $this->Application->getUnitOption($this->Prefix, 'ForeignKey', Array ()); $dependent_fields = $fields_hash['ParentId'] = $fields_hash['ParentPrefix'] = Array (); + /* @var $foreign_keys Array */ - if (is_array($foreign_keys)) { + if ( is_array($foreign_keys) ) { foreach ($foreign_keys as $prefix => $field_name) { $dependent_fields[$field_name] = $this->GetDBField($field_name); $fields_hash['ParentPrefix'][] = $prefix; @@ -1323,18 +1105,18 @@ $fields_hash['DependentFields'] = $dependent_fields; - // works only, when main item is present in url, when subitem is changed + // works only, when main item is present in url, when sub-item is changed $master_id = $this->Application->GetVar($main_prefix . '_id'); - if ($master_id === false) { - // works in case of we are not editing topmost item, when subitem is created/updated/deleted + if ( $master_id === false ) { + // works in case of we are not editing topmost item, when sub-item is created/updated/deleted $master_id = $this->getParentId('auto', true); } $fields_hash['MasterId'] = $master_id; } - switch ($mode) { + switch ( $mode ) { case ChangeLog::UPDATE: $to_save = array_merge($this->GetTitleField(), $this->GetChangedFields()); break; @@ -1346,6 +1128,10 @@ case ChangeLog::DELETE: $to_save = array_merge($this->GetTitleField(), $this->GetRealFields()); break; + + default: + $to_save = Array (); + break; } $fields_hash['Changes'] = serialize($to_save); @@ -1453,22 +1239,7 @@ */ public function GetRealFields() { - if (function_exists('array_diff_key')) { - $db_fields = array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields); - } - else { - $db_fields = Array(); - - foreach ($this->FieldValues as $key => $value) { - if (array_key_exists($key, $this->VirtualFields) || array_key_exists($key, $this->CalculatedFields)) { - continue; - } - - $db_fields[$key] = $value; - } - } - - return $db_fields; + return array_diff_key($this->FieldValues, $this->VirtualFields, $this->CalculatedFields); } /** @@ -1542,22 +1313,37 @@ /** * Sets new required flag to field * - * @param string $field + * @param mixed $fields * @param bool $is_required */ - public function setRequired($field, $is_required = true) + public function setRequired($fields, $is_required = true) { - $this->Fields[$field]['required'] = $is_required; + if ( !is_array($fields) ) { + $fields = explode(',', $fields); + } + + foreach ($fields as $field) { + $this->Fields[$field]['required'] = $is_required; + } } + /** + * Removes all data from an object + * + * @param int $new_id + * @return bool + * @access public + */ public function Clear($new_id = null) { $this->Loaded = false; - $this->FieldValues = Array(); - $this->OriginalFieldValues = Array (); + $this->FieldValues = $this->OriginalFieldValues = Array (); $this->SetDefaultValues(); // will wear off kDBItem::setID effect, so set it later - $this->FieldErrors = Array(); + if ( is_object($this->validator) ) { + $this->validator->reset(); + } + $this->setID($new_id); return $this->Loaded; @@ -1570,13 +1356,13 @@ protected function saveCustomFields() { - if (!$this->customFields || $this->inCloning) { + if ( !$this->customFields || $this->inCloning ) { return true; } $cdata_key = rtrim($this->Prefix . '-cdata.' . $this->Special, '.'); - $cdata =& $this->Application->recallObject($cdata_key, null, Array('skip_autoload' => true)); + $cdata =& $this->Application->recallObject($cdata_key, null, Array ('skip_autoload' => true, 'populate_ml_fields' => true)); /* @var $cdata kDBItem */ $resource_id = $this->GetDBField('ResourceId'); @@ -1586,25 +1372,9 @@ $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); /* @var $ml_formatter kMultiLanguage */ - $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper'); - /* @var $ml_helper kMultiLanguageHelper */ - foreach ($this->customFields as $custom_id => $custom_name) { - $field_options = $cdata->GetFieldOptions('cust_' . $custom_id); - $force_primary = isset($field_options['force_primary']) && $field_options['force_primary']; - - if ($force_primary) { - $cdata->SetDBField($ml_formatter->LangFieldName('cust_' . $custom_id, true), $this->GetDBField('cust_' . $custom_name)); - } - else { - for ($language_id = 1; $language_id <= $ml_helper->languageCount; $language_id++) { - if (!$ml_helper->LanguageFound($language_id)) { - continue; - } - - $cdata->SetDBField('l' . $language_id . '_cust_' . $custom_id, $this->GetDBField('l' . $language_id . '_cust_' . $custom_name)); - } - } + $force_primary = $cdata->GetFieldOption('cust_' . $custom_id, 'force_primary'); + $cdata->SetDBField($ml_formatter->LangFieldName('cust_' . $custom_id, $force_primary), $this->GetDBField('cust_' . $custom_name)); } return $cdata->isLoaded() ? $cdata->Update() : $cdata->Create(); Index: kernel/kbase.php =================================================================== --- kernel/kbase.php (revision 14590) +++ kernel/kbase.php (working copy) @@ -165,6 +165,20 @@ public $TableName = ''; /** + * Form name, used for validation + * + * @var string + */ + protected $formName = ''; + + /** + * Final form configuration + * + * @var Array + */ + protected $formConfig = Array (); + + /** * SELECT, FROM, JOIN parts of SELECT query (no filters, no limit, no ordering) * * @var string @@ -409,9 +423,10 @@ * - field definitions (including field modifiers, formatters, default values) * * @param bool $populate_ml_fields create all ml fields from db in config or not + * @param string $form_name form name for validation * @access public */ - public function Configure($populate_ml_fields = null) + public function Configure($populate_ml_fields = null, $form_name = null) { if ( isset($populate_ml_fields) ) { $this->populateMultiLangFields = $populate_ml_fields; @@ -420,6 +435,7 @@ $this->IDField = $this->Application->getUnitOption($this->Prefix, 'IDField'); $this->TableName = $this->Application->getUnitOption($this->Prefix, 'TableName'); + $this->initForm($form_name); $this->defineFields(); $this->ApplyFieldModifiers(); // should be called only after all fields definitions been set @@ -432,6 +448,29 @@ } /** + * Adjusts object accoding to given form name + * + */ + protected function initForm($form_name = null) + { + $forms = $this->Application->getUnitOption($this->Prefix, 'Forms', Array ()); + + $this->formName = $form_name; + $this->formConfig = isset($forms['default']) ? $forms['default'] : Array (); + + if ( !$this->formName ) { + return ; + } + + if ( !isset($forms[$this->formName]) ) { + trigger_error('Form "' . $this->formName . '" isn\'t declared in "' . $this->Prefix . '" unit config.', E_USER_NOTICE); + } + else { + $this->formConfig = kUtil::array_merge_recursive($this->formConfig, $forms[$this->formName]); + } + } + + /** * Add field definitions from all possible sources * Used field sources: database fields, custom fields, virtual fields, calculated fields, aggregated calculated fields * @@ -439,19 +478,48 @@ */ protected function defineFields() { - $this->Fields = $this->Application->getUnitOption($this->Prefix, 'Fields', Array ()); - $this->customFields = $this->Application->getUnitOption($this->Prefix, 'CustomFields', Array()); + $this->Fields = $this->getFormOption('Fields', Array ()); + $this->customFields = $this->getFormOption('CustomFields', Array()); - $this->setVirtualFields( $this->Application->getUnitOption($this->Prefix, 'VirtualFields', Array ()) ); + $this->setVirtualFields( $this->getFormOption('VirtualFields', Array ()) ); - $calculated_fields = $this->Application->getUnitOption($this->Prefix, 'CalculatedFields', Array()); + $calculated_fields = $this->getFormOption('CalculatedFields', Array()); $this->CalculatedFields = $this->getFieldsBySpecial($calculated_fields); - $aggregated_calculated_fields = $this->Application->getUnitOption($this->Prefix, 'AggregatedCalculatedFields', Array()); + $aggregated_calculated_fields = $this->getFormOption('AggregatedCalculatedFields', Array()); $this->AggregatedCalculatedFields = $this->getFieldsBySpecial($aggregated_calculated_fields); } /** + * Returns form name, used for validation + * + * @return string + */ + public function getFormName() + { + return $this->formName; + } + + /** + * Reads unit (specified by $prefix) option specified by $option and applies form change to it + * + * @param string $option + * @param mixed $default + * @return string + * @access public + */ + public function getFormOption($option, $default = false) + { + $ret = $this->Application->getUnitOption($this->Prefix, $option, $default); + + if ( isset($this->formConfig[$option]) ) { + $ret = kUtil::array_merge_recursive($ret, $this->formConfig[$option]); + } + + return $ret; + } + + /** * Only exteracts fields, that match current object Special * * @param Array $fields @@ -537,38 +605,41 @@ /** * Override field options with ones defined in submit via "field_modfiers" array (common for all prefixes) * + * @param Array $field_modifiers + * @return void + * @access public * @author Alex - * @access public */ public function ApplyFieldModifiers($field_modifiers = null) { - $allowed_modifiers = Array('required', 'multiple'); + $allowed_modifiers = Array ('required', 'multiple'); - if ($this->Application->isAdminUser) { + if ( $this->Application->isAdminUser ) { // can change upload dir on the fly (admin only!) $allowed_modifiers[] = 'upload_dir'; } - if (!isset($field_modifiers)) { + if ( !isset($field_modifiers) ) { $field_modifiers = $this->Application->GetVar('field_modifiers'); - if (!$field_modifiers) { + if ( !$field_modifiers ) { // no field modifiers - return false; + return ; } $field_modifiers = getArrayValue($field_modifiers, $this->getPrefixSpecial()); } - if (!$field_modifiers) { + if ( !$field_modifiers ) { // no field modifiers for current prefix_special - return false; + return ; } - foreach ($field_modifiers as $field => $field_options) - { - foreach ($field_options as $option_name => $option_value) - { - if ( !in_array(strtolower($option_name), $allowed_modifiers) ) continue; + foreach ($field_modifiers as $field => $field_options) { + foreach ($field_options as $option_name => $option_value) { + if ( !in_array(strtolower($option_name), $allowed_modifiers) ) { + continue; + } + $this->Fields[$field][$option_name] = $option_value; } } @@ -722,13 +793,14 @@ */ public function GetField($name, $format = null) { - $options = $this->GetFieldOptions($name); + $formatter_class = $this->GetFieldOption($name, 'formatter'); - if (array_key_exists('formatter', $options)) { - $formatter_class = $options['formatter']; + if ( $formatter_class ) { $value = ($formatter_class == 'kMultiLanguage') && !preg_match('/^l[0-9]+_/', $name) ? '' : $this->GetDBField($name); $formatter =& $this->Application->recallObject($formatter_class); + /* @var $formatter kFormatter */ + return $formatter->Format($value, $name, $this, $format); } @@ -766,16 +838,19 @@ * * @param Array $fields * @access public - * @todo maybe should not be publically accessable + * @todo Maybe should not be publicly accessible */ public function UpdateFormattersSubFields($fields = null) { - if (!is_array($fields)) { + if ( !is_array($fields) ) { $fields = array_keys($this->Fields); } + foreach ($fields as $field) { if ( isset($this->Fields[$field]['formatter']) ) { $formatter =& $this->Application->recallObject($this->Fields[$field]['formatter']); + /* @var $formatter kFormatter */ + $formatter->UpdateSubFields($field, $this->GetDBField($field), $this->Fields[$field], $this); } } Index: kernel/utility/formatters/date_formatter.php =================================================================== --- kernel/utility/formatters/date_formatter.php (revision 14590) +++ kernel/utility/formatters/date_formatter.php (working copy) @@ -124,7 +124,7 @@ // 1. add DATE virtual field $opts = Array('master_field' => $field_name, 'formatter' => 'kDateFormatter', 'format' => $display_format['date'], 'input_format' => $input_format['date']); - $copy_options = Array ('default', 'required', 'use_timezone', 'error_msgs'); + $copy_options = Array ('type', 'default', 'required', 'use_timezone', 'error_msgs'); foreach ($copy_options as $copy_option) { if (array_key_exists($copy_option, $field_options) ) { $opts[$copy_option] = $field_options[$copy_option]; @@ -157,15 +157,27 @@ $object->setVirtualFields($add_fields); } - function UpdateSubFields($field, $value, &$options, &$object) + /** + * Used for split fields like timestamp -> date, time + * Called from DBItem to update sub fields values after loading item + * + * @param string $field + * @param string $value + * @param Array $options + * @param kDBItem $object + * @return void + * @access public + */ + public function UpdateSubFields($field, $value, &$options, &$object) { - if ( $sub_fields = getArrayValue($options, 'sub_fields') ) { - if( isset($value) && $value ) - { - $object->SetDBField( $sub_fields['date'], $value ); - $object->SetDBField( $sub_fields['time'], $value ); - } + $sub_fields = getArrayValue($options, 'sub_fields'); + + if ( !$sub_fields || !isset($value) || !$value ) { + return ; } + + $object->SetDBField($sub_fields['date'], $value); + $object->SetDBField($sub_fields['time'], $value); } /** @@ -210,7 +222,15 @@ } } -//function Format($value, $options, &$errors) + /** + * Formats value of a given field + * + * @param string $value + * @param string $field_name + * @param kDBItem|kDBList $object + * @param string $format + * @return string + */ function Format($value, $field_name, &$object, $format=null) { if ( is_null($value) ) return ''; @@ -331,9 +351,10 @@ * @param mixed $value * @param string $field_name * @param kDBItem $object - * @return string + * @return mixed + * @access public */ - function Parse($value, $field_name, &$object) + public function Parse($value, $field_name, &$object) { $options = $object->GetFieldOptions($field_name); Index: kernel/utility/formatters/formatter.php =================================================================== --- kernel/utility/formatters/formatter.php (revision 14590) +++ kernel/utility/formatters/formatter.php (working copy) @@ -62,39 +62,31 @@ function TypeCast($value, $options) { $ret = true; - if( isset($options['type']) ) - { + + if ( isset($options['type']) ) { $field_type = $options['type']; + if ($field_type == 'numeric') { - trigger_error('Invalid field type '.$field_type.' (in TypeCast method), please use float instead', E_USER_NOTICE); + trigger_error('Invalid field type ' . $field_type . ' (in TypeCast method), please use float instead', E_USER_NOTICE); $field_type = 'float'; } - $type_ok = preg_match('#int|integer|double|float|real|numeric|string#', $field_type); - if ($field_type == 'string') { - if (!$this->Application->isAdmin && isset($options['allow_html']) && $options['allow_html']) { + elseif ( $field_type == 'string' ) { + if ( !$this->Application->isAdmin && isset($options['allow_html']) && $options['allow_html'] ) { // this allows to revert htmlspecialchars call for each field submitted on front-end $value = kUtil::unhtmlentities($value); } + return $value; } - static $comma = null; - static $thousands = null; - if (is_null($comma) || is_null($thousands)) { - $lang =& $this->Application->recallObject('lang.current'); - $comma = $lang->GetDBField('DecimalPoint'); - $thousands = $lang->GetDBField('ThousandSep'); - } + $value = $this->formatNumber($value); + $type_ok = preg_match('#int|integer|double|float|real|numeric|string#', $field_type); - $value = str_replace($thousands, '', $value); - $value = str_replace($comma, '.', $value); + if ( $value != '' && $type_ok ) { + $ret = is_numeric($value); - if ($value != '' && $type_ok) - { - $ret = is_numeric($value); - if($ret) - { - $f = 'is_'.$field_type; + if ($ret) { + $f = 'is_' . $field_type; settype($value, $field_type); $ret = $f($value); } @@ -104,21 +96,62 @@ return $ret ? $value : false; } - function TypeCastArray($src, &$object) + /** + * Formats number, according to regional settings + * + * @param string $number + * @return float + */ + function formatNumber($number) { - $dst = array(); + static $comma = null, $thousands = null; + + if ( !isset($comma) || !isset($thousands) ) { + $lang =& $this->Application->recallObject('lang.current'); + /* @var $lang LanguagesItem */ + + $comma = $lang->GetDBField('DecimalPoint'); + $thousands = $lang->GetDBField('ThousandSep'); + } + + $number = str_replace($thousands, '', $number); + $number = str_replace($comma, '.', $number); + + return $number; + } + + /** + * Applies type casting on each array element + * @param Array $src + * @param kDBItem|kDBList|kDBBase $object + * @return Array + * @access public + */ + public function TypeCastArray($src, &$object) + { + $dst = array (); + foreach ($src as $id => $row) { - $tmp_row = array(); + $tmp_row = array (); foreach ($row as $fld => $value) { $field_options = $object->GetFieldOptions($fld); $tmp_row[$fld] = $this->TypeCast($value, $field_options); } $dst[$id] = $tmp_row; } + return $dst; } -//function Format($value, $options, &$errors) + /** + * Formats value of a given field + * + * @param string $value + * @param string $field_name + * @param kDBItem|kDBList|kDBBase $object + * @param string $format + * @return string + */ function Format($value, $field_name, &$object, $format = null) { if ( is_null($value) ) { @@ -148,6 +181,8 @@ if (preg_match('#int|integer|double|float|real|numeric#', $options['type'])) { $lang =& $this->Application->recallObject('lang.current'); + /* @var $lang LanguagesItem */ + return $lang->formatNumber($value); } elseif ($options['type'] == 'string') { @@ -162,17 +197,19 @@ * * @param mixed $value * @param string $field_name - * @param kDBItem $object + * @param kDBItem|kDBList|kDBBase $object * @return mixed + * @access public */ - function Parse($value, $field_name, &$object) + public function Parse($value, $field_name, &$object) { if ($value == '') { return NULL; } $options = $object->GetFieldOptions($field_name); - $tc_value = $this->TypeCast($value,$options); + $tc_value = $this->TypeCast($value, $options); + if ($tc_value === false) { return $value; // for leaving badly formatted date on the form } @@ -216,12 +253,14 @@ * Used for split fields like timestamp -> date, time * Called from DBItem to update sub fields values after loading item * - * @param unknown_type $field - * @param unknown_type $value - * @param unknown_type $options - * @param unknown_type $object + * @param string $field + * @param string $value + * @param Array $options + * @param kDBItem|kDBList|kDBBase $object + * @return void + * @access public */ - function UpdateSubFields($field, $value, &$options, &$object) + public function UpdateSubFields($field, $value, &$options, &$object) { } @@ -233,26 +272,25 @@ * @param string $field * @param mixed $value * @param Array $options - * @param kDBItem $object + * @param kDBItem|kDBList|kDBBase $object */ function UpdateMasterFields($field, $value, &$options, &$object) { } -/* function GetErrorMsg($pseudo_error, $options) + /** + * Return sample value, that can be entered in this field + * + * @param string $field + * @param Array $options + * @param kDBItem|kDBList|kDBBase $object + * @return string + * @access public + */ + public function GetSample($field, &$options, &$object) { - if ( isset($options['error_msgs'][$pseudo_error]) ) { - return $options['error_msgs'][$pseudo_error]; - } - else { - return $this->ErrorMsgs[$pseudo_error]; - } - }*/ - - function GetSample($field, &$options, &$object) - { - if (isset($options['sample_value'])) return $options['sample_value']; + return isset($options['sample_value']) ? $options['sample_value'] : ''; } } \ No newline at end of file Index: kernel/utility/formatters/multilang_formatter.php =================================================================== --- kernel/utility/formatters/multilang_formatter.php (revision 14590) +++ kernel/utility/formatters/multilang_formatter.php (working copy) @@ -74,7 +74,7 @@ $lang_field_name = $this->LangFieldName($field_name); - //substitude title field + //substitute title field $title_field = $this->Application->getUnitOption($object->Prefix, 'TitleField'); if ($title_field == $field_name) { $this->Application->setUnitOption($object->Prefix, 'TitleField', $lang_field_name); @@ -85,7 +85,7 @@ $fields = $this->Application->getUnitOption($object->Prefix, 'Fields', Array ()); $virtual_fields = $this->Application->getUnitOption($object->Prefix, 'VirtualFields', Array ()); - // substitude real field + // substitute real field if (array_key_exists($field_name, $fields)) { $tmp_field_options = $fields[$field_name]; $tmp_field_options['master_field'] = $field_name; @@ -116,9 +116,10 @@ $object->SetFieldOptions($field_name, $object_fields[$field_name], true); } elseif (array_key_exists($field_name, $virtual_fields)) { - // substitude virtual field - $calculated_fields = $this->Application->getUnitOption($object->Prefix, 'CalculatedFields'); + // substitute virtual field + $calculated_fields = $this->Application->getUnitOption($object->Prefix, 'CalculatedFields', Array ()); $calculated_field_special = array_key_exists($object->Special, $calculated_fields) ? $object->Special : (array_key_exists('', $calculated_fields) ? '' : false); + /* @var $calculated_fields Array */ $tmp_field_options = $virtual_fields[$field_name]; $tmp_field_options['master_field'] = $field_name; @@ -138,7 +139,7 @@ $virtual_fields[$translated_field] = $tmp_field_options; $object->SetFieldOptions($translated_field, $tmp_field_options, true); - // substitude calculated fields associated with given virtual field + // substitute calculated fields associated with given virtual field foreach ($calculated_fields as $special => $special_fields) { if (!array_key_exists($field_name, $special_fields)) { continue; @@ -178,8 +179,10 @@ $object->SetFieldOptions($field_name, $virtual_field_options, true); } - //substitude grid fields - $grids = $this->Application->getUnitOption($object->Prefix, 'Grids', Array()); + // substitute grid fields + $grids = $this->Application->getUnitOption($object->Prefix, 'Grids', Array ()); + /* @var $grids Array */ + foreach ($grids as $name => $grid) { if ( getArrayValue($grid, 'Fields', $field_name) ) { // used by column picker to track column position @@ -207,8 +210,10 @@ } $this->Application->setUnitOption($object->Prefix, 'Grids', $grids); - //substitude default sortings - $sortings = $this->Application->getUnitOption($object->Prefix, 'ListSortings', Array()); + // substitute default sortings + $sortings = $this->Application->getUnitOption($object->Prefix, 'ListSortings', Array ()); + /* @var $sortings Array */ + foreach ($sortings as $special => $the_sortings) { if (isset($the_sortings['ForcedSorting'])) { kUtil::array_rename_key($sortings[$special]['ForcedSorting'], $field_name, $lang_field_name); @@ -219,7 +224,7 @@ } $this->Application->setUnitOption($object->Prefix, 'ListSortings', $sortings); - //TODO: substitude possible language-fields sortings after changing language + // TODO: substitute possible language-fields sortings after changing language $fields[$field_name]['options_processed'] = $field_options['options_processed'] = true; $this->Application->setUnitOption($object->Prefix, 'Fields', $fields); $this->Application->setUnitOption($object->Prefix, 'VirtualFields', $virtual_fields); @@ -250,8 +255,9 @@ $lang = $this->Application->GetVar('m_lang'); $def_lang = $this->Application->GetDefaultLanguageId(); - if (!$this->Application->GetVar('allow_translation') && ($lang != $def_lang) && getArrayValue($options, 'required')) { + if ( !$this->Application->GetVar('allow_translation') && ($lang != $def_lang) && $object->isRequired($field) ) { $def_lang_field = 'l' . $def_lang . '_' . $master_field; + if ( !$object->ValidateRequired($def_lang_field, $options) ) { $object->SetError($master_field, 'primary_lang_required'); @@ -263,11 +269,11 @@ } /** - * Formats field value + * Formats value of a given field * * @param string $value * @param string $field_name - * @param kDBItem $object + * @param kDBItem|kDBList $object * @param string $format * @return string */ @@ -302,9 +308,10 @@ * @param mixed $value * @param string $field_name * @param kDBItem $object - * @return string + * @return mixed + * @access public */ - function Parse($value, $field_name, &$object) + public function Parse($value, $field_name, &$object) { if ($value == '') return NULL; Index: kernel/utility/formatters/serialized_formatter.php =================================================================== --- kernel/utility/formatters/serialized_formatter.php (revision 14590) +++ kernel/utility/formatters/serialized_formatter.php (working copy) @@ -14,7 +14,16 @@ class kSerializedFormatter extends kFormatter { - function Parse($value, $field_name, &$object) + /** + * Performs basic type validation on form field value + * + * @param mixed $value + * @param string $field_name + * @param kDBItem $object + * @return mixed + * @access public + */ + public function Parse($value, $field_name, &$object) { $options = $object->GetFieldOptions($field_name); $value = kUtil::array_merge_recursive(unserialize($options['default']), $value); @@ -22,6 +31,15 @@ return serialize($value); } + /** + * Formats value of a given field + * + * @param string $value + * @param string $field_name + * @param kDBItem|kDBList $object + * @param string $format + * @return string + */ function Format($value, $field_name, &$object, $format = null) { $data = unserialize($value); Index: kernel/utility/formatters/unit_formatter.php =================================================================== --- kernel/utility/formatters/unit_formatter.php (revision 14590) +++ kernel/utility/formatters/unit_formatter.php (working copy) @@ -28,9 +28,12 @@ if( !isset($field_options['master_field']) ) { $regional =& $this->Application->recallObject('lang.current'); + /* @var $regional LanguagesItem */ + $add_fields = Array(); $options_a = Array('type' => 'int','error_field' => $field_name,'master_field' => $field_name,'format' => '%d' ); $options_b = Array('type' => 'double','error_field' => $field_name,'master_field' => $field_name,'format' => '%0.2f' ); + switch( $regional->GetDBField('UnitSystem') ) { case 2: // US/UK @@ -41,6 +44,7 @@ break; default: } + $add_fields = kUtil::array_merge_recursive($add_fields, $object->getVirtualFields()); $object->setVirtualFields($add_fields); } @@ -57,60 +61,68 @@ */ function UpdateMasterFields($field, $value, &$options, &$object) { - if( !isset($options['master_field']) ) - { - if ($value == -1) return; // for infinity setting, otherwise infinity is incorrectly converted back to Kg - $regional =& $this->Application->recallObject('lang.current'); - switch( $regional->GetDBField('UnitSystem') ) - { - case 2: // US/UK - $major = $this->TypeCast($object->GetDBField($field.'_a'), $options); - $minor = $this->TypeCast($object->GetDBField($field.'_b'), $options); - if($major === '' && $minor === '') - { - $value = null; - } - elseif($major === null && $minor === null) - { - $fields = $object->getFields(); - unset($fields[$field]); - $object->setFields($fields); - return; - } - else - { - $value = kUtil::Pounds2Kg($major, $minor); - } - break; - default: + if ( isset($options['master_field']) || ($value == -1) ) { + // for infinity setting, otherwise infinity is incorrectly converted back to Kg + return ; + } + + $regional =& $this->Application->recallObject('lang.current'); + /* @var $regional LanguagesItem */ + + if ( $regional->GetDBField('UnitSystem') == 2 ) { + // US/UK + $major = $this->TypeCast($object->GetDBField($field . '_a'), $options); + $minor = $this->TypeCast($object->GetDBField($field . '_b'), $options); + + if ( $major === '' && $minor === '' ) { + $value = null; } - $object->SetDBField($field, $value); + elseif ( $major === null && $minor === null ) { + $fields = $object->getFields(); + unset($fields[$field]); + + $object->setFields($fields); + return; + } + else { + $value = kUtil::Pounds2Kg($major, $minor); + } } + + $object->SetDBField($field, $value); } - function UpdateSubFields($field, $value, &$options, &$object) + /** + * Used for split fields like timestamp -> date, time + * Called from DBItem to update sub fields values after loading item + * + * @param string $field + * @param string $value + * @param Array $options + * @param kDBItem $object + * @return void + * @access public + */ + public function UpdateSubFields($field, $value, &$options, &$object) { - if( !isset($options['master_field']) ) - { + if ( !isset($options['master_field']) ) { $regional =& $this->Application->recallObject('lang.current'); - switch( $regional->GetDBField('UnitSystem') ) - { - case 2: // US/UK - if($value === null) - { - $major = null; - $minor = null; - } - else - { - list($major,$minor) = kUtil::Kg2Pounds($value); - /*$major = floor( $value / 0.5 ); - $minor = ($value - $major * 0.5) * 32;*/ - } - $object->SetDBField($field.'_a', $major); - $object->SetDBField($field.'_b', $minor); - break; - default: + /* @var $regional LanguagesItem */ + + if ( $regional->GetDBField('UnitSystem') == 2 ) { + // US/UK + if ( $value === null ) { + $major = null; + $minor = null; + } + else { + list($major, $minor) = kUtil::Kg2Pounds($value); +// $major = floor( $value / 0.5 ); +// $minor = ($value - $major * 0.5) * 32; + } + + $object->SetDBField($field . '_a', $major); + $object->SetDBField($field . '_b', $minor); } } } Index: kernel/utility/validator.php =================================================================== --- kernel/utility/validator.php (revision 0) +++ kernel/utility/validator.php (revision 0) @@ -0,0 +1,493 @@ + '!la_err_required!', // Field is required + 'unique' => '!la_err_unique!', // Field value must be unique + 'value_out_of_range' => '!la_err_value_out_of_range!', // Field is out of range, possible values from %s to %s + 'length_out_of_range' => '!la_err_length_out_of_range!', // Field is out of range + 'bad_type' => '!la_err_bad_type!', // Incorrect data format, please use %s + 'invalid_format' => '!la_err_invalid_format!', // Incorrect data format, please use %s + 'bad_date_format' => '!la_err_bad_date_format!', // Incorrect date format, please use (%s) ex. (%s) + 'primary_lang_required' => '!la_err_primary_lang_required!', // Primary Lang. value Required + ); + + /** + * Sets data source for validation + * + * @param kDBItem $object + */ + public function setDataSource(&$object) + { + if ( $object->getFormName() === $this->lastFormName && $object->getPrefixSpecial() === $this->lastPrefixSpecial ) { + return ; + } + + $this->reset(); + + $this->dataSource =& $object; + $this->lastFormName = $object->getFormName(); + $this->lastPrefixSpecial = $object->getPrefixSpecial(); + } + + /** + * Validate all item fields based on + * constraints set in each field options + * in config + * + * @return bool + * @access private + */ + public function Validate() + { + // order is critical - should be called BEFORE checking errors + $this->dataSource->UpdateFormattersMasterFields(); + + $global_res = true; + $fields = array_keys( $this->dataSource->getFields() ); + + foreach ($fields as $field) { + // call separately, otherwise 2+ validation errors will be ignored + $res = $this->ValidateField($field); + + $global_res = $global_res && $res; + } + + if ( !$global_res && $this->Application->isDebugMode() ) { + $error_msg = ' Validation failed in prefix ' . $this->dataSource->Prefix . ', + FieldErrors follow (look at items with "pseudo" key set) + You may ignore this notice if submitted data really has a validation error'; + trigger_error(trim($error_msg), E_USER_NOTICE); + + $this->Application->Debugger->dumpVars($this->FieldErrors); + } + + return $global_res; + } + + /** + * Validates given field + * + * @param string $field + * @return bool + * @access public + */ + public function ValidateField($field) + { + $options = $this->dataSource->GetFieldOptions($field); + + $error_field = isset($options['error_field']) ? $options['error_field'] : $field; + $res = $this->GetErrorPseudo($error_field) == ''; + + $res = $res && $this->ValidateRequired($field, $options); + $res = $res && $this->ValidateType($field, $options); + $res = $res && $this->ValidateRange($field, $options); + $res = $res && $this->ValidateUnique($field, $options); + $res = $res && $this->CustomValidation($field, $options); + + return $res; + } + + /** + * Check if value is set for required field + * + * @param string $field field name + * @param Array $params field options from config + * @return bool + * @access public + */ + public function ValidateRequired($field, $params) + { + if ( !isset($params['required']) || !$params['required'] ) { + return true; + } + + $value = $this->dataSource->GetDBField($field); + + if ( $this->Application->ConfigValue('TrimRequiredFields') ) { + $value = trim($value); + } + + if ( (string)$value == '' ) { + $this->SetError($field, 'required'); + + return false; + } + + return true; + } + + /** + * Check if value in field matches field type specified in config + * + * @param string $field field name + * @param Array $params field options from config + * @return bool + */ + protected function ValidateType($field, $params) + { + $val = $this->dataSource->GetDBField($field); + $type_regex = "#int|integer|double|float|real|numeric|string#"; + + if ( $val == '' || !isset($params['type']) || !preg_match($type_regex, $params['type']) ) { + return true; + } + + if ( $params['type'] == 'numeric' ) { + trigger_error('Invalid field type ' . $params['type'] . ' (in ValidateType method), please use float instead', E_USER_NOTICE); + $params['type'] = 'float'; + } + + $res = is_numeric($val); + + if ( $params['type'] == 'string' || $res ) { + $f = 'is_' . $params['type']; + settype($val, $params['type']); + + $res = $f($val) && ($val == $this->dataSource->GetDBField($field)); + } + + if ( !$res ) { + $this->SetError($field, 'bad_type', null, Array ($params['type'])); + + return false; + } + + return true; + } + + /** + * Check if field value is in range specified in config + * + * @param string $field field name + * @param Array $params field options from config + * @return bool + * @access private + */ + protected function ValidateRange($field, $params) + { + $res = true; + $val = $this->dataSource->GetDBField($field); + + if ( isset($params['type']) && preg_match("#int|integer|double|float|real#", $params['type']) && strlen($val) > 0 ) { + // validate number + if ( isset($params['max_value_inc'])) { + $res = $res && $val <= $params['max_value_inc']; + $max_val = $params['max_value_inc'].' (inclusive)'; + } + + if ( isset($params['min_value_inc'])) { + $res = $res && $val >= $params['min_value_inc']; + $min_val = $params['min_value_inc'].' (inclusive)'; + } + + if ( isset($params['max_value_exc'])) { + $res = $res && $val < $params['max_value_exc']; + $max_val = $params['max_value_exc'].' (exclusive)'; + } + + if ( isset($params['min_value_exc'])) { + $res = $res && $val > $params['min_value_exc']; + $min_val = $params['min_value_exc'].' (exclusive)'; + } + } + + if ( !$res ) { + if ( !isset($min_val) ) $min_val = '-∞'; + if ( !isset($max_val) ) $max_val = '∞'; + + $this->SetError($field, 'value_out_of_range', null, Array ($min_val, $max_val)); + + return false; + } + + // validate string + if ( isset($params['max_len']) ) { + $res = $res && mb_strlen($val) <= $params['max_len']; + } + + if ( isset($params['min_len']) ) { + $res = $res && mb_strlen($val) >= $params['min_len']; + } + + if ( !$res ) { + $error_params = Array (getArrayValue($params, 'min_len'), getArrayValue($params, 'max_len'), mb_strlen($val)); + $this->SetError($field, 'length_out_of_range', null, $error_params); + + return false; + } + + return true; + } + + /** + * Validates that current record has unique field combination among other table records + * + * @param string $field field name + * @param Array $params field options from config + * @return bool + * @access private + */ + protected function ValidateUnique($field, $params) + { + $unique_fields = getArrayValue($params, 'unique'); + + if ( $unique_fields === false ) { + return true; + } + + $where = Array (); + array_push($unique_fields, $field); + + foreach ($unique_fields as $unique_field) { + // if field is not empty or if it is required - we add where condition + $field_value = $this->dataSource->GetDBField($unique_field); + + if ( (string)$field_value != '' || $this->dataSource->isRequired($unique_field) ) { + $where[] = '`' . $unique_field . '` = ' . $this->Conn->qstr($field_value); + } + else { + // not good if we check by less fields than indicated + return true; + } + } + + // This can ONLY happen if all unique fields are empty and not required. + // In such case we return true, because if unique field is not required there may be numerous empty values + // if (!$where) return true; + + $sql = 'SELECT COUNT(*) + FROM %s + WHERE (' . implode(') AND (', $where) . ') AND (' . $this->dataSource->IDField . ' <> ' . (int)$this->dataSource->GetID() . ')'; + + $res_temp = $this->Conn->GetOne( str_replace('%s', $this->dataSource->TableName, $sql) ); + + $current_table_only = getArrayValue($params, 'current_table_only'); // check unique record only in current table + $res_live = $current_table_only ? 0 : $this->Conn->GetOne( str_replace('%s', $this->Application->GetLiveName($this->dataSource->TableName), $sql) ); + + $res = ($res_temp == 0) && ($res_live == 0); + + if ( !$res ) { + $this->SetError($field, 'unique'); + + return false; + } + + return true; + } + + /** + * Check field value by user-defined alghoritm + * + * @param string $field field name + * @param Array $params field options from config + * @return bool + */ + protected function CustomValidation($field, $params) + { + return true; + } + + /** + * Set's field error, if pseudo passed not found then create it with message text supplied. + * Don't overwrite existing pseudo translation. + * + * @param string $field + * @param string $pseudo + * @param string $error_label + * @param Array $error_params + * + * @return bool + * @access public + */ + public function SetError($field, $pseudo, $error_label = null, $error_params = null) + { + $error_field = $this->dataSource->GetFieldOption($field, 'error_field', false, $field); + + if ( $this->GetErrorPseudo($error_field) ) { + // don't set more then one error on field + return false; + } + + $this->FieldErrors[$error_field]['pseudo'] = $pseudo; + + if ( isset($error_params) ) { + if ( array_key_exists('value', $error_params) ) { + $this->FieldErrors[$error_field]['value'] = $error_params['value']; + unset($error_params['value']); + } + + // additional params, that helps to determine error sources + $this->FieldErrors[$error_field]['params'] = $error_params; + } + + if ( isset($error_label) && !isset($this->ErrorMsgs[$pseudo]) ) { + // label for error (only when not already set) + $this->ErrorMsgs[$pseudo] = (substr($error_label, 0, 1) == '+') ? substr($error_label, 1) : '!'.$error_label.'!'; + } + + return true; + } + + /** + * Return error message for field + * + * @param string $field + * @return string + * @access public + */ + public function GetErrorMsg($field, $force_escape = null) + { + $error_pseudo = $this->GetErrorPseudo($field); + + if ( !$error_pseudo ) { + return ''; + } + + // if special error msg defined in config + $error_msgs = $this->dataSource->GetFieldOption($field, 'error_msgs', false, Array ()); + + if ( isset($error_msgs[$error_pseudo]) ) { + $msg = $error_msgs[$error_pseudo]; + } + else { + // fallback to defaults + if ( !isset($this->ErrorMsgs[$error_pseudo]) ) { + trigger_error('No user message is defined for pseudo error ' . $error_pseudo . '', E_USER_WARNING); + + return $error_pseudo; //return the pseudo itself + } + + $msg = $this->ErrorMsgs[$error_pseudo]; + } + + $msg = $this->Application->ReplaceLanguageTags($msg, $force_escape); + + if ( isset($this->FieldErrors[$field]['params']) ) { + return vsprintf($msg, $this->FieldErrors[$field]['params']); + } + + return $msg; + } + + /** + * Returns error pseudo + * + * @param string $field + * @return string + * @access public + * + */ + public function GetErrorPseudo($field) + { + if ( !isset($this->FieldErrors[$field]) ) { + return ''; + } + + return isset($this->FieldErrors[$field]['pseudo']) ? $this->FieldErrors[$field]['pseudo'] : ''; + } + + /** + * Removes error on field + * + * @param string $field + * @access public + */ + public function RemoveError($field) + { + unset( $this->FieldErrors[$field] ); + } + + /** + * Returns field errors + * + * @return Array + * @access public + */ + public function GetFieldErrors() + { + return $this->FieldErrors; + } + + /** + * Check if item has errors + * + * @param Array $skip_fields fields to skip during error checking + * @return bool + * @access public + */ + public function HasErrors( $skip_fields = Array () ) + { + $fields = array_keys( $this->dataSource->getFields() ); + $fields = array_diff($fields, $skip_fields); + + foreach ($fields as $field) { + // if Formatter has set some error messages during values parsing + if ( $this->GetErrorPseudo($field) ) { + return true; + } + } + + return false; + } + + /** + * Clears all validation errors + * + * @access public + */ + public function reset() + { + $this->FieldErrors = Array(); + } +} \ No newline at end of file Property changes on: kernel\utility\validator.php ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + LF Index: units/configuration/configuration_tag_processor.php =================================================================== --- units/configuration/configuration_tag_processor.php (revision 14590) +++ units/configuration/configuration_tag_processor.php (working copy) @@ -163,7 +163,7 @@ $field_options = $object->GetDBField('Validation'); $field_options = $field_options ? unserialize($field_options) : Array (); - return array_key_exists('required', $field_options) && $field_options['required']; + return isset($field_options['required']) && $field_options['required']; } function Error($params) Index: units/forms/forms/forms_eh.php =================================================================== --- units/forms/forms/forms_eh.php (revision 14590) +++ units/forms/forms/forms_eh.php (working copy) @@ -87,22 +87,38 @@ return $forms; } - function OnSave(&$event) + /** + * Saves content of temp table into live and + * redirects to event' default redirect (normally grid template) + * + * @param kEvent $event + * @return void + * @access protected + */ + protected function OnSave(&$event) { parent::OnSave($event); - if ($event->status == kEvent::erSUCCESS) { + if ( $event->status == kEvent::erSUCCESS ) { $this->OnCreateFormFields($event); - $this->_deleteSectionCache(); } } - function OnMassDelete(&$event) + /** + * Deletes all selected items. + * Automatically recurse into sub-items using temp handler, and deletes sub-items + * by calling its Delete method if sub-item has AutoDelete set to true in its config file + * + * @param kEvent $event + * @return void + * @access protected + */ + protected function OnMassDelete(&$event) { parent::OnMassDelete($event); - if ($event->status == kEvent::erSUCCESS) { + if ( $event->status == kEvent::erSUCCESS ) { $this->_deleteSectionCache(); } } @@ -116,7 +132,7 @@ } /** - * Dynamically fills customdata config + * Dynamically fills custom data config * * @param kEvent $event */ @@ -157,41 +173,47 @@ * Enter description here... * * @param kEvent $event + * @return void + * @access protected */ - function OnFormSubmit(&$event) + protected function OnFormSubmit(&$event) { - $object =& $event->GetObject(); + $object =& $event->getObject(); + /* @var $object kDBItem */ $fields = explode(',',$this->Application->GetVar('fields')); $required_fields = explode(',', $this->Application->GetVar('required_fields')); $fields_params = $this->Application->GetVar('fields_params'); + $virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields'); + foreach ($fields as $field) { - $virt_fields[$field] = Array(); - if (in_array($field, $required_fields)) { - $virt_fields[$field]['required'] = 1; + $virtual_fields[$field] = Array (); + + if ( in_array($field, $required_fields) ) { + $virtual_fields[$field]['required'] = 1; } + $params = getArrayValue($fields_params, $field); - if ($params !== false) { - if (getArrayValue($params, 'Type') == 'email') { - //'formatter'=>'kFormatter', 'regexp'=>'/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', 'error_msgs' => Array('invalid_format'=>'!la_invalid_email!') - $virt_fields[$field]['formatter'] = 'kFormatter'; - $virt_fields[$field]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i'; - $virt_fields[$field]['error_msgs'] = Array('invalid_format'=>'!la_invalid_email!'); + + if ( $params !== false ) { + if ( getArrayValue($params, 'Type') == 'email' ) { + $virtual_fields[$field]['formatter'] = 'kFormatter'; + $virtual_fields[$field]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i'; + $virtual_fields[$field]['error_msgs'] = Array ('invalid_format' => '!la_invalid_email!'); } - if (getArrayValue($params, 'Type') == 'file') { - $virt_fields[$field]['formatter'] = 'kUploadFormatter'; - $virt_fields[$field]['upload_dir'] = '/uploads/sketches/'; + + if ( getArrayValue($params, 'Type') == 'file' ) { + $virtual_fields[$field]['formatter'] = 'kUploadFormatter'; + $virtual_fields[$field]['upload_dir'] = '/uploads/sketches/'; } } } - $object->SetVirtualFields($virt_fields); + $object->SetVirtualFields($virtual_fields); $field_values = $this->getSubmittedFields($event); + $checkboxes = explode(',', $this->Application->GetVar('checkbox_fields')); // MailingList,In-Link,In-Newz,In-Bulletin - - $checkboxes = Array('MailingList', 'In-Link', 'In-Newz', 'In-Bulletin'); - $checkboxes = explode(',', $this->Application->GetVar('checkbox_fields')); foreach ($checkboxes as $checkbox) { if (isset($field_values[$checkbox])) { $field_values[$checkbox] = 1; @@ -202,16 +224,21 @@ } $object->SetFieldsFromHash($field_values); - if ($object->Validate()) { + + if ( $object->Validate() ) { $event->redirect = $this->Application->GetVar('success_template'); $this->Application->EmailEventAdmin($this->Application->GetVar('email_event')); - $this->Application->EmailEventUser($this->Application->GetVar('email_event'), null, - Array('to_email' => $field_values[$this->Application->GetVar('email_field')], - 'to_name' => $field_values[$this->Application->GetVar('name_field')])); - if ($field_values['MailingList']) { + $send_params = Array ( + 'to_email' => $field_values[$this->Application->GetVar('email_field')], + 'to_name' => $field_values[$this->Application->GetVar('name_field')] + ); + + $this->Application->EmailEventUser($this->Application->GetVar('email_event'), null, $send_params); + + if ( $field_values['MailingList'] ) { $this->Application->StoreVar('SubscriberEmail', $field_values['Email']); - $this->Application->HandleEvent($sub_event, 'u:OnSubscribeUser', Array('no_unsubscribe' => 1)); + $this->Application->HandleEvent($sub_event, 'u:OnSubscribeUser', Array ('no_unsubscribe' => 1)); } } else { @@ -223,25 +250,37 @@ * Don't use security image, when form requires login * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemCreate(&$event) + protected function OnBeforeItemCreate(&$event) { parent::OnBeforeItemCreate($event); - $this->_validatePopSettings($event); - $this->_disableSecurityImage($event); - $this->_setRequired($event); + $this->itemChanged($event); } /** * Don't use security image, when form requires login * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemUpdate(&$event) + protected function OnBeforeItemUpdate(&$event) { parent::OnBeforeItemUpdate($event); + $this->itemChanged($event); + } + + /** + * Occurs before item is changed + * + * @param kEvent $event + */ + function itemChanged(&$event) + { $this->_validatePopSettings($event); $this->_disableSecurityImage($event); $this->_setRequired($event); @@ -327,9 +366,7 @@ $fields = array_merge($fields, $bounce_fields); } - foreach ($fields as $field) { - $object->setRequired($field, $required); - } + $object->setRequired($fields, $required); } /** Index: units/helpers/cat_dbitem_export_helper.php =================================================================== --- units/helpers/cat_dbitem_export_helper.php (revision 14590) +++ units/helpers/cat_dbitem_export_helper.php (working copy) @@ -147,12 +147,12 @@ * Fill required fields with dummy values * * @param kEvent $event - * @param kCatDBItem $object + * @param kCatDBItem|bool $object * @param bool $set_status */ function fillRequiredFields(&$event, &$object, $set_status = false) { - if ($object == $this->false) { + if ( $object == $this->false ) { $object =& $event->getObject(); /* @var $object kCatDBItem */ } @@ -161,13 +161,21 @@ $fields = $object->getFields(); foreach ($fields as $field_name => $field_options) { - if ($object->isVirtualField($field_name) || !getArrayValue($field_options, 'required') ) continue; - if ( $object->GetDBField($field_name) ) continue; + if ( $object->isVirtualField($field_name) || !$object->isRequired($field_name) ) { + continue; + } + if ( $object->GetDBField($field_name) ) { + continue; + } + $formatter_class = getArrayValue($field_options, 'formatter'); - if ($formatter_class) // not tested - { + + if ( $formatter_class ) { + // not tested $formatter =& $this->Application->recallObject($formatter_class); + /* @var $formatter kFormatter */ + $sample_value = $formatter->GetSample($field_name, $field_options, $object); } @@ -176,7 +184,7 @@ } $object->UpdateFormattersSubFields(); - if ($set_status && $has_empty) { + if ( $set_status && $has_empty ) { $object->SetDBField('Status', 0); } } @@ -185,8 +193,10 @@ * Verifies that all user entered export params are correct * * @param kEvent $event + * @return bool + * @access protected */ - function verifyOptions(&$event) + protected function verifyOptions(&$event) { if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid')) { @@ -197,12 +207,12 @@ $this->fillRequiredFields($event, $this->false); $object =& $event->getObject(); - /* @var $object kDBItem */ + /* @var $object kCatDBItem */ $cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy'); if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field { - $object->setRequired('CategorySeparator', true); + $object->setRequired('CategorySeparator'); $cross_unique_fields[] = 'CategorySeparator'; } @@ -265,7 +275,7 @@ foreach ($fields as $field_name => $field_options) { if ($object->skipField($field_name)) continue; - if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) { + if ( $object->isRequired($field_name) && !in_array($field_name, $this->exportOptions['ExportColumns']) ) { $missing_columns[] = $field_name; $object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing'); $ret = false; @@ -406,10 +416,12 @@ function getCustomSQL() { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); + /* @var $ml_formatter kMultiLanguage */ $custom_sql = ''; + foreach ($this->customFields as $custom_id => $custom_name) { - $custom_sql .= 'custom_data.'.$ml_formatter->LangFieldName('cust_'.$custom_id).' AS cust_'.$custom_name.', '; + $custom_sql .= 'custom_data.' . $ml_formatter->LangFieldName('cust_' . $custom_id) . ' AS cust_' . $custom_name . ', '; } return substr($custom_sql, 0, -2); @@ -424,10 +436,12 @@ } else { $items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List'); + /* @var $items_list kDBList */ + $items_list->SetPerPage(-1); if ($options['export_ids'] != '') { - $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')'); + $items_list->addFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')'); } if ($count_only) { @@ -596,7 +610,7 @@ // 1. convert custom field $field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name); - // 2. convert category field (mixed version & serparated version) + // 2. convert category field (mixed version & separated version) $field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name); $valid_fields = $object->getPossibleExportColumns(); @@ -686,31 +700,38 @@ $this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) ); } - function setFieldValue($field_index, $value) + /** + * Sets value of import/export object + * @param int $field_index + * @param mixed $value + * @return void + * @access protected + */ + protected function setFieldValue($field_index, $value) { - if (empty($value)) { + if ( empty($value) ) { $value = null; } $field_name = getArrayValue($this->exportFields, $field_index); - if ($field_name == 'ResourceId') { - return false; + if ( $field_name == 'ResourceId' ) { + return ; } - if (substr($field_name, 0, 7) == 'Custom_') { - $field_name = 'cust_'.substr($field_name, 7); + if ( substr($field_name, 0, 7) == 'Custom_' ) { + $field_name = 'cust_' . substr($field_name, 7); $this->curItem->SetField($field_name, $value); } - elseif ($field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath') { - $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array(); + elseif ( $field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath' ) { + $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array (); } - elseif (substr($field_name, 0, 8) == 'Category') { - $this->curItem->CategoryPath[ (int)substr($field_name, 8) - 1 ] = $value; + elseif ( substr($field_name, 0, 8) == 'Category' ) { + $this->curItem->CategoryPath[(int)substr($field_name, 8) - 1] = $value; } - elseif (substr($field_name, 0, 20) == '__CATEGORY__Category') { - $this->curItem->CategoryPath[ (int)substr($field_name, 20) ] = $value; + elseif ( substr($field_name, 0, 20) == '__CATEGORY__Category' ) { + $this->curItem->CategoryPath[(int)substr($field_name, 20)] = $value; } - elseif (substr($field_name, 0, 11) == '__VIRTUAL__') { + elseif ( substr($field_name, 0, 11) == '__VIRTUAL__' ) { $field_name = substr($field_name, 11); $this->curItem->SetField($field_name, $value); } @@ -724,6 +745,14 @@ } } + /** + * Resets import object + * + * @param kEvent $event + * @param int $object_type + * @param Array $record_data + * @return void + */ function resetImportObject(&$event, $object_type, $record_data = null) { switch ($object_type) { @@ -1051,39 +1080,43 @@ { $category_id = $this->curItem->GetDBField('CategoryId'); $category_path = $this->getFromCache('category_path', $category_id); - if (!$category_path) - { + + if ( !$category_path ) { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); - $sql = 'SELECT '.$ml_formatter->LangFieldName('CachedNavbar').' - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$category_id; + /* @var $ml_formatter kMultiLanguage */ + + $sql = 'SELECT ' . $ml_formatter->LangFieldName('CachedNavbar') . ' + FROM ' . TABLE_PREFIX . 'Category + WHERE CategoryId = ' . $category_id; $category_path = $this->Conn->GetOne($sql); - $category_path = $category_path ? explode('&|&', $category_path) : Array(); - if ($category_path && strtolower($category_path[0]) == 'content') { + $category_path = $category_path ? explode('&|&', $category_path) : Array (); + + if ( $category_path && strtolower($category_path[0]) == 'content' ) { array_shift($category_path); } - if ($this->exportOptions['IsBaseCategory']) { + if ( $this->exportOptions['IsBaseCategory'] ) { $i = $this->exportOptions['BaseLevel']; - while ($i > 0) { + while ( $i > 0 ) { array_shift($category_path); $i--; } } $category_count = $this->getMaxCategoryLevel(); - if ($this->exportOptions['CategoryFormat'] == 1) { + + if ( $this->exportOptions['CategoryFormat'] == 1 ) { // category path in single field - $category_path = $category_count ? Array( implode($this->exportOptions['CategorySeparator'], $category_path) ) : Array(); + $category_path = $category_count ? Array (implode($this->exportOptions['CategorySeparator'], $category_path)) : Array (); } else { // category path in separated fields $levels_used = count($category_path); - if ($levels_used < $category_count) - { + + if ( $levels_used < $category_count ) { $i = 0; - while ($i < $category_count - $levels_used) { + while ( $i < $category_count - $levels_used ) { $category_path[] = ''; $i++; } @@ -1157,17 +1190,31 @@ return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']); } + /** + * Saves import/export options + * + * @param kEvent $event + * @param Array $options + * @return void + */ function saveOptions(&$event, $options = null) { - if (!isset($options)) { + if ( !isset($options) ) { $options = $this->exportOptions; } - $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) ); + + $this->Application->StoreVar($event->getPrefixSpecial() . '_options', serialize($options)); } + /** + * Loads import/export options + * + * @param kEvent $event + * @return void + */ function loadOptions(&$event) { - return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options')); + return unserialize( $this->Application->RecallVar($event->getPrefixSpecial() . '_options') ); } /** @@ -1178,6 +1225,7 @@ function prepareExportColumns(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); + /* @var $object kCatDBItem */ if ( !$object->isField('ExportColumns') ) { // import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported @@ -1206,11 +1254,13 @@ foreach ($fields as $field_name => $field_options) { if ( !$object->skipField($field_name) ) { - $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : ''); + $available_columns[$field_name] = $field_name.( $object->isRequired($field_name) ? '*' : ''); } } $handler =& $this->Application->recallObject($event->Prefix.'_EventHandler'); + /* @var $handler kDBEventHandler */ + $available_columns = array_merge($available_columns, $handler->getCustomExportColumns($event)); // custom fields @@ -1253,19 +1303,32 @@ $this->PrepareExportPresets($event); } + /** + * Prepares export presets + * + * @param kEvent $event + * @return void + */ function PrepareExportPresets(&$event) { - $object =& $event->getObject( Array('skip_autoload' => true) ); + $object =& $event->getObject(Array ('skip_autoload' => true)); + /* @var $object kDBItem */ + $options = $object->GetFieldOptions('ExportPresets'); + $export_settings = $this->Application->RecallPersistentVar('export_settings'); - $export_settings = $this->Application->RecallPersistentVar('export_settings'); - if (!$export_settings) return ; + if ( !$export_settings ) { + return; + } + $export_settings = unserialize($export_settings); - if (!isset($export_settings[$event->Prefix])) return ; + if ( !isset($export_settings[$event->Prefix]) ) { + return; + } - - $export_presets = array(''=>''); + $export_presets = array ('' => ''); + foreach ($export_settings[$event->Prefix] as $key => $val) { $export_presets[implode('|', $val['ExportColumns'])] = $key; } @@ -1292,28 +1355,32 @@ * Updates uploaded files list * * @param kEvent $event + * @return void + * @access protected */ - function updateImportFiles(&$event) + protected function updateImportFiles(&$event) { - if ($event->Special != 'import') { - return false; + if ( $event->Special != 'import' ) { + return ; } $object =& $event->getObject(); - $import_filenames = Array(); + $import_filenames = Array (); $file_helper =& $this->Application->recallObject('FileHelper'); /* @var $file_helper FileHelper */ $file_helper->CheckFolder(EXPORT_PATH); - if ($folder_handle = opendir(EXPORT_PATH)) { - while (false !== ($file = readdir($folder_handle))) { - if (is_dir(EXPORT_PATH.'/'.$file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH.'/'.$file) == 0) continue; + if ( $folder_handle = opendir(EXPORT_PATH) ) { + while ( false !== ($file = readdir($folder_handle)) ) { + if ( is_dir(EXPORT_PATH . '/' . $file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH . '/' . $file) == 0 ) { + continue; + } - $file_size = kUtil::formatSize( filesize(EXPORT_PATH.'/'.$file) ); - $import_filenames[$file] = $file.' ('.$file_size.')'; + $file_size = kUtil::formatSize(filesize(EXPORT_PATH . '/' . $file)); + $import_filenames[$file] = $file . ' (' . $file_size . ')'; } closedir($folder_handle); } @@ -1344,16 +1411,18 @@ */ function OnExportBegin(&$event) { - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if (!$items_info) - { - $items_info = unserialize( $this->Application->RecallVar($event->getPrefixSpecial().'_ItemsInfo') ); + $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); + + if ( !$items_info ) { + $items_info = unserialize($this->Application->RecallVar($event->getPrefixSpecial() . '_ItemsInfo')); $this->Application->SetVar($event->getPrefixSpecial(true), $items_info); } list($item_id, $field_values) = each($items_info); - $object =& $event->getObject( Array('skip_autoload' => true) ); + $object =& $event->getObject(Array ('skip_autoload' => true)); + /* @var $object kDBItem */ + $object->SetFieldsFromHash($field_values); $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!! @@ -1361,45 +1430,45 @@ $this->setRequiredFields($event); // save export/import options - if ($event->Special == 'export') - { - $export_ids = $this->Application->RecallVar($event->Prefix.'_export_ids'); - $export_cats_ids = $this->Application->RecallVar($event->Prefix.'_export_cats_ids'); + if ( $event->Special == 'export' ) { + $export_ids = $this->Application->RecallVar($event->Prefix . '_export_ids'); + $export_cats_ids = $this->Application->RecallVar($event->Prefix . '_export_cats_ids'); // used for multistep export $field_values['export_ids'] = $export_ids ? explode(',', $export_ids) : false; - $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array( $this->Application->GetVar('m_cat_id') ); + $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array ($this->Application->GetVar('m_cat_id')); } $field_values['ExportColumns'] = $field_values['ExportColumns'] ? explode('|', substr($field_values['ExportColumns'], 1, -1) ) : Array(); $field_values['start_from'] = 0; - $this->Application->HandleEvent($nevent, $event->Prefix.':OnBeforeExportBegin', array('options'=>$field_values)); + $nevent = new kEvent($event->Prefix . ':OnBeforeExportBegin'); + $nevent->setEventParam('options', $field_values); + $this->Application->HandleEvent($nevent); $field_values = $nevent->getEventParam('options'); $this->saveOptions($event, $field_values); - if( $this->verifyOptions($event) ) - { - if ($this->_getExportSavePreset($object)) { + if ( $this->verifyOptions($event) ) { + if ( $this->_getExportSavePreset($object) ) { $name = $object->GetDBField('ExportPresetName'); $export_settings = $this->Application->RecallPersistentVar('export_settings'); - $export_settings = $export_settings ? unserialize($export_settings) : array(); + $export_settings = $export_settings ? unserialize($export_settings) : array (); $export_settings[$event->Prefix][$name] = $field_values; $this->Application->StorePersistentVar('export_settings', serialize($export_settings)); } $progress_t = $this->Application->RecallVar('export_progress_t'); - if ($progress_t) { + if ( $progress_t ) { $this->Application->RemoveVar('export_progress_t'); } else { - $progress_t = $this->getModuleName($event).'/'.$event->Special.'_progress'; + $progress_t = $this->getModuleName($event) . '/' . $event->Special . '_progress'; } $event->redirect = $progress_t; - if ($event->Special == 'import') { + if ( $event->Special == 'import' ) { $import_category = (int)$this->Application->RecallVar('ImportCategory'); // in future could use module root category if import category will be unavailable :) @@ -1407,11 +1476,11 @@ $this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking } } - else - { + else { // make uploaded file local & change source selection $filename = getArrayValue($field_values, 'ImportFilename'); - if ($filename) { + + if ( $filename ) { $this->updateImportFiles($event); $object->SetDBField('ImportSource', 2); $field_values['ImportSource'] = 2; @@ -1452,6 +1521,8 @@ $required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns'); $object =& $event->getObject(); + /* @var $object kDBItem */ + if ($this->_getExportSavePreset($object)) { $required_fields['export'][] = 'ExportPresetName'; } @@ -1470,9 +1541,7 @@ } $required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]); - foreach ($required_fields as $required_field) { - $object->setRequired($required_field, true); - } + $object->setRequired($required_fields); } } \ No newline at end of file Index: units/mailing_lists/mailing_list_eh.php =================================================================== --- units/mailing_lists/mailing_list_eh.php (revision 14590) +++ units/mailing_lists/mailing_list_eh.php (working copy) @@ -62,8 +62,11 @@ * Don't allow to delete mailings in progress * * @param kEvent $event + * @param string $type + * @return void + * @access protected */ - function customProcessing(&$event, $type) + protected function customProcessing(&$event, $type) { if ($event->Name == 'OnMassDelete' && $type == 'before') { $ids = $event->getEventParam('ids'); @@ -135,15 +138,17 @@ * Checks, that at least one message text field is filled * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemCreate(&$event) + protected function OnBeforeItemCreate(&$event) { parent::OnBeforeItemCreate($event); $object =& $event->getObject(); /* @var $object kDBItem */ - if (!$this->Application->GetVar('mailing_recipient_type')) { + if ( !$this->Application->GetVar('mailing_recipient_type') ) { // user manually typed email addresses -> normalize $recipients = str_replace(',', ';', $object->GetDBField('To')); $recipients = array_map('trim', explode(';', $recipients)); @@ -151,8 +156,8 @@ $object->SetDBField('To', implode(';', $recipients)); } - if (!$object->GetDBField('MessageText')) { - $object->setRequired('MessageHtml', true); + if ( !$object->GetDBField('MessageText') ) { + $object->setRequired('MessageHtml'); } // remember user, who created mailing, because of his name Index: units/phrases/phrases_event_handler.php =================================================================== --- units/phrases/phrases_event_handler.php (revision 14590) +++ units/phrases/phrases_event_handler.php (working copy) @@ -17,27 +17,24 @@ class PhrasesEventHandler extends kDBEventHandler { /** - * Apply some special processing to - * object beeing recalled before using - * it in other events that call prepareObject + * Apply some special processing to object being + * recalled before using it in other events that + * call prepareObject * - * @param Object $object + * @param kDBItem|kDBList $object * @param kEvent $event + * @return void * @access protected */ - function prepareObject(&$object, &$event) + protected function prepareObject(&$object, &$event) { // don't call parent if ($event->Special == 'import' || $event->Special == 'export') { $this->RemoveRequiredFields($object); - $object->setRequired('LangFile'); - $object->setRequired('PhraseType'); - $object->setRequired('Module'); + $object->setRequired( Array ('LangFile', 'PhraseType', 'Module') ); // allow multiple phrase types to be selected during import/export - $field_options = $object->GetFieldOptions('PhraseType'); - $field_options['type'] = 'string'; - $object->SetFieldOptions('PhraseType', $field_options); + $object->SetFieldOption('PhraseType', 'type', 'string'); } } @@ -45,8 +42,10 @@ * Allow to create phrases from front end in debug mode with DBG_PHRASES constant set * * @param kEvent $event + * @return bool + * @access public */ - function CheckPermission(&$event) + public function CheckPermission(&$event) { if (!$this->Application->isAdmin && $this->Application->isDebugMode(false) && kUtil::constOn('DBG_PHRASES')) { $allow_events = Array ('OnCreate', 'OnUpdate'); @@ -217,8 +216,10 @@ * Set last change info, when phrase is created * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemCreate(&$event) + protected function OnBeforeItemCreate(&$event) { parent::OnBeforeItemCreate($event); @@ -227,7 +228,7 @@ $primary_language_id = $this->Application->GetDefaultLanguageId(); - if (!$object->GetDBField('l' . $primary_language_id . '_Translation')) { + if ( !$object->GetDBField('l' . $primary_language_id . '_Translation') ) { // no translation on primary language -> try to copy from other language $src_languages = Array ('lang_id', 'm_lang'); // editable language, theme language @@ -235,7 +236,7 @@ $src_language = $this->Application->GetVar($src_language); $src_value = $src_language ? $object->GetDBField('l' . $src_language . '_Translation') : false; - if ($src_value) { + if ( $src_value ) { $object->SetDBField('l' . $primary_language_id . '_Translation', $src_value); break; } @@ -249,8 +250,10 @@ * Update last change info, when phrase is updated * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemUpdate(&$event) + protected function OnBeforeItemUpdate(&$event) { parent::OnBeforeItemUpdate($event); Index: units/users/users_config.php =================================================================== --- units/users/users_config.php (revision 14590) +++ units/users/users_config.php (working copy) @@ -30,17 +30,6 @@ Array ( 'Mode' => hBEFORE, 'Conditional' => false, - 'HookToPrefix' => 'affil', - 'HookToSpecial' => '*', - 'HookToEvent' => Array('OnCheckAffiliateAgreement'), - 'DoPrefix' => '', - 'DoSpecial' => '*', - 'DoEvent' => 'OnSubstituteSubscriber', - ), - - Array ( - 'Mode' => hBEFORE, - 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnAfterConfigRead'), @@ -342,148 +331,227 @@ ), ), - 'Fields' => Array - ( - 'PortalUserId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), - 'Login' => Array ( - 'type' => 'string', 'max_len' => 255, - 'formatter' => 'kFormatter', 'regexp' => '/^[A-Z\d_\-\.]+$/i', - 'error_msgs' => Array('unique' => '!lu_user_already_exist!', 'invalid_format' => '!la_error_InvalidLogin!', 'banned' => '!la_error_UserBanned!'), - 'not_null' => 1, 'unique' => Array (), 'default' => '', - ), - 'Password' => Array ('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyPassword', 'skip_empty' => 1, 'default' => md5('')), - 'FirstName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''), - 'LastName' => Array ('type' => 'string', 'not_null' => 1, 'default' => ''), - 'Company' => Array ('type' => 'string','not_null' => 1,'default' => ''), - 'Email' => Array ( - 'type' => 'string', - 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', - 'sample_value' => 'email@domain.com', - 'error_msgs' => Array ( - 'invalid_format' => '!la_invalid_email!', 'unique' => '!lu_email_already_exist!' - ), - 'not_null' => 1, 'unique' => Array (), 'required' => 1, 'default' => '' - ), - 'CreatedOn' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'), - 'Phone' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'Fax' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'Street' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'Street2' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'City' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'State' => Array( - 'type' => 'string', - 'formatter' => 'kOptionsFormatter', 'options' => Array(), - 'not_null' => 1, - 'default' => '', - ), - 'Zip' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'Country' => Array( - 'type' => 'string', - 'formatter' => 'kOptionsFormatter', - 'options_sql' => ' SELECT IF(l%2$s_Name = "", l%3$s_Name, l%2$s_Name) AS Name, IsoCode - FROM ' . TABLE_PREFIX . 'CountryStates - WHERE Type = ' . DESTINATION_TYPE_COUNTRY . ' - ORDER BY Name', - 'option_key_field' => 'IsoCode', 'option_title_field' => 'Name', - 'not_null' => 1, 'default' => '', - ), - 'ResourceId' => Array('type' => 'int','not_null' => 1, 'default' => 0), - 'Status' => Array('type' => 'int', 'formatter'=>'kOptionsFormatter', 'options'=>Array(1=>'la_Enabled', 0=>'la_Disabled', 2=>'la_Pending'), 'use_phrases'=>1, 'not_null' => 1, 'default' => 1), - 'Modified' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL), - 'dob' => Array('type'=>'int', 'formatter' => 'kDateFormatter', 'default' => NULL), - 'tz' => Array('type' => 'int', 'default' => NULL), - 'ip' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'IsBanned' => Array('type' => 'int','not_null' => 1, 'default' => 0), - 'PwResetConfirm' => Array('type' => 'string', 'not_null' => 1, 'default' => ''), - 'PwRequestTime' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL), - 'AdminLanguage' => Array ( - 'type' => 'int', - 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName', 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName', - 'default' => NULL + 'Forms' => Array ( + 'default' => Array ( + 'Fields' => Array ( + 'PortalUserId' => Array ('default' => 0), + 'Login' => Array ( + 'max_len' => 255, + 'formatter' => 'kFormatter', 'regexp' => '/^[A-Z\d_\-\.]+$/i', + 'error_msgs' => Array( + 'unique' => '!lu_user_already_exist!', 'invalid_format' => '!la_error_InvalidLogin!', 'banned' => '!la_error_UserBanned!' ), - 'DisplayToPublic' => Array ( - 'type' => 'string', - 'formatter' => 'kOptionsFormatter', 'options' => Array ( - 'FirstName' => 'lu_fld_FirstName', 'LastName' => 'lu_fld_LastName', 'dob' => 'lu_fld_BirthDate', - 'Email' => 'lu_fld_Email', 'Phone' => 'lu_fld_Phone', 'Street' => 'lu_fld_AddressLine1', - 'Street2' => 'lu_fld_AddressLine2', 'City' => 'lu_fld_City', 'State' => 'lu_fld_State', - 'Zip' => 'lu_fld_Zip', 'Country' => 'lu_fld_Country', - ), 'use_phrases' => 1, 'multiple' => 1, - 'default' => NULL - ), - 'UserType' => Array ( - 'type' => 'int', - 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_UserTypeUser', 1 => 'la_opt_UserTypeAdmin'), 'use_phrases' => 1, - 'not_null' => 1, 'default' => 0 - ), - 'PrimaryGroupId' => Array ( - 'type' => 'int', - 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %1$s FROM ' . TABLE_PREFIX . 'PortalGroup WHERE Enabled = 1 AND FrontRegistration = 1', 'option_key_field' => 'GroupId', 'option_title_field' => 'Name', - 'default' => NULL - ), - 'OldStyleLogin' => Array ( - 'type' => 'int', - 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, - 'not_null' => 1, 'default' => 0 - ), - ), + 'unique' => Array (), 'default' => '', + ), + 'Password' => Array ( + 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyPassword', + 'default' => 'd41d8cd98f00b204e9800998ecf8427e' + ), + 'FirstName' => Array ('default' => ''), + 'LastName' => Array ('default' => ''), + 'Company' => Array ('default' => ''), + 'Email' => Array ( + 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', + 'sample_value' => 'email@domain.com', 'error_msgs' => Array ( + 'invalid_format' => '!la_invalid_email!', 'unique' => '!lu_email_already_exist!' + ), + 'unique' => Array (), 'required' => 1, 'default' => '' + ), + 'CreatedOn' => Array ('formatter' => 'kDateFormatter', 'default' => '#NOW#'), + 'Phone' => Array ('default' => ''), + 'Fax' => Array ('default' => ''), + 'Street' => Array ('default' => ''), + 'Street2' => Array ('default' => ''), + 'City' => Array ('default' => ''), + 'State' => Array ( + 'formatter' => 'kOptionsFormatter', 'options' => Array (), + 'default' => '', + ), + 'Zip' => Array ('default' => ''), + 'Country' => Array ( + 'formatter' => 'kOptionsFormatter', + 'options_sql' => ' SELECT IF(l%2$s_Name = "", l%3$s_Name, l%2$s_Name) AS Name, IsoCode + FROM ' . TABLE_PREFIX . 'CountryStates + WHERE Type = ' . DESTINATION_TYPE_COUNTRY . ' + ORDER BY Name', + 'option_key_field' => 'IsoCode', 'option_title_field' => 'Name', + 'default' => '', + ), + 'ResourceId' => Array ('default' => 0), + 'Status' => Array ( + 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Enabled', 0 => 'la_Disabled', 2 => 'la_Pending'), 'use_phrases' => 1, + 'default' => 1 + ), + 'Modified' => Array ('formatter' => 'kDateFormatter', 'default' => NULL), + 'dob' => Array ('formatter' => 'kDateFormatter', 'default' => NULL), + 'tz' => Array ('default' => NULL), + 'ip' => Array ('default' => ''), + 'IsBanned' => Array ('default' => 0), + 'PwResetConfirm' => Array ('default' => ''), + 'PwRequestTime' => Array ('formatter' => 'kDateFormatter', 'default' => NULL), + 'AdminLanguage' => Array ( + 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Language ORDER BY PackName', + 'option_key_field' => 'LanguageId', 'option_title_field' => 'LocalName', 'default' => NULL + ), + 'DisplayToPublic' => Array ( + 'formatter' => 'kOptionsFormatter', 'options' => Array ( + 'FirstName' => 'lu_fld_FirstName', 'LastName' => 'lu_fld_LastName', 'dob' => 'lu_fld_BirthDate', + 'Email' => 'lu_fld_Email', 'Phone' => 'lu_fld_Phone', 'Street' => 'lu_fld_AddressLine1', + 'Street2' => 'lu_fld_AddressLine2', 'City' => 'lu_fld_City', 'State' => 'lu_fld_State', + 'Zip' => 'lu_fld_Zip', 'Country' => 'lu_fld_Country', + ), 'use_phrases' => 1, 'multiple' => 1, + 'default' => NULL + ), + 'UserType' => Array ( + 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_UserTypeUser', 1 => 'la_opt_UserTypeAdmin'), 'use_phrases' => 1, + 'default' => 0 + ), + 'PrimaryGroupId' => Array ( + 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %1$s FROM ' . TABLE_PREFIX . 'PortalGroup WHERE Enabled = 1 AND FrontRegistration = 1', + 'option_key_field' => 'GroupId', 'option_title_field' => 'Name', 'default' => NULL + ), + 'OldStyleLogin' => Array ( + 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, + 'default' => 0 + ), + ), - 'VirtualFields' => Array( - 'ValidateLogin' => Array('type'=>'string','default'=>''), - 'SubscribeEmail' => Array('type'=>'string','default'=>''), - 'PrimaryGroup' => Array('type' => 'string', 'default' => ''), - 'RootPassword' => Array('type' => 'string', 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', 'verify_field' => 'VerifyRootPassword', 'skip_empty' => 1, 'default' => md5('') ), - 'EmailPassword' => Array ('type' => 'string', 'default' => ''), - 'FullName' => Array ('type' => 'string', 'default' => ''), - 'AltName' => Array ('type' => 'string', 'default' => ''), - 'SameImages' => Array ('type' => 'string', 'default' => ''), - 'LocalThumb' => Array ('type' => 'string', 'default' => ''), - 'ThumbPath' => Array ('type' => 'string', 'default' => ''), - 'ThumbUrl' => Array ('type' => 'string', 'default' => ''), - 'LocalImage' => Array ('type' => 'string', 'default' => ''), - 'LocalPath' => Array ('type' => 'string', 'default' => ''), - 'FullUrl' => Array ('type' => 'string', 'default' => ''), + 'VirtualFields' => Array ( + 'PrimaryGroup' => Array ('default' => ''), + 'RootPassword' => Array ( + 'formatter' => 'kPasswordFormatter', 'encryption_method' => 'md5', + 'verify_field' => 'VerifyRootPassword', 'default' => 'd41d8cd98f00b204e9800998ecf8427e' + ), + 'EmailPassword' => Array ('default' => ''), + 'FullName' => Array ('default' => ''), + 'AltName' => Array ('default' => ''), + 'SameImages' => Array ('default' => ''), + 'LocalThumb' => Array ('default' => ''), + 'ThumbPath' => Array ('default' => ''), + 'ThumbUrl' => Array ('default' => ''), + 'LocalImage' => Array ('default' => ''), + 'LocalPath' => Array ('default' => ''), + 'FullUrl' => Array ('default' => ''), + ), + ), - // for login form - 'UserLogin' => Array ( - 'type' => 'string', - 'error_msgs' => Array ( - 'no_permission' => '!la_no_permissions!', 'invalid_password' => '!la_invalid_password!' + 'registration' => Array ( + // Front-End user registration form + /*'Fields' => Array ( + 'FirstName' => Array ('required' => 1), + ),*/ + ), + + 'recommend' => Array ( + 'VirtualFields' => Array ( + 'RecommendEmail' => Array ( + 'type' => 'string', + 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', + 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!', 'send_error' => '!lu_email_send_error!'), + 'sample_value' => 'email@domain.com', + 'required' => 1, 'default' => '' + ), ), - 'default' => '' ), - 'UserPassword' => Array ('type' => 'string', 'default' => ''), - 'UserRememberLogin' => Array ('type' => 'int', 'default' => 0), - // for recommend form - 'RecommendEmail' => Array ( - 'type' => 'string', - 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', - 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!', 'send_error' => '!lu_email_send_error!'), - 'sample_value' => 'email@domain.com', 'default' => '' - ), + 'subscription' => Array ( + 'VirtualFields' => Array ( + 'SubscriberEmail' => Array ( + 'type' => 'string', + 'formatter' => 'kFormatter', 'regexp' => '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', + 'error_msgs' => Array ('required' => '!lu_InvalidEmail!', 'invalid_format' => '!lu_InvalidEmail!'), + 'sample_value' => 'email@domain.com', + 'required' => 1, 'default' => '' + ), + ), + ), - // for forgot password form - 'ForgotLogin' => Array ( - 'type' => 'string', - 'error_msgs' => Array ( - 'required' => '!lu_ferror_forgotpw_nodata!', - 'unknown_username' => '!lu_ferror_unknown_username!', - 'reset_denied' => '!lu_ferror_reset_denied!', - ), - 'default' => '' - ), - 'ForgotEmail' => Array ( - 'type' => 'string', - 'error_msgs' => Array ( - 'required' => '!lu_ferror_forgotpw_nodata!', - 'unknown_email' => '!lu_ferror_unknown_email!', - 'reset_denied' => '!lu_ferror_reset_denied!', - ), - 'default' => '' - ), + 'forgot_password' => Array ( + 'VirtualFields' => Array ( + 'ForgotLogin' => Array ( + 'type' => 'string', + 'error_msgs' => Array ( + 'required' => '!lu_ferror_forgotpw_nodata!', + 'unknown_username' => '!lu_ferror_unknown_username!', + 'reset_denied' => '!lu_ferror_reset_denied!', + ), + 'default' => '' + ), + 'ForgotEmail' => Array ( + 'type' => 'string', + 'error_msgs' => Array ( + 'required' => '!lu_ferror_forgotpw_nodata!', + 'unknown_email' => '!lu_ferror_unknown_email!', + 'reset_denied' => '!lu_ferror_reset_denied!', + ), + 'default' => '' + ), + ), + ), + + 'login' => Array ( + 'VirtualFields' => Array ( + 'UserLogin' => Array ( + 'type' => 'string', + 'error_msgs' => Array ( + 'no_permission' => '!la_no_permissions!', 'invalid_password' => '!la_invalid_password!' + ), + 'default' => '' + ), + 'UserPassword' => Array ('type' => 'string', 'default' => ''), + 'UserRememberLogin' => Array ('type' => 'int', 'default' => 0), + ), + ), ), + 'Fields' => Array ( + 'PortalUserId' => Array ('type' => 'int', 'not_null' => 1), + 'Login' => Array ('type' => 'string', 'not_null' => 1), + 'Password' => Array ('type' => 'string', 'skip_empty' => 1), + 'FirstName' => Array ('type' => 'string', 'not_null' => 1), + 'LastName' => Array ('type' => 'string', 'not_null' => 1), + 'Company' => Array ('type' => 'string','not_null' => 1), + 'Email' => Array ('type' => 'string', 'not_null' => 1), + 'CreatedOn' => Array ('type' => 'int'), + 'Phone' => Array ('type' => 'string', 'not_null' => 1), + 'Fax' => Array ('type' => 'string', 'not_null' => 1), + 'Street' => Array ('type' => 'string', 'not_null' => 1), + 'Street2' => Array ('type' => 'string', 'not_null' => 1), + 'City' => Array ('type' => 'string', 'not_null' => 1), + 'State' => Array ('type' => 'string', 'not_null' => 1), + 'Zip' => Array ('type' => 'string', 'not_null' => 1), + 'Country' => Array ('type' => 'string', 'not_null' => 1), + 'ResourceId' => Array ('type' => 'int', 'not_null' => 1), + 'Status' => Array ('type' => 'int', 'not_null' => 1), + 'Modified' => Array ('type' => 'int'), + 'dob' => Array ('type' => 'int'), + 'tz' => Array ('type' => 'int'), + 'ip' => Array ('type' => 'string', 'not_null' => 1), + 'IsBanned' => Array ('type' => 'int', 'not_null' => 1), + 'PwResetConfirm' => Array ('type' => 'string', 'not_null' => 1), + 'PwRequestTime' => Array ('type' => 'int'), + 'AdminLanguage' => Array ('type' => 'int'), + 'DisplayToPublic' => Array ('type' => 'string'), + 'UserType' => Array ('type' => 'int', 'not_null' => 1), + 'PrimaryGroupId' => Array ('type' => 'int'), + 'OldStyleLogin' => Array ('type' => 'int', 'not_null' => 1), + ), + + 'VirtualFields' => Array ( + 'PrimaryGroup' => Array ('type' => 'string'), + 'RootPassword' => Array ('type' => 'string', 'skip_empty' => 1), + 'EmailPassword' => Array ('type' => 'string'), + 'FullName' => Array ('type' => 'string'), + 'AltName' => Array ('type' => 'string'), + 'SameImages' => Array ('type' => 'string'), + 'LocalThumb' => Array ('type' => 'string'), + 'ThumbPath' => Array ('type' => 'string'), + 'ThumbUrl' => Array ('type' => 'string'), + 'LocalImage' => Array ('type' => 'string'), + 'LocalPath' => Array ('type' => 'string'), + 'FullUrl' => Array ('type' => 'string'), + ), + 'Grids' => Array( // not in use 'Default' => Array( @@ -493,15 +561,15 @@ 2 => 'icon16_user_pending.png' ), 'Fields' => Array( - 'Login' => Array ('title' => 'column:la_fld_Username', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter'), - 'LastName' => Array ('filter_block' => 'grid_like_filter'), - 'FirstName' => Array ('filter_block' => 'grid_like_filter'), - 'Email' => Array ('filter_block' => 'grid_like_filter'), - 'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter'), - 'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter'), - 'Modified' => Array('filter_block' => 'grid_date_range_filter'), - 'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ), - ), + 'Login' => Array ('title' => 'column:la_fld_Username', 'data_block' => 'grid_checkbox_td', 'filter_block' => 'grid_like_filter'), + 'LastName' => Array ('filter_block' => 'grid_like_filter'), + 'FirstName' => Array ('filter_block' => 'grid_like_filter'), + 'Email' => Array ('filter_block' => 'grid_like_filter'), + 'PrimaryGroup' => Array ('title' => 'la_col_PrimaryGroup', 'filter_block' => 'grid_like_filter'), + 'CreatedOn' => Array ('filter_block' => 'grid_date_range_filter'), + 'Modified' => Array('filter_block' => 'grid_date_range_filter'), + 'Status' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, ), + ), ), // used Index: units/users/users_event_handler.php =================================================================== --- units/users/users_event_handler.php (revision 14590) +++ units/users/users_event_handler.php (working copy) @@ -17,7 +17,7 @@ class UsersEventHandler extends kDBEventHandler { /** - * Allows to override standart permission mapping + * Allows to override standard permission mapping * */ function mapPermissions() @@ -61,7 +61,10 @@ { parent::OnItemBuild($event); - if ($event->Special == 'forgot') { + $object =& $event->getObject(); + /* @var $object kDBItem */ + + if ( $event->Special == 'forgot' || $object->getFormName() == 'registration' ) { $this->_makePasswordRequired($event); } } @@ -70,8 +73,11 @@ * Shows only admins when required * * @param kEvent $event + * @return void + * @access protected + * @see kDBEventHandler::OnListBuild() */ - function SetCustomQuery(&$event) + protected function SetCustomQuery(&$event) { $object =& $event->getObject(); /* @var $object kDBList */ @@ -110,31 +116,34 @@ } /** - * Checks permissions of user + * Checks user permission to execute given $event * * @param kEvent $event + * @return bool + * @access public */ - function CheckPermission(&$event) + public function CheckPermission(&$event) { - if ($event->Name == 'OnLogin' || $event->Name == 'OnLogout') { + if ( $event->Name == 'OnLogin' || $event->Name == 'OnLogout' ) { // permission is checked in OnLogin event directly return true; } - if (!$this->Application->isAdminUser) { + 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 == USER_GUEST) { + if ( $event->Name == 'OnCreate' && $user_id == USER_GUEST ) { // "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)); + if ( $event->Name == 'OnUpdate' && $user_id > 0 ) { + $user_dummy =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true)); + /* @var $user_dummy UsersItem */ foreach ($items_info as $id => $field_values) { - if ($id != $user_id) { + if ( $id != $user_id ) { // registered users can update their record only return false; } @@ -142,12 +151,12 @@ $user_dummy->Load($id); $status_field = array_shift($this->Application->getUnitOption($event->Prefix, 'StatusField')); - if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) { + 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]) { + if ( isset($field_values[$status_field]) && $user_dummy->GetDBField($status_field) != $field_values[$status_field] ) { // user can't change status by himself return false; } @@ -158,10 +167,10 @@ if ( $event->Name == 'OnResetLostPassword' && $event->Special == 'forgot' && $user_id == USER_GUEST ) { // non-logged in users can reset their password, when reset code is valid - return is_numeric( $this->getPassedID($event) ); + return is_numeric($this->getPassedID($event)); } - if ($event->Name == 'OnUpdate' && $user_id <= 0) { + if ( $event->Name == 'OnUpdate' && $user_id <= 0 ) { // guests are not allowed to update their record, because they don't have it :) return false; } @@ -232,7 +241,7 @@ */ function OnLogin(&$event) { - $object =& $event->getObject(); + $object =& $event->getObject( Array ('form_name' => 'login') ); /* @var $object kDBItem */ $object->SetFieldsFromHash( $this->getSubmittedFields($event) ); @@ -279,6 +288,8 @@ function OnInpLogin(&$event) { $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); + /* @var $sync_manager UsersSyncronizeManager */ + $sync_manager->performAction('LoginUser', $event->getEventParam('user'), $event->getEventParam('pass') ); if ($event->redirect && is_string($event->redirect)) { @@ -295,6 +306,8 @@ function OnInpLogout(&$event) { $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); + /* @var $sync_manager UsersSyncronizeManager */ + $sync_manager->performAction('LogoutUser'); } @@ -308,194 +321,100 @@ } /** - * Redirects user after succesfull registration to confirmation template (on Front only) + * Redirects user after successful registration to confirmation template (on Front only) * * @param kEvent $event + * @return void + * @access protected */ - function OnAfterItemCreate(&$event) + protected function OnAfterItemCreate(&$event) { parent::OnAfterItemCreate($event); $this->afterItemChanged($event); - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $primary_group_id = $object->GetDBField('PrimaryGroupId'); - - if ($primary_group_id) { - $ug_table = TABLE_PREFIX . 'UserGroup'; - - if ( $object->IsTempTable() ) { - $ug_table = $this->Application->GetTempName($ug_table, 'prefix:' . $event->Prefix); - } - - $fields_hash = Array ( - 'PortalUserId' => $object->GetID(), - 'GroupId' => $primary_group_id, - ); - - $this->Conn->doInsert($fields_hash, $ug_table, 'REPLACE'); - } + $this->assignToPrimaryGroup($event); } /** - * Login user if possible, if not then redirect to corresponding template + * Performs user registration * * @param kEvent $event */ - function autoLoginUser(&$event) + function OnCreate(&$event) { - $object =& $event->getObject(); - $this->Application->SetVar('u.current_id', $object->GetID()); + if ( $this->Application->isAdmin ) { + parent::OnCreate($event); - if ( $object->GetDBField('Status') == STATUS_ACTIVE ) { - $user_helper =& $this->Application->recallObject('UserHelper'); - /* @var $user_helper UserHelper */ - - if ( $user_helper->checkLoginPermission() ) { - $user_helper->loginUserById( $object->GetID() ); - } + return ; } - } + $object =& $event->getObject( Array('form_name' => 'registration') ); + /* @var $object UsersItem */ - /** - * 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) ); + $field_values = $this->getSubmittedFields($event); + $user_email = getArrayValue($field_values, 'Email'); + $subscriber_id = $user_email ? $this->getSubscriberByEmail($user_email) : false; - $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 ( $subscriber_id ) { + // update existing subscriber + $object->Load($subscriber_id); + $object->SetDBField('PrimaryGroupId', $this->Application->ConfigValue('User_NewGroup')); + $this->Application->SetVar($event->getPrefixSpecial(true), Array ($object->GetID() => $field_values)); } - if ( isset($event->MasterEvent) ) { - $event->MasterEvent->setEventParam('is_subscriber_only', $ret); - } - else { - $event->setEventParam('is_subscriber_only', $ret); - } - } + $object->SetFieldsFromHash($field_values); + $status = $object->isLoaded() ? $object->Update() : $object->Create(); - /** - * Enter description here... - * - * @param kEvent $event - * @param bool $dry_run - * @return bool - */ - function isSubscriberOnly(&$event, $dry_run = false) - { - $event->CallSubEvent('OnSubstituteSubscriber'); - $is_subscriber = $event->getEventParam('is_subscriber_only'); - - if ($dry_run) { - return $is_subscriber; + if ( !$status ) { + $event->status = kEvent::erFAIL; + $event->redirect = false; + $object->setID( (int)$object->GetID() ); } - if ($is_subscriber) { - $object =& $event->getObject( Array('skip_autoload' => true) ); - $this->OnUpdate($event); + $this->setNextTemplate($event, true); - if ($event->status == kEvent::erSUCCESS) { - $this->OnAfterItemCreate($event); - $object->SendEmailEvents(); + if ( ($event->status == kEvent::erSUCCESS) && $event->redirect ) { + $this->assignToPrimaryGroup($event); - if (!$this->Application->isAdmin && $event->redirect) { - $this->autoLoginUser($event); - } - } + $object->SendEmailEvents(); + $this->autoLoginUser($event); } - - return $is_subscriber; } /** - * Creates new user + * Returns subscribed user ID by given e-mail address * - * @param kEvent $event + * @param string $email */ - function OnCreate(&$event) + function getSubscriberByEmail($email) { - if (!$this->Application->isAdminUser) { - $this->setUserStatus($event); - } + $verify_user =& $this->Application->recallObject('u.verify', null, Array ('skip_autoload' => true)); + /* @var $verify_user UsersItem */ - if ( !$this->isSubscriberOnly($event) ) { - $object =& $event->getObject( Array('skip_autoload' => true) ); - /* @var $object UsersItem */ + $verify_user->Load($email, 'Email'); - if ( $this->Application->ConfigValue('User_Password_Auto') ) { - $password = $object->generatePassword( rand(5, 8) ); - $this->Application->SetVar('user_password', $password); - } - - 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 == kEvent::erSUCCESS) && $event->redirect) { - $object->SendEmailEvents(); - $this->autoLoginUser($event); - } - } + return $verify_user->isLoaded() && $verify_user->isSubscriberOnly() ? $verify_user->GetID() : false; } /** - * Set's new user status based on config options + * Login user if possible, if not then redirect to corresponding template * * @param kEvent $event */ - function setUserStatus(&$event) + function autoLoginUser(&$event) { - $object =& $event->getObject( Array('skip_autoload' => true) ); + $object =& $event->getObject(); + $this->Application->SetVar('u.current_id', $object->GetID()); - $new_users_allowed = $this->Application->ConfigValue('User_Allow_New'); + if ( $object->GetDBField('Status') == STATUS_ACTIVE ) { + $user_helper =& $this->Application->recallObject('UserHelper'); + /* @var $user_helper UserHelper */ - 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; + if ( $user_helper->checkLoginPermission() ) { + $user_helper->loginUserById( $object->GetID() ); + } } } @@ -503,15 +422,23 @@ * Set's new unique resource id to user * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemCreate(&$event) + protected function OnBeforeItemCreate(&$event) { parent::OnBeforeItemCreate($event); + $this->beforeItemChanged($event); + $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ - if ( !$this->isSubscriberOnly($event, true) ) { + $object =& $event->getObject(); + /* @var $object UsersItem */ + + if ( !$object->isSubscriberOnly() ) { + // don't checck state-to-country relations for subscribers $cs_helper->CheckStateField($event, 'State', 'Country'); } @@ -519,13 +446,10 @@ $cs_helper->PopulateStates($event, 'State', 'Country'); - $object =& $event->getObject(); - /* @var $object UsersItem */ - if ( $this->Application->ConfigValue('Email_As_Login') ) { - $field_options = $object->GetFieldOptions('Email'); - $field_options['error_msgs']['unique'] = $this->Application->Phrase('lu_user_and_email_already_exist'); - $object->SetFieldOptions('Email', $field_options); + $error_msgs = $object->GetFieldOption('Email', 'error_msgs'); + $error_msgs['unique'] = '!lu_user_and_email_already_exist!'; + $object->SetFieldOption('Email', 'error_msgs', $error_msgs); } $this->setUserGroup($object); @@ -533,7 +457,7 @@ $user_helper =& $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ - if (!$user_helper->checkBanRules($object)) { + if ( !$user_helper->checkBanRules($object) ) { $object->SetError('Login', 'banned'); } } @@ -571,6 +495,34 @@ } /** + * Assigns a user to it's primary group + * + * @param kEvent $event + */ + protected function assignToPrimaryGroup(&$event) + { + $object =& $event->getObject(); + /* @var $object kDBItem */ + + $primary_group_id = $object->GetDBField('PrimaryGroupId'); + + if ($primary_group_id) { + $ug_table = TABLE_PREFIX . 'UserGroup'; + + if ( $object->IsTempTable() ) { + $ug_table = $this->Application->GetTempName($ug_table, 'prefix:' . $event->Prefix); + } + + $fields_hash = Array ( + 'PortalUserId' => $object->GetID(), + 'GroupId' => $primary_group_id, + ); + + $this->Conn->doInsert($fields_hash, $ug_table, 'REPLACE'); + } + } + + /** * Set's new unique resource id to user * * @param kEvent $event @@ -595,10 +547,9 @@ */ function OnRecommend(&$event) { - $object =& $event->getObject(); + $object =& $event->getObject( Array ('form_name' => 'recommend') ); /* @var $object kDBItem */ - $object->setRequired('RecommendEmail'); $object->SetFieldsFromHash( $this->getSubmittedFields($event) ); if ( !$object->ValidateField('RecommendEmail') ) { @@ -633,13 +584,15 @@ */ function OnUpdateAddress(&$event) { - $object =& $event->getObject( Array('skip_autoload' => true) ); + $object =& $event->getObject(Array ('skip_autoload' => true)); + /* @var $object kDBItem */ - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); + $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); - if ($items_info) { + if ( $items_info ) { list ($id, $field_values) = each($items_info); - if ($id > 0) { + + if ( $id > 0 ) { $object->Load($id); } @@ -663,35 +616,29 @@ */ function OnSubscribeQuery(&$event) { - $user_email = $this->Application->GetVar('subscriber_email'); + $object =& $event->getObject( Array ('form_name' => 'subscription') ); + /* @var $object UsersItem */ - 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 */ + $object->SetFieldsFromHash( $this->getSubmittedFields($event) ); - $object->Load($user_email, 'Email'); - $event->SetRedirectParam('subscriber_email', $user_email); + if ( !$object->ValidateField('SubscriberEmail') ) { + $event->status = kEvent::erFAIL; - if ( $object->isLoaded() ) { - if ( $this->isSubscribed($object) ) { - $event->redirect = $this->Application->GetVar('unsubscribe_template'); - } - else { - $event->redirect = $this->Application->GetVar('subscribe_template'); - } - } - else { - $event->redirect = $this->Application->GetVar('subscribe_template'); - } + return ; } - 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 = kEvent::erFAIL; + $user_email = $object->GetDBField('SubscriberEmail'); + $object->Load($user_email, 'Email'); + $event->SetRedirectParam('subscriber_email', $user_email); + + if ( $object->isLoaded() && $object->isSubscribed() ) { + $event->redirect = $this->Application->GetVar('unsubscribe_template'); } + else { + $event->redirect = $this->Application->GetVar('subscribe_template'); + } + + $event->SetRedirectParam('pass', 'm'); } /** @@ -701,50 +648,59 @@ */ function OnSubscribeUser(&$event) { - $object = &$this->Application->recallObject($this->Prefix . '.subscriber', null, Array('skip_autoload' => true)); + $object =& $event->getObject( Array ('form_name' => 'subscription') ); /* @var $object UsersItem */ $user_email = $this->Application->GetVar('subscriber_email'); + $object->SetDBField('SubscriberEmail', $user_email); - if ( preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $user_email) ) { - $this->RemoveRequiredFields($object); - $object->Load($user_email, 'Email'); + if ( !$object->ValidateField('SubscriberEmail') ) { + $event->status = kEvent::erFAIL; - if ( $object->isLoaded() ) { - if ( $this->isSubscribed($object) ) { - if ( $event->getEventParam('no_unsubscribe') ) { - // for customization code from FormsEventHandler - return ; - } + return ; + } - if ( $object->isSubscriberOnly() ) { - $this->Application->SetVar($object->getPrefixSpecial(true) . '_id', $object->GetID()); - $delete_event = new kEvent($object->getPrefixSpecial() . ':OnDelete'); - $this->Application->HandleEvent($delete_event); - } - else { - $this->RemoveSubscriberGroup( $object->GetID() ); - } + $this->RemoveRequiredFields($object); + $object->Load($user_email, 'Email'); - $event->redirect = $this->Application->GetVar('unsubscribe_ok_template'); + if ( $object->isLoaded() ) { + if ( $object->isSubscribed() ) { + if ( $event->getEventParam('no_unsubscribe') ) { + // for customization code from FormsEventHandler + return ; } + + if ( $object->isSubscriberOnly() ) { + $temp_handler =& $this->Application->recallObject($event->Prefix . '_TempHandler', 'kTempTablesHandler'); + /* @var $temp_handler kTempTablesHandler */ + + $temp_handler->DeleteItems($event->Prefix, '', Array($object->GetID())); + } else { - $this->AddSubscriberGroup($object); - $event->redirect = $this->Application->GetVar('subscribe_ok_template'); + $this->RemoveSubscriberGroup( $object->GetID() ); } + + $event->redirect = $this->Application->GetVar('unsubscribe_ok_template'); } else { - $object->generatePassword(); + $this->AddSubscriberGroup($object); + $event->redirect = $this->Application->GetVar('subscribe_ok_template'); + } + } + else { + $object->generatePassword(); + $object->SetDBField('Email', $user_email); - $object->SetDBField('Email', $user_email); + if ( $object->isRequired('Login') ) { $object->SetDBField('Login', $user_email); - $object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default - $object->SetDBField('ip', $_SERVER['REMOTE_ADDR']); + } - if ( $object->Create() ) { - $this->AddSubscriberGroup($object); - $event->redirect = $this->Application->GetVar('subscribe_ok_template'); - } + $object->SetDBField('Status', STATUS_ACTIVE); // make user subscriber Active by default + $object->SetDBField('ip', $_SERVER['REMOTE_ADDR']); + + if ( $object->Create() ) { + $this->AddSubscriberGroup($object); + $event->redirect = $this->Application->GetVar('subscribe_ok_template'); } } } @@ -787,30 +743,14 @@ } /** - * Checks user subscription status - * - * @param kDBItem $object - * @return bool - */ - function isSubscribed(&$object) - { - $group_id = $this->Application->ConfigValue('User_SubscriberGroup'); - - $sql = 'SELECT GroupId - FROM ' . TABLE_PREFIX . 'UserGroup - WHERE (PortalUserId = ' . $object->GetID() . ') AND (GroupId = ' . $group_id . ')'; - - return $this->Conn->GetOne($sql); - } - - /** - * Checks, that user can reset his password - * + * Validates forgot password form and sends password reset confirmation e-mail + * * @param kEvent $event + * @return void */ function OnForgotPassword(&$event) { - $object =& $event->getObject(); + $object =& $event->getObject( Array ('form_name' => 'forgot_password') ); /* @var $object kDBItem */ $object->SetFieldsFromHash( $this->getSubmittedFields($event) ); @@ -873,28 +813,34 @@ { parent::OnUpdate($event); - $this->setNextTemplate($event); + if ( !$this->Application->isAdmin ) { + $this->setNextTemplate($event); + } } /** * Checks state against country * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeItemUpdate(&$event) + protected function OnBeforeItemUpdate(&$event) { parent::OnBeforeItemUpdate($event); + $this->beforeItemChanged($event); + $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ $cs_helper->CheckStateField($event, 'State', 'Country'); $cs_helper->PopulateStates($event, 'State', 'Country'); - if ($event->Special == 'forgot') { - $object =& $event->getObject(); - /* @var $object kDBItem */ + $object =& $event->getObject(); + /* @var $object kDBItem */ + if ($event->Special == 'forgot') { $object->SetDBField('PwResetConfirm', ''); $object->SetDBField('PwRequestTime_date', NULL); $object->SetDBField('PwRequestTime_time', NULL); @@ -909,26 +855,72 @@ } /** - * Enter description here... + * Occurs before item is changed * * @param kEvent $event */ - function setNextTemplate(&$event) + function beforeItemChanged(&$event) { - if ($this->Application->isAdmin) { - return ; + $object =& $event->getObject(); + /* @var $object UsersItem */ + + if ( !$this->Application->isAdmin && $object->getFormName() == 'registration' ) { + // sets new user's status based on config options + $status_map = Array (1 => STATUS_ACTIVE, 2 => STATUS_DISABLED, 3 => STATUS_PENDING, 4 => STATUS_PENDING); + $object->SetDBField('Status', $status_map[ $this->Application->ConfigValue('User_Allow_New') ]); + + if ( $this->Application->ConfigValue('User_Password_Auto') ) { + $object->generatePassword( rand(5, 8) ); + } + + if ( $this->Application->ConfigValue('RegistrationCaptcha') ) { + $captcha_helper =& $this->Application->recallObject('CaptchaHelper'); + /* @var $captcha_helper kCaptchaHelper */ + + $captcha_helper->validateCode($event, false); + } + + if ( $event->Name == 'OnBeforeItemUpdate' ) { + // when a subscriber-only users performs normal registration, then assign him to Member group + $this->setUserGroup($object); + } } + } + /** + * Sets redirect template based on user status & user request contents + * + * @param kEvent $event + * @param bool $for_registration + */ + function setNextTemplate(&$event, $for_registration = false) + { $event->SetRedirectParam('opener', 's'); + $object =& $event->getObject(); + /* @var $object UsersItem */ - if ($object->GetDBField('Status') == STATUS_ACTIVE) { + $next_template = false; + + if ( $object->GetDBField('Status') == STATUS_ACTIVE && $this->Application->GetVar('next_template') ) { $next_template = $this->Application->GetVar('next_template'); + } + elseif ( $for_registration ) { + switch ( $this->Application->ConfigValue('User_Allow_New') ) { + case 1: // Immediate + $next_template = $this->Application->GetVar('registration_confirm_template'); + break; - if ($next_template) { - $event->redirect = $next_template; + case 3: // Upon Approval + case 4: // Email Activation + $next_template = $this->Application->GetVar('registration_confirm_pending_template'); + break; } } + + if ($next_template) { + $event->redirect = $next_template; + } } /** @@ -982,17 +974,21 @@ } /** - * Enter description here... + * Used to keep user registration form data, while showing affiliate registration form fields * * @param kEvent $event + * @return void + * @access protected */ - function OnRefreshForm(&$event) + protected function OnRefreshForm(&$event) { $event->redirect = false; - $item_info = $this->Application->GetVar($event->getPrefixSpecial()); + $item_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); list($id, $fields) = each($item_info); - $object =& $event->getObject( Array('skip_autoload' => true) ); + $object =& $event->getObject( Array ('skip_autoload' => true) ); + /* @var $object kDBItem */ + $object->setID($id); $object->IgnoreValidation = true; $object->SetFieldsFromHash($fields); @@ -1075,28 +1071,34 @@ * Allows to change root password * * @param kEvent $event + * @return void + * @access protected */ - function OnUpdatePassword(&$event) + protected function OnUpdatePassword(&$event) { - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if (!$items_info) return ; + $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 == USER_ROOT)) { - $user_dummy =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true)); + + if ( $id == $user_id && ($user_id > 0 || $user_id == USER_ROOT) ) { + $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')); + $status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') ); - if ($user_dummy->GetDBField($status_field) != STATUS_ACTIVE) { + 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; + return ; } } - if ($user_id == USER_ROOT) { - $object =& $event->getObject( Array('skip_autoload' => true) ); + if ( $user_id == USER_ROOT ) { + $object =& $event->getObject(Array ('skip_autoload' => true)); /* @var $object UsersItem */ // put salt to user's config @@ -1104,7 +1106,7 @@ $field_options['salt'] = 'b38'; // this is internal hack to allow root/root passwords for dev - if ($this->Application->isDebugMode() && $field_values['RootPassword'] == 'root') { + if ( $this->Application->isDebugMode() && $field_values['RootPassword'] == 'root' ) { $field_options['min_length'] = 4; } @@ -1116,14 +1118,12 @@ $this->RemoveRequiredFields($object); $object->SetDBField('RootPassword', $this->Application->ConfigValue('RootPass')); - $object->SetFieldsFromHash($field_values); - $object->setID(-1); - $status = $object->Validate(); - if ($status) { + $object->SetFieldsFromHash($field_values); + $object->setID(-1); + + if ( $object->Validate() ) { // validation on, password match too - $fields_hash = Array ( - 'VariableValue' => $object->GetDBField('RootPassword') - ); + $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'); @@ -1131,50 +1131,22 @@ else { $event->status = kEvent::erFAIL; $event->redirect = false; - return; + return ; } } else { $object =& $event->getObject(); $object->SetFieldsFromHash($field_values); - if (!$object->Update()) { + if ( !$object->Update() ) { $event->status = kEvent::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)) { @@ -1243,7 +1215,7 @@ * * @param kEvent $event */ - function afterItemChanged(&$event) + protected function afterItemChanged(&$event) { $this->saveUserImages($event); @@ -1263,16 +1235,17 @@ * Stores user's original Status before overwriting with data from temp table * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeDeleteFromLive(&$event) + protected function OnBeforeDeleteFromLive(&$event) { - $user_status = $this->Application->GetVar('user_status'); - if (!$user_status) { - $user_status = Array (); - } + parent::OnBeforeDeleteFromLive($event); $user_id = $event->getEventParam('id'); - if ($user_id > 0) { + $user_status = $this->Application->GetVar('user_status', Array ()); + + if ( $user_id > 0 ) { $user_status[$user_id] = $this->getUserStatus($user_id); $this->Application->SetVar('user_status', $user_status); } @@ -1375,7 +1348,8 @@ { parent::OnAfterConfigRead($event); - $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); + $forms = $this->Application->getUnitOption($event->Prefix, 'Forms'); + $form_fields =& $forms['default']['Fields']; // 1. arrange user registration countries $site_helper =& $this->Application->recallObject('SiteHelper'); @@ -1389,7 +1363,7 @@ if ($first_country) { // update user country dropdown sql - $fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (CountryStateId = '.$first_country.', 1, 0) DESC, \\1', $fields['Country']['options_sql']); + $form_fields['Country']['options_sql'] = preg_replace('/ORDER BY (.*)/', 'ORDER BY IF (CountryStateId = '.$first_country.', 1, 0) DESC, \\1', $form_fields['Country']['options_sql']); } $max_username = $this->Application->ConfigValue('MaxUserName'); @@ -1397,7 +1371,7 @@ $fields['Login']['max_len'] = $max_username ? $max_username : 255; // 2. set default user registration group - $fields['PrimaryGroupId']['default'] = $this->Application->ConfigValue('User_NewGroup'); + $form_fields['PrimaryGroupId']['default'] = $this->Application->ConfigValue('User_NewGroup'); // 3. allow avatar upload on Front-End $file_helper =& $this->Application->recallObject('FileHelper'); @@ -1407,7 +1381,7 @@ if ($this->Application->isAdminUser) { // 4. when in administrative console, then create all users with Active status - $fields['Status']['default'] = STATUS_ACTIVE; + $form_fields['Status']['default'] = STATUS_ACTIVE; // 5. remove groups tab on editing forms when AdvancedUserManagement config variable not set if (!$this->Application->ConfigValue('AdvancedUserManagement')) { @@ -1430,10 +1404,10 @@ if ( !$this->Application->ConfigValue('Email_As_Login') ) { // Login becomes required only, when it's used in registration process - $fields['Login']['required'] = 1; + $form_fields['Login']['required'] = 1; } - $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); + $this->Application->setUnitOption($event->Prefix, 'Forms', $forms); } /** @@ -1460,9 +1434,13 @@ * When cloning users, reset password (set random) * * @param kEvent $event + * @return void + * @access protected */ - function OnBeforeClone(&$event) + protected function OnBeforeClone(&$event) { + parent::OnBeforeClone($event); + $object =& $event->getObject(); /* @var $object UsersItem */ @@ -1539,8 +1517,10 @@ * Loads user images * * @param kEvent $event + * @return void + * @access protected */ - function OnAfterItemLoad(&$event) + protected function OnAfterItemLoad(&$event) { parent::OnAfterItemLoad($event); @@ -1582,13 +1562,15 @@ * Makes password required for new users * * @param kEvent $event + * @return void + * @access protected */ function OnPreCreate(&$event) { parent::OnPreCreate($event); - if ($event->status != kEvent::erSUCCESS) { - return ; + if ( $event->status != kEvent::erSUCCESS ) { + return; } $object =& $event->getObject(); @@ -1596,7 +1578,7 @@ $user_type = $this->Application->GetVar('user_type'); - if ($user_type) { + if ( $user_type ) { $object->SetDBField('UserType', $user_type); if ( $user_type == UserType::ADMIN ) { @@ -1616,41 +1598,27 @@ * * @param kEvent $event */ - function OnNew(&$event) - { - parent::OnNew($event); - - if ($event->status == kEvent::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); - } + $object->setRequired($required_fields); } /** * Load item if id is available * * @param kEvent $event + * @return void + * @access protected */ - function LoadItem(&$event) + protected function LoadItem(&$event) { $id = $this->getPassedID($event); - if ($id < 0) { + if ( $id < 0 ) { // when root, guest and so on $object =& $event->getObject(); Index: units/users/users_item.php =================================================================== --- units/users/users_item.php (revision 14590) +++ units/users/users_item.php (working copy) @@ -43,7 +43,7 @@ function SendEmailEvents() { - switch ($this->GetDBField('Status')) { + switch ( $this->GetDBField('Status') ) { case STATUS_ACTIVE: $event_name = $this->Application->ConfigValue('User_Password_Auto') ? 'USER.VALIDATE' : 'USER.ADD'; $this->Application->EmailEventAdmin($event_name); @@ -62,45 +62,87 @@ * * @return bool */ - function isSubscriberOnly() + public function isSubscriberOnly() { return $this->GetDBField('PrimaryGroupId') == $this->Application->ConfigValue('User_SubscriberGroup'); } - function Create($force_id=false, $system_create=false) + /** + * Checks that user is subscribed + * + * @return bool + */ + public function isSubscribed() { + $group_id = $this->Application->ConfigValue('User_SubscriberGroup'); + + $sql = 'SELECT GroupId + FROM ' . TABLE_PREFIX . 'UserGroup + WHERE (PortalUserId = ' . $this->GetID() . ') AND (GroupId = ' . $group_id . ')'; + + return $this->Conn->GetOne($sql); + } + + /** + * Creates a record in the database table with current item' values + * + * @param mixed $force_id Set to TRUE to force creating of item's own ID or to value to force creating of passed id. Do not pass 1 for true, pass exactly TRUE! + * @param bool $system_create + * @return bool + * @access public + */ + public function Create($force_id = false, $system_create = false) + { $ret = parent::Create($force_id, $system_create); - if ($ret) { - // find out how to syncronize user only when it's copied to live table - $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); + if ( $ret ) { + // find out how to synchronize user only when it's copied to live table + $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize')); + /* @var $sync_manager UsersSyncronizeManager */ + $sync_manager->performAction('createUser', $this->FieldValues); } return $ret; } - - function Update($id=null, $system_update=false) + /** + * Updates previously loaded record with current item' values + * + * @access public + * @param int $id Primary Key Id to update + * @param bool $system_update + * @return bool + * @access public + */ + public function Update($id = null, $system_update = false) { $ret = parent::Update($id, $system_update); - if ($ret) { - // find out how to syncronize user only when it's copied to live table - $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); + + if ( $ret ) { + // find out how to synchronize user only when it's copied to live table + $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize')); + /* @var $sync_manager UsersSyncronizeManager */ + $sync_manager->performAction('updateUser', $this->FieldValues); } + return $ret; } /** - * Deletes the record from databse - * - * @access public - * @return bool - */ - function Delete($id = null) + * Deletes the record from database + * + * @param int $id + * @return bool + * @access public + */ + public function Delete($id = null) { $ret = parent::Delete($id); - if ($ret) { - $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array(), Array ('InPortalSyncronize')); + + if ( $ret ) { + $sync_manager =& $this->Application->recallObject('UsersSyncronizeManager', null, Array (), Array ('InPortalSyncronize')); + /* @var $sync_manager UsersSyncronizeManager */ + $sync_manager->performAction('deleteUser', $this->FieldValues); } Index: units/users/users_tag_processor.php =================================================================== --- units/users/users_tag_processor.php (revision 14590) +++ units/users/users_tag_processor.php (working copy) @@ -162,45 +162,6 @@ return $this->Application->ConfigValue('Smtp_AdminMailFrom'); } - function AffiliatePaymentTypeChecked($params) - { - static $checked = false; - - if( $this->Application->GetVar('PaymentTypeId') ) - { - $apt_object =& $this->Application->recallObject('apt.active'); - if( $this->Application->GetVar('PaymentTypeId') == $apt_object->GetDBField('PaymentTypeId') ) - { - return 1; - } - else - { - return 0; - } - } - - if(!$checked) - { - $checked = true; - return 1; - } - else - { - return 0; - } - } - - function HasError($params) - { - $res = parent::HasError($params); - if($this->SelectParam($params,'field,fields') == 'any') - { - $res = $res || $this->Application->GetVar('MustAgreeToTerms'); // need to do it not put module fields into kernel ! (noticed by Alex) - $res = $res || $this->Application->GetVar('SSNRequiredError'); - } - return $res; - } - /** * Returns login name of user * |