Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Wed, Apr 30, 12:25 AM

in-portal

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: branches/5.0.x/core/kernel/processors/tag_processor.php
===================================================================
--- branches/5.0.x/core/kernel/processors/tag_processor.php (revision 12342)
+++ branches/5.0.x/core/kernel/processors/tag_processor.php (revision 12343)
@@ -1,313 +1,313 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
- class TagProcessor extends kBase {
+ class kTagProcessor extends kBase {
/**
* Processes tag
*
* @param Tag $tag
* @return string
* @access public
*/
function ProcessTag(&$tag)
{
return $this->ProcessParsedTag($tag->Tag, $tag->NP, $tag->getPrefixSpecial());
}
function CheckTag($tag, $prefix)
{
$Method = $tag;
if(method_exists($this, $Method))
{
return true;
}
else {
if ($this->Application->hasObject('TagsAggregator')) {
$aggregator =& $this->Application->recallObject('TagsAggregator');
$tmp = $this->Application->processPrefix($prefix);
$tag_mapping = $aggregator->GetArrayValue($tmp['prefix'], $Method);
if ($tag_mapping) {
return true;
}
}
}
}
function FormCacheKey($tag, $params, $prefix)
{
$k = $this->Application->Parser->TemplateName;
$k .= $prefix.'_'.$tag;
foreach (array('m_cat_id','m_cat_page','m_lang','m_theme') as $m_var) {
$params[$m_var] = $this->Application->GetVar($m_var);
}
ksort($params);
foreach ($params as $p => $v) {
$k .= "$p=$v&";
}
return md5($k);
}
function ProcessParsedTag($tag, $params, $prefix, $file='unknown', $line=0)
{
$Method = $tag;
if (method_exists($this, $Method)) {
if (defined('DEBUG_MODE') && defined('DBG_SHOW_TAGS') && DBG_SHOW_TAGS && $this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Processing PreParsed Tag '.$Method.' in '.$this->Prefix);
}
$backup_prefix = $this->Prefix;
$backup_special = $this->Special;
if ($this->Application->ConfigValue('SystemTagCache') && isset($params['cache_timeout'])) {
if ($res = $this->Application->CacheGet($this->FormCacheKey($tag, $params, $prefix))) {
return $res;
}
}
$original_params = $params;
$flag_values = $this->PreparePostProcess($params);
// pass_params for non ParseBlock tags :)
if ($flag_values['pass_params']) {
$params = array_merge_recursive2($this->Application->Parser->Params, $params);
}
$ret = $this->$Method($params);
$this->Prefix = $backup_prefix;
$this->Special = $backup_special;
$ret = $this->PostProcess($ret, $flag_values);
if ($this->Application->ConfigValue('SystemTagCache') && $flag_values['cache_timeout'] && isset($this->Application->Memcached)) {
$this->Application->CacheSet($this->FormCacheKey($tag, $original_params, $prefix), $ret, $flag_values['cache_timeout']);
}
return $ret;
}
else {
list ($ret, $tag_found) = $this->processAggregatedTag($tag, $params, $prefix, $file, $line);
if ($tag_found) {
return $ret;
}
$this->Application->handleError(E_USER_ERROR, 'Tag Undefined:<br><b>'.$prefix.':'.$tag.'</b>', $file, $line);
return false;
}
}
function processAggregatedTag($tag, $params, $prefix, $file = 'unknown', $line = 0)
{
if ($this->Application->hasObject('TagsAggregator')) {
$Method = $tag;
$aggregator =& $this->Application->recallObject('TagsAggregator');
$tmp = $this->Application->processPrefix($prefix);
$tag_mapping = $aggregator->GetArrayValue($tmp['prefix'], $Method);
if ($tag_mapping) {
// aggregated tag defined
$tmp = $this->Application->processPrefix($tag_mapping[0]);
$__tag_processor = $tmp['prefix'].'_TagProcessor';
$processor =& $this->Application->recallObject($__tag_processor);
$processor->Prefix = $tmp['prefix'];
$processor->Special = getArrayValue($tag_mapping, 2) ? $tag_mapping[2] : $tmp['special'];
$params['original_tag'] = $Method; // allows to define same method for different aggregated tags in same tag processor
$params['PrefixSpecial'] = $this->getPrefixSpecial(); // $prefix;
$ret = $processor->ProcessParsedTag($tag_mapping[1], $params, $prefix);
if (isset($params['result_to_var'])) {
$this->Application->Parser->SetParam($params['result_to_var'], $ret);
$ret = '';
}
return Array ($ret, true);
}
else {
// aggregated tag not defined
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendTrace();
}
$this->Application->handleError(E_USER_ERROR, 'Tag <b>'.$Method.'</b> Undefined in '.get_class($this).'[Agregated Tag]:<br><b>'.$tag.'</b>', $file, $line);
}
}
return Array ('', false);
}
function PreparePostProcess(&$params)
{
$flags = Array('js_escape', 'equals_to', 'result_to_var', 'pass_params', 'html_escape', 'strip_nl', 'trim', 'cache_timeout');
$flag_values = Array();
foreach ($flags as $flag_name) {
$flag_values[$flag_name] = false;
if (isset($params[$flag_name])) {
$flag_values[$flag_name] = $params[$flag_name];
unset($params[$flag_name]);
}
}
return $flag_values;
}
function PostProcess($ret, $flag_values)
{
if ($flag_values['html_escape']) {
$ret = htmlspecialchars($ret);
}
if ($flag_values['js_escape']) {
$ret = addslashes($ret);
$ret = str_replace(Array("\r", "\n"), Array('\r', '\n'), $ret);
$ret = str_replace('</script>', "</'+'script>", $ret);
}
if ($flag_values['strip_nl']) {
// 1 - strip \r,\n; 2 - strip tabs too
$ret = preg_replace($flag_values['strip_nl'] == 2 ? "/[\r\n\t]/" : "/[\r\n]/", '', $ret);
}
if ($flag_values['trim']) {
$ret = trim($ret);
}
// TODO: in new parser implement this parameter in compiled code (by Alex)
if ($flag_values['equals_to'] !== false) {
$equals_to = explode('|', $flag_values['equals_to']);
$ret = in_array($ret, $equals_to);
}
if ($flag_values['result_to_var']) {
$this->Application->Parser->SetParam($flag_values['result_to_var'], $ret);
$ret = '';
}
return $ret;
}
/**
* Not tag, method for parameter
* selection from list in this TagProcessor
*
* @param Array $params
* @param string $possible_names
* @return string
* @access public
*/
function SelectParam($params, $possible_names = null)
{
if (!isset($possible_names)) {
// select 1st parameter non-empty parameter value
$possible_names = explode(',', $params['possible_names']);
foreach ($possible_names as $param_name) {
$value = $this->Application->Parser->GetParam($param_name);
if (((string)$value != '') && ((string)$value != '0')) {
return $value;
}
}
return '';
}
if (!is_array($params)) {
// really happens?
return;
}
if (!is_array($possible_names)) {
$possible_names = explode(',', $possible_names);
}
foreach ($possible_names as $name) {
if( isset($params[$name]) ) return $params[$name];
}
return false;
}
/**
* Returns templates path for module, which is gathered from prefix module
*
* @param Array $params
* @return string
* @author Alex
*/
function ModulePath($params)
{
$force_module = getArrayValue($params, 'module');
if ($force_module) {
if ($force_module == '#session#') {
$force_module = preg_replace('/([^:]*):.*/', '\1', $this->Application->RecallVar('module'));
if (!$force_module) $force_module = 'core';
}
else {
$force_module = mb_strtolower($force_module);
}
if ($force_module == 'core') {
$module_folder = 'core';
}
else {
$module_folder = trim( $this->Application->findModule('Name', $force_module, 'Path'), '/');
}
}
else {
$module_folder = $this->Application->getUnitOption($this->Prefix, 'ModuleFolder');
}
return '../../'.$module_folder.'/admin_templates/';
}
}
/*class ProcessorsPool {
var $Processors = Array();
var $Application;
var $Prefixes = Array();
var $S;
function ProcessorsPool()
{
$this->Application =& KernelApplication::Instance();
$this->S =& $this->Application->Session;
}
function RegisterPrefix($prefix, $path, $class)
{
// echo " RegisterPrefix $prefix, $path, $class <br>";
$prefix_item = Array(
'path' => $path,
'class' => $class
);
$this->Prefixes[$prefix] = $prefix_item;
}
function CreateProcessor($prefix, &$tag)
{
// echo " prefix : $prefix <br>";
if (!isset($this->Prefixes[$prefix]))
$this->Application->ApplicationDie ("<b>Filepath and ClassName for prefix $prefix not defined while processing ".htmlspecialchars($tag->GetFullTag())."!</b>");
include_once($this->Prefixes[$prefix]['path']);
$ClassName = $this->Prefixes[$prefix]['class'];
$a_processor = new $ClassName($prefix);
$this->SetProcessor($prefix, $a_processor);
}
function SetProcessor($prefix, &$a_processor)
{
$this->Processors[$prefix] =& $a_processor;
}
function &GetProcessor($prefix, &$tag)
{
if (!isset($this->Processors[$prefix]))
$this->CreateProcessor($prefix, $tag);
return $this->Processors[$prefix];
}
}*/
\ No newline at end of file
Index: branches/5.0.x/core/kernel/processors/main_processor.php
===================================================================
--- branches/5.0.x/core/kernel/processors/main_processor.php (revision 12342)
+++ branches/5.0.x/core/kernel/processors/main_processor.php (revision 12343)
@@ -1,1006 +1,1006 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
-class kMainTagProcessor extends TagProcessor {
+class kMainTagProcessor extends kTagProcessor {
function Init($prefix, $special, $event_params = null)
{
parent::Init($prefix, $special, $event_params);
$actions =& $this->Application->recallObject('kActions');
$actions->Set('t', $this->Application->GetVar('t'));
$actions->Set('sid', $this->Application->GetSID());
$actions->Set('m_opener', $this->Application->GetVar('m_opener') );
}
/**
* Base folder for all template includes
*
* @param Array $params
* @return string
*/
function TemplatesBase($params)
{
$force_admin = array_key_exists('force_admin', $params) && $params['force_admin'];
$module = array_key_exists('module', $params) ? $params['module'] : 'core';
if ($this->Application->IsAdmin() || $force_admin) {
if ($module == 'in-portal') {
$module = 'kernel';
}
$path = $force_admin ? '/core/admin_templates' : THEMES_PATH;
$path = preg_replace('/\/(.*?)\/(.*)/', $module.'/\\2', $path); // remove leading slash + substitute module
}
else {
$path = mb_substr(THEMES_PATH, 1);
if (mb_strtolower($module) == 'in-portal') {
$module_folder = 'platform';
}
else {
$module_folder = $this->Application->findModule('Name', $module, 'TemplatePath');
}
$path .= rtrim('/' . trim($module_folder, '/'), '/') . '/';
}
return $this->Application->BaseURL() . $path;
}
/**
* Creates <base href ..> HTML tag for all templates
* affects future css, js files and href params of links
*
* @return string
* @access public
*/
function Base_Ref($params)
{
return '<base href="'.$this->TemplatesBase($params).'/" />';
}
/**
* Returns base url for web-site
*
* @return string
* @access public
*/
function BaseURL()
{
return $this->Application->BaseURL();
}
//for compatability with K3 tags
function Base($params)
{
return $this->TemplatesBase($params).'/';
}
function ProjectBase($params)
{
return $this->Application->BaseURL();
}
/*function Base($params)
{
return $this->Application->BaseURL().$params['add'];
}*/
/**
* Used to create link to any template.
* use "pass" paramter if "t" tag to specify
* prefix & special of object to be represented
* in resulting url
*
* @param Array $params
* @return string
* @access public
*/
function T($params)
{
//by default link to current template
$t = $this->SelectParam($params, 't,template');
unset($params['t']);
unset($params['template']);
$prefix=isset($params['prefix']) ? $params['prefix'] : ''; unset($params['prefix']);
$index_file = isset($params['index_file']) ? $params['index_file'] : null; unset($params['index_file']);
return $this->Application->HREF($t, $prefix, $params, $index_file);
}
function Link($params)
{
if (isset($params['template'])) {
$params['t'] = $params['template'];
unset($params['template']);
}
if (!isset($params['pass']) && !isset($params['no_pass'])) $params['pass'] = 'm';
if (isset($params['no_pass'])) unset($params['no_pass']);
if ( $this->Application->GetVar('admin') ) {
$params['admin'] = 1;
if (!array_key_exists('editing_mode', $params)) {
$params['editing_mode'] = EDITING_MODE;
}
}
return $this->T($params);
}
function Env($params)
{
$t = $params['template'];
unset($params['template']);
return $this->Application->BuildEnv($t, $params, 'm', null, false);
}
function FormAction($params)
{
$params['pass'] = 'all,m';
$params['pass_category'] = 1;
return $this->Application->HREF('', '', $params);
}
/*// NEEDS TEST
function Config($params)
{
return $this->Application->ConfigOption($params['var']);
}
function Object($params)
{
$name = $params['name'];
$method = $params['method'];
$tmp =& $this->Application->recallObject($name);
if ($tmp != null) {
if (method_exists($tmp, $method))
return $tmp->$method($params);
else
echo "Method $method does not exist in object ".get_class($tmp)." named $name<br>";
}
else
echo "Object $name does not exist in the appliaction<br>";
}*/
/**
* Tag, that always returns true.
* For parser testing purposes
*
* @param Array $params
* @return bool
* @access public
*/
function True($params)
{
return true;
}
/**
* Tag, that always returns false.
* For parser testing purposes
*
* @param Array $params
* @return bool
* @access public
*/
function False($params)
{
return false;
}
/**
* Returns block parameter by name (used only as "check" parameter value for "m_if" tag !)
*
* @param Array $params
* @return stirng
* @access public
*/
function Param($params)
{
$name = $params['name'];
/*if (isset($this->Application->LateParsed[$name])) {
$f = $this->Application->PreParsedBlocks['capture_'.$name.$this->Application->LateParsed[$name]];
$this->Application->Parser->SetParam($name, $f(array()));
}*/
$res = $this->Application->Parser->GetParam($params['name']);
if ($res === false) {
$res = '';
}
if (isset($params['plus'])) {
$res += $params['plus'];
}
return $res;
}
/**
* Compares block parameter with value specified
*
* @param Array $params
* @return bool
* @access public
*/
function ParamEquals($params)
{
$name = $this->SelectParam($params, 'name,var,param');
$value = $params['value'];
return ($this->Application->Parser->GetParam($name) == $value);
}
/*function PHP_Self($params)
{
return $HTTP_SERVER_VARS['PHP_SELF'];
}
*/
/**
* Returns session variable value by name
*
* @param Array $params
* @return string
* @access public
*/
function Recall($params)
{
$var_name = $this->SelectParam($params,'name,var,param');
if (isset($params['persistent']) && $params['persistent']) {
$ret = $this->Application->RecallPersistentVar($var_name);
}
else {
$ret = $this->Application->RecallVar($var_name);
}
$ret = ($ret === false && isset($params['no_null'])) ? '' : $ret;
if (getArrayValue($params, 'special') || getArrayValue($params, 'htmlchars')) {
$ret = htmlspecialchars($ret);
}
if (getArrayValue($params, 'urlencode')) {
$ret = urlencode($ret);
}
return $ret;
}
function RemoveVar($params)
{
$this->Application->RemoveVar( $this->SelectParam($params,'name,var,param') );
}
// bad style to store something from template to session !!! (by Alex)
// Used here only to test how session works, nothing more
function Store($params)
{
//echo"Store $params[name]<br>";
$name = $params['name'];
$value = $params['value'];
$this->Application->StoreVar($name,$value);
}
/**
* Sets application variable value(-s)
*
* @param Array $params
* @access public
*/
function Set($params)
{
foreach ($params as $param => $value) {
$this->Application->SetVar($param, $value);
}
}
/**
* Increment application variable
* specified by number specified
*
* @param Array $params
* @access public
*/
function Inc($params)
{
$this->Application->SetVar($params['param'], $this->Application->GetVar($params['param']) + $params['by']);
}
/**
* Retrieves application variable
* value by name
*
* @param Array $params
* @return string
* @access public
*/
function Get($params)
{
$ret = $this->Application->GetVar($this->SelectParam($params, 'name,var,param'), '');
return getArrayValue($params, 'htmlchars') ? htmlspecialchars($ret) : $ret;
}
/**
* Retrieves application constant
* value by name
*
* @param Array $params
* @return string
* @access public
*/
function GetConst($params)
{
$constant_name = $this->SelectParam($params, 'name,const');
return defined($constant_name) ? constant($constant_name) : '';
}
/**
* Retrieves configuration variable value by name
*
* @param Array $params
* @return string
* @access public
*/
function GetConfig($params)
{
$config_name = $this->SelectParam($params, 'name,var');
$ret = $this->Application->ConfigValue($config_name);
if( getArrayValue($params, 'escape') ) $ret = addslashes($ret);
return $ret;
}
function ConfigEquals($params)
{
$option = $this->SelectParam($params, 'name,option,var');
return $this->Application->ConfigValue($option) == getArrayValue($params, 'value');
}
/**
* Creates all hidden fields
* needed for kernel_form
*
* @param Array $params
* @return string
* @access public
*/
function DumpSystemInfo($params)
{
$actions =& $this->Application->recallObject('kActions');
$actions->Set('t', $this->Application->GetVar('t') );
$params = $actions->GetParams();
$o='';
foreach ($params AS $name => $val)
{
$o .= "<input type='hidden' name='$name' id='$name' value='$val'>\n";
}
return $o;
}
/**
* Used for search sidebox on front-end only
*
* @param Array $params
* @return string
* @author Alex
*/
function GetFormHiddens($params)
{
$t = $this->SelectParam($params, 'template,t');
unset($params['template']);
$form_fields = Array ();
if ($this->Application->RewriteURLs()) {
$session =& $this->Application->recallObject('Session');
if ($session->NeedQueryString()) {
$form_fields['sid'] = $this->Application->GetSID();
}
}
else {
$form_fields['env'] = $this->Application->BuildEnv($t, $params, 'm', null, false);
}
if ($this->Application->GetVar('admin') == 1) {
$form_fields['admin'] = 1;
}
$ret = '';
$field_tpl = '<input type="hidden" name="%1$s" id="%1$s" value="%2$s"/>'."\n";
foreach ($form_fields as $form_field => $field_value) {
$ret .= sprintf($field_tpl, $form_field, $field_value);
}
return $ret;
}
function Odd_Even($params)
{
$odd = $params['odd'];
$even = $params['even'];
if (!isset($params['var'])) {
$var = 'odd_even';
}
else {
$var = $params['var'];
}
if ($this->Application->GetVar($var) == 'even') {
if (!isset($params['readonly']) || !$params['readonly']) {
$this->Application->SetVar($var, 'odd');
}
return $even;
}
else {
if (!isset($params['readonly']) || !$params['readonly']) {
$this->Application->SetVar($var, 'even');
}
return $odd;
}
}
/**
* Returns phrase translation by name
*
* @param Array $params
* @return string
* @access public
*/
function Phrase($params)
{
// m:phrase name="phrase_name" default="Tr-alala" updated="2004-01-29 12:49"
$phrase_name = $this->SelectParam($params, 'label,name,title');
if (isset($params['source']) && $params['source']) {
$phrase_name = $this->Application->GetVar($phrase_name);
if (array_key_exists('default', $params) && !$phrase_name) {
$phrase_name = $params['default'];
}
}
$no_editing = array_key_exists('no_editing', $params) && $params['no_editing'];
$translation = $this->Application->Phrase($phrase_name, !$no_editing);
if (isset($params['escape']) && $params['escape']) {
$translation = htmlspecialchars($translation, ENT_QUOTES);
$translation = addslashes($translation);
}
return $translation;
}
// for tabs
function is_active($params)
{
$test_templ = $this->SelectParam($params, 'templ,template,t');
if ( !getArrayValue($params,'allow_empty') )
{
$if_true=getArrayValue($params,'true') ? $params['true'] : 1;
$if_false=getArrayValue($params,'false') ? $params['false'] : 0;
}
else
{
$if_true=$params['true'];
$if_false=$params['false'];
}
if ( preg_match("/^".str_replace('/', '\/', $test_templ)."/i", $this->Application->GetVar('t'))) {
return $if_true;
}
else {
return $if_false;
}
}
function IsNotActive($params)
{
return !$this->is_active($params);
}
function IsActive($params)
{
return $this->is_active($params);
}
function is_t_active($params)
{
return $this->is_active($params);
}
function CurrentTemplate($params)
{
return $this->is_active($params);
}
/**
* Checks if session variable
* specified by name value match
* value passed as parameter
*
* @param Array $params
* @return string
* @access public
*/
function RecallEquals($params)
{
$name = $this->SelectParam($params, 'name,var');
$value = $params['value'];
if (isset($params['persistent']) && $params['persistent']) {
return $this->Application->RecallPersistentVar($name) == $value;
}
return ($this->Application->RecallVar($name) == $value);
}
/**
* Checks if application variable
* specified by name value match
* value passed as parameter
*
* @param Array $params
* @return bool
* @access public
*/
function GetEquals($params)
{
$name = $this->SelectParam($params, 'var,name,param');
$value = $params['value'];
if ($this->Application->GetVar($name) == $value) {
return 1;
}
}
function ModuleInclude($params)
{
$ret = '';
$block_params = array_merge($params, Array('is_silent' => 2)); // don't make fatal errors in case if template is missing
$current_template = $this->Application->GetVar('t');
$replace_main = isset($params['replace_m']) && $params['replace_m'];
$skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array();
$cms_mode = $this->Application->GetVar('admin');
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$module_key = mb_strtolower($module_name);
if ($module_name == 'In-Portal') {
if (!$cms_mode && $this->Application->IsAdmin()) {
// don't process In-Portal templates in admin
continue;
}
// Front-End still relies on In-Portal module
$module_prefix = $module_data['TemplatePath'];
}
else {
$module_prefix = $this->Application->IsAdmin() ? $module_key.'/' : rtrim($module_data['TemplatePath'], '/').'/';
}
$block_params['t'] = $module_prefix.$this->SelectParam($params, $module_key.'_template,'.$module_key.'_t,template,t');
$check_prefix = $module_data['Var'];
if ($check_prefix == 'adm' && $replace_main) {
$check_prefix = 'c';
}
if ($block_params['t'] == $current_template || in_array($check_prefix, $skip_prefixes)) {
continue;
}
$no_data = $this->SelectParam($params, $module_key.'_block_no_data,block_no_data');
if ($no_data) {
$block_params['block_no_data'] = $module_prefix.'/'.$no_data;
}
$ret .= $this->Application->Parser->IncludeTemplate($block_params, isset($block_params['is_silent']) ? 1 : 0);
}
return $ret;
}
function ModuleEnabled($params)
{
return $this->Application->isModuleEnabled( $params['module'] );
}
/**
* Checks if debug mode is on
*
* @param Array $params
* @return bool
* @access public
*/
function IsDebugMode($params)
{
return defined('DEBUG_MODE') && $this->Application->isDebugMode();
}
/*function MassParse($params)
{
$qty = $params['qty'];
$block = $params['block'];
$mode = $params['mode'];
$o = '';
if ($mode == 'func') {
$func = create_function('$params', '
$o = \'<tr>\';
$o.= \'<td>a\'.$params[\'param1\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param2\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param3\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param4\'].\'</td>\';
$o.= \'</tr>\';
return $o;
');
for ($i=1; $i<$qty; $i++) {
$block_params['param1'] = rand(1, 10000);
$block_params['param2'] = rand(1, 10000);
$block_params['param3'] = rand(1, 10000);
$block_params['param4'] = rand(1, 10000);
$o .= $func($block_params);
}
return $o;
}
$block_params['name'] = $block;
for ($i=0; $i<$qty; $i++) {
$block_params['param1'] = rand(1, 10000);
$block_params['param2'] = rand(1, 10000);
$block_params['param3'] = rand(1, 10000);
$block_params['param4'] = rand(1, 10000);
$block_params['passed'] = $params['passed'];
$block_params['prefix'] = 'm';
$o.= $this->Application->ParseBlock($block_params, 1);
}
return $o;
}*/
function LoggedIn($params)
{
return $this->Application->LoggedIn();
}
/**
* Allows to check if permission exists directly in template and perform additional actions if required
*
* @param Array $params
* @return bool
*/
function CheckPermission($params)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
return $perm_helper->TagPermissionCheck($params);
}
/**
* Checks if user is logged in and if not redirects it to template passed
*
* @param Array $params
*/
function RequireLogin($params)
{
$t = $this->Application->GetVar('t');
if ($next_t = getArrayValue($params, 'next_template')) {
$t = $next_t;
}
// check by permissions: begin
if ((isset($params['perm_event']) && $params['perm_event']) ||
(isset($params['perm_prefix']) && $params['perm_prefix']) ||
(isset($params['permissions']) && $params['permissions'])) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_status = $perm_helper->TagPermissionCheck($params);
if (!$perm_status) {
list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params);
$this->Application->Redirect($redirect_template, $redirect_params);
}
else {
return ;
}
}
// check by permissions: end
// check by configuration value: begin
$condition = getArrayValue($params, 'condition');
if (!$condition) {
$condition = true;
}
else {
if (substr($condition, 0, 1) == '!') {
$condition = !$this->Application->ConfigValue(substr($condition, 1));
}
else {
$condition = $this->Application->ConfigValue($condition);
}
}
// check by configuration value: end
// check by belonging to group: begin
$group = $this->SelectParam($params, 'group');
$group_access = true;
if ($group) {
$conn =& $this->Application->GetADODBConnection();
$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
if ($group_id) {
$groups = explode(',', $this->Application->RecallVar('UserGroups'));
$group_access = in_array($group_id, $groups);
}
}
// check by belonging to group: end
if ((!$this->Application->LoggedIn() || !$group_access) && $condition) {
$redirect_params = $this->Application->HttpQuery->getRedirectParams(true);
$redirect_params['next_template'] = $t;
if (array_key_exists('pass_category', $params)) {
$redirect_params['pass_category'] = $params['pass_category'];
}
if ( $this->Application->LoggedIn() && !$group_access) {
$this->Application->Redirect( $params['no_group_perm_template'], $redirect_params);
}
$this->Application->Redirect($params['login_template'], $redirect_params);
}
}
function IsMember($params)
{
$group = getArrayValue($params, 'group');
$conn =& $this->Application->DB;
$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
if ($group_id) {
$groups = explode(',', $this->Application->RecallVar('UserGroups'));
$group_access = in_array($group_id, $groups);
}
return $group_access;
}
/**
* Checks if SSL is on and redirects to SSL URL if needed
* If SSL_URL is not defined in config - the tag does not do anything
* If for_logged_in_only="1" exits if user is not logged in.
* If called without params forces https right away. If called with by_config="1" checks the
* Require SSL setting from General Config and if it is ON forces https
*
* @param unknown_type $params
*/
function CheckSSL($params)
{
$ssl = $this->Application->IsAdmin() ? $this->Application->ConfigValue('AdminSSL_URL') : false;
if (!$ssl) {
// not in admin or admin ssl url is empty
$ssl = $this->Application->ConfigValue('SSL_URL');
}
if (!$ssl) return; //SSL URL is not set - no way to require SSL
$require = false;
if (isset($params['mode']) && $params['mode'] == 'required') {
$require = true;
if (isset($params['for_logged_in_only']) && $params['for_logged_in_only'] && !$this->Application->LoggedIn()) {
$require = false;
}
if (isset($params['condition'])) {
if (!$this->Application->ConfigValue($params['condition'])) {
$require = false;
}
}
}
$http_query =& $this->Application->recallObject('HTTPQuery');
$pass = $http_query->getRedirectParams();
if ($require) {
if (PROTOCOL == 'https://') {
$this->Application->SetVar('__KEEP_SSL__', 1);
return;
}
$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 1)));
}
else {
if (PROTOCOL == 'https://' && $this->Application->ConfigValue('Force_HTTP_When_SSL_Not_Required')) {
if ($this->Application->GetVar('__KEEP_SSL__')) return;
// $pass_more = Array ('pass' => 'm', 'm_cat_id' => 0, '__SSL__' => 0);
$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 0))); // $pass_more
}
}
}
function ConstOn($params)
{
$name = $this->SelectParam($params,'name,const');
return constOn($name);
}
function SetDefaultCategory($params)
{
$category_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
$this->Application->SetVar('m_cat_id', $category_id);
}
function XMLTemplate($params)
{
safeDefine('DBG_SKIP_REPORTING', 1);
if (isset($params['cache']) && $params['cache']) {
$nextyear = intval(date('Y') + 1);
$format = "D, d M Y H:i:s";
$expiration = gmdate($format, mktime() + $params['cache']).' GMT';
$last_modified = mktime();
header ('Cache-Control: public, cache, max-age='.$params['cache']);
header ("Expires: $expiration");
header ('Pragma: public');
// Getting headers sent by the client.
$headers = request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) > $last_modified-$params['cache'])) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.date($format, strtotime($headers['If-Modified-Since'])).' GMT', true, 304);
exit();
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate($format, $last_modified).' GMT', true, 200);
}
}
// xml documents are usually long
set_time_limit(0);
ini_set('memory_limit', -1);
return $this->Application->XMLHeader(getArrayValue($params, 'xml_version'));
}
function Header($params)
{
header($params['data']);
}
function NoDebug($params)
{
if (!$this->Application->GetVar('debug')) {
define('DBG_SKIP_REPORTING', 1);
}
}
function RootCategoryName($params)
{
$root_phrase = $this->Application->ConfigValue('Root_Name');
return $this->Application->Phrase($root_phrase);
}
/**
* Allows to attach file directly from email event template
*
* @param Array $params
*/
function AttachFile($params)
{
$esender =& $application->recallObject('EmailSender'.(isset($params['special']) ? '.'.$params['special'] : ''));
/* @var $esender kEmailSendingHelper */
$path = FULL_PATH.'/'.$params['path'];
if (file_exists($path)) {
$esender->AddAttachment($path);
}
}
function CaptchaImage($params)
{
$this->Application->SetVar('skip_last_template', 1);
$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
/* @var $captcha_helper kCaptchaHelper */
$captcha_helper->GenerateCaptchaImage(
$this->Application->RecallVar($this->Application->GetVar('var')),
$this->Application->GetVar('w'),
$this->Application->GetVar('h'),
true
);
}
function SID($params)
{
return $this->Application->GetSID();
}
function ModuleInfo($params)
{
return $this->Application->findModule($params['key'], $params['value'], $params['return']);
}
function Random($params)
{
return rand(1, 100000000);
}
/**
* Prints parser params, available at current deep level
*
* @param Array $params
* @return string
*/
function PrintCurrentParams($params)
{
$current_params = $this->Application->Parser->Params;
foreach ($current_params as $param_name => $param_value) {
$current_params[$param_name] = $param_name . ' = "' . $param_value . '"';
}
return '<pre>' . implode("\n", $current_params) . '</pre>';
}
/**
* Gets previously defined counter result
*
* @param Array $params
* @return int
*/
function GetCounter($params)
{
return $this->Application->getCounter($params['name'], $params);
}
/**
* Increments PageHit counter
*
* @param Array $params
* @return int
*/
function RegisterPageHit($params)
{
if ($this->Application->ConfigValue('UsePageHitCounter')) {
$db =& $this->Application->GetADODBConnection();
// get current counte
$sql = 'SELECT VariableValue
FROM '.TABLE_PREFIX.'ConfigurationValues
WHERE VariableName = "PageHitCounter"';
$page_counter = (int)$db->GetOne($sql);
$sql = 'UPDATE LOW_PRIORITY '.TABLE_PREFIX.'ConfigurationValues
SET VariableValue = '.($page_counter + 1).'
WHERE VariableName = "PageHitCounter"';
$db->Query($sql);
}
}
function Timestamp($params)
{
$format = isset($params['format']) ? $params['format'] : 'd.m.Y H:i:s';
return adodb_date($format);
}
}
Index: branches/5.0.x/core/kernel/session/inp_session.php
===================================================================
--- branches/5.0.x/core/kernel/session/inp_session.php (nonexistent)
+++ branches/5.0.x/core/kernel/session/inp_session.php (revision 12343)
@@ -0,0 +1,148 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class InpSession extends Session
+ {
+ function Init($prefix,$special)
+ {
+ $this->SessionTimeout = $this->Application->ConfigValue('SessionTimeout');
+
+ $path = (BASE_PATH == '') ? '/' : BASE_PATH;
+// if ( $this->Application->IsAdmin() ) $path = rtrim($path, '/').'/admin';
+ $this->SetCookiePath($path);
+
+ $cookie_name = $this->Application->ConfigValue('SessionCookieName');
+ if (!$cookie_name) $cookie_name = 'sid';
+ if (($this->Application->IsAdmin() && $special !== 'front') || $special == 'admin' ) { // || $this->Application->GetVar('admin') == 1
+ $cookie_name = 'adm_'.$cookie_name;
+ }
+ $this->SetCookieName($cookie_name);
+
+ $this->SetCookieDomain(SERVER_NAME);
+
+ if( $this->Application->IsAdmin()) { // && $this->Application->GetVar('admin') != 1
+ $mode = smAUTO;
+ }
+ elseif (constOn('IS_INSTALL')) {
+ $mode = smCOOKIES_ONLY;
+ }
+ else {
+ $ses_mode = $this->Application->ConfigValue('CookieSessions');
+ if ($ses_mode == 2) $mode = smAUTO;
+ if ($ses_mode == 1) $mode = smCOOKIES_ONLY;
+ if ($ses_mode == 0) $mode = smGET_ONLY;
+ }
+ $this->SetMode($mode);
+
+ parent::Init($prefix,$special);
+
+ if( !$this->Application->IsAdmin() && $this->GetField('PortalUserId') <= 0 )
+ {
+ $group_list = $this->Application->ConfigValue('User_GuestGroup').','.$this->Application->ConfigValue('User_LoggedInGroup');
+ $this->SetField('GroupId', $this->Application->ConfigValue('User_GuestGroup'));
+ $this->SetField('GroupList', $group_list);
+ }
+ }
+
+ function Destroy()
+ {
+ $this->Storage->DeleteSession($this);
+ $this->Storage->DeleteEditTables();
+ $this->Data = new Params();
+ $this->SID = $this->CachedSID = '';
+ if ($this->CookiesEnabled) $this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty
+
+ $this->SetSession(); //will create a new session
+ }
+
+ }
+
+class InpSessionStorage extends SessionStorage {
+
+ function Init($prefix,$special)
+ {
+ parent::Init($prefix,$special);
+ $this->setTableName(TABLE_PREFIX.'UserSession');
+ $this->SessionDataTable = TABLE_PREFIX.'SessionData';
+ $this->setIDField('SessionKey');
+ $this->TimestampField = 'LastAccessed';
+ $this->DataValueField = 'VariableValue';
+ $this->DataVarField = 'VariableName';
+ }
+
+ function LocateSession($sid)
+ {
+ $res = parent::LocateSession($sid);
+ if ($res) {
+ $this->Expiration += $this->SessionTimeout;
+ }
+ return $res;
+ }
+
+ function UpdateSession(&$session)
+ {
+ $time = adodb_mktime();
+ // Update LastAccessed only if it's newer than 1/10 of session timeout - perfomance optimization to eliminate needless updates on every click
+// if ($time - $this->DirectVars['LastAccessed'] > $this->SessionTimeout/10) {
+ $this->SetField($session, $this->TimestampField, $time + $this->SessionTimeout);
+// }
+ }
+
+
+ function StoreSession(&$session, $additional_fields = Array())
+ {
+ $fields_hash = Array (
+ 'PortalUserId' => $this->Application->IsAdmin() ? 0 : -2, // Guest
+ 'Language' => $this->Application->GetDefaultLanguageId(),
+ 'Theme' => $this->Application->GetDefaultThemeId(),
+ 'IpAddress' => $_SERVER['REMOTE_ADDR'],
+ 'GroupId' => $this->Application->ConfigValue('User_GuestGroup'),
+ 'GroupList' => $this->Application->ConfigValue('User_GuestGroup'),
+ 'CurrentTempKey'=> $session->SID,
+ );
+
+ parent::StoreSession($session, $fields_hash);
+ }
+
+ function GetExpiredSIDs()
+ {
+ $query = ' SELECT '.$this->IDField.' FROM '.$this->TableName.' WHERE '.$this->TimestampField.' < '.(adodb_mktime());
+ $ret = $this->Conn->GetCol($query);
+ if($ret) {
+ $this->DeleteEditTables();
+ }
+ return $ret;
+
+ }
+
+ function DeleteEditTables()
+ {
+ $tables = $this->Conn->GetCol('SHOW TABLES');
+ $mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_(.*)/';
+ $mask_search_table = '/'.TABLE_PREFIX.'ses_(.*?)_(.*)/';
+
+ $sql='SELECT COUNT(*) FROM '.$this->TableName.' WHERE '.$this->IDField.' = \'%s\'';
+ foreach($tables as $table)
+ {
+ if( preg_match($mask_edit_table,$table,$rets) || preg_match($mask_search_table,$table,$rets) )
+ {
+ $sid = preg_replace('/(.*)_(.*)/', '\\1', $rets[1]); // remove popup's wid from sid
+ $is_alive = $this->Conn->GetOne( sprintf($sql,$sid) );
+ if(!$is_alive) $this->Conn->Query('DROP TABLE IF EXISTS '.$table);
+ }
+ }
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/kernel/session/inp_session.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.23.2.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/kernel/db/cat_dbitem.php
===================================================================
--- branches/5.0.x/core/kernel/db/cat_dbitem.php (nonexistent)
+++ branches/5.0.x/core/kernel/db/cat_dbitem.php (revision 12343)
@@ -0,0 +1,598 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class kCatDBItem extends kDBItem {
+
+ /**
+ * Category path, needed for import
+ *
+ * @var Array
+ */
+ var $CategoryPath = Array();
+
+ /**
+ * Use automatic filename generation
+ *
+ * @var bool
+ */
+ var $useFilenames = true;
+
+ /**
+ * Use pending editing abilities during item (delegated by permissions)
+ *
+ * @var bool
+ */
+ var $usePendingEditing = false;
+
+ function Clear($new_id = null)
+ {
+ parent::Clear($new_id);
+ $this->CategoryPath = Array();
+ }
+
+ /**
+ * Set's prefix and special
+ *
+ * @param string $prefix
+ * @param string $special
+ * @access public
+ */
+ function Init($prefix, $special, $event_params = null)
+ {
+ parent::Init($prefix, $special, $event_params);
+ $this->usePendingEditing = $this->Application->getUnitOption($this->Prefix, 'UsePendingEditing');
+ }
+
+ function Create($force_id = false, $system_create = false)
+ {
+ // TODO: move to OnBeforeItemCreate method
+ if ($this->Validate()) {
+ // TODO: such approach will not respect changes from OnBeforeItemCreate event
+ $this->SetDBField('ResourceId', $this->Application->NextResourceId());
+ }
+
+ $this->SetDBField('Modified_date', adodb_mktime() );
+ $this->SetDBField('Modified_time', adodb_mktime() );
+
+ if ($this->mode != 't' && !$this->Application->IsAdmin()) {
+ $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+ $this->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
+ }
+
+ if ($this->useFilenames) {
+ $this->checkFilename();
+ $this->generateFilename();
+ }
+
+ $ret = parent::Create($force_id, $system_create);
+
+ if ($ret) {
+ // TODO: move to OnAfterItemCreate method
+ $this->assignPrimaryCategory();
+ }
+ return $ret;
+ }
+
+ function assignPrimaryCategory()
+ {
+ $primary_category = $this->GetDBField('CategoryId') > 0 ? $this->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
+ $this->assignToCategory($primary_category, true);
+ }
+
+ function Update($id=null, $system_update=false)
+ {
+ $this->VirtualFields['ResourceId'] = Array();
+ $this->SetDBField('Modified', adodb_mktime() );
+ $this->UpdateFormattersSubFields(array('Modified'));
+ $this->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
+
+ if ($this->useFilenames) {
+ $this->checkFilename();
+ $this->generateFilename();
+ }
+
+ $ret = parent::Update($id, $system_update);
+
+ if ($ret) {
+ $filename = $this->useFilenames ? $this->GetDBField('Filename') : '';
+ $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;
+ }
+
+ /**
+ * Returns CategoryItems table based on current item mode (temp/live)
+ *
+ * @return string
+ */
+ function CategoryItemsTable()
+ {
+ $table = TABLE_PREFIX.'CategoryItems';
+ if ($this->Application->IsTempTable($this->TableName)) {
+ $table = $this->Application->GetTempName($table, 'prefix:'.$this->Prefix);
+ }
+
+ return $table;
+ }
+
+
+ function checkFilename()
+ {
+ if( !$this->GetDBField('AutomaticFilename') )
+ {
+ $filename = $this->GetDBField('Filename');
+ $this->SetDBField('Filename', $this->stripDisallowed($filename) );
+ }
+ }
+
+ function Copy($cat_id=null)
+ {
+ if (!isset($cat_id)) $cat_id = $this->Application->GetVar('m_cat_id');
+ $this->NameCopy($cat_id);
+ return $this->Create($cat_id);
+ }
+
+ function NameCopy($master=null, $foreign_key=null)
+ {
+ $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
+ if (!$title_field) return;
+
+ $new_name = $this->GetDBField($title_field);
+ $cat_id = $this->Application->GetVar('m_cat_id');
+ $original_checked = false;
+ do {
+ if ( preg_match('/Copy ([0-9]*) *of (.*)/', $new_name, $regs) ) {
+ $new_name = 'Copy '.( (int)$regs[1] + 1 ).' of '.$regs[2];
+ }
+ elseif ($original_checked) {
+ $new_name = 'Copy of '.$new_name;
+ }
+ $query = 'SELECT '.$title_field.' FROM '.$this->TableName.'
+ LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON
+ ('.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$this->TableName.'.ResourceId)
+ WHERE ('.TABLE_PREFIX.'CategoryItems.CategoryId = '.$cat_id.') AND '.
+ $title_field.' = '.$this->Conn->qstr($new_name);
+ $res = $this->Conn->GetOne($query);
+ $original_checked = true;
+ } while ($res !== false);
+ $this->SetDBField($title_field, $new_name);
+
+ // this is needed, because Create will create items in its own CategoryId (if it's set),
+ // but we need to create it in target Paste category @see{kCatDBItem::Create} and its primary_category detection
+ $this->SetDBField('CategoryId', $cat_id);
+ }
+
+ /**
+ * Changes item primary category to given/current category
+ *
+ * @param int $category_id
+ */
+ function MoveToCat($category_id = null)
+ {
+// $this->NameCopy();
+ if (!isset($category_id)) {
+ $category_id = $this->Application->GetVar('m_cat_id');
+ }
+
+ $table_name = TABLE_PREFIX . 'CategoryItems';
+ if ($this->IsTempTable()) {
+ $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix);
+ }
+
+ // check if the item already exists in destination category
+ $sql = 'SELECT PrimaryCat
+ FROM ' . $table_name . '
+ WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
+ $is_primary = $this->Conn->GetOne($sql);
+
+ // if it's not found is_primary will be FALSE, if it's found but not primary it will be int 0
+ $exists = $is_primary !== false;
+
+ if ($exists) {
+ // if the item already exists in destination category
+ if ($is_primary) {
+ // do nothing when we paste to primary
+ return ;
+ }
+
+ // if it's not primary - delete it from destination category, as we will move it from current primary below
+ $sql = 'DELETE FROM ' . $table_name . '
+ WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
+ $this->Conn->Query($sql);
+ }
+
+ // change category id in existing primary category record
+ $sql = 'UPDATE ' . $table_name . '
+ SET CategoryId = ' . $category_id . '
+ WHERE (ItemResourceId = ' . $this->GetDBField('ResourceId') . ') AND (PrimaryCat = 1)';
+ $this->Conn->Query($sql);
+
+ $this->Update();
+ }
+
+ /**
+ * When item is deleted, then also delete it from all categories
+ *
+ * @param int $id
+ * @return bool
+ */
+ function Delete($id = null)
+ {
+ if( isset($id) ) {
+ $this->setID($id);
+ }
+
+ $this->Load($this->GetID());
+
+ $ret = parent::Delete();
+
+ if ($ret) {
+ // TODO: move to OnAfterItemDelete method
+ $query = ' DELETE FROM ' . $this->CategoryItemsTable() . '
+ WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
+ $this->Conn->Query($query);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Deletes item from categories
+ *
+ * @param Array $delete_category_ids
+ * @author Alex
+ */
+ function DeleteFromCategories($delete_category_ids)
+ {
+ $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); // because item was loaded before by ResourceId
+
+ $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)';
+
+ $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);
+ }
+ 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 ) );
+ }
+ }
+ }
+
+ /**
+ * replace not allowed symbols with "_" chars + remove duplicate "_" chars in result
+ *
+ * @param string $string
+ * @return string
+ */
+ function stripDisallowed($filename)
+ {
+ $filenames_helper =& $this->Application->recallObject('FilenamesHelper');
+ $table = $this->mode == 't' ? $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems', 'prefix:'.$this->Prefix) : TABLE_PREFIX.'CategoryItems';
+
+ return $filenames_helper->stripDisallowed($table, 'ItemResourceId', $this->GetDBField('ResourceId'), $filename);
+ }
+
+ /* commented out because it's called only from stripDisallowed body, which is moved to helper
+
+ function checkAutoFilename($filename)
+ {
+ $filenames_helper =& $this->Application->recallObject('FilenamesHelper');
+ return $filenames_helper->checkAutoFilename($this->TableName, $this->IDField, $this->GetID(), $filename);
+ }*/
+
+ /**
+ * Generate item's filename based on it's title field value
+ *
+ * @return string
+ */
+ function generateFilename()
+ {
+ if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) return false;
+
+ $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
+ 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];
+ }
+ $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 (!$res) {
+ $this->SetError($field, 'required');
+ }
+ return $res;
+ }
+
+ /**
+ * Adds item to other category
+ *
+ * @param int $category_id
+ * @param bool $is_primary
+ */
+ function assignToCategory($category_id, $is_primary = false)
+ {
+ $table = $this->CategoryItemsTable();
+ $key_clause = '(ItemResourceId = '.$this->GetDBField('ResourceId').')';
+
+ // get all cateories, 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;
+ }
+ }
+
+ if ($primary_found && ($item_category_id == $category_id) && !$is_primary) {
+ // want to make primary category as non-primary :(
+ return true;
+ }
+ else if (!$primary_found) {
+ $is_primary = true;
+ }
+
+ if ($is_primary && $item_categories) {
+ // reset primary mark from all other categories
+ $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.')';
+ $this->Conn->Query($sql);
+ }
+ else {
+ $fields_hash = Array(
+ 'CategoryId' => $category_id,
+ 'ItemResourceId' => $this->GetField('ResourceId'),
+ 'PrimaryCat' => $is_primary ? 1 : 0,
+ 'ItemPrefix' => $this->Prefix,
+ 'Filename' => $this->useFilenames ? $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();
+ }
+
+ /**
+ * Removes item from category specified
+ *
+ * @param int $category_id
+ */
+ function removeFromCategory($category_id)
+ {
+ $sql = 'DELETE FROM '.TABLE_PREFIX.'CategoryItems WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
+ $this->Conn->Query( sprintf($sql, $category_id, $this->GetDBField('ResourceId')) );
+ }
+
+ /**
+ * Returns list of columns, that could exist in imported file
+ *
+ * @return Array
+ */
+ function getPossibleExportColumns()
+ {
+ static $columns = null;
+ if (!is_array($columns)) {
+ $columns = array_merge($this->Fields['AvailableColumns']['options'], $this->Fields['ExportColumns']['options']);
+ }
+ return $columns;
+ }
+
+ /**
+ * Returns item's primary image data
+ *
+ * @return Array
+ */
+ function getPrimaryImageData()
+ {
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'Images
+ WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (DefaultImg = 1)';
+ $image_data = $this->Conn->GetRow($sql);
+ if (!$image_data) {
+ // 2. no primary image, then get image with name "main"
+ $sql = 'SELECT *
+ FROM '.TABLE_PREFIX.'Images
+ WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (Name = "main")';
+ $image_data = $this->Conn->GetRow($sql);
+ }
+ return $image_data;
+ }
+
+ function ChangeStatus($new_status)
+ {
+ $status_field = array_shift( $this->Application->getUnitOption($this->Prefix,'StatusField') );
+ if ($new_status != $this->GetDBField($status_field)) {
+ // status was changed
+ $this->sendEmailEvents($new_status);
+ }
+ $this->SetDBField($status_field, $new_status);
+
+ return $this->Update();
+ }
+
+ function sendEmailEvents($new_status)
+ {
+ $perm_prefix = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix');
+ $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+
+ $event_name = $perm_prefix.'.'.($new_status == STATUS_ACTIVE ? 'APPROVE' : 'DENY');
+ $this->Application->EmailEventUser($event_name, $this->GetDBField($owner_field));
+ }
+
+ /**
+ * Approves changes made to category item
+ *
+ * @return bool
+ */
+ function ApproveChanges()
+ {
+ $original_id = $this->GetDBField('OrgId');
+
+ 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))) {
+ // 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));
+
+ $this->SetDBField('OrgId', 0);
+ return $this->ChangeStatus(STATUS_ACTIVE);
+ }
+
+ return false;
+ }
+
+ /**
+ * Decline changes made to category item
+ *
+ * @return bool
+ */
+ function DeclineChanges()
+ {
+ $original_id = $this->GetDBField('OrgId');
+
+ 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()));
+
+ // original item is not changed here, because it is already enabled (thrus pending copy is visible to item's owner or admin with permission)
+ return true;
+ }
+
+ function RegisterHit()
+ {
+ $already_viewed = $this->Application->RecallVar($this->getPrefixSpecial().'_already_viewed');
+ $already_viewed = $already_viewed ? unserialize($already_viewed) : Array ();
+
+ $id = $this->GetID();
+ if (!in_array($id, $already_viewed)) {
+ $property_map = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
+ if (!$property_map) {
+ return ;
+ }
+ $hits_field = $property_map['ClickField'];
+ $new_hits = $this->GetDBField($hits_field) + 1;
+
+ $sql = 'SELECT MAX('.$hits_field.')
+ FROM '.$this->TableName.'
+ WHERE FLOOR('.$hits_field.') = '.$new_hits;
+ $max_hits = $this->Conn->GetOne($sql);
+ if ($max_hits) {
+ $new_hits = $max_hits + 0.000001;
+ }
+
+ $fields_hash = Array (
+ $hits_field => $new_hits,
+ );
+ $this->Conn->doUpdate($fields_hash, $this->TableName, $this->IDField.' = '.$id);
+
+ array_push($already_viewed, $id);
+ $this->Application->StoreVar($this->getPrefixSpecial().'_already_viewed', serialize($already_viewed));
+ }
+ }
+
+ /**
+ * 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)
+ {
+ if ($method == 'load') {
+ // for item with many categories makes primary to load
+ $ci_table = TABLE_PREFIX.'CategoryItems';
+ if ($this->IsTempTable()) {
+ $ci_table = $this->Application->GetTempName($ci_table, 'prefix:'.$this->Prefix);
+ }
+ $keys_hash = Array(
+ $this->IDField => $this->ID,
+ '`'.$ci_table.'`.`PrimaryCat`' => 1,
+ );
+ }
+ return parent::GetKeyClause($method, $keys_hash);
+ }
+
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/kernel/db/cat_dbitem.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.40.2.6
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/kernel/db/db_tag_processor.php
===================================================================
--- branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 12342)
+++ branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 12343)
@@ -1,2514 +1,2514 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
-class kDBTagProcessor extends TagProcessor {
+class kDBTagProcessor extends kTagProcessor {
/**
* Description
*
* @var kDBConnection
* @access public
*/
var $Conn;
function kDBTagProcessor()
{
parent::kBase();
$this->Conn =& $this->Application->GetADODBConnection();
}
/**
* Returns true if "new" button was pressed in toolbar
*
* @param Array $params
* @return bool
*/
function IsNewMode($params)
{
$object =& $this->getObject($params);
return $object->GetID() <= 0;
}
/**
* Returns view menu name for current prefix
*
* @param Array $params
* @return string
*/
function GetItemName($params)
{
$item_name = $this->Application->getUnitOption($this->Prefix, 'ViewMenuPhrase');
return $this->Application->Phrase($item_name);
}
function ViewMenu($params)
{
$block_params = $params;
unset($block_params['block']);
$block_params['name'] = $params['block'];
$list =& $this->GetList($params);
$block_params['PrefixSpecial'] = $list->getPrefixSpecial();
return $this->Application->ParseBlock($block_params);
}
function SearchKeyword($params)
{
$list =& $this->GetList($params);
return $this->Application->RecallVar($list->getPrefixSpecial().'_search_keyword');
}
/**
* Draw filter menu content (for ViewMenu) based on filters defined in config
*
* @param Array $params
* @return string
*/
function DrawFilterMenu($params)
{
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['spearator_block'];
$separator = $this->Application->ParseBlock($block_params);
$filter_menu = $this->Application->getUnitOption($this->Prefix,'FilterMenu');
if (!$filter_menu) {
trigger_error('<span class="debug_error">no filters defined</span> for prefix <b>'.$this->Prefix.'</b>, but <b>DrawFilterMenu</b> tag used', E_USER_WARNING);
return '';
}
// Params: label, filter_action, filter_status
$block_params['name'] = $params['item_block'];
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter');
if ($view_filter === false) {
$event_params = Array ('prefix' => $this->Prefix, 'special' => $this->Special, 'name' => 'OnRemoveFilters');
$this->Application->HandleEvent( new kEvent($event_params) );
$view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter');
}
$view_filter = unserialize($view_filter);
$filters = Array();
$prefix_special = $this->getPrefixSpecial();
foreach ($filter_menu['Filters'] as $filter_key => $filter_params) {
$group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][ $filter_params['group_id'] ] : Array();
if (!isset($group_params['element_type'])) {
$group_params['element_type'] = 'checkbox';
}
if (!$filter_params) {
$filters[] = $separator;
continue;
}
$block_params['label'] = addslashes( $this->Application->Phrase($filter_params['label']) );
if (getArrayValue($view_filter,$filter_key)) {
$submit = 0;
if (isset($params['old_style'])) {
$status = $group_params['element_type'] == 'checkbox' ? 1 : 2;
}
else {
$status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']';
}
}
else {
$submit = 1;
$status = 'null';
}
$block_params['filter_action'] = 'set_filter("'.$prefix_special.'","'.$filter_key.'","'.$submit.'",'.$params['ajax'].');';
$block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image
$filters[] = $this->Application->ParseBlock($block_params);
}
return implode('', $filters);
}
/**
* Draws auto-refresh submenu in View Menu.
*
* @param Array $params
* @return string
*/
function DrawAutoRefreshMenu($params)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
if (!$refresh_intervals) {
trigger_error('<span class="debug_error">no filters defined</span> for prefix <strong>'.$this->Prefix.'</strong>, but <strong>DrawAutoRefreshMenu</strong> tag used', E_USER_WARNING);
return '';
}
$refresh_intervals = explode(',', $refresh_intervals);
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
if ($current_refresh_interval === false) {
// if no interval was selected before, then choose 1st interval
$current_refresh_interval = $refresh_intervals[0];
}
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($refresh_intervals as $refresh_interval) {
$block_params['label'] = $this->_formatInterval($refresh_interval);
$block_params['refresh_interval'] = $refresh_interval;
$block_params['selected'] = $current_refresh_interval == $refresh_interval;
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Tells, that current grid is using auto refresh
*
* @param Array $params
* @return bool
*/
function UseAutoRefresh($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name);
}
/**
* Returns current grid refresh interval
*
* @param Array $params
* @return bool
*/
function AutoRefreshInterval($params)
{
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name);
}
/**
* Formats time interval using given text for hours and minutes
*
* @param int $intervalmMinutes
* @param string $hour_text Text for hours
* @param string $min_text Text for minutes
* @return unknown
*/
function _formatInterval($interval, $hour_text = 'h', $min_text = 'min')
{
// 65
$minutes = $interval % 60;
$hours = ($interval - $minutes) / 60;
$ret = '';
if ($hours) {
$ret .= $hours.$hour_text.' ';
}
if ($minutes) {
$ret .= $minutes.$min_text;
}
return $ret;
}
function IterateGridFields($params)
{
$mode = $params['mode'];
$def_block = isset($params['block']) ? $params['block'] : '';
$force_block = isset($params['force_block']) ? $params['force_block'] : false;
$grids = $this->Application->getUnitOption($this->Prefix,'Grids');
$grid_config = $grids[$params['grid']]['Fields'];
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
$picker_helper->ApplyPicker($this->getPrefixSpecial(), $grid_config, $params['grid']);
if ($mode == 'fields') {
return "'".join("','", array_keys($grid_config))."'";
}
$std_params['pass_params'] = 'true';
$std_params['PrefixSpecial'] = $this->getPrefixSpecial();
$object =& $this->GetList($params);
$o = '';
$i = 0;
foreach ($grid_config as $field => $options) {
$i++;
$block_params = Array();
$block_params['name'] = $force_block ? $force_block : (isset($options[$mode.'_block']) ? $options[$mode.'_block'] : $def_block);
$block_params['field'] = $field;
$block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field;
$block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field;
$w = $picker_helper->GetWidth($field);
if ($w) $options['width'] = $w;
/*if (isset($options['filter_width'])) {
$block_params['filter_width'] = $options['filter_width'];
}
elseif (isset($options['width'])) {
if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) {
if ($options['width'] < 60) {
$options['width'] = 60;
$block_params['filter_width'] = 20;
}
else {
$block_params['filter_width'] = $options['width'] - 40;
}
}
else {
$block_params['filter_width'] = max($options['width']-10, 20);
}
}*/
/*if (isset($block_params['filter_width'])) $block_params['filter_width'] .= 'px';
if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) {
$block_params['filter_width'] = '20px';
}
else {
$block_params['filter_width'] = '97%';
// $block_params['filter_width'] = max($options['width']-10, 20);
}*/
$field_options = $object->GetFieldOptions($field);
if (array_key_exists('use_phrases', $field_options)) {
$block_params['use_phrases'] = $field_options['use_phrases'];
}
$block_params['is_last'] = ($i == count($grid_config));
$block_params = array_merge($std_params, $options, $block_params);
$o.= $this->Application->ParseBlock($block_params, 1);
}
return $o;
}
function PickerCRC($params)
{
/* @var $picker_helper kColumnPickerHelper */
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
$picker_helper->SetGridName($params['grid']);
$data = $picker_helper->LoadColumns($this->getPrefixSpecial());
return $data['crc'];
}
function FreezerPosition($params)
{
/* @var $picker_helper kColumnPickerHelper */
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
$picker_helper->SetGridName($params['grid']);
$data = $picker_helper->LoadColumns($this->getPrefixSpecial());
$freezer_pos = array_search('__FREEZER__', $data['order']);
return $freezer_pos === false || in_array('__FREEZER__', $data['hidden_fields']) ? 1 : ++$freezer_pos;
}
function GridFieldsCount($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
$grid_config = $grids[$params['grid']]['Fields'];
return count($grid_config);
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList($params)
{
$params['no_table'] = 1;
return $this->PrintList2($params);
}
function InitList($params)
{
$list_name = isset($params['list_name']) ? $params['list_name'] : '';
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping');
if( !getArrayValue($names_mapping, $this->Prefix, $list_name) )
{
$list =& $this->GetList($params);
}
}
function BuildListSpecial($params)
{
return $this->Special;
}
/**
* Returns key, that identifies each list on template (used internally, not tag)
*
* @param Array $params
* @return string
*/
function getUniqueListKey($params)
{
$types = $this->SelectParam($params, 'types');
$except = $this->SelectParam($params, 'except');
$list_name = $this->SelectParam($params, 'list_name');
if (!$list_name) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
return $types.$except.$list_name;
}
/**
* Enter description here...
*
* @param Array $params
* @return kDBList
*/
function &GetList($params)
{
$list_name = $this->SelectParam($params, 'list_name,name');
if (!$list_name) {
$list_name = $this->Application->Parser->GetParam('list_name');
}
$requery = isset($params['requery']) && $params['requery'];
if ($list_name && !$requery) {
$names_mapping = $this->Application->GetVar('NamesToSpecialMapping');
$special = is_array($names_mapping) && isset($names_mapping[$this->Prefix]) && isset($names_mapping[$this->Prefix][$list_name]) ? $names_mapping[$this->Prefix][$list_name] : false;
// $special = getArrayValue($names_mapping, $this->Prefix, $list_name);
if (!$special) {
$special = $this->BuildListSpecial($params);
}
}
else {
$special = $this->BuildListSpecial($params);
}
$prefix_special = rtrim($this->Prefix.'.'.$special, '.');
$params['skip_counting'] = true;
$list =& $this->Application->recallObject( $prefix_special, $this->Prefix.'_List', $params);
/* @var $list kDBList */
if (!array_key_exists('skip_quering', $params) || !$params['skip_quering']) {
if ($requery) {
$this->Application->HandleEvent($an_event, $prefix_special.':OnListBuild', $params);
}
if (array_key_exists('offset', $params)) {
$list->Offset += $params['offset']; // apply custom offset
}
$list->Query($requery);
if (array_key_exists('offset', $params)) {
$list->Offset -= $params['offset']; // remove custom offset
}
}
$this->Special = $special;
if ($list_name) {
$names_mapping[$this->Prefix][$list_name] = $special;
$this->Application->SetVar('NamesToSpecialMapping', $names_mapping);
}
return $list;
}
function ListMarker($params)
{
$list =& $this->GetList($params);
$ret = $list->getPrefixSpecial();
if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/');
return $ret;
}
/**
* Prepares name for field with event in it (used only on front-end)
*
* @param Array $params
* @return string
*/
function SubmitName($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
return 'events['.$prefix_special.']['.$params['event'].']';
}
/**
* Prints list content using block specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintList2($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
if ($per_page !== false) $params['per_page'] = $per_page;
$list =& $this->GetList($params);
$o = '';
$direction = (isset($params['direction']) && $params['direction']=="H")?"H":"V";
$columns = (isset($params['columns'])) ? $params['columns'] : 1;
$id_field = (isset($params['id_field'])) ? $params['id_field'] : $this->Application->getUnitOption($this->Prefix, 'IDField');
if ($columns > 1 && $direction == 'V') {
$records_left = array_splice($list->Records, $list->SelectedCount); // because we have 1 more record for "More..." link detection (don't need to sort it)
$list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage());
$list->Records = array_merge($list->Records, $records_left);
}
$list->GoFirst();
$block_params=$this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
$block_params['column_width'] = $params['column_width'] = 100 / $columns;
$block_start_row_params = $this->prepareTagParams($params);
$block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block');
$block_end_row_params=$this->prepareTagParams($params);
$block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block');
$block_empty_cell_params = $this->prepareTagParams($params);
$block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block');
$i=0;
$backup_id=$this->Application->GetVar($this->Prefix."_id");
$displayed = array();
$column_number = 1;
$cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') && $this->Application->RewriteURLs();
$limit = isset($params['limit']) ? $params['limit'] : false;
while (!$list->EOL() && (!$limit || $i<$limit))
{
$this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET
$this->Application->SetVar( $this->Prefix.'_id', $list->GetDBField($id_field) );
$block_params['is_last'] = ($i == $list->SelectedCount - 1);
$block_params['last_row'] = ($i + (($i+1) % $columns) >= $list->SelectedCount - 1);
$block_params['not_last'] = !$block_params['is_last']; // for front-end
if ($cache_mod_rw) {
if ($this->Prefix == 'c') {
// for listing subcategories in category
$this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('NamedParentPath'));
$this->Application->setCache('category_tree', $list->GetDBField($id_field), $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight'));
} else {
// for listing items in category
$this->Application->setCache('filenames', 'c_'.$list->GetDBField('CategoryId'), $list->GetDBField('CategoryFilename'));
$this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('Filename'));
}
}
if ($i % $columns == 0) {
// record in this iteration is first in row, then open row
$column_number = 1;
$o.= $block_start_row_params['name'] ?
$this->Application->ParseBlock($block_start_row_params, 1) :
(!isset($params['no_table']) ? '<tr>' : '');
}
else {
$column_number++;
}
$block_params['first_col'] = $column_number == 1 ? 1 : 0;
$block_params['last_col'] = $column_number == $columns ? 1 : 0;
$block_params['column_number'] = $column_number;
$block_params['num'] = ($i+1);
$this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList
$o.= $this->Application->ParseBlock($block_params, 1);
array_push($displayed, $list->GetDBField($id_field));
if($direction == 'V' && $list->SelectedCount % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->SelectedCount % ceil($list->SelectedCount / $columns)) {
// if vertical output, then draw empty cells vertically, not horizontally
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params, 1) : '<td>&nbsp;</td>';
$i++;
}
if (($i + 1) % $columns == 0) {
// record in next iteration is first in row too, then close this row
$o.= $block_end_row_params['name'] ?
$this->Application->ParseBlock($block_end_row_params, 1) :
(!isset($params['no_table']) ? '</tr>' : '');
}
$list->GoNext();
$i++;
}
// append empty cells in place of missing cells in last row
while ($i % $columns != 0) {
// until next cell will be in new row append empty cells
$o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params, 1) : '<td>&nbsp;</td>';
if (($i+1) % $columns == 0) {
// record in next iteration is first in row too, then close this row
$o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params, 1) : '</tr>';
}
$i++;
}
$cur_displayed = $this->Application->GetVar($this->Prefix.'_displayed_ids');
if (!$cur_displayed) {
$cur_displayed = Array();
}
else {
$cur_displayed = explode(',', $cur_displayed);
}
$displayed = array_unique(array_merge($displayed, $cur_displayed));
$this->Application->SetVar($this->Prefix.'_displayed_ids', implode(',',$displayed));
$this->Application->SetVar( $this->Prefix.'_id', $backup_id);
$this->Application->SetVar( $this->getPrefixSpecial().'_id', '');
if (isset($params['more_link_render_as'])) {
$block_params = $params;
$params['render_as'] = $params['more_link_render_as'];
$o .= $this->MoreLink($params);
}
return $o;
}
/**
* Allows to modify block params & current list record before PrintList parses record
*
* @param kDBList $object
* @param Array $block_params
*/
function PrepareListElementParams(&$object, &$block_params)
{
// $fields_hash =& $object->getCurrentRecord();
}
function MoreLink($params)
{
$per_page = $this->SelectParam($params, 'per_page,max_items');
if ($per_page !== false) $params['per_page'] = $per_page;
$list =& $this->GetList($params);
if ($list->PerPage < $list->RecordsCount) {
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
return $this->Application->ParseBlock($block_params);
}
}
function NotLastItem($params)
{
$object =& $this->getList($params); // maybe we should use $this->GetList($params) instead
return ($object->CurrentIndex < min($object->PerPage == -1 ? $object->RecordsCount : $object->PerPage, $object->RecordsCount) - 1);
}
function PageLink($params)
{
$t = isset($params['template']) ? $params['template'] : '';
unset($params['template']);
if (!$t) $t = $this->Application->GetVar('t');
if (isset($params['page'])) {
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $params['page']);
unset($params['page']);
}
if (!isset($params['pass'])) {
$params['pass'] = 'm,'.$this->getPrefixSpecial();
}
return $this->Application->HREF($t, '', $params);
}
function ColumnWidth($params)
{
$columns = $this->Application->Parser->GetParam('columns');
return round(100/$columns).'%';
}
/**
* Append prefix and special to tag
* params (get them from tagname) like
* they were really passed as params
*
* @param Array $tag_params
* @return Array
* @access protected
*/
function prepareTagParams($tag_params = Array())
{
/*if (isset($tag_params['list_name'])) {
$list =& $this->GetList($tag_params);
$this->Init($list->Prefix, $list->Special);
}*/
$ret = $tag_params;
$ret['Prefix'] = $this->Prefix;
$ret['Special'] = $this->Special;
$ret['PrefixSpecial'] = $this->getPrefixSpecial();
return $ret;
}
function GetISO($currency)
{
if ($currency == 'selected') {
$iso = $this->Application->RecallVar('curr_iso');
}
elseif ($currency == 'primary' || $currency == '') {
$iso = $this->Application->GetPrimaryCurrency();
}
else { //explicit currency
$iso = $currency;
}
return $iso;
}
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;
}
function AddCurrencySymbol($value, $iso)
{
$currency =& $this->Application->recallObject('curr.-'.$iso, null, Array('skip_autoload' => true));
if( !$currency->isLoaded() ) $currency->Load($iso, 'ISO');
$symbol = $currency->GetDBField('Symbol');
if (!$symbol) $symbol = $currency->GetDBField('ISO').'&nbsp;';
if ($currency->GetDBField('SymbolPosition') == 0) {
$value = $symbol.$value;
}
if ($currency->GetDBField('SymbolPosition') == 1) {
$value = $value.$symbol;
}
return $value;
}
/**
* Get's requested field value
*
* @param Array $params
* @return string
* @access public
*/
function Field($params)
{
$field = $this->SelectParam($params, 'name,field');
if( !$this->Application->IsAdmin() ) $params['no_special'] = 'no_special';
$object =& $this->getObject($params);
if ( $this->HasParam($params, 'db') )
{
$value = $object->GetDBField($field);
}
else
{
if( $this->HasParam($params, 'currency') )
{
$iso = $this->GetISO($params['currency']);
$original = $object->GetDBField($field);
$value = $this->ConvertCurrency($original, $iso);
$object->SetDBField($field, $value);
$object->Fields[$field]['converted'] = true;
}
$format = getArrayValue($params, 'format');
if (!$format || $format == '$format') {
$format = null;
}
$value = $object->GetField($field, $format);
if( $this->SelectParam($params, 'negative') )
{
if(strpos($value, '-') === 0)
{
$value = substr($value, 1);
}
else
{
$value = '-'.$value;
}
}
if( $this->HasParam($params, 'currency') )
{
$value = $this->AddCurrencySymbol($value, $iso);
$params['no_special'] = 1;
}
}
if( !$this->HasParam($params, 'no_special') ) $value = htmlspecialchars($value);
if( getArrayValue($params,'checked' ) ) $value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : '';
if( isset($params['plus_or_as_label']) ) {
$value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value);
}
elseif( isset($params['as_label']) && $params['as_label'] ) $value = $this->Application->Phrase($value);
$first_chars = $this->SelectParam($params,'first_chars,cut_first');
if($first_chars)
{
$needs_cut = mb_strlen($value) > $first_chars;
$value = mb_substr($value, 0, $first_chars);
if ($needs_cut) $value .= ' ...';
}
if( getArrayValue($params,'nl2br' ) ) $value = nl2br($value);
if ($value != '') $this->Application->Parser->DataExists = true;
if( $this->HasParam($params, 'currency') )
{
//restoring value in original currency, for other Field tags to work properly
$object->SetDBField($field, $original);
}
return $value;
}
function SetField($params)
{
// <inp2:SetField field="Value" src=p:cust_{$custom_name}"/>
$object =& $this->getObject($params);
$dst_field = $this->SelectParam($params, 'name,field');
list($prefix_special, $src_field) = explode(':', $params['src']);
$src_object =& $this->Application->recallObject($prefix_special);
$object->SetDBField($dst_field, $src_object->GetDBField($src_field));
}
/**
* Checks if parameter is passed
* Note: works like Tag and line simple method too
*
* @param Array $params
* @param string $param_name
* @return bool
*/
function HasParam($params, $param_name = null)
{
if ( !isset($param_name) ) {
$param_name = $this->SelectParam($params, 'name');
$params = $this->Application->Parser->Params;
}
$value = isset($params[$param_name]) ? $params[$param_name] : false;
return $value && ($value != '$'.$param_name);
}
function PhraseField($params)
{
$field_label = $this->Field($params);
$translation = $this->Application->Phrase( $field_label );
return $translation;
}
function Error($params)
{
$field = $this->SelectParam($params, 'name,field');
$object =& $this->getObject($params);
$msg = $object->GetErrorMsg($field, false);
return $msg;
}
function HasError($params)
{
if ($params['field'] == 'any')
{
$object =& $this->getObject($params);
$skip_fields = getArrayValue($params, 'except');
$skip_fields = $skip_fields ? explode(',', $skip_fields) : Array();
return $object->HasErrors($skip_fields);
}
else
{
$fields = $this->SelectParam($params, 'field,fields');
$fields = explode(',', $fields);
$res = false;
foreach($fields as $field)
{
$params['field'] = $field;
$res = $res || ($this->Error($params) != '');
}
return $res;
}
}
function ErrorWarning($params)
{
if (!isset($params['field'])) {
$params['field'] = 'any';
}
if ($this->HasError($params)) {
$params['prefix'] = $this->getPrefixSpecial();
return $this->Application->ParseBlock($params);
}
}
function IsRequired($params)
{
$field = $params['field'];
$object =& $this->getObject($params);;
$formatter_class = getArrayValue($object->Fields, $field, 'formatter');
if ($formatter_class == 'kMultiLanguage')
{
$formatter =& $this->Application->recallObject($formatter_class);
$field = $formatter->LangFieldName($field);
}
$options = $object->GetFieldOptions($field);
return getArrayValue($options,'required');
}
function FieldOption($params)
{
$object =& $this->getObject($params);;
$options = $object->GetFieldOptions($params['field']);
$ret = isset($options[$params['option']]) ? $options[$params['option']] : '';
if (isset($params['as_label']) && $params['as_label']) $ret = $this->Application->ReplaceLanguageTags($ret);
return $ret;
}
function PredefinedOptions($params)
{
$object =& $this->getObject($params);
$field = $params['field'];
$value = array_key_exists('value', $params) ? $params['value'] : $object->GetDBField($field);
$field_options = $object->GetFieldOptions($field);
if (!array_key_exists('options', $field_options) || !is_array($field_options['options'])) {
trigger_error('Options not defined for <strong>'.$object->Prefix.'</strong> field <strong>'.$field.'</strong>', E_USER_WARNING);
return '';
}
$options = $field_options['options'];
if ($this->HasParam($params, 'has_empty')) {
$empty_value = array_key_exists('empty_value', $params) ? $params['empty_value'] : '';
$options = array_merge_recursive2(Array ($empty_value => ''), $options); // don't use other array merge function, because they will reset keys !!!
}
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
$block_params['pass_params'] = 'true';
if (method_exists($object, 'EOL') && count($object->Records) == 0) {
// for drawing grid column filter
$block_params['field_name'] = '';
}
else {
$block_params['field_name'] = $this->InputName($params); // depricated (produces warning when used as grid filter), but used in Front-End (submission create), admin (submission view)
}
$selected_param_name = getArrayValue($params, 'selected_param');
if (!$selected_param_name) {
$selected_param_name = $params['selected'];
}
$selected = $params['selected'];
$o = '';
if ($this->HasParam($params, 'no_empty') && !getArrayValue($options, '')) {
// removes empty option, when present (needed?)
array_shift($options);
}
if (strpos($value, '|') !== false) {
// multiple checkboxes OR multiselect
$value = explode('|', substr($value, 1, -1) );
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : '');
$o .= $this->Application->ParseBlock($block_params, 1);
}
}
else {
// single selection radio OR checkboxes OR dropdown
foreach ($options as $key => $val) {
$block_params['key'] = $key;
$block_params['option'] = $val;
$block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : '');
$o .= $this->Application->ParseBlock($block_params, 1);
}
}
return $o;
}
function PredefinedSearchOptions($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$params['value'] = $this->SearchField($params);
return $this->PredefinedOptions($params);
}
function Format($params)
{
$field = $this->SelectParam($params, 'name,field');
$object =& $this->getObject($params);
$options = $object->GetFieldOptions($field);
$format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ];
$formatter_class = getArrayValue($options,'formatter');
if ($formatter_class) {
$formatter =& $this->Application->recallObject($formatter_class);
$human_format = getArrayValue($params,'human');
$edit_size = getArrayValue($params,'edit_size');
$sample = getArrayValue($params,'sample');
if($sample)
{
return $formatter->GetSample($field, $options, $object);
}
elseif($human_format || $edit_size)
{
$format = $formatter->HumanFormat($format);
return $edit_size ? strlen($format) : $format;
}
}
return $format;
}
/**
* Returns grid padination information
* Can return links to pages
*
* @param Array $params
* @return mixed
*/
function PageInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
$type = $params['type'];
unset($params['type']); // remove parameters used only by current tag
$ret = '';
switch ($type) {
case 'current':
$ret = $object->Page;
break;
case 'total':
$ret = $object->GetTotalPages();
break;
case 'prev':
$ret = $object->Page > 1 ? $object->Page - 1 : false;
break;
case 'next':
$ret = $object->Page < $object->GetTotalPages() ? $object->Page + 1 : false;
break;
}
if ($ret && isset($params['as_link']) && $params['as_link']) {
unset($params['as_link']); // remove parameters used only by current tag
$params['page'] = $ret;
$current_page = $object->Page; // backup current page
$ret = $this->PageLink($params);
$this->Application->SetVar($object->getPrefixSpecial().'_Page', $current_page); // restore page
}
return $ret;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PrintPages($params)
{
$list =& $this->GetList($params);
$prefix_special = $list->getPrefixSpecial();
$total_pages = $list->GetTotalPages();
if ($total_pages > 1) $this->Application->Parser->DataExists = true;
if($total_pages == 0) $total_pages = 1; // display 1st page as selected in case if we have no pages at all
$o = '';
// what are these 2 lines for?
$this->Application->SetVar($prefix_special.'_event','');
$this->Application->SetVar($prefix_special.'_id','');
$current_page = $list->Page; // $this->Application->RecallVar($prefix_special.'_Page');
$block_params = $this->prepareTagParams($params);
$split = ( isset($params['split'] ) ? $params['split'] : 10 );
$split_start = $current_page - ceil($split/2);
if ($split_start < 1){
$split_start = 1;
}
$split_end = $split_start + $split-1;
if ($split_end > $total_pages) {
$split_end = $total_pages;
$split_start = max($split_end - $split + 1, 1);
}
if ($current_page > 1){
$prev_block_params = $this->prepareTagParams();
if ($total_pages > $split){
$prev_block_params['page'] = max($current_page-$split, 1);
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_split_render_as,prev_page_split_block');
if ($prev_block_params['name']){
$o .= $this->Application->ParseBlock($prev_block_params, 1);
}
}
$prev_block_params['name'] = 'page';
$prev_block_params['page'] = $current_page-1;
$prev_block_params['name'] = $this->SelectParam($params, 'prev_page_render_as,block_prev_page,prev_page_block');
if ($prev_block_params['name']) {
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page-1);
$o .= $this->Application->ParseBlock($prev_block_params, 1);
}
}
else {
if ( $no_prev_page_block = $this->SelectParam($params, 'no_prev_page_render_as,block_no_prev_page') ) {
$block_params['name'] = $no_prev_page_block;
$o .= $this->Application->ParseBlock($block_params, 1);
}
}
$separator_params['name'] = $this->SelectParam($params, 'separator_render_as,block_separator');
for ($i = $split_start; $i <= $split_end; $i++)
{
if ($i == $current_page) {
$block = $this->SelectParam($params, 'current_render_as,active_render_as,block_current,active_block');
}
else {
$block = $this->SelectParam($params, 'link_render_as,inactive_render_as,block_link,inactive_block');
}
$block_params['name'] = $block;
$block_params['page'] = $i;
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $i);
$o .= $this->Application->ParseBlock($block_params, 1);
if ($this->SelectParam($params, 'separator_render_as,block_separator')
&& $i < $split_end)
{
$o .= $this->Application->ParseBlock($separator_params, 1);
}
}
if ($current_page < $total_pages){
$next_block_params = $this->prepareTagParams();
$next_block_params['page']=$current_page+1;
$next_block_params['name'] = $this->SelectParam($params, 'next_page_render_as,block_next_page,next_page_block');
if ($next_block_params['name']){
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page+1);
$o .= $this->Application->ParseBlock($next_block_params, 1);
}
if ($total_pages > $split){
$next_block_params['page']=min($current_page+$split, $total_pages);
$next_block_params['name'] = $this->SelectParam($params, 'next_page_split_render_as,next_page_split_block');
if ($next_block_params['name']){
$o .= $this->Application->ParseBlock($next_block_params, 1);
}
}
}
else {
if ( $no_next_page_block = $this->SelectParam($params, 'no_next_page_render_as,block_no_next_page') ) {
$block_params['name'] = $no_next_page_block;
$o .= $this->Application->ParseBlock($block_params, 1);
}
}
$this->Application->SetVar($this->getPrefixSpecial().'_Page', $current_page);
return $o;
}
/**
* Print grid pagination using
* block names specified
*
* @param Array $params
* @return string
* @access public
*/
function PaginationBar($params)
{
return $this->PrintPages($params);
}
/**
* Returns field name (processed by kMultiLanguage formatter
* if required) and item's id from it's IDField or field required
*
* @param Array $params
* @return Array (id,field)
* @access private
*/
function prepareInputName($params)
{
$field = $this->SelectParam($params, 'name,field');
$object =& $this->getObject($params);
$formatter_class = getArrayValue($object->Fields, $field, 'formatter');
if ($formatter_class == 'kMultiLanguage') {
$formatter =& $this->Application->recallObject($formatter_class);
/* @var $formatter kMultiLanguage */
$force_primary = isset($object->Fields[$field]['force_primary']) && $object->Fields[$field]['force_primary'];
$field = $formatter->LangFieldName($field, $force_primary);
}
if (array_key_exists('force_id', $params)) {
$id = $params['force_id'];
}
else {
$id_field = getArrayValue($params, 'IdField');
$id = $id_field ? $object->GetDBField($id_field) : $object->GetID();
}
return Array($id, $field);
}
/**
* Returns input field name to
* be placed on form (for correct
* event processing)
*
* @param Array $params
* @return string
* @access public
*/
function InputName($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = $this->getPrefixSpecial().'['.$id.']['.$field.']';
if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/');
return $ret;
}
/**
* Allows to override various field options through hidden fields with specific names in submit.
* This tag generates this special names
*
* @param Array $params
* @return string
* @author Alex
*/
function FieldModifier($params)
{
list($id, $field) = $this->prepareInputName($params);
$ret = 'field_modifiers['.$this->getPrefixSpecial().']['.$field.']['.$params['type'].']';
if( getArrayValue($params, 'as_preg') ) $ret = preg_quote($ret, '/');
if (isset($params['value'])) {
$object =& $this->getObject($params);
$field_modifiers[$field][$params['type']] = $params['value'];
$object->ApplyFieldModifiers($field_modifiers);
}
return $ret;
}
/**
* Returns index where 1st changable sorting field begins
*
* @return int
* @access private
*/
function getUserSortIndex()
{
$list_sortings = $this->Application->getUnitOption($this->Prefix, 'ListSortings');
$sorting_prefix = getArrayValue($list_sortings, $this->Special) ? $this->Special : '';
$user_sorting_start = 0;
if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) {
$user_sorting_start = count($forced_sorting);
}
return $user_sorting_start;
}
/**
* Returns order direction for given field
*
*
*
* @param Array $params
* @return string
* @access public
*/
function Order($params)
{
$field = $params['field'];
$user_sorting_start = $this->getUserSortIndex();
$list =& $this->GetList($params);
if ($list->GetOrderField($user_sorting_start) == $field)
{
return strtolower($list->GetOrderDirection($user_sorting_start));
}
elseif($this->Application->ConfigValue('UseDoubleSorting') && $list->GetOrderField($user_sorting_start+1) == $field)
{
return '2_'.strtolower($list->GetOrderDirection($user_sorting_start+1));
}
else
{
return 'no';
}
}
/**
* Detects, that current sorting is not default
*
* @param Array $params
* @return bool
*/
function OrderChanged($params)
{
$list =& $this->GetList($params);
$user_sorting_start = $this->getUserSortIndex();
$sorting_configs = $this->Application->getUnitOption($this->Prefix, 'ConfigMapping', Array ());
$list_sortings = $this->Application->getUnitOption($this->Prefix, 'ListSortings', Array ());
$sorting_prefix = getArrayValue($list_sortings, $this->Special) ? $this->Special : '';
if (array_key_exists('DefaultSorting1Field', $sorting_configs)) {
$list_sortings[$sorting_prefix]['Sorting'] = Array (
$this->Application->ConfigValue($sorting_configs['DefaultSorting1Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting1Dir']),
$this->Application->ConfigValue($sorting_configs['DefaultSorting2Field']) => $this->Application->ConfigValue($sorting_configs['DefaultSorting2Dir']),
);
}
$sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting');
$sort_fields = is_array($sorting) ? array_keys($sorting) : Array ();
for ($order_number = 0; $order_number < 2; $order_number++) {
// currect sorting in list
$sorting_pos = $user_sorting_start + $order_number;
$current_order_field = $list->GetOrderField($sorting_pos, true);
$current_order_direction = $list->GetOrderDirection($sorting_pos, true);
if (!$current_order_field || !$current_order_direction) {
// no sorting defined for this sorting position
continue;
}
// user sorting found
if (array_key_exists($order_number, $sort_fields)) {
// default sorting found
$default_order_field = $sort_fields[$order_number];
$default_order_direction = $sorting[$default_order_field];
if ($current_order_field != $default_order_field || $current_order_direction != $default_order_direction) {
// #1. user sorting differs from default sorting -> changed
return true;
}
}
else {
// #2. user sorting + no default sorting -> changed
return true;
}
}
// #3. user sorting match default or not defined -> not changed
return false;
}
/**
* Get's information of sorting field at "pos" position,
* like sorting field name (type="field") or sorting direction (type="direction")
*
* @param Array $params
* @return mixed
*/
function OrderInfo($params)
{
$user_sorting_start = $this->getUserSortIndex() + --$params['pos'];
$list =& $this->GetList($params);
// $object =& $this->Application->recallObject( $this->getPrefixSpecial() );
if($params['type'] == 'field') return $list->GetOrderField($user_sorting_start);
if($params['type'] == 'direction') return $list->GetOrderDirection($user_sorting_start);
}
/**
* Checks if sorting field/direction matches passed field/direction parameter
*
* @param Array $params
* @return bool
*/
function IsOrder($params)
{
$params['type'] = isset($params['field']) ? 'field' : 'direction';
$value = $this->OrderInfo($params);
if( isset($params['field']) ) return $params['field'] == $value;
if( isset($params['direction']) ) return $params['direction'] == $value;
}
/**
* Returns list perpage
*
* @param Array $params
* @return int
*/
function PerPage($params)
{
$object =& $this->getObject($params);
return $object->PerPage;
}
/**
* Checks if list perpage matches value specified
*
* @param Array $params
* @return bool
*/
function PerPageEquals($params)
{
$object =& $this->getObject($params);
return $object->PerPage == $params['value'];
}
function SaveEvent($params)
{
// SaveEvent is set during OnItemBuild, but we may need it before any other tag calls OnItemBuild
$object =& $this->getObject($params);
return $this->Application->GetVar($this->getPrefixSpecial().'_SaveEvent');
}
function NextId($params)
{
$object =& $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i < count($ids) - 1 ? $ids[$i + 1] : '';
}
return '';
}
function PrevId($params)
{
$object =& $this->getObject($params);
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = explode(',', $this->Application->RecallVar($session_name));
$cur_id = $object->GetID();
$i = array_search($cur_id, $ids);
if ($i !== false) {
return $i > 0 ? $ids[$i - 1] : '';
}
return '';
}
function IsSingle($params)
{
return ($this->NextId($params) === '' && $this->PrevId($params) === '');
}
function IsLast($params)
{
return ($this->NextId($params) === '');
}
function IsFirst($params)
{
return ($this->PrevId($params) === '');
}
/**
* Checks if field value is equal to proposed one
*
* @param Array $params
* @return bool
*/
function FieldEquals($params)
{
$object =& $this->getObject($params);
$ret = $object->GetDBField($this->SelectParam($params, 'name,field')) == $params['value'];
// if( getArrayValue($params,'inverse') ) $ret = !$ret;
return $ret;
}
/**
* Checks, that grid has icons defined and they should be shown
*
* @param Array $params
* @return bool
*/
function UseItemIcons($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
return array_key_exists('Icons', $grids[ $params['grid'] ]);
}
/**
* Returns corresponding to grid layout selector column width
*
* @param Array $params
* @return int
*/
function GridSelectorColumnWidth($params)
{
$width = 0;
if ($params['selector']) {
$width += $params['selector_width'];
}
if ($this->UseItemIcons($params)) {
$width += $params['icon_width'];
}
return $width;
}
/**
* Returns grids item selection mode (checkbox, radio, )
*
* @param Array $params
* @return string
*/
function GridSelector($params)
{
$grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
return array_key_exists('Selector', $grids[ $params['grid'] ]) ? $grids[ $params['grid'] ]['Selector'] : $params['default'];
}
function ItemIcon($params)
{
$object =& $this->getObject($params);
$grids = $this->Application->getUnitOption($this->Prefix,'Grids');
$icons =& $grids[ $params['grid'] ]['Icons'];
$key = '';
$status_fields = $this->Application->getUnitOption($this->Prefix,'StatusField');
if(!$status_fields) return $icons['default'];
foreach($status_fields as $status_field)
{
$key .= $object->GetDBField($status_field).'_';
}
$key = rtrim($key,'_');
$value = ($key !== false) ? $key : 'default';
return isset($icons[$value]) ? $icons[$value] : $icons['default'];
}
/**
* Generates bluebar title + initializes prefixes used on page
*
* @param Array $params
* @return string
*/
function SectionTitle($params)
{
$preset_name = replaceModuleSection($params['title_preset']);
$title_presets = $this->Application->getUnitOption($this->Prefix,'TitlePresets');
$title_info = getArrayValue($title_presets, $preset_name);
if ($title_info === false) {
$title = str_replace('#preset_name#', $preset_name, $params['title']);
if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) {
$title .= ' - '.$params['group_title'];
}
return $title;
}
if (getArrayValue($title_presets,'default')) {
// use default labels + custom labels specified in preset used
$title_info = array_merge_recursive2($title_presets['default'], $title_info);
}
$title = $title_info['format'];
// 1. get objects in use for title construction
$objects = Array();
$object_status = Array();
$status_labels = Array();
$prefixes = getArrayValue($title_info,'prefixes');
$all_tag_params = getArrayValue($title_info,'tag_params');
if ($prefixes) {
// extract tag_perams passed directly to SectionTitle tag for specific prefix
foreach ($params as $tp_name => $tp_value) {
if (preg_match('/(.*)\[(.*)\]/', $tp_name, $regs)) {
$all_tag_params[ $regs[1] ][ $regs[2] ] = $tp_value;
unset($params[$tp_name]);
}
}
$tag_params = Array();
foreach ($prefixes as $prefix_special) {
$prefix_data = $this->Application->processPrefix($prefix_special);
$prefix_data['prefix_special'] = rtrim($prefix_data['prefix_special'],'.');
if ($all_tag_params) {
$tag_params = getArrayValue($all_tag_params, $prefix_data['prefix_special']);
if (!$tag_params) $tag_params = Array();
}
$tag_params = array_merge_recursive2($params, $tag_params);
$objects[ $prefix_data['prefix_special'] ] =& $this->Application->recallObject($prefix_data['prefix_special'], $prefix_data['prefix'], $tag_params);
$object_status[ $prefix_data['prefix_special'] ] = $objects[ $prefix_data['prefix_special'] ]->IsNewItem() ? 'new' : 'edit';
// a. set object's status field (adding item/editing item) for each object in title
if (getArrayValue($title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ],$prefix_data['prefix_special'])) {
$status_labels[ $prefix_data['prefix_special'] ] = $title_info[ $object_status[ $prefix_data['prefix_special'] ].'_status_labels' ][ $prefix_data['prefix_special'] ];
$title = str_replace('#'.$prefix_data['prefix_special'].'_status#', $status_labels[ $prefix_data['prefix_special'] ], $title);
}
// b. setting object's titlefield value (in titlebar ONLY) to default in case if object beeing created with no titlefield filled in
if ($object_status[ $prefix_data['prefix_special'] ] == 'new') {
$new_value = $this->getInfo( $objects[ $prefix_data['prefix_special'] ], 'titlefield' );
if(!$new_value && getArrayValue($title_info['new_titlefield'],$prefix_data['prefix_special']) ) $new_value = $this->Application->Phrase($title_info['new_titlefield'][ $prefix_data['prefix_special'] ]);
$title = str_replace('#'.$prefix_data['prefix_special'].'_titlefield#', $new_value, $title);
}
}
}
// replace to section title
$section = array_key_exists('section', $params) ? $params['section'] : false;
if ($section) {
$sections_helper =& $this->Application->recallObject('SectionsHelper');
/* @var $sections_helper kSectionsHelper */
$section_data =& $sections_helper->getSectionData($section);
$title = str_replace('#section_label#', '!' . $section_data['label'] . '!', $title);
}
// 2. replace phrases if any found in format string
$title = $this->Application->ReplaceLanguageTags($title, false);
// 3. find and replace any replacement vars
preg_match_all('/#(.*_.*)#/Uis',$title,$rets);
if ($rets[1]) {
$replacement_vars = array_keys( array_flip($rets[1]) );
foreach ($replacement_vars as $replacement_var) {
$var_info = explode('_',$replacement_var,2);
$object =& $objects[ $var_info[0] ];
$new_value = $this->getInfo($object,$var_info[1]);
$title = str_replace('#'.$replacement_var.'#', $new_value, $title);
}
}
// replace trailing spaces inside title preset + '' occurences into single space
$title = preg_replace('/[ ]*\'\'[ ]*/', ' ', $title);
if ($this->Application->ConfigValue('UseSmallHeader') && isset($params['group_title']) && $params['group_title']) {
$title .= ' - '.$params['group_title'];
}
$cut_first = getArrayValue($params, 'cut_first');
if ($cut_first && mb_strlen($title) > $cut_first) {
if (!preg_match('/<a href="(.*)">(.*)<\/a>/',$title)) {
$title = mb_substr($title, 0, $cut_first).' ...';
}
}
return $title;
}
function getInfo(&$object, $info_type)
{
switch ($info_type)
{
case 'titlefield':
$field = $this->Application->getUnitOption($object->Prefix,'TitleField');
return $field !== false ? $object->GetField($field) : 'TitleField Missing';
break;
case 'recordcount':
$of_phrase = $this->Application->Phrase('la_of');
return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' '.$of_phrase.' '.$object->NoFilterCount : $object->RecordsCount;
break;
default:
return $object->GetField($info_type);
break;
}
}
function GridInfo($params)
{
$object =& $this->GetList($params);
/* @var $object kDBList */
switch ($params['type']) {
case 'filtered':
return $object->GetRecordsCount();
case 'total':
return $object->GetNoFilterCount();
case 'from':
return $object->RecordsCount ? $object->Offset+1 : 0; //0-based
case 'to':
return $object->PerPage > 0 ? min($object->Offset + $object->PerPage, $object->RecordsCount) : $object->RecordsCount;
case 'total_pages':
return $object->GetTotalPages();
case 'needs_pagination':
return ($object->PerPage != -1) && (($object->RecordsCount > $object->PerPage) || ($object->Page > 1));
}
}
/**
* Parses block depending on its element type.
* For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2
* format. key=value can be substituted by <SQL>SELECT f1 AS OptionName, f2 AS OptionValue... FROM <PREFIX>TableName </SQL>
* where prefix is TABLE_PREFIX
*
* @param Array $params
* @return string
*/
function ConfigFormElement($params)
{
$object =& $this->getObject($params);
$field = $params['field'];
$helper =& $this->Application->recallObject('InpCustomFieldsHelper');
/* @var $helper InpCustomFieldsHelper */
$element_type = $object->GetDBField($params['element_type_field']);
if($element_type == 'label') $element_type = 'text';
$params['name'] = $params['blocks_prefix'].$element_type;
switch ($element_type) {
case 'select':
case 'multiselect':
case 'radio':
$field_options = $object->GetFieldOptions($field, 'options');
if ($object->GetDBField('DirectOptions')) {
// used for custom fields
$field_options['options'] = $object->GetDBField('DirectOptions');
}
else {
// used for configuration
$field_options['options'] = $helper->GetValuesHash($object->GetDBField($params['value_list_field']), ',');
}
$object->SetFieldOptions($field, $field_options);
break;
case 'text':
case 'textarea':
$params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field']));
break;
case 'password':
case 'checkbox':
default:
break;
}
return $this->Application->ParseBlock($params, 1);
}
/**
* Get's requested custom field value
*
* @param Array $params
* @return string
* @access public
*/
function CustomField($params)
{
$params['name'] = 'cust_'.$this->SelectParam($params, 'name,field');
return $this->Field($params);
}
function CustomFieldLabel($params)
{
$object =& $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
$sql = 'SELECT FieldLabel
FROM '.$this->Application->getUnitOption('cf', 'TableName').'
WHERE FieldName = '.$this->Conn->qstr($field);
return $this->Application->Phrase($this->Conn->GetOne($sql));
}
/**
* transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters
*
* @param array $arr
* @param int $columns
* @param int $per_page
* @return array
*/
function LinearToVertical(&$arr, $columns, $per_page)
{
$rows = $columns;
// in case if after applying per_page limit record count less then
// can fill requrested column count, then fill as much as we can
$cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns));
$imatrix = array();
for ($row = 0; $row < $rows; $row++) {
for ($col = 0; $col < $cols; $col++) {
$source_index = $row * $cols + $col;
if (!isset($arr[$source_index])) {
// in case if source array element count is less then element count in one row
continue;
}
$imatrix[$col * $rows + $row] = $arr[$source_index];
}
}
ksort($imatrix);
return array_values($imatrix);
}
/**
* If data was modfied & is in TempTables mode, then parse block with name passed;
* remove modification mark if not in TempTables mode
*
* @param Array $params
* @return string
* @access public
* @author Alexey
*/
function SaveWarning($params)
{
$main_prefix = getArrayValue($params, 'main_prefix');
if ($main_prefix && $main_prefix != '$main_prefix') {
$top_prefix = $main_prefix;
}
else {
$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix);
}
$temp_tables = substr($this->Application->GetVar($top_prefix.'_mode'), 0, 1) == 't';
$modified = $this->Application->RecallVar($top_prefix.'_modified');
if ($temp_tables && $modified) {
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $this->SelectParam($params, 'render_as,name');
$block_params['edit_mode'] = $temp_tables ? 1 : 0;
return $this->Application->ParseBlock($block_params);
}
$this->Application->RemoveVar($top_prefix.'_modified');
return '';
}
/**
* Returns list record count queries (on all pages)
*
* @param Array $params
* @return int
*/
function TotalRecords($params)
{
$list =& $this->GetList($params);
if (!$list->Counted) $list->CountRecs();
return $list->RecordsCount;
}
/**
* Range filter field name
*
* @param Array $params
* @return string
*/
function SearchInputName($params)
{
$field = $this->SelectParam($params, 'field,name');
$ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']';
if (isset($params['type'])) {
$ret .= '['.$params['type'].']';
}
return $ret;
}
/**
* Return range filter field value
*
* @param Array $params
* @return string
*/
function SearchField($params) // RangeValue
{
$field = $this->SelectParam($params, 'field,name');
$view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view');
$custom_filter = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_custom_filter.'.$view_name/*, ALLOW_DEFAULT_SETTINGS*/);
$custom_filter = $custom_filter ? unserialize($custom_filter) : Array();
if (isset($custom_filter[ $params['grid'] ][$field])) {
$ret = $custom_filter[ $params['grid'] ][$field][ $params['filter_type'] ]['submit_value'];
if (isset($params['type'])) {
$ret = $ret[ $params['type'] ];
}
if( !$this->HasParam($params, 'no_special') ) $ret = htmlspecialchars($ret);
return $ret;
}
return '';
}
function SearchFormat($params)
{
$field = $params['field'];
$object =& $this->GetList($params);
$options = $object->GetFieldOptions($field);
$format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ];
$formatter_class = getArrayValue($options,'formatter');
if($formatter_class)
{
$formatter =& $this->Application->recallObject($formatter_class);
$human_format = getArrayValue($params,'human');
$edit_size = getArrayValue($params,'edit_size');
$sample = getArrayValue($params,'sample');
if($sample)
{
return $formatter->GetSample($field, $options, $object);
}
elseif($human_format || $edit_size)
{
$format = $formatter->HumanFormat($format);
return $edit_size ? strlen($format) : $format;
}
}
return $format;
}
/**
* Returns error of range field
*
* @param unknown_type $params
* @return unknown
*/
function SearchError($params)
{
$field = $this->SelectParam($params, 'field,name');
$error_var_name = $this->getPrefixSpecial().'_'.$field.'_error';
$pseudo = $this->Application->RecallVar($error_var_name);
if ($pseudo) {
$this->Application->RemoveVar($error_var_name);
}
$object =& $this->Application->recallObject($this->Prefix.'.'.$this->Special.'-item', null, Array('skip_autoload' => true));
/* @var $object kDBItem */
$object->SetError($field, $pseudo);
return $object->GetErrorMsg($field, false);
}
/**
* Returns object used in tag processor
*
* @access public
* @return kDBBase
*/
function &getObject($params = Array())
{
$object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params);
if (isset($params['requery']) && $params['requery']) {
$this->Application->HandleEvent($q_event, $this->getPrefixSpecial().':LoadItem', $params);
}
return $object;
}
/**
* Checks if object propery value matches value passed
*
* @param Array $params
* @return bool
*/
function PropertyEquals($params)
{
$object =& $this->getObject($params);
$property_name = $this->SelectParam($params, 'name,var,property');
return $object->$property_name == $params['value'];
}
/**
* Group list records by header, saves internal order in group
*
* @param Array $records
* @param string $heading_field
*/
function groupRecords(&$records, $heading_field)
{
$sorted = Array();
$i = 0; $record_count = count($records);
while ($i < $record_count) {
$sorted[ $records[$i][$heading_field] ][] = $records[$i];
$i++;
}
$records = Array();
foreach ($sorted as $heading => $heading_records) {
$records = array_merge_recursive($records, $heading_records);
}
}
function DisplayOriginal($params)
{
return false;
}
/*function MultipleEditing($params)
{
$wid = $this->Application->GetTopmostWid($this->Prefix);
$session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$selected_ids = explode(',', $this->Application->RecallVar($session_name));
$ret = '';
if ($selected_ids) {
$selected_ids = explode(',', $selected_ids);
$object =& $this->getObject( array_merge_recursive2($params, Array('skip_autoload' => true)) );
$params['name'] = $params['render_as'];
foreach ($selected_ids as $id) {
$object->Load($id);
$ret .= $this->Application->ParseBlock($params);
}
}
return $ret;
}*/
/**
* Returns import/export process percent
*
* @param Array $params
* @return int
* @deprecated Please convert to event-model, not tag based
*/
function ExportStatus($params)
{
$export_object =& $this->Application->recallObject('CatItemExportHelper');
$event = new kEvent($this->getPrefixSpecial().':OnDummy');
$action_method = 'perform'.ucfirst($this->Special);
$field_values = $export_object->$action_method($event);
// finish code is done from JS now
if ($field_values['start_from'] >= $field_values['total_records'])
{
if ($this->Special == 'import') {
// this is used?
$this->Application->StoreVar('PermCache_UpdateRequired', 1);
$this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1, 'no_amp' => 1));
}
elseif ($this->Special == 'export') {
// used for orders export in In-Commerce
$finish_t = $this->Application->RecallVar('export_finish_t');
$this->Application->Redirect($finish_t, Array('pass' => 'all'));
$this->Application->RemoveVar('export_finish_t');
}
}
$export_options = $export_object->loadOptions($event);
return $export_options['start_from'] * 100 / $export_options['total_records'];
}
/**
* Returns path where exported category items should be saved
*
* @param Array $params
*/
function ExportPath($params)
{
$ret = EXPORT_PATH.'/';
if( getArrayValue($params, 'as_url') )
{
$ret = str_replace( FULL_PATH.'/', $this->Application->BaseURL(), $ret);
}
$export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial().'_options'));
$ret .= $export_options['ExportFilename'].'.'.($export_options['ExportFormat'] == 1 ? 'csv' : 'xml');
return $ret;
}
function FieldTotal($params)
{
$list =& $this->GetList($params);
return $list->GetFormattedTotal($this->SelectParam($params, 'field,name'), $params['function']);
}
/**
* Returns FCKEditor locale, that matches default site language
*
* @return string
*/
function _getFCKLanguage()
{
static $language_code = null;
if (!isset($language_code)) {
$language_code = 'en'; // defaut value
$sql = 'SELECT Locale
FROM '. $this->Application->getUnitOption('lang', 'TableName') . '
WHERE LanguageId = ' . $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang');
$locale = strtolower( $this->Conn->GetOne($sql) );
if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js')) {
// found language file, that exactly matches locale name (e.g. "en")
$language_code = $locale;
}
else {
$locale = explode('-', $locale);
if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js')) {
// language file matches first part of locale (e.g. "ru-RU")
$language_code = $locale[0];
}
}
}
return $language_code;
}
function FCKEditor($params)
{
$params['no_special'] = 1;
$params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready';
$value = $this->Field($params);
$name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params);
$theme_path = substr($this->Application->GetFrontThemePath(), 1) . '/inc/';
if (!file_exists(FULL_PATH . '/' . $theme_path . 'style.css')) {
$theme_path = EDITOR_PATH;
}
$styles_xml = $this->Application->BaseURL() . $theme_path . 'styles.xml';
$styles_css = $this->Application->BaseURL() . $theme_path . 'style.css';
$bgcolor = array_key_exists('bgcolor', $params) ? $params['bgcolor'] : $this->Application->GetVar('bgcolor');
if (!$bgcolor) {
$bgcolor = '#ffffff';
}
$preview_url = '';
$page_id = $this->Application->GetVar('c_id');
$content_id = $this->Application->GetVar('content_id');
if ($page_id && $content_id) {
// editing content block from Front-End, not category in admin
$sql = 'SELECT NamedParentPath
FROM ' . $this->Application->getUnitOption('c', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('c', 'IDField') . ' = ' . $page_id;
$template = strtolower( $this->Conn->GetOne($sql) );
$url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CONTENT, 'pass' => 'm');
$preview_url = $this->Application->HREF($template, '_FRONT_END_', $url_params, 'index.php');
$preview_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $preview_url);
}
include_once(FULL_PATH . EDITOR_PATH . 'fckeditor.php');
$oFCKeditor = new FCKeditor($name);
$oFCKeditor->FullUrl = $this->Application->BaseURL();
$oFCKeditor->BaseUrl = BASE_PATH . '/';
$oFCKeditor->BasePath = BASE_PATH . EDITOR_PATH;
$oFCKeditor->Width = $params['width'] ;
$oFCKeditor->Height = $params['height'] ;
$oFCKeditor->ToolbarSet = $page_id && $content_id ? 'Advanced' : 'Default';
$oFCKeditor->Value = $value;
$oFCKeditor->PreviewUrl = $preview_url;
$oFCKeditor->DefaultLanguage = $this->_getFCKLanguage();
$oFCKeditor->LateLoad = array_key_exists('late_load', $params) && $params['late_load'];
$oFCKeditor->Config = Array (
//'UserFilesPath' => $pathtoroot.'kernel/user_files',
'ProjectPath' => BASE_PATH . '/',
'CustomConfigurationsPath' => $this->Application->BaseURL() . 'core/admin_templates/js/inp_fckconfig.js',
'StylesXmlPath' => $styles_xml,
'EditorAreaCSS' => $styles_css,
'DefaultStyleLabel' => $this->Application->Phrase('la_editor_default_style'),
// 'Debug' => 1,
'Admin' => 1,
'K4' => 1,
'newBgColor' => $bgcolor,
'PreviewUrl' => $preview_url,
'BaseUrl' => BASE_PATH . '/',
'DefaultLanguage' => $this->_getFCKLanguage(),
'EditorAreaStyles' => 'body { background-color: '.$bgcolor.' }',
);
return $oFCKeditor->CreateHtml();
}
function IsNewItem($params)
{
$object =& $this->getObject($params);
return $object->IsNewItem();
}
/**
* Creates link to an item including only it's id
*
* @param Array $params
* @return string
*/
function ItemLink($params)
{
$object =& $this->getObject($params);
if (!isset($params['pass'])) {
$params['pass'] = 'm';
}
$params[$object->getPrefixSpecial().'_id'] = $object->GetID();
$m =& $this->Application->recallObject('m_TagProcessor');
return $m->t($params);
}
/**
* Calls OnNew event from template, when no other event submitted
*
* @param Array $params
*/
function PresetFormFields($params)
{
$prefix = $this->getPrefixSpecial();
if (!$this->Application->GetVar($prefix.'_event')) {
$this->Application->HandleEvent(new kEvent($prefix.':OnNew'));
}
}
function PrintSerializedFields($params)
{
$object =& $this->getObject();
$field = $this->SelectParam($params, 'field');
$data = unserialize($object->GetDBField($field));
$o = '';
$std_params['name'] = $params['render_as'];
$std_params['field'] = $params['field'];
$std_params['pass_params'] = true;
foreach ($data as $key => $row) {
$block_params = array_merge($std_params, $row, array('key'=>$key));
$o .= $this->Application->ParseBlock($block_params);
}
return $o;
}
/**
* Checks if current prefix is main item
*
* @param Array $params
* @return bool
*/
function IsTopmostPrefix($params)
{
return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix);
}
function PermSection($params)
{
$section = $this->SelectParam($params, 'section,name');
$perm_sections = $this->Application->getUnitOption($this->Prefix, 'PermSection');
return isset($perm_sections[$section]) ? $perm_sections[$section] : '';
}
function PerPageSelected($params)
{
$list =& $this->GetList($params);
return $list->PerPage == $params['per_page'] ? $params['selected'] : '';
}
/**
* Returns prefix + generated sepcial + any word
*
* @param Array $params
* @return string
*/
function VarName($params)
{
$list =& $this->GetList($params);
return $list->getPrefixSpecial().'_'.$params['type'];
}
/**
* Returns edit tabs by specified preset name or false in case of error
*
* @param string $preset_name
* @return mixed
*/
function getEditTabs($preset_name)
{
$presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets');
if (!$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0) {
return false;
}
return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false;
}
/**
* Detects if specified preset has tabs in it
*
* @param Array $params
* @return bool
*/
function HasEditTabs($params)
{
return $this->getEditTabs($params['preset_name']) ? true : false;
}
/**
* Sorts edit tabs based on their priority
*
* @param Array $tab_a
* @param Array $tab_b
* @return int
*/
function sortEditTabs($tab_a, $tab_b)
{
if ($tab_a['priority'] == $tab_b['priority']) {
return 0;
}
return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1;
}
/**
* Prints edit tabs based on preset name specified
*
* @param Array $params
* @return string
*/
function PrintEditTabs($params)
{
$edit_tabs = $this->getEditTabs($params['preset_name']);
if (!$edit_tabs) {
return ;
}
usort($edit_tabs, Array (&$this, 'sortEditTabs'));
$ret = '';
$block_params = $this->prepareTagParams($params);
$block_params['name'] = $params['render_as'];
foreach ($edit_tabs as $tab_info) {
$block_params['title'] = $tab_info['title'];
$block_params['template'] = $tab_info['t'];
$ret .= $this->Application->ParseBlock($block_params);
}
return $ret;
}
/**
* Performs image resize to required dimensions and returns resulting url (cached resized image)
*
* @param Array $params
* @return string
*/
function ImageSrc($params)
{
$max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false;
$max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false;
$logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false;
$logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false;
$logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false;
$object =& $this->getObject($params);
$field = $this->SelectParam($params, 'name,field');
return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin);
}
/**
* Allows to retrieve given setting from unit config
*
* @param Array $params
* @return mixed
*/
function UnitOption($params)
{
return $this->Application->getUnitOption($this->Prefix, $params['name']);
}
/**
* Returns list of allowed toolbar buttons or false, when all is allowed
*
* @param Array $params
* @return string
*/
function VisibleToolbarButtons($params)
{
$preset_name = replaceModuleSection($params['title_preset']);
$title_presets = $this->Application->getUnitOption($this->Prefix, 'TitlePresets');
if (!array_key_exists($preset_name, $title_presets)) {
trigger_error('Title preset not specified or missing (in tag "<strong>' . $this->getPrefixSpecial() . ':' . __METHOD__ . '</strong>")', E_USER_WARNING);
return false;
}
$preset_info = $title_presets[$preset_name];
if (!array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons'])) {
return false;
}
// always add search buttons
array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt');
$toolbar_buttons = array_map('addslashes', $preset_info['toolbar_buttons']);
return $toolbar_buttons ? "'" . implode("', '", $toolbar_buttons) . "'" : 'false';
}
/**
* Checks, that "To" part of at least one of range filters is used
*
* @param Array $params
* @return bool
*/
function RangeFiltersUsed($params)
{
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']);
}
/**
* This is abstract tag, used to modify unit config data based on template, where it's used.
* Tag is called from "combined_header" block in admin only.
*
* @param Array $params
*/
function ModifyUnitConfig($params)
{
}
/**
* Checks, that field is visible on edit form
*
* @param Array $params
* @return bool
*/
function FieldVisible($params)
{
$check_field = $params['field'];
$fields = $this->Application->getUnitOption($this->Prefix, 'Fields');
if (!array_key_exists($check_field, $fields)) {
// field not found in real fields array -> it's 100% virtual then
$fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields');
}
if (!array_key_exists($check_field, $fields)) {
$params['field'] = 'Password';
return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true;
}
$show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true;
if ($show_mode === smDEBUG) {
return defined('DEBUG_MODE') && DEBUG_MODE;
}
return $show_mode;
}
/**
* Checks, that there area visible fields in given section on edit form
*
* @param Array $params
* @return bool
*/
function FieldsVisible($params)
{
if (!$params['fields']) {
return true;
}
$check_fields = explode(',', $params['fields']);
$fields = $this->Application->getUnitOption($this->Prefix, 'Fields');
$virtual_fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields');
foreach ($check_fields as $check_field) {
// when at least one field in subsection is visible, then subsection is visible too
if (array_key_exists($check_field, $fields)) {
$show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true;
}
else {
$show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true;
}
if (($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE))) {
// field is visible
return true;
}
}
return false;
}
}
\ No newline at end of file
Index: branches/5.0.x/core/kernel/db/cat_tag_processor.php
===================================================================
--- branches/5.0.x/core/kernel/db/cat_tag_processor.php (nonexistent)
+++ branches/5.0.x/core/kernel/db/cat_tag_processor.php (revision 12343)
@@ -0,0 +1,789 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kCatDBTagProcessor extends kDBTagProcessor {
+
+ /**
+ * Permission Helper
+ *
+ * @var kPermissionsHelper
+ */
+ var $PermHelper = null;
+
+ function kCatDBTagProcessor()
+ {
+ parent::kDBTagProcessor();
+ $this->PermHelper = $this->Application->recallObject('PermissionsHelper');
+ }
+
+ function ItemIcon($params)
+ {
+ $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params);
+
+ $grids = $this->Application->getUnitOption($this->Prefix,'Grids');
+ $icons =& $grids[ $params['grid'] ]['Icons'];
+
+ $status_fields = $this->Application->getUnitOption($this->Prefix,'StatusField');
+ if (!$status_fields) return $icons['default'];
+
+ $value = $object->GetDBField($status_fields[0]); // sets base status icon
+ /* @var $object kDBItem */
+ if ($value == STATUS_ACTIVE) {
+ if( $object->HasField('IsPop') && $object->GetDBField('IsPop') ) $value = 'POP';
+ if( $object->HasField('IsHot') && $object->GetDBField('IsHot') ) $value = 'HOT';
+ if( $object->HasField('IsNew') && $object->GetDBField('IsNew') ) $value = 'NEW';
+ if( $object->HasField('EditorsPick') && $object->GetDBField('EditorsPick') ) $value = 'PICK';
+ }
+
+ return isset($icons[$value]) ? $icons[$value] : $icons['default'];
+ }
+
+ /**
+ * Allows to create valid mod-rewrite compatible link to module item
+ *
+ * @param Array $params
+ * @param string $id_prefix
+ * @return string
+ */
+ function ItemLink($params, $id_prefix = null)
+ {
+ if (!isset($params['pass'])) {
+ $params['pass'] = 'm,'.$this->Prefix;
+ }
+
+ $item_id = isset($params[$id_prefix.'_id']) && $params[$id_prefix.'_id'];
+ if (!$item_id) {
+ $item_id = $this->Application->GetVar($this->getPrefixSpecial().'_id');
+ if (!$item_id) {
+ $item_id = $this->Application->GetVar($this->Prefix.'_id');
+ }
+ }
+ $params[$this->Prefix.'_id'] = $item_id;
+
+ $object =& $this->getObject($params);
+ $params['m_cat_id'] = $object->GetDBField('CategoryId');
+ $params['m_cat_page'] = 1;
+ $params['pass_category'] = 1;
+
+ return $this->Application->ProcessParsedTag('m', 't', $params);
+ }
+
+ function CategoryPath($params)
+ {
+ if ($this->Application->IsAdmin()) {
+ // path for module root category in admin
+ if (!isset($params['cat_id'])) {
+ $params['cat_id'] = $this->Application->RecallVar($params['session_var'], 0);
+ }
+ }
+ else {
+ // path for category item category in front-end
+ $object =& $this->getObject($params);
+ $params['cat_id'] = $object->GetDBField('CategoryId');
+ }
+
+ return $this->Application->ProcessParsedTag('c', 'CategoryPath', $params);
+ }
+
+ function BuildListSpecial($params)
+ {
+ if ($this->Special != '') return $this->Special;
+ if ( isset($params['parent_cat_id']) ) {
+ $parent_cat_id = $params['parent_cat_id'];
+ }
+ else {
+ $parent_cat_id = $this->Application->GetVar('c_id');
+ if (!$parent_cat_id) {
+ $parent_cat_id = $this->Application->GetVar('m_cat_id');
+ }
+ }
+
+ $recursive = isset($params['recursive']);
+
+ $list_unique_key = $this->getUniqueListKey($params).$recursive;
+ if ($list_unique_key == '') {
+ return parent::BuildListSpecial($params);
+ }
+
+ return crc32($parent_cat_id.$list_unique_key);
+ }
+
+ function CatalogItemCount($params)
+ {
+ $params['skip_quering'] = true;
+ $object =& $this->GetList($params);
+
+ if (!$object->Counted) {
+ $object->CountRecs();
+ }
+
+ return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount;
+ }
+
+ function ListReviews($params)
+ {
+ $prefix = $this->Prefix.'-rev';
+ $review_tag_processor =& $this->Application->recallObject($prefix.'.item_TagProcessor');
+ return $review_tag_processor->PrintList($params);
+ }
+
+ function ReviewCount($params)
+ {
+ $review_tag_processor =& $this->Application->recallObject('rev.item_TagProcessor');
+ return $review_tag_processor->TotalRecords($params);
+ }
+
+ function InitCatalogTab($params)
+ {
+ $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible
+ $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab
+ $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid
+
+ // set default params (same as in catalog)
+ if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi';
+ if ($tab_params['special'] === false) $tab_params['special'] = '';
+ if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes';
+
+ // pass params to block with tab content
+ $params['name'] = $params['render_as'];
+ $special = $tab_params['special'] ? $tab_params['special'] : $this->Special;
+
+ $params['prefix'] = trim($this->Prefix.'.'.$special, '.');
+
+ $prefix_append = $this->Application->GetVar('prefix_append');
+ if ($prefix_append) {
+ $params['prefix'] .= $prefix_append;
+ }
+
+ $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default';
+ $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio';
+
+
+ $params['cat_prefix'] = trim('c.'.$special, '.');
+ $params['tab_mode'] = $tab_params['mode'];
+ $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid;
+ $params['tab_dependant'] = $tab_params['dependant'];
+ $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name
+
+ if ($special == 'showall' || $special == 'user') {
+ $params['grid_name'] .= 'ShowAll';
+ }
+
+ return $this->Application->ParseBlock($params, 1);
+ }
+
+ /**
+ * Show CachedNavbar of current item primary category
+ *
+ * @param Array $params
+ * @return string
+ */
+ function CategoryName($params)
+ {
+ // show category cachednavbar of
+ $object =& $this->getObject($params);
+ $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
+
+ $category_path = $this->Application->getCache('category_paths', $category_id);
+ if ($category_path === false) {
+ // not chached
+ if ($category_id > 0) {
+ $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $object->GetField('CachedNavbar'));
+ $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > ');
+ }
+ else {
+ $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
+ }
+ $this->Application->setCache('category_paths', $category_id, $category_path);
+ }
+ return $category_path;
+ }
+
+ /**
+ * Allows to determine if original value should be shown
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function DisplayOriginal($params)
+ {
+ // original id found & greather then zero + show original
+ $display_original = isset($params['display_original']) && $params['display_original'];
+
+ $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+
+ $object =& $this->getObject($params);
+ $perm_value = $this->PermHelper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $this->Prefix);
+
+ return $display_original && ($perm_value == 1) && $this->Application->GetVar($this->Prefix.'.original_id');
+ }
+
+ /**
+ * Checks if user have one of required permissions
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function HasPermission($params)
+ {
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $params['raise_warnings'] = 0;
+ $object =& $this->getObject($params);
+ /* @var $object kCatDBItem */
+
+ // 1. category restriction
+ $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id');
+
+ // 2. owner restriction
+ $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+ $is_owner = $object->GetDBField($owner_field) == $this->Application->RecallVar('user_id');
+
+ return $perm_helper->TagPermissionCheck($params, $is_owner);
+ }
+
+ /**
+ * Creates link to current category or to module root category, when current category is home
+ *
+ * @param Array $params
+ * @return string
+ */
+ function SuggestItemLink($params)
+ {
+ if (!isset($params['cat_id'])) {
+ $params['cat_id'] = $this->Application->GetVar('m_cat_id');
+ }
+
+ if ($params['cat_id'] == 0) {
+ $params['cat_id'] = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
+ }
+
+ $params['m_cat_page'] = 1;
+
+ return $this->Application->ProcessParsedTag('c', 'CategoryLink', $params);
+ }
+
+ /**
+ * Allows to detect if item has any additional images available
+ *
+ * @param Array $params
+ * @return string
+ */
+ function HasAdditionalImages($params)
+ {
+ $object =& $this->getObject($params);
+ $sql = 'SELECT ImageId
+ FROM '.$this->Application->getUnitOption('img', 'TableName').'
+ WHERE ResourceId = '.$object->GetDBField('ResourceId').' AND DefaultImg != 1 AND Enabled = 1';
+ return $this->Conn->GetOne($sql) ? 1 : 0;
+ }
+
+ /**
+ * Checks that item is pending
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function IsPending($params)
+ {
+ $object =& $this->getObject($params);
+
+ $pending_status = Array (STATUS_PENDING, STATUS_PENDING_EDITING);
+ return in_array($object->GetDBField('Status'), $pending_status);
+ }
+
+ function IsFavorite($params)
+ {
+ static $favorite_status = Array ();
+
+ $object =& $this->getObject($params);
+ /* @var $object kDBList */
+
+ if (!isset($favorite_status[$this->Special])) {
+ $resource_ids = $object->GetCol('ResourceId');
+
+ $user_id = $this->Application->RecallVar('user_id');
+ $sql = 'SELECT FavoriteId, ResourceId
+ FROM '.$this->Application->getUnitOption('fav', 'TableName').'
+ WHERE (PortalUserId = '.$user_id.') AND (ResourceId IN ('.implode(',', $resource_ids).'))';
+ $favorite_status[$this->Special] = $this->Conn->GetCol($sql, 'ResourceId');
+ }
+
+ return isset($favorite_status[$this->Special][$object->GetDBField('ResourceId')]);
+ }
+
+ /**
+ * Returns item's editors pick status (using not formatted value)
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function IsEditorsPick($params)
+ {
+ $object =& $this->getObject($params);
+
+ return $object->GetDBField('EditorsPick') == 1;
+ }
+
+ function FavoriteToggleLink($params)
+ {
+ $fav_prefix = $this->Prefix.'-fav';
+
+ $params['pass'] = implode(',', Array('m', $this->Prefix, $fav_prefix));
+ $params[$fav_prefix.'_event'] = 'OnFavoriteToggle';
+
+ return $this->ItemLink($params);
+ }
+
+ /**
+ * Checks if item is passed in url
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function ItemAvailable($params)
+ {
+ return $this->Application->GetVar($this->getPrefixSpecial().'_id') > 0;
+ }
+
+ function SortingSelected($params)
+ {
+ $list =& $this->GetList($params);
+ $user_sorting_start = $this->getUserSortIndex();
+
+ $sorting_field = $list->GetOrderField($user_sorting_start);
+ $sorting = strtolower($sorting_field . '|' . $list->GetOrderDirection($user_sorting_start));
+
+ $field_options = $list->GetFieldOptions($sorting_field);
+ if (array_key_exists('formatter', $field_options) && $field_options['formatter'] == 'kMultiLanguage') {
+ // remove language prefix
+ $sorting = preg_replace('/^l[\d]+_(.*)/', '\\1', $sorting);
+ $params['sorting'] = preg_replace('/^l[\d]+_(.*)/', '\\1', $params['sorting']);
+ }
+
+ return $sorting == strtolower($params['sorting']) ? $params['selected'] : '';
+ }
+
+ function CombinedSortingDropDownName($params)
+ {
+ return $this->Prefix.'_CombinedSorting';
+ }
+
+ /**
+ * Prepares name for field with event in it (used only on front-end)
+ *
+ * @param Array $params
+ * @return string
+ */
+ function SubmitName($params)
+ {
+ return 'events['.$this->Prefix.']['.$params['event'].']';
+ }
+
+ /**
+ * Returns prefix + any word (used for shared between categories per page settings)
+ *
+ * @param Array $params
+ * @return string
+ */
+ function VarName($params)
+ {
+ return $this->Prefix.'_'.$params['type'];
+ }
+
+ /**
+ * Checks if we are viewing module root category
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function IsModuleHome($params)
+ {
+ $root_category = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
+
+ return $root_category == $this->Application->GetVar('m_cat_id');
+ }
+
+ /**
+ * Dynamic votes indicator
+ *
+ * @param Array $params
+ *
+ * @return string
+ */
+ function VotesIndicator($params)
+ {
+ $object =& $this->getObject($params);
+ /* @var $object kDBItem */
+
+ $rating_helper =& $this->Application->recallObject('RatingHelper');
+ /* @var $rating_helper RatingHelper */
+
+ $small_style = array_key_exists('small_style', $params) ? $params['small_style'] : false;
+
+ return $rating_helper->ratingBar($object, true, '', $small_style);
+ }
+
+ function RelevanceIndicator($params)
+ {
+ $object =& $this->getObject($params);
+
+ $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+ $sql = 'SELECT Relevance
+ FROM '.$search_results_table.'
+ WHERE ResourceId = '.$object->GetDBField('ResourceId');
+
+ $percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql)));
+ $percents_off = ($percents_off < 0) ? 0 : $percents_off;
+ if ($percents_off) {
+ $params['percent_off'] = $percents_off;
+ $params['percent_on'] = 100 - $percents_off;
+ $params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal');
+ }
+ else {
+ $params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full');
+ }
+ return $this->Application->ParseBlock($params);
+ }
+
+ function SearchResultField($params)
+ {
+ $ret = $this->Field($params);
+
+ $keywords = unserialize( $this->Application->RecallVar('highlight_keywords') );
+ $opening = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_opening_render_as,block_highlight_opening')) );
+ $closing = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_closing_render_as,block_highlight_closing')) );
+
+ foreach ($keywords as $index => $keyword) {
+ $keywords[$index] = preg_quote($keyword, '/');
+ }
+
+ return preg_replace('/('.implode('|', $keywords).')/i', $opening.'\\1'.$closing, $ret);
+ }
+
+ /**
+ * Shows keywords, that user searched
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function SearchKeywords($params)
+ {
+ $keywords = $this->Application->GetVar('keywords');
+ $sub_search = $this->Application->GetVar('search_type') == 'subsearch';
+
+ return ($keywords !== false) && !$sub_search ? $keywords : $this->Application->RecallVar('keywords');
+ }
+
+ function AdvancedSearchForm($params)
+ {
+ $search_table = $this->Application->getUnitOption('confs', 'TableName');
+ $module_name = $this->Application->findModule('Var', $this->Prefix, 'Name');
+
+ $sql = 'SELECT *
+ FROM '.$search_table.'
+ WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)
+ ORDER BY DisplayOrder';
+ $search_config = $this->Conn->Query($sql);
+
+ $ret = '';
+ foreach ($search_config as $record) {
+ $params['name'] = $this->SelectParam($params, 'and_or_render_as,and_or_block');
+ $params['field'] = $record['FieldName'];
+ $params['andor'] = $this->Application->ParseBlock($params);
+
+ $params['name'] = $this->SelectParam($params, $record['FieldType'].'_render_as,'.$record['FieldType'].'_block');
+ $params['caption'] = $this->Application->Phrase($record['DisplayName']);
+ $ret .= $this->Application->ParseBlock($params);
+ }
+ return $ret;
+ }
+
+ /**
+ * Returns last modification date of items in category / system
+ *
+ * @param Array $params
+ * @return string
+ */
+ function LastUpdated($params)
+ {
+ $category_id = $this->Application->GetVar('m_cat_id');
+ $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
+
+ if (isset($params['local']) && $params['local'] && $category_id > 0) {
+ // scan only current category & it's children
+ $sql = 'SELECT TreeLeft, TreeRight
+ FROM '.TABLE_PREFIX.'Category
+ WHERE CategoryId = '.$category_id;
+ $tree_info = $this->Conn->GetRow($sql);
+
+ $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate
+ FROM '.$table_name.' item_table
+ LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId)
+ LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
+ WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight'];
+ }
+ else {
+ // scan all categories in system
+ $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
+ FROM '.$table_name;
+ }
+
+ $row_data = $this->Conn->GetRow($sql);
+ if (!$row_data) {
+ return '';
+ }
+
+ $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ];
+
+ // format date
+ $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat';
+ if (preg_match("/_regional_(.*)/", $format, $regs)) {
+ $lang =& $this->Application->recallObject('lang.current');
+ if ($regs[1] == 'DateTimeFormat') {
+ // combined format
+ $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat');
+ }
+ else {
+ // simple format
+ $format = $lang->GetDBField($regs[1]);
+ }
+ }
+
+ return adodb_date($format, $date);
+ }
+
+ /**
+ * Counts category item count in system (not category-dependent)
+ *
+ * @param Array $params
+ * @return int
+ */
+ function ItemCount($params)
+ {
+ $count_helper =& $this->Application->recallObject('CountHelper');
+ /* @var $count_helper kCountHelper */
+
+ $today_only = isset($params['today']) && $params['today'];
+ return $count_helper->ItemCount($this->Prefix, $today_only);
+ }
+
+ function CategorySelector($params)
+ {
+ $category_id = isset($params['category_id']) && is_numeric($params['category_id']) ? $params['category_id'] : false;
+ if ($category_id === false) {
+ // if category id not given use module root category
+ $category_id = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
+ }
+
+ $id_field = $this->Application->getUnitOption('c', 'IDField');
+ $title_field = $this->Application->getUnitOption('c', 'TitleField');
+ $table_name = $this->Application->getUnitOption('c', 'TableName');
+
+ $count_helper =& $this->Application->recallObject('CountHelper');
+ /* @var $count_helper kCountHelper */
+
+ list ($view_perm, $view_filter) = $count_helper->GetPermissionClause('c', 'perm_cache');
+
+ // get category list (permission based)
+ $sql = 'SELECT c.'.$title_field.', c.'.$id_field.'
+ FROM '.$table_name.' c
+ INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId
+ WHERE (ParentId = '.$category_id.') AND ('.$view_filter.') AND (perm_cache.PermId = '.$view_perm.') AND (c.Status = '.STATUS_ACTIVE.')
+ ORDER BY c.'.$title_field.' ASC';
+ $categories = $this->Conn->GetCol($sql, $id_field);
+
+ $block_params = $this->prepareTagParams($params);
+ $block_params['name'] = $params['render_as'];
+ $block_params['strip_nl'] = 2;
+
+ $ret = '';
+ foreach ($categories as $category_id => $category_name) {
+ // print category
+ $block_params['separator'] = isset($params['category_id']) ? $params['separator'] : ''; // return original separator, remove separator for top level categories
+ $block_params['category_id'] = $category_id;
+ $block_params['category_name'] = $category_name;
+ $ret .= $this->Application->ParseBlock($block_params);
+
+ // print it's children
+ $block_params['separator'] = '&nbsp;&nbsp;&nbsp;'.$params['separator'];
+ $ret .= $this->CategorySelector($block_params);
+ }
+
+ return $ret;
+ }
+
+ function PrintMoreCategories($params)
+ {
+ $object =& $this->getObject();
+ /* @var $object kDBItem */
+
+ $category_ids = $this->Field($params);
+ if (!$category_ids) {
+ return '';
+ }
+
+ $category_ids = explode('|', substr($category_ids, 1, -1));
+
+ $id_field = $this->Application->getUnitOption('c', 'IDField');
+ $title_field = $this->Application->getUnitOption('c', 'TitleField');
+ $table_name = $this->Application->getUnitOption('c', 'TableName');
+
+ $sql = 'SELECT '.$title_field.', '.$id_field.'
+ FROM '.$table_name.'
+ WHERE '.$id_field.' IN ('.implode(',', $category_ids).')';
+ $categories = $this->Conn->GetCol($sql, $id_field);
+
+ $block_params = $this->prepareTagParams($params);
+ $block_params['name'] = $params['render_as'];
+
+ $ret = '';
+ foreach ($categories as $category_id => $category_name) {
+ $block_params['category_id'] = $category_id;
+ $block_params['category_name'] = $category_name;
+ $ret .= $this->Application->ParseBlock($block_params);
+ }
+
+ return $ret;
+ }
+
+ function DownloadFileLink($params)
+ {
+ $params[$this->getPrefixSpecial().'_event'] = 'OnDownloadFile';
+
+ return $this->ItemLink($params);
+ }
+
+ function ImageSrc($params)
+ {
+ list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
+ return $tag_processed ? $ret : false;
+ }
+
+ /**
+ * Registers hit for item (one time per session)
+ *
+ * @param Array $params
+ */
+ function RegisterHit($params)
+ {
+ $object =& $this->getObject();
+ /* @var $object kCatDBItem */
+
+ if ($object->isLoaded()) {
+ $object->RegisterHit();
+ }
+ }
+
+ /**
+ * Returns link to item's author public profile
+ *
+ * @param Array $params
+ * @return string
+ */
+ function ProfileLink($params)
+ {
+ $object =& $this->getObject($params);
+ $owner_field = array_key_exists('owner_field', $params) ? $params['owner_field'] : 'CreatedById';
+ $params['user_id'] = $object->GetDBField($owner_field);
+ unset($params['owner_field']);
+
+ return $this->Application->ProcessParsedTag('m', 'Link', $params);
+ }
+
+ /**
+ * Checks, that "view in browse mode" functionality available
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function BrowseModeAvailable($params)
+ {
+ $valid_special = $valid_special = $params['Special'] != 'user';
+ $not_selector = $this->Application->GetVar('type') != 'item_selector';
+
+ return $valid_special && $not_selector;
+ }
+
+ /**
+ * Returns a link for editing product
+ *
+ * @param Array $params
+ * @return string
+ */
+ function ItemEditLink($params)
+ {
+ $object =& $this->getObject();
+ /* @var $object kDBList */
+
+ $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit';
+
+ $url_params = Array (
+ 'm_opener' => 'd',
+ $this->Prefix.'_mode' => 't',
+ $this->Prefix.'_event' => 'OnEdit',
+ $this->Prefix.'_id' => $object->GetID(),
+ 'm_cat_id' => $object->GetDBField('CategoryId'),
+ 'pass' => 'all,'.$this->Prefix,
+ 'no_pass_through' => 1,
+ );
+
+ return $this->Application->HREF($edit_template,'', $url_params);
+ }
+
+ function LanguageVisible($params)
+ {
+ $field = $this->SelectParam($params, 'name,field');
+
+ preg_match('/l([\d]+)_(.*)/', $field, $regs);
+ $params['name'] = $regs[2];
+
+ return $this->HasLanguageError($params) || $this->Application->GetVar('m_lang') == $regs[1];
+ }
+
+ function HasLanguageError($params)
+ {
+ static $languages = null;
+
+ if (!isset($languages)) {
+ $sql = 'SELECT ' . $this->Application->getUnitOption('lang', 'IDField') . '
+ FROM ' . $this->Application->getUnitOption('lang', 'TableName') . '
+ WHERE Enabled = 1';
+ $languages = $this->Conn->GetCol($sql);
+ }
+
+ $field = $this->SelectParam($params, 'name,field');
+
+ $object =& $this->getObject($params);
+ /* @var $object kDBItem */
+
+ foreach ($languages as $language_id) {
+ $check_field = 'l' . $language_id . '_' . $field;
+ if ($object->GetErrorMsg($check_field, false)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/kernel/db/cat_tag_processor.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.38.2.25
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/kernel/db/cat_event_handler.php
===================================================================
--- branches/5.0.x/core/kernel/db/cat_event_handler.php (nonexistent)
+++ branches/5.0.x/core/kernel/db/cat_event_handler.php (revision 12343)
@@ -0,0 +1,2653 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class kCatDBEventHandler extends kDBEventHandler {
+
+ /**
+ * Allows to override standart permission mapping
+ *
+ */
+ function mapPermissions()
+ {
+ parent::mapPermissions();
+ $permissions = Array(
+ 'OnSaveSettings' => Array ('self' => 'add|edit|advanced:import'),
+ 'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'),
+ 'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
+
+ 'OnCopy' => Array ('self' => true),
+ 'OnDownloadFile' => Array ('self' => 'view'),
+ 'OnCancelAction' => Array ('self' => true),
+ 'OnItemBuild' => Array ('self' => true),
+ 'OnMakeVote' => Array ('self' => true),
+ );
+
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ /**
+ * Load item if id is available
+ *
+ * @param kEvent $event
+ */
+ function LoadItem(&$event)
+ {
+ $object =& $event->getObject();
+ $id = $this->getPassedID($event);
+ if ($object->Load($id)) {
+ $actions =& $this->Application->recallObject('kActions');
+ $actions->Set($event->Prefix_Special.'_id', $object->GetID() );
+
+ $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
+ if ($use_pending_editing && $event->Special != 'original') {
+ $this->Application->SetVar($event->Prefix.'.original_id', $object->GetDBField('OrgId'));
+ }
+ }
+ else {
+ $object->setID($id);
+ }
+ }
+
+ /**
+ * Checks permissions of user
+ *
+ * @param kEvent $event
+ */
+ function CheckPermission(&$event)
+ {
+ if (!$this->Application->IsAdmin()) {
+ if ($event->Name == 'OnSetSortingDirect') {
+ // allow sorting on front event without view permission
+ return true;
+ }
+ }
+
+ if ($event->Name == 'OnExport') {
+ // save category_id before doing export
+ $this->Application->LinkVar('m_cat_id');
+ }
+
+ if (in_array($event->Name, $this->_getMassPermissionEvents())) {
+ $items = $this->_getPermissionCheckInfo($event);
+
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ if (($event->Name == 'OnSave') && array_key_exists(0, $items)) {
+ // adding new item (ID = 0)
+ $perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0;
+ }
+ else {
+ // leave only items, that can be edited
+ $ids = Array ();
+ $check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
+ foreach ($items as $item_id => $item_data) {
+ if ($perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0) {
+ $ids[] = $item_id;
+ }
+ }
+
+ if (!$ids) {
+ // no items left for editing -> no permission
+ return $perm_helper->finalizePermissionCheck($event, false);
+ }
+
+ $perm_value = true;
+ $event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
+ }
+
+ return $perm_helper->finalizePermissionCheck($event, $perm_value);
+ }
+
+ $export_events = Array ('OnSaveSettings', 'OnResetSettings', 'OnExportBegin');
+ if (in_array($event->Name, $export_events)) {
+ // when import settings before selecting target import category
+ return $this->Application->CheckPermission('in-portal:main_import.view');
+ }
+
+ if ($event->Name == 'OnProcessSelected') {
+ if ($this->Application->RecallVar('dst_field') == 'ImportCategory') {
+ // when selecting target import category
+ return $this->Application->CheckPermission('in-portal:main_import.view');
+ }
+ }
+
+ return parent::CheckPermission($event);
+ }
+
+ /**
+ * Returns events, that require item-based (not just event-name based) permission check
+ *
+ * @return Array
+ */
+ function _getMassPermissionEvents()
+ {
+ return Array (
+ 'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
+ 'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
+ 'OnCut',
+ );
+ }
+
+ /**
+ * Returns category item IDs, that require permission checking
+ *
+ * @param kEvent $event
+ * @return string
+ */
+ function _getPermissionCheckIDs(&$event)
+ {
+ if ($event->Name == 'OnSave') {
+ $selected_ids = implode(',', $this->getSelectedIDs($event, true));
+ if (!$selected_ids) {
+ $selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
+ }
+ }
+ else {
+ // OnEdit, OnMassDelete events, when items are checked in grid
+ $selected_ids = implode(',', $this->StoreSelectedIDs($event));
+ }
+
+ return $selected_ids;
+ }
+
+ /**
+ * Returns information used in permission checking
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function _getPermissionCheckInfo(&$event)
+ {
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ // when saving data from temp table to live table check by data from temp table
+ $item_ids = $this->_getPermissionCheckIDs($event);
+ $items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave');
+
+ if (!$items) {
+ // when item not present in temp table, then permission is not checked, because there are no data in db to check
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ list ($id, $fields_hash) = each($items_info);
+
+ if (array_key_exists('CategoryId', $fields_hash)) {
+ $item_category = $fields_hash['CategoryId'];
+ }
+ else {
+ $item_category = $this->Application->GetVar('m_cat_id');
+ }
+
+ $items[$id] = Array (
+ 'CreatedById' => $this->Application->RecallVar('use_id'),
+ 'CategoryId' => $item_category,
+ );
+ }
+
+ return $items;
+ }
+
+ /**
+ * Add selected items to clipboard with mode = COPY (CLONE)
+ *
+ * @param kEvent $event
+ */
+ function OnCopy(&$event)
+ {
+ $this->Application->RemoveVar('clipboard');
+ $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
+ $clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Add selected items to clipboard with mode = CUT
+ *
+ * @param kEvent $event
+ */
+ function OnCut(&$event)
+ {
+ $this->Application->RemoveVar('clipboard');
+ $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
+ $clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Checks permission for OnPaste event
+ *
+ * @param kEvent $event
+ * @return bool
+ */
+ function _checkPastePermission(&$event)
+ {
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $category_id = $this->Application->GetVar('m_cat_id');
+ if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
+ // no items left for editing -> no permission
+ return $perm_helper->finalizePermissionCheck($event, false);
+ }
+
+ return true;
+ }
+
+ /**
+ * Performs category item paste
+ *
+ * @param kEvent $event
+ */
+ function OnPaste(&$event)
+ {
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) {
+ return;
+ }
+
+ $clipboard_data = $event->getEventParam('clipboard_data');
+
+ if (!$clipboard_data['cut'] && !$clipboard_data['copy']) {
+ return false;
+ }
+
+ if ($clipboard_data['copy']) {
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ /* @var $temp kTempTablesHandler */
+
+ $this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone"
+ $temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']);
+ }
+
+ if ($clipboard_data['cut']) {
+ $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix, Array('skip_autoload' => true));
+
+ foreach ($clipboard_data['cut'] as $id) {
+ $object->Load($id);
+ $object->MoveToCat();
+ }
+ }
+ }
+
+ /**
+ * 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
+ */
+ function OnMassDelete(&$event)
+ {
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ return;
+ }
+
+ $event->status=erSUCCESS;
+
+ $ids = $this->StoreSelectedIDs($event);
+
+ $to_delete = array();
+ if ($recycle_bin = $this->Application->ConfigValue('RecycleBinFolder')) {
+ $rb =& $this->Application->recallObject('c.recycle', null, array('skip_autoload' => true));
+ $rb->Load($recycle_bin);
+ $object =& $this->Application->recallObject($event->Prefix.'.recycleitem', null, Array ('skip_autoload' => true));
+ foreach ($ids as $id) {
+ $object->Load($id);
+ if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $object->GetDBField('ParentPath'))) {
+ $to_delete[] = $id;
+ continue;
+ }
+ $object->MoveToCat($recycle_bin);
+ }
+ $ids = $to_delete;
+ }
+
+ $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+
+ $event->setEventParam('ids', $ids);
+ $this->customProcessing($event, 'before');
+ $ids = $event->getEventParam('ids');
+
+ if($ids)
+ {
+ $temp->DeleteItems($event->Prefix, $event->Special, $ids);
+ }
+ $this->clearSelectedIDs($event);
+ }
+
+
+ /**
+ * Return type clauses for list bulding on front
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function getTypeClauses(&$event)
+ {
+ $types = $event->getEventParam('types');
+ $types = $types ? explode(',', $types) : Array ();
+
+ $except_types = $event->getEventParam('except');
+ $except_types = $except_types ? explode(',', $except_types) : Array ();
+
+ $type_clauses = Array();
+
+ $user_id = $this->Application->RecallVar('user_id');
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ $type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id;
+ $type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id;
+ $type_clauses['my_items']['having_filter'] = false;
+
+ $type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
+ $type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
+ $type_clauses['pick']['having_filter'] = false;
+
+ $type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1';
+ $type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1';
+ $type_clauses['hot']['having_filter'] = true;
+
+ $type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1';
+ $type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1';
+ $type_clauses['pop']['having_filter'] = true;
+
+ $type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1';
+ $type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1';
+ $type_clauses['new']['having_filter'] = true;
+
+ $type_clauses['displayed']['include'] = '';
+ $displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids');
+ if ($displayed) {
+ $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
+ $type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')';
+ }
+ else {
+ $type_clauses['displayed']['except'] = '';
+ }
+ $type_clauses['displayed']['having_filter'] = false;
+
+ if (in_array('search', $types) || in_array('search', $except_types)) {
+ $event_mapping = Array(
+ 'simple' => 'OnSimpleSearch',
+ 'subsearch' => 'OnSubSearch',
+ 'advanced' => 'OnAdvancedSearch');
+ if($this->Application->GetVar('INPORTAL_ON') && $this->Application->GetVar('Action') == 'm_simple_subsearch')
+ {
+ $type = 'subsearch';
+ }
+ else
+ {
+ $type = $this->Application->GetVar('search_type') ? $this->Application->GetVar('search_type') : 'simple';
+ }
+
+ if($keywords = $event->getEventParam('keyword_string')) // processing keyword_string param of ListProducts tag
+ {
+ $this->Application->SetVar('keywords', $keywords);
+ $type = 'simple';
+ }
+ $search_event = $event_mapping[$type];
+ $this->$search_event($event);
+
+ $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+ $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
+ if ($this->Conn->Query($sql)) {
+ $search_res_ids = $this->Conn->GetCol('SELECT ResourceId FROM '.$search_table);
+ }
+
+ if (isset($search_res_ids) && $search_res_ids) {
+ $type_clauses['search']['include'] = '%1$s.ResourceId IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
+ $type_clauses['search']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
+ }
+ else {
+ $type_clauses['search']['include'] = '0';
+ $type_clauses['search']['except'] = '1';
+ }
+ $type_clauses['search']['having_filter'] = false;
+ }
+
+ if (in_array('related', $types) || in_array('related', $except_types)) {
+
+ $related_to = $event->getEventParam('related_to');
+ if (!$related_to) {
+ $related_prefix = $event->Prefix;
+ }
+ else {
+ $sql = 'SELECT Prefix
+ FROM '.TABLE_PREFIX.'ItemTypes
+ WHERE ItemName = '.$this->Conn->qstr($related_to);
+ $related_prefix = $this->Conn->GetOne($sql);
+ }
+
+ $rel_table = $this->Application->getUnitOption('rel', 'TableName');
+ $item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
+
+ if ($item_type == 0) {
+ trigger_error('<strong>ItemType</strong> not defined for prefix <strong>' . $event->Prefix . '</strong>', E_USER_WARNING);
+ }
+
+ // process case, then this list is called inside another list
+ $prefix_special = $event->getEventParam('PrefixSpecial');
+ if (!$prefix_special) {
+ $prefix_special = $this->Application->Parser->GetParam('PrefixSpecial');
+ }
+
+ $id = false;
+ if ($prefix_special !== false) {
+ $processed_prefix = $this->Application->processPrefix($prefix_special);
+ if ($processed_prefix['prefix'] == $related_prefix) {
+ // printing related categories within list of items (not on details page)
+ $list =& $this->Application->recallObject($prefix_special);
+ /* @var $list kDBList */
+
+ $id = $list->GetID();
+ }
+ }
+
+ if ($id === false) {
+ // printing related categories for single item (possibly on details page)
+ if ($related_prefix == 'c') {
+ $id = $this->Application->GetVar('m_cat_id');
+ }
+ else {
+ $id = $this->Application->GetVar($related_prefix . '_id');
+ }
+ }
+
+ $p_item =& $this->Application->recallObject($related_prefix.'.current', null, Array('skip_autoload' => true));
+ $p_item->Load( (int)$id );
+
+ $p_resource_id = $p_item->GetDBField('ResourceId');
+
+ $sql = 'SELECT SourceId, TargetId FROM '.$rel_table.'
+ WHERE
+ (Enabled = 1)
+ AND (
+ (Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
+ OR
+ (Type = 1
+ AND (
+ (SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
+ OR
+ (TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.')
+ )
+ )
+ )';
+
+ $related_ids_array = $this->Conn->Query($sql);
+ $related_ids = Array();
+
+ foreach ($related_ids_array as $key => $record) {
+ $related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ];
+ }
+
+ if (count($related_ids) > 0) {
+ $type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
+ $type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
+ }
+ else {
+ $type_clauses['related']['include'] = '0';
+ $type_clauses['related']['except'] = '1';
+ }
+ $type_clauses['related']['having_filter'] = false;
+ }
+
+ if (in_array('favorites', $types) || in_array('favorites', $except_types)) {
+ $sql = 'SELECT ResourceId
+ FROM '.$this->Application->getUnitOption('fav', 'TableName').'
+ WHERE PortalUserId = '.$this->Application->RecallVar('user_id');
+ $favorite_ids = $this->Conn->GetCol($sql);
+ if ($favorite_ids) {
+ $type_clauses['favorites']['include'] = '%1$s.ResourceId IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
+ $type_clauses['favorites']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
+ }
+ else {
+ $type_clauses['favorites']['include'] = 0;
+ $type_clauses['favorites']['except'] = 1;
+ }
+ $type_clauses['favorites']['having_filter'] = false;
+ }
+
+ return $type_clauses;
+ }
+
+ /**
+ * Returns SQL clause, that will help to select only data from specified category & it's children
+ *
+ * @param int $category_id
+ * @return string
+ */
+ function getCategoryLimitClause($category_id)
+ {
+ if (!$category_id) {
+ return false;
+ }
+
+ $tree_indexes = $this->Application->getTreeIndex($category_id);
+ if (!$tree_indexes) {
+ // id of non-existing category was given
+ return 'FALSE';
+ }
+
+ return TABLE_PREFIX.'Category.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight'];
+ }
+
+ /**
+ * Apply filters to list
+ *
+ * @param kEvent $event
+ */
+ function SetCustomQuery(&$event)
+ {
+ parent::SetCustomQuery($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBList */
+
+ // add category filter if needed
+ if ($event->Special != 'showall' && $event->Special != 'user') {
+ if ($event->getEventParam('parent_cat_id') !== false) {
+ $parent_cat_id = $event->getEventParam('parent_cat_id');
+ }
+ else {
+ $parent_cat_id = $this->Application->GetVar('c_id');
+ if (!$parent_cat_id) {
+ $parent_cat_id = $this->Application->GetVar('m_cat_id');
+ }
+ if (!$parent_cat_id) {
+ $parent_cat_id = 0;
+ }
+ }
+
+ if ("$parent_cat_id" == '0') {
+ // replace "0" category with "Content" category id (this way template
+ $parent_cat_id = $this->Application->findModule('Name', 'Core', 'RootCat');
+ }
+
+ if ((string)$parent_cat_id != 'any') {
+ if ($event->getEventParam('recursive')) {
+ $filter_clause = $this->getCategoryLimitClause($parent_cat_id);
+ if ($filter_clause !== false) {
+ $object->addFilter('category_filter', $filter_clause);
+ }
+
+ $object->addFilter('primary_filter', 'PrimaryCat = 1');
+ }
+ else {
+ $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id );
+ }
+ }
+ else {
+ $object->addFilter('primary_filter', 'PrimaryCat = 1');
+ }
+ }
+ else {
+ $object->addFilter('primary_filter', 'PrimaryCat = 1');
+
+ // if using recycle bin don't show items from there
+ $recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
+ if ($recycle_bin) {
+ $object->addFilter('recyclebin_filter', TABLE_PREFIX.'CategoryItems.CategoryId <> '.$recycle_bin);
+ }
+ }
+
+ if ($event->Special == 'user') {
+ $editable_user = $this->Application->GetVar('u_id');
+ $object->addFilter('owner_filter', '%1$s.'.$this->getOwnerField($event->Prefix).' = '.$editable_user);
+ }
+
+ // add permission filter
+ if ($this->Application->RecallVar('user_id') == -1) {
+ // for "root" CATEGORY.VIEW permission is checked for items lists too
+ $view_perm = 1;
+ }
+ else {
+ // for any real user itemlist view permission is checked instead of CATEGORY.VIEW
+ $count_helper =& $this->Application->recallObject('CountHelper');
+ /* @var $count_helper kCountHelper */
+
+ list ($view_perm, $view_filter) = $count_helper->GetPermissionClause($event->Prefix, 'perm');
+ $object->addFilter('perm_filter2', $view_filter);
+ }
+
+ $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm);
+
+
+ $types = $event->getEventParam('types');
+ $this->applyItemStatusFilter($object, $types);
+
+ $except_types = $event->getEventParam('except');
+ $type_clauses = $this->getTypeClauses($event);
+
+ // convert prepared type clauses into list filters
+ $includes_or_filter =& $this->Application->makeClass('kMultipleFilter');
+ $includes_or_filter->setType(FLT_TYPE_OR);
+
+ $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter');
+ $excepts_and_filter->setType(FLT_TYPE_AND);
+
+ $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter');
+ $includes_or_filter_h->setType(FLT_TYPE_OR);
+
+ $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter');
+ $excepts_and_filter_h->setType(FLT_TYPE_AND);
+
+ if ($types) {
+ $types_array = explode(',', $types);
+ for ($i = 0; $i < sizeof($types_array); $i++) {
+ $type = trim($types_array[$i]);
+ if (isset($type_clauses[$type])) {
+ if ($type_clauses[$type]['having_filter']) {
+ $includes_or_filter_h->removeFilter('filter_'.$type);
+ $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']);
+ }else {
+ $includes_or_filter->removeFilter('filter_'.$type);
+ $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']);
+ }
+ }
+ }
+ }
+
+ if ($except_types) {
+ $except_types_array = explode(',', $except_types);
+ for ($i = 0; $i < sizeof($except_types_array); $i++) {
+ $type = trim($except_types_array[$i]);
+ if (isset($type_clauses[$type])) {
+ if ($type_clauses[$type]['having_filter']) {
+ $excepts_and_filter_h->removeFilter('filter_'.$type);
+ $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']);
+ }else {
+ $excepts_and_filter->removeFilter('filter_'.$type);
+ $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']);
+ }
+ }
+ }
+ }
+
+ /*if ( !$this->Application->IsAdmin() ) {
+ $object->addFilter('expire_filter', '%1$s.Expire IS NULL OR %1$s.Expire > UNIX_TIMESTAMP()');
+ }*/
+
+ /*$list_type = $event->getEventParam('ListType');
+ switch($list_type)
+ {
+ case 'favorites':
+ $fav_table = $this->Application->getUnitOption('fav','TableName');
+ $user_id =& $this->Application->RecallVar('user_id');
+
+ $sql = 'SELECT DISTINCT f.ResourceId
+ FROM '.$fav_table.' f
+ LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId
+ WHERE f.PortalUserId = '.$user_id;
+ $ids = $this->Conn->GetCol($sql);
+ if(!$ids) $ids = Array(-1);
+ $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1');
+ $object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
+ break;
+ case 'search':
+ $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+ $sql = ' SELECT DISTINCT ResourceId
+ FROM '.$search_results_table.'
+ WHERE ItemType=11';
+ $ids = $this->Conn->GetCol($sql);
+ if(!$ids) $ids = Array(-1);
+ $object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
+ break;
+ } */
+
+ $object->addFilter('includes_filter', $includes_or_filter);
+ $object->addFilter('excepts_filter', $excepts_and_filter);
+
+ $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER);
+ $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER);
+ }
+
+ /**
+ * Adds filter that filters out items with non-required statuses
+ *
+ * @param kDBList $object
+ * @param string $types
+ */
+ function applyItemStatusFilter(&$object, $types)
+ {
+ // Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID]
+ $pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing');
+
+ if ( !$this->Application->IsAdmin() ) {
+ $types = explode(',', $types);
+ if (in_array('my_items', $types)) {
+ $allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING);
+ $object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')');
+
+ if ($pending_editing) {
+ $user_id = $this->Application->RecallVar('user_id');
+ $this->applyPendingEditingFilter($object, $user_id);
+ }
+ }
+ else {
+ $object->addFilter('status_filter', '(%1$s.Status = ' . STATUS_ACTIVE . ') AND (' . TABLE_PREFIX . 'Category.Status = ' . STATUS_ACTIVE . ')');
+ if ($pending_editing) {
+ // if category item uses pending editing abilities, then in no cases show pending copies on front
+ $object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL');
+ }
+ }
+ }
+ else {
+ if ($pending_editing) {
+ $this->applyPendingEditingFilter($object);
+ }
+ }
+ }
+
+ /**
+ * Adds filter, that removes live items if they have pending editing copies
+ *
+ * @param kDBList $object
+ * @param int $user_id
+ */
+ function applyPendingEditingFilter(&$object, $user_id = null)
+ {
+ $sql = 'SELECT OrgId
+ FROM '.$object->TableName.'
+ WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL';
+
+ if (isset($user_id)) {
+ $owner_field = $this->getOwnerField($object->Prefix);
+ $sql .= ' AND '.$owner_field.' = '.$user_id;
+ }
+
+ $pending_ids = $this->Conn->GetCol($sql);
+ if ($pending_ids) {
+ $object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')');
+ }
+ }
+
+ /**
+ * Adds calculates fields for item statuses
+ *
+ * @param kCatDBItem $object
+ * @param kEvent $event
+ */
+ function prepareObject(&$object, &$event)
+ {
+ $this->prepareItemStatuses($event);
+
+ $object->addCalculatedField('CachedNavbar', 'l'.$this->Application->GetVar('m_lang').'_CachedNavbar');
+
+ if ($event->Special == 'export' || $event->Special == 'import') {
+ $export_helper =& $this->Application->recallObject('CatItemExportHelper');
+ $export_helper->prepareExportColumns($event);
+ }
+ }
+
+ /**
+ * Creates calculated fields for all item statuses based on config settings
+ *
+ * @param kEvent $event
+ */
+ function prepareItemStatuses(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
+ if (!$property_map) {
+ return ;
+ }
+
+ // new items
+ $object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2,
+ IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
+ $this->Application->ConfigValue($property_map['NewDays']).
+ '*3600*24), 1, 0),
+ %1$s.NewItem
+ )');
+
+ // hot items (cache updated every hour)
+ $sql = 'SELECT Data
+ FROM '.TABLE_PREFIX.'Cache
+ WHERE (VarName = "'.$property_map['HotLimit'].'") AND (Cached >'.(adodb_mktime() - 3600).')';
+ $hot_limit = $this->Conn->GetOne($sql);
+ if ($hot_limit === false) {
+ $hot_limit = $this->CalculateHotLimit($event);
+ }
+ $object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2,
+ IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0),
+ %1$s.HotItem
+ )');
+
+ // popular items
+ $object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2,
+ IF(%1$s.CachedVotesQty >= '.
+ $this->Application->ConfigValue($property_map['MinPopVotes']).
+ ' AND %1$s.CachedRating >= '.
+ $this->Application->ConfigValue($property_map['MinPopRating']).
+ ', 1, 0),
+ %1$s.PopItem)');
+
+ }
+
+ function CalculateHotLimit(&$event)
+ {
+ $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
+ if (!$property_map) {
+ return;
+ }
+ $click_field = $property_map['ClickField'];
+
+ $last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1;
+ $sql = 'SELECT '.$click_field.' FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
+ ORDER BY '.$click_field.' DESC
+ LIMIT '.$last_hot.', 1';
+ $res = $this->Conn->GetCol($sql);
+ $hot_limit = (double)array_shift($res);
+ $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("'.$property_map['HotLimit'].'", "'.$hot_limit.'", '.adodb_mktime().')');
+ return $hot_limit;
+
+ return 0;
+ }
+
+ /**
+ * Moves item to preferred category, updates item hits
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemUpdate(&$event)
+ {
+ parent::OnBeforeItemUpdate($event);
+
+ // update hits field
+ $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
+ if ($property_map) {
+ $click_field = $property_map['ClickField'];
+
+ $object =& $event->getObject();
+ /* @var $object kCatDBItem */
+
+ if( $this->Application->IsAdmin() && ($this->Application->GetVar($click_field.'_original') !== false) &&
+ floor($this->Application->GetVar($click_field.'_original')) != $object->GetDBField($click_field) )
+ {
+ $sql = 'SELECT MAX('.$click_field.') FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
+ WHERE FLOOR('.$click_field.') = '.$object->GetDBField($click_field);
+ $hits = ( $res = $this->Conn->GetOne($sql) ) ? $res + 0.000001 : $object->GetDBField($click_field);
+ $object->SetDBField($click_field, $hits);
+ }
+ }
+
+ // change category
+ $target_category = $object->GetDBField('CategoryId');
+ if ($object->GetOriginalField('CategoryId') != $target_category) {
+ $object->MoveToCat($target_category);
+ }
+ }
+
+ /**
+ * Load price from temp table if product mode is temp table
+ *
+ * @param kEvent $event
+ */
+ function OnAfterItemLoad(&$event)
+ {
+ $special = substr($event->Special, -6);
+
+ $object =& $event->getObject();
+ /* @var $object kCatDBItem */
+
+ if ($special == 'import' || $special == 'export') {
+ $image_data = $object->getPrimaryImageData();
+
+ if ($image_data) {
+ $thumbnail_image = $image_data[$image_data['LocalThumb'] ? 'ThumbPath' : 'ThumbUrl'];
+ if ($image_data['SameImages']) {
+ $full_image = '';
+ }
+ else {
+ $full_image = $image_data[$image_data['LocalImage'] ? 'LocalPath' : 'Url'];
+ }
+ $object->SetDBField('ThumbnailImage', $thumbnail_image);
+ $object->SetDBField('FullImage', $full_image);
+ $object->SetDBField('ImageAlt', $image_data['AltName']);
+ }
+ }
+
+ // substituiting pending status value for pending editing
+ if ($object->HasField('OrgId') && $object->GetDBField('OrgId') > 0 && $object->GetDBField('Status') == -2) {
+ $options = $object->Fields['Status']['options'];
+ foreach ($options as $key => $val) {
+ if ($key == 2) $key = -2;
+ $new_options[$key] = $val;
+ }
+ $object->Fields['Status']['options'] = $new_options;
+ }
+
+ // linking existing images for item with virtual fields
+ $image_helper =& $this->Application->recallObject('ImageHelper');
+ /* @var $image_helper ImageHelper */
+
+ $image_helper->LoadItemImages($object);
+
+ // linking existing files for item with virtual fields
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ $file_helper->LoadItemFiles($object);
+
+ // set item's additional categories to virtual field (used in editing)
+ $item_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
+ $object->SetDBField('MoreCategories', $item_categories ? '|'.implode('|', $item_categories).'|' : '');
+ }
+
+ function OnAfterItemUpdate(&$event)
+ {
+ $this->CalculateHotLimit($event);
+
+ if ( substr($event->Special, -6) == 'import') {
+ $this->setCustomExportColumns($event);
+ }
+
+ if (!$this->Application->IsAdmin()) {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $image_helper =& $this->Application->recallObject('ImageHelper');
+ /* @var $image_helper ImageHelper */
+
+ // process image upload in virtual fields
+ $image_helper->SaveItemImages($object);
+
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ // process file upload in virtual fields
+ $file_helper->SaveItemFiles($object);
+
+ if ($event->Special != '-item') {
+ // don't touch categories during cloning
+ $this->processAdditionalCategories($object, 'update');
+ }
+ }
+ }
+
+ /**
+ * sets values for import process
+ *
+ * @param kEvent $event
+ */
+ function OnAfterItemCreate(&$event)
+ {
+ if ( substr($event->Special, -6) == 'import') {
+ $this->setCustomExportColumns($event);
+ }
+
+ if (!$this->Application->IsAdmin()) {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $image_helper =& $this->Application->recallObject('ImageHelper');
+ /* @var $image_helper ImageHelper */
+
+ // process image upload in virtual fields
+ $image_helper->SaveItemImages($object);
+
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ // process file upload in virtual fields
+ $file_helper->SaveItemFiles($object);
+
+ if ($event->Special != '-item') {
+ // don't touch categories during cloning
+ $this->processAdditionalCategories($object, 'create');
+ }
+ }
+ }
+
+ /**
+ * Make record to search log
+ *
+ * @param string $keywords
+ * @param int $search_type 0 - simple search, 1 - advanced search
+ */
+ function saveToSearchLog($keywords, $search_type = 0)
+ {
+ // don't save keywords for each module separately, just one time
+ // static variable can't help here, because each module uses it's own class instance !
+ if (!$this->Application->GetVar('search_logged')) {
+ $sql = 'UPDATE '.TABLE_PREFIX.'SearchLog
+ SET Indices = Indices + 1
+ WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search
+ $this->Conn->Query($sql);
+ if ($this->Conn->getAffectedRows() == 0) {
+ $fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type);
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLog');
+ }
+
+ $this->Application->SetVar('search_logged', 1);
+ }
+ }
+
+ /**
+ * Makes simple search for products
+ * based on keywords string
+ *
+ * @param kEvent $event
+ * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
+ */
+ function OnSimpleSearch(&$event)
+ {
+ if($this->Application->GetVar('INPORTAL_ON') && !($this->Application->GetVar('Action') == 'm_simple_search'))
+ {
+ return;
+ }
+
+ $event->redirect = false;
+ $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+
+ $keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) );
+
+ $query_object =& $this->Application->recallObject('HTTPQuery');
+ $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
+
+ if(!isset($query_object->Get['keywords']) &&
+ !isset($query_object->Post['keywords']) &&
+ $this->Conn->Query($sql))
+ {
+ return; // used when navigating by pages or changing sorting in search results
+ }
+ if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length'))
+ {
+ $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
+ $this->Application->SetVar('keywords_too_short', 1);
+ return; // if no or too short keyword entered, doing nothing
+ }
+
+ $this->Application->StoreVar('keywords', $keywords);
+ if (!$this->Application->GetVar('INPORTAL_ON')) {
+ // don't save search log, because in-portal already saved it
+ $this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search
+ }
+
+ $keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_'));
+
+ $event->setPseudoClass('_List');
+
+ $object =& $event->getObject();
+ /* @var $object kDBList */
+
+ $this->Application->SetVar($event->getPrefixSpecial().'_Page', 1);
+ $lang = $this->Application->GetVar('m_lang');
+ $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
+ $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
+
+ $sql = 'SELECT *
+ FROM ' . $this->Application->getUnitOption('confs', 'TableName') . '
+ WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1';
+ $search_config = $this->Conn->Query($sql, 'FieldName');
+
+ $field_list = array_keys($search_config);
+
+ $join_clauses = Array();
+
+ // field processing
+ $weight_sum = 0;
+
+ $alias_counter = 0;
+
+ $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
+ if ($custom_fields) {
+ $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
+ $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
+ }
+
+ // what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
+ $search_config_map = Array();
+
+ foreach ($field_list as $key => $field) {
+ $options = $object->getFieldOptions($field);
+ $local_table = TABLE_PREFIX.$search_config[$field]['TableName'];
+ $weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause
+
+ // processing multilingual fields
+ if (getArrayValue($options, 'formatter') == 'kMultiLanguage') {
+ $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
+ $field_list[$key] = 'l'.$lang.'_'.$field;
+
+ if (!isset($search_config[$field]['ForeignField'])) {
+ $field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary'];
+ $search_config_map[ $field_list[$key.'_primary'] ] = $field;
+ }
+ }
+
+ // processing fields from other tables
+ if ($foreign_field = $search_config[$field]['ForeignField']) {
+ $exploded = explode(':', $foreign_field, 2);
+ if ($exploded[0] == 'CALC') {
+ // ignoring having type clauses in simple search
+ unset($field_list[$key]);
+ continue;
+ }
+ else {
+ $multi_lingual = false;
+ if ($exploded[0] == 'MULTI') {
+ $multi_lingual = true;
+ $foreign_field = $exploded[1];
+ }
+
+ $exploded = explode('.', $foreign_field); // format: table.field_name
+ $foreign_table = TABLE_PREFIX.$exploded[0];
+
+ $alias_counter++;
+ $alias = 't'.$alias_counter;
+
+ if ($multi_lingual) {
+ $field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1];
+ $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
+ $search_config_map[ $field_list[$key] ] = $field;
+ $search_config_map[ $field_list[$key.'_primary'] ] = $field;
+ }
+ else {
+ $field_list[$key] = $alias.'.'.$exploded[1];
+ $search_config_map[ $field_list[$key] ] = $field;
+ }
+
+ $join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']);
+ $join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
+
+ $join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.'
+ ON '.$join_clause;
+ }
+ }
+ else {
+ // processing fields from local table
+ if ($search_config[$field]['CustomFieldId']) {
+ $local_table = 'custom_data';
+
+ // search by custom field value on current language
+ $custom_field_id = array_search($field_list[$key], $custom_fields);
+ $field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id;
+
+ // search by custom field value on primary language
+ $field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id;
+ $search_config_map[ $field_list[$key.'_primary'] ] = $field;
+ }
+
+ $field_list[$key] = $local_table.'.'.$field_list[$key];
+ $search_config_map[ $field_list[$key] ] = $field;
+ }
+ }
+
+ // keyword string processing
+ $search_helper =& $this->Application->recallObject('SearchHelper');
+ /* @var $search_helper kSearchHelper */
+
+ $where_clause = Array ();
+ foreach ($field_list as $field) {
+ if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) {
+ // local real field
+ $filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false);
+ if ($filter_data) {
+ $where_clause[] = $filter_data['value'];
+ }
+ }
+ elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) {
+ $custom_field_name = 'cust_' . $search_config_map[$field];
+ $filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false);
+ if ($filter_data) {
+ $where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']);
+ }
+ }
+ else {
+ $where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field));
+ }
+ }
+
+ $where_clause = '(' . implode(') OR (', $where_clause) . ')';
+
+ $search_scope = $this->Application->GetVar('search_scope');
+ if ($search_scope == 'category') {
+ $category_id = $this->Application->GetVar('m_cat_id');
+ $category_filter = $this->getCategoryLimitClause($category_id);
+ if ($category_filter !== false) {
+ $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON '.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$items_table.'.ResourceId';
+ $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'Category ON '.TABLE_PREFIX.'Category.CategoryId = '.TABLE_PREFIX.'CategoryItems.CategoryId';
+
+ $where_clause = '('.$this->getCategoryLimitClause($category_id).') AND '.$where_clause;
+ }
+ }
+
+ $where_clause = $where_clause.' AND '.$items_table.'.Status=1';
+
+ if($this->Application->GetVar('Action') == 'm_simple_subsearch') // subsearch, In-portal
+ {
+ if( $event->getEventParam('ResultIds') )
+ {
+ $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->specificParams['ResultIds']).')';
+ }
+ }
+ if( $event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild' ) // subsearch, k4
+ {
+ if( $event->MasterEvent->getEventParam('ResultIds') )
+ {
+ $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')';
+ }
+ }
+
+ // making relevance clause
+ $positive_words = $search_helper->getPositiveKeywords($keywords);
+ $this->Application->StoreVar('highlight_keywords', serialize($positive_words));
+ $revelance_parts = Array();
+ reset($search_config);
+
+ foreach ($positive_words as $keyword_index => $positive_word) {
+ $positive_words[$keyword_index] = mysql_real_escape_string($positive_word);
+ }
+
+ foreach ($field_list as $field) {
+
+ if (!array_key_exists($field, $search_config_map)) {
+ $map_key = $search_config_map[$items_table . '.' . $field];
+ }
+ else {
+ $map_key = $search_config_map[$field];
+ }
+
+ $config_elem = $search_config[ $map_key ];
+ $weight = $config_elem['Priority'];
+ $revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)';
+ foreach ($positive_words as $keyword) {
+ $revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$weight.', 0)';
+ }
+ }
+ $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
+ $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
+ $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
+ $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
+ $relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords;
+ if ($rel_pop && isset($object->Fields['Hits'])) {
+ $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
+ }
+ if ($rel_rating && isset($object->Fields['CachedRating'])) {
+ $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
+ }
+
+ // building final search query
+ if (!$this->Application->GetVar('do_not_drop_search_table') && !$this->Application->GetVar('INPORTAL_ON')) {
+ $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event
+ $this->Application->SetVar('do_not_drop_search_table', true);
+ }
+
+
+ $search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
+ if ($search_table_exists) {
+ $select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
+ }
+ else {
+ $select_intro = 'CREATE TABLE '.$search_table.' AS ';
+ }
+
+ $edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0';
+
+
+ $sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance,
+ '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId,
+ '.$items_table.'.ResourceId,
+ '.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType,
+ '.$edpick_clause.' AS EdPick
+ FROM '.$object->TableName.'
+ '.implode(' ', $join_clauses).'
+ WHERE '.$where_clause.'
+ GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField');
+
+ $res = $this->Conn->Query($sql);
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function OnSubSearch(&$event)
+ {
+ $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+ $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
+ if($this->Conn->Query($sql))
+ {
+ $sql = 'SELECT DISTINCT ResourceId FROM '.$search_table;
+ $ids = $this->Conn->GetCol($sql);
+ }
+ $event->setEventParam('ResultIds', $ids);
+ $event->CallSubEvent('OnSimpleSearch');
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
+ */
+ function OnAdvancedSearch(&$event)
+ {
+ $query_object =& $this->Application->recallObject('HTTPQuery');
+ if(!isset($query_object->Post['andor']))
+ {
+ return; // used when navigating by pages or changing sorting in search results
+ }
+
+ $this->Application->RemoveVar('keywords');
+ $this->Application->RemoveVar('Search_Keywords');
+
+ $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
+
+ $sql = 'SELECT *
+ FROM '.$this->Application->getUnitOption('confs', 'TableName').'
+ WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)';
+ $search_config = $this->Conn->Query($sql);
+
+ $lang = $this->Application->GetVar('m_lang');
+ $object =& $event->getObject();
+ $object->SetPage(1);
+
+ $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ $search_keywords = $this->Application->GetVar('value'); // will not be changed
+
+ $keywords = $this->Application->GetVar('value'); // will be changed down there
+ $verbs = $this->Application->GetVar('verb');
+ $glues = $this->Application->GetVar('andor');
+
+ $and_conditions = Array();
+ $or_conditions = Array();
+ $and_having_conditions = Array();
+ $or_having_conditions = Array();
+ $join_clauses = Array();
+ $highlight_keywords = Array();
+ $relevance_parts = Array();
+
+ $alias_counter = 0;
+
+ $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
+ if ($custom_fields) {
+ $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
+ $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
+ }
+
+ $search_log = '';
+ $weight_sum = 0;
+
+ // processing fields and preparing conditions
+ foreach ($search_config as $record) {
+ $field = $record['FieldName'];
+ $join_clause = '';
+ $condition_mode = 'WHERE';
+
+ // field processing
+
+ $options = $object->getFieldOptions($field);
+ $local_table = TABLE_PREFIX.$record['TableName'];
+ $weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause
+
+ // processing multilingual fields
+ if (getArrayValue($options, 'formatter') == 'kMultiLanguage') {
+ $field_name = 'l'.$lang.'_'.$field;
+ }
+ else {
+ $field_name = $field;
+ }
+
+ // processing fields from other tables
+ if ($foreign_field = $record['ForeignField']) {
+ $exploded = explode(':', $foreign_field, 2);
+ if($exploded[0] == 'CALC')
+ {
+ $user_groups = $this->Application->RecallVar('UserGroups');
+ $field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]);
+ $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']);
+ $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause);
+ $join_clause = ' LEFT JOIN '.$join_clause;
+
+ $condition_mode = 'HAVING';
+ }
+ else {
+ $exploded = explode('.', $foreign_field);
+ $foreign_table = TABLE_PREFIX.$exploded[0];
+
+ if($record['CustomFieldId']) {
+ $exploded[1] = 'l'.$lang.'_'.$exploded[1];
+ }
+
+ $alias_counter++;
+ $alias = 't'.$alias_counter;
+
+ $field_name = $alias.'.'.$exploded[1];
+ $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']);
+ $join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
+
+ if($record['CustomFieldId'])
+ {
+ $join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId'];
+ }
+ $join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.'
+ ON '.$join_clause;
+ }
+ }
+ else
+ {
+ // processing fields from local table
+ if ($record['CustomFieldId']) {
+ $local_table = 'custom_data';
+ $field_name = 'l'.$lang.'_cust_'.array_search($field_name, $custom_fields);
+ }
+
+ $field_name = $local_table.'.'.$field_name;
+ }
+
+ $condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
+ if ($record['CustomFieldId'] && strlen($condition)) {
+ // search in primary value of custom field + value in current language
+ $field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields);
+ $primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
+ $condition = '('.$condition.' OR '.$primary_condition.')';
+ }
+
+ if ($condition) {
+ if ($join_clause) {
+ $join_clauses[] = $join_clause;
+ }
+
+ $relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)';
+ if ($glues[$field] == 1) { // and
+ if ($condition_mode == 'WHERE') {
+ $and_conditions[] = $condition;
+ }
+ else {
+ $and_having_conditions[] = $condition;
+ }
+ }
+ else { // or
+ if ($condition_mode == 'WHERE') {
+ $or_conditions[] = $condition;
+ }
+ else {
+ $or_having_conditions[] = $condition;
+ }
+ }
+
+ // create search log record
+ $search_log_data = Array('search_config' => $record, 'verb' => getArrayValue($verbs, $field), 'value' => ($record['FieldType'] == 'range') ? $search_keywords[$field.'_from'].'|'.$search_keywords[$field.'_to'] : $search_keywords[$field]);
+ $search_log[] = $this->Application->Phrase('la_Field').' "'.$this->getHuman('Field', $search_log_data).'" '.$this->getHuman('Verb', $search_log_data).' '.$this->Application->Phrase('la_Value').' '.$this->getHuman('Value', $search_log_data).' '.$this->Application->Phrase($glues[$field] == 1 ? 'lu_And' : 'lu_Or');
+ }
+ }
+
+ if ($search_log) {
+ $search_log = implode('<br />', $search_log);
+ $search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log);
+ $this->saveToSearchLog($search_log, 1); // advanced search
+ }
+
+ $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords));
+
+ // making relevance clause
+ if($relevance_parts)
+ {
+ $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
+ $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
+ $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
+ $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
+ $relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords;
+ $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
+ $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
+ }
+ else
+ {
+ $relevance_clause = '0';
+ }
+
+ // building having clause
+ if($or_having_conditions)
+ {
+ $and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')';
+ }
+ $having_clause = implode(' AND ', $and_having_conditions);
+ $having_clause = $having_clause ? ' HAVING '.$having_clause : '';
+
+ // building where clause
+ if($or_conditions)
+ {
+ $and_conditions[] = '('.implode(' OR ', $or_conditions).')';
+ }
+// $and_conditions[] = $items_table.'.Status = 1';
+ $where_clause = implode(' AND ', $and_conditions);
+ if(!$where_clause)
+ {
+ if($having_clause)
+ {
+ $where_clause = '1';
+ }
+ else
+ {
+ $where_clause = '0';
+ $this->Application->SetVar('adv_search_error', 1);
+ }
+ }
+ $where_clause .= ' AND '.$items_table.'.Status = 1';
+
+ // building final search query
+ $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
+
+ $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
+
+ $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
+ $fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
+ $pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0';
+
+ $sql = ' CREATE TABLE '.$search_table.'
+ SELECT '.$relevance_clause.' AS Relevance,
+ '.$items_table.'.'.$id_field.' AS ItemId,
+ '.$items_table.'.ResourceId AS ResourceId,
+ 11 AS ItemType,
+ '.$pick_field.' AS EdPick
+ FROM '.$items_table.'
+ '.implode(' ', $join_clauses).'
+ WHERE '.$where_clause.'
+ GROUP BY '.$items_table.'.'.$id_field.
+ $having_clause;
+
+ $res = $this->Conn->Query($sql);
+ }
+
+ function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords)
+ {
+ $field = $record['FieldName'];
+
+ $condition_patterns = Array (
+ 'any' => '%s LIKE %s',
+ 'contains' => '%s LIKE %s',
+ 'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)',
+ 'is' => '%s = %s',
+ 'isnot' => '(%1$s != %2$s OR %1$s IS NULL)'
+ );
+
+ $condition = '';
+ switch ($record['FieldType']) {
+ case 'select':
+ $keywords[$field] = unhtmlentities( $keywords[$field] );
+ if ($keywords[$field]) {
+ $condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] ));
+ }
+ break;
+
+ case 'multiselect':
+ $keywords[$field] = unhtmlentities( $keywords[$field] );
+ if ($keywords[$field]) {
+ $condition = Array ();
+ $values = explode('|', substr($keywords[$field], 1, -1));
+ foreach ($values as $selected_value) {
+ $condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%'));
+ }
+ $condition = '('.implode(' OR ', $condition).')';
+ }
+ break;
+
+ case 'text':
+ $keywords[$field] = unhtmlentities( $keywords[$field] );
+
+ if (mb_strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) {
+ $highlight_keywords[] = $keywords[$field];
+ if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) {
+ $keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%';
+ }
+ $condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] ));
+ }
+ break;
+
+ case 'boolean':
+ if ($keywords[$field] != -1) {
+ $property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
+ $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ switch ($field) {
+ case 'HotItem':
+ $hot_limit_var = getArrayValue($property_mappings, 'HotLimit');
+ if ($hot_limit_var) {
+ $sql = 'SELECT Data
+ FROM '.TABLE_PREFIX.'Cache
+ WHERE VarName = "'.$hot_limit_var.'"';
+ $hot_limit = (int)$this->Conn->GetOne($sql);
+
+ $condition = 'IF('.$items_table.'.HotItem = 2,
+ IF('.$items_table.'.Hits >= '.
+ $hot_limit.
+ ', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field];
+ }
+ break;
+
+ case 'PopItem':
+ $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop');
+ $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop');
+ if ($votes2pop_var && $rating2pop_var) {
+ $condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '.
+ $this->Application->ConfigValue($votes2pop_var).
+ ' AND '.$items_table.'.CachedRating >= '.
+ $this->Application->ConfigValue($rating2pop_var).
+ ', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field];
+ }
+ break;
+
+ case 'NewItem':
+ $new_days_var = getArrayValue($property_mappings, 'NewDays');
+ if ($new_days_var) {
+ $condition = 'IF('.$items_table.'.NewItem = 2,
+ IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '.
+ $this->Application->ConfigValue($new_days_var).
+ '*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field];
+ }
+ break;
+
+ case 'EditorsPick':
+ $condition = $items_table.'.EditorsPick = '.$keywords[$field];
+ break;
+ }
+ }
+ break;
+
+ case 'range':
+ $range_conditions = Array();
+ if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) {
+ $range_conditions[] = $field_name.' >= '.$keywords[$field.'_from'];
+ }
+ if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) {
+ $range_conditions[] = $field_name.' <= '.$keywords[$field.'_to'];
+ }
+ if ($range_conditions) {
+ $condition = implode(' AND ', $range_conditions);
+ }
+ break;
+
+ case 'date':
+ if ($keywords[$field]) {
+ if (in_array($keywords[$field], Array('today', 'yesterday'))) {
+ $current_time = getdate();
+ $day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']);
+ $time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400));
+ $min_time = $time_mapping[$keywords[$field]];
+ }
+ else {
+ $time_mapping = Array (
+ 'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000,
+ 'last_6_months' => 15768000, 'last_year' => 31536000,
+ );
+ $min_time = adodb_mktime() - $time_mapping[$keywords[$field]];
+ }
+ $condition = $field_name.' > '.$min_time;
+ }
+ break;
+ }
+
+ return $condition;
+ }
+
+ function getHuman($type, $search_data)
+ {
+ $type = ucfirst(strtolower($type));
+ extract($search_data);
+
+ switch ($type) {
+ case 'Field':
+ return $this->Application->Phrase($search_config['DisplayName']);
+ break;
+
+ case 'Verb':
+ return $verb ? $this->Application->Phrase('lu_advsearch_'.$verb) : '';
+ break;
+
+ case 'Value':
+ switch ($search_config['FieldType']) {
+ case 'date':
+ $values = Array(0 => 'lu_comm_Any', 'today' => 'lu_comm_Today',
+ 'yesterday' => 'lu_comm_Yesterday', 'last_week' => 'lu_comm_LastWeek',
+ 'last_month' => 'lu_comm_LastMonth', 'last_3_months' => 'lu_comm_Last3Months',
+ 'last_6_months' => 'lu_comm_Last6Months', 'last_year' => 'lu_comm_LastYear');
+ $ret = $this->Application->Phrase($values[$value]);
+ break;
+
+ case 'range':
+ $value = explode('|', $value);
+ return $this->Application->Phrase('lu_comm_From').' "'.$value[0].'" '.$this->Application->Phrase('lu_comm_To').' "'.$value[1].'"';
+ break;
+
+ case 'boolean':
+ $values = Array(1 => 'lu_comm_Yes', 0 => 'lu_comm_No', -1 => 'lu_comm_Both');
+ $ret = $this->Application->Phrase($values[$value]);
+ break;
+
+ default:
+ $ret = $value;
+ break;
+
+ }
+ return '"'.$ret.'"';
+ break;
+ }
+ }
+
+
+
+ /**
+ * Set's correct page for list
+ * based on data provided with event
+ *
+ * @param kEvent $event
+ * @access private
+ * @see OnListBuild
+ */
+ function SetPagination(&$event)
+ {
+ // get PerPage (forced -> session -> config -> 10)
+ $per_page = $this->getPerPage($event);
+
+
+ $object =& $event->getObject();
+ $object->SetPerPage($per_page);
+ $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1);
+
+ $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page');
+ if (!$page)
+ {
+ $page = $this->Application->GetVar($event->getPrefixSpecial(true).'_Page');
+ }
+
+ if (!$page)
+ {
+ if( $this->Application->RewriteURLs() )
+ {
+ $page = $this->Application->GetVar($event->Prefix.'_Page');
+ if (!$page)
+ {
+ $page = $this->Application->RecallVar($event->Prefix.'_Page');
+ }
+ if($page) $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page);
+ }
+ else
+ {
+ $page = $this->Application->RecallVar($event->getPrefixSpecial().'_Page');
+ }
+ }
+ else {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page);
+ }
+
+ if( !$event->getEventParam('skip_counting') )
+ {
+ $pages = $object->GetTotalPages();
+ if($page > $pages)
+ {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1);
+ $page = 1;
+ }
+ }
+
+ /*$cur_per_page = $per_page;
+ $per_page = $event->getEventParam('per_page');
+ if ($per_page == 'list_next') {
+
+ $cur_page = $page;
+
+ $object =& $this->Application->recallObject($event->Prefix);
+ $object->SetPerPage(1);
+ $cur_item_index = $object->CurrentIndex;
+
+ $page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1;
+ $object->SetPerPage(1);
+ }*/
+
+ $object->SetPage($page);
+ }
+
+/* === RELATED TO IMPORT/EXPORT: BEGIN === */
+
+ /**
+ * Shows export dialog
+ *
+ * @param kEvent $event
+ */
+ function OnExport(&$event)
+ {
+ $selected_ids = $this->StoreSelectedIDs($event);
+ if (implode(',', $selected_ids) == '') {
+ // K4 fix when no ids found bad selected ids array is formed
+ $selected_ids = false;
+ }
+
+ $selected_cats_ids = $this->Application->GetVar('export_categories');
+
+ $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
+ $this->Application->StoreVar($event->Prefix.'_export_cats_ids', $selected_cats_ids);
+
+ $export_helper =& $this->Application->recallObject('CatItemExportHelper');
+ /* @var $export_helper kCatDBItemExportHelper */
+
+ $redirect_params = Array (
+ $this->Prefix.'.export_event' => 'OnNew',
+ 'pass' => 'all,'.$this->Prefix.'.export'
+ );
+
+ $event->setRedirectParams($redirect_params);
+ }
+
+ /**
+ * Performs each export step & displays progress percent
+ *
+ * @param kEvent $event
+ */
+ function OnExportProgress(&$event)
+ {
+ $export_object =& $this->Application->recallObject('CatItemExportHelper');
+ /* @var $export_object kCatDBItemExportHelper */
+
+ $event = new kEvent($event->getPrefixSpecial().':OnDummy');
+
+ $action_method = 'perform'.ucfirst($event->Special);
+ $field_values = $export_object->$action_method($event);
+
+ // finish code is done from JS now
+ if ($field_values['start_from'] == $field_values['total_records']) {
+ if ($event->Special == 'import') {
+ $this->Application->StoreVar('PermCache_UpdateRequired', 1);
+ $url_params = Array(
+ 't' => 'catalog/catalog',
+ 'm_cat_id' => $this->Application->RecallVar('ImportCategory'),
+ 'anchor' => 'tab-' . $event->Prefix,
+ );
+ $this->Application->EventManager->openerStackChange($url_params);
+
+ $event->SetRedirectParam('opener', 'u');
+ }
+ elseif ($event->Special == 'export') {
+ $event->redirect = $this->Application->getUnitOption($event->Prefix, 'ModuleFolder') . '/' . $event->Special . '_finish';
+ $event->SetRedirectParam('pass', 'all');
+ }
+
+ return ;
+ }
+
+ $export_options = $export_object->loadOptions($event);
+ echo $export_options['start_from'] * 100 / $export_options['total_records'];
+
+ $event->status = erSTOP;
+ }
+
+ /**
+ * Returns specific to each item type columns only
+ *
+ * @param kEvent $event
+ * @return Array
+ */
+ function getCustomExportColumns(&$event)
+ {
+ return Array( '__VIRTUAL__ThumbnailImage' => 'ThumbnailImage',
+ '__VIRTUAL__FullImage' => 'FullImage',
+ '__VIRTUAL__ImageAlt' => 'ImageAlt');
+ }
+
+ /**
+ * Sets non standart virtual fields (e.g. to other tables)
+ *
+ * @param kEvent $event
+ */
+ function setCustomExportColumns(&$event)
+ {
+ $this->restorePrimaryImage($event);
+ }
+
+ /**
+ * Create/Update primary image record in info found in imported data
+ *
+ * @param kEvent $event
+ */
+ function restorePrimaryImage(&$event)
+ {
+ $object =& $event->getObject();
+
+ $has_image_info = $object->GetDBField('ImageAlt') && ($object->GetDBField('ThumbnailImage') || $object->GetDBField('FullImage'));
+ if (!$has_image_info) {
+ return false;
+ }
+
+ $image_data = $object->getPrimaryImageData();
+
+ $image =& $this->Application->recallObject('img', null, Array('skip_autoload' => true));
+ if ($image_data) {
+ $image->Load($image_data['ImageId']);
+ }
+ else {
+ $image->Clear();
+ $image->SetDBField('Name', 'main');
+ $image->SetDBField('DefaultImg', 1);
+ $image->SetDBField('ResourceId', $object->GetDBField('ResourceId'));
+ }
+
+ $image->SetDBField('AltName', $object->GetDBField('ImageAlt'));
+
+ if ($object->GetDBField('ThumbnailImage')) {
+ $thumbnail_field = $this->isURL( $object->GetDBField('ThumbnailImage') ) ? 'ThumbUrl' : 'ThumbPath';
+ $image->SetDBField($thumbnail_field, $object->GetDBField('ThumbnailImage') );
+ $image->SetDBField('LocalThumb', $thumbnail_field == 'ThumbPath' ? 1 : 0);
+ }
+
+ if (!$object->GetDBField('FullImage')) {
+ $image->SetDBField('SameImages', 1);
+ }
+ else {
+ $image->SetDBField('SameImages', 0);
+ $full_field = $this->isURL( $object->GetDBField('FullImage') ) ? 'Url' : 'LocalPath';
+ $image->SetDBField($full_field, $object->GetDBField('FullImage') );
+ $image->SetDBField('LocalImage', $full_field == 'LocalPath' ? 1 : 0);
+ }
+
+ if ($image->isLoaded()) {
+ $image->Update();
+ }
+ else {
+ $image->Create();
+ }
+ }
+
+ function isURL($path)
+ {
+ return preg_match('#(http|https)://(.*)#', $path);
+ }
+
+ /**
+ * Prepares item for import/export operations
+ *
+ * @param kEvent $event
+ */
+ function OnNew(&$event)
+ {
+ parent::OnNew($event);
+
+ if ($event->Special == 'import' || $event->Special == 'export') {
+ $export_helper =& $this->Application->recallObject('CatItemExportHelper');
+ $export_helper->setRequiredFields($event);
+ }
+ }
+
+ /**
+ * Process items selected in item_selector
+ *
+ * @param kEvent $event
+ */
+ function OnProcessSelected(&$event)
+ {
+ $selected_ids = $this->Application->GetVar('selected_ids');
+
+ $dst_field = $this->Application->RecallVar('dst_field');
+
+ if ($dst_field == 'ItemCategory') {
+ // Item Edit -> Categories Tab -> New Categories
+ $object =& $event->getObject();
+ $category_ids = explode(',', $selected_ids['c']);
+ foreach ($category_ids as $category_id) {
+ $object->assignToCategory($category_id);
+ }
+ }
+
+ if ($dst_field == 'ImportCategory') {
+ // Tools -> Import -> Item Import -> Select Import Category
+ $this->Application->StoreVar('ImportCategory', $selected_ids['c']);
+// $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 1); // not to loose import/export values on form refresh
+
+ $url_params = Array (
+ $event->getPrefixSpecial() . '_id' => 0,
+ $event->getPrefixSpecial() . '_event' => 'OnExportBegin',
+// 'm_opener' => 's',
+ );
+
+ $this->Application->EventManager->openerStackChange($url_params);
+ }
+
+ $event->SetRedirectParam('opener', 'u');
+ }
+
+ /**
+ * Saves Import/Export settings to session
+ *
+ * @param kEvent $event
+ */
+ function OnSaveSettings(&$event)
+ {
+ $event->redirect = false;
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info) {
+ list($id, $field_values) = each($items_info);
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $object->SetFieldsFromHash($field_values);
+ $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
+ $field_values['ImportSource'] = 2;
+ $field_values['ImportLocalFilename'] = $object->GetDBField('ImportFilename');
+ $items_info[$id] = $field_values;
+
+ $this->Application->StoreVar($event->getPrefixSpecial().'_ItemsInfo', serialize($items_info));
+ }
+ }
+
+ /**
+ * Saves Import/Export settings to session
+ *
+ * @param kEvent $event
+ */
+ function OnResetSettings(&$event)
+ {
+ $this->Application->StoreVar('ImportCategory', $this->Application->findModule('Name', 'Core', 'RootCat'));
+ }
+
+ function OnCancelAction(&$event)
+ {
+ $event->redirect_params = Array('pass' => 'all,'.$event->GetPrefixSpecial());
+ $event->redirect = $this->Application->GetVar('cancel_template');
+ }
+
+/* === RELATED TO IMPORT/EXPORT: END === */
+
+ /**
+ * Stores item's owner login into separate field together with id
+ *
+ * @param kEvent $event
+ * @param string $id_field
+ * @param string $cached_field
+ */
+ function cacheItemOwner(&$event, $id_field, $cached_field)
+ {
+ $object =& $event->getObject();
+
+ $user_id = $object->GetDBField($id_field);
+ $options = $object->GetFieldOptions($id_field);
+ if (isset($options['options'][$user_id])) {
+ $object->SetDBField($cached_field, $options['options'][$user_id]);
+ }
+ else {
+ $id_field = $this->Application->getUnitOption('u', 'IDField');
+ $table_name = $this->Application->getUnitOption('u', 'TableName');
+
+ $sql = 'SELECT Login
+ FROM '.$table_name.'
+ WHERE '.$id_field.' = '.$user_id;
+ $object->SetDBField($cached_field, $this->Conn->GetOne($sql));
+ }
+ }
+
+ /**
+ * Saves item beeing edited into temp table
+ *
+ * @param kEvent $event
+ */
+ function OnPreSave(&$event)
+ {
+ parent::OnPreSave($event);
+ $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
+ if ($event->status == erSUCCESS && $use_pending_editing) {
+ // decision: clone or not clone
+
+ $object =& $event->getObject();
+ if ($object->GetID() == 0 || $object->GetDBField('OrgId') > 0) {
+ // new items or cloned items shouldn't be cloned again
+ return true;
+ }
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ if ($perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix) == 2) {
+
+ // 1. clone original item
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($object->GetID()), null, null, null, true);
+ $ci_table = $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems');
+
+ // 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
+ $sql = 'SELECT ResourceId
+ FROM '.$object->TableName.'
+ WHERE '.$object->IDField.' = '.$cloned_ids[0];
+ $clone_resource_id = $this->Conn->GetOne($sql);
+
+ $sql = 'DELETE FROM '.$ci_table.'
+ WHERE ItemResourceId = '.$clone_resource_id.' AND PrimaryCat = 1';
+ $this->Conn->Query($sql);
+
+ // 3. copy main item categoryitems to cloned item
+ $sql = ' INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
+ SELECT CategoryId, '.$clone_resource_id.' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
+ FROM '.$ci_table.'
+ WHERE ItemResourceId = '.$object->GetDBField('ResourceId');
+ $this->Conn->Query($sql);
+
+ // 4. put cloned id to OrgId field of item being cloned
+ $sql = 'UPDATE '.$object->TableName.'
+ SET OrgId = '.$object->GetID().'
+ WHERE '.$object->IDField.' = '.$cloned_ids[0];
+ $this->Conn->Query($sql);
+
+ // 5. substitute id of item being cloned with clone id
+ $this->Application->SetVar($event->getPrefixSpecial().'_id', $cloned_ids[0]);
+
+ $selected_ids = $this->getSelectedIDs($event, true);
+ $selected_ids[ array_search($object->GetID(), $selected_ids) ] = $cloned_ids[0];
+ $this->StoreSelectedIDs($event, $selected_ids);
+
+ // 6. delete original item from temp table
+ $temp_handler->DeleteItems($event->Prefix, $event->Special, Array($object->GetID()));
+ }
+ }
+ }
+
+ /**
+ * Sets default expiration based on module setting
+ *
+ * @param kEvent $event
+ */
+ function OnPreCreate(&$event)
+ {
+ parent::OnPreCreate($event);
+
+ if ($event->status == erSUCCESS) {
+ $object =& $event->getObject();
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ $object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
+ }
+ }
+
+ /**
+ * Occures before original item of item in pending editing got deleted (for hooking only)
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeDeleteOriginal(&$event)
+ {
+
+ }
+
+ /**
+ * 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!
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeClone(&$event)
+ {
+ if ($this->Application->GetVar('ResetCatBeforeClone')) {
+ $object =& $event->getObject();
+ $object->SetDBField('CategoryId', null);
+ }
+ }
+
+ /**
+ * Set status for new category item based on user permission in category
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemCreate(&$event)
+ {
+ if ($this->Application->IsAdmin()) {
+ return true;
+ }
+
+ $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
+ if ($use_pending_editing) {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
+ $item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix);
+ if ($item_status == STATUS_DISABLED) {
+ $event->status = erFAIL;
+ return false;
+ }
+ else {
+ $object->SetDBField('Status', $item_status);
+ }
+ }
+ }
+
+ /**
+ * Creates category item & redirects to confirmation template (front-end only)
+ *
+ * @param kEvent $event
+ */
+ function OnCreate(&$event)
+ {
+ parent::OnCreate($event);
+ $this->SetFrontRedirectTemplate($event, 'suggest');
+ }
+
+ /**
+ * Returns item's categories (allows to exclude primary category)
+ *
+ * @param int $resource_id
+ * @param bool $with_primary
+ * @return Array
+ */
+ function getItemCategories($resource_id, $with_primary = false)
+ {
+ $sql = 'SELECT CategoryId
+ FROM '.TABLE_PREFIX.'CategoryItems
+ WHERE (ItemResourceId = '.$resource_id.')';
+
+ if (!$with_primary) {
+ $sql .= ' AND (PrimaryCat = 0)';
+ }
+
+ return $this->Conn->GetCol($sql);
+ }
+
+ /**
+ * Adds new and removes old additional categories from category item
+ *
+ * @param kCatDBItem $object
+ */
+ function processAdditionalCategories(&$object, $mode)
+ {
+ $process_categories = $object->GetDBField('MoreCategories');
+ if ($process_categories === '') {
+ // field was not in submit & have default value (when no categories submitted, then value is null)
+ return ;
+ }
+
+ if ($mode == 'create') {
+ // prevents first additional category to become primary
+ $object->assignPrimaryCategory();
+ }
+
+ $process_categories = $process_categories ? explode('|', substr($process_categories, 1, -1)) : Array ();
+ $existing_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
+
+ $add_categories = array_diff($process_categories, $existing_categories);
+ foreach ($add_categories as $category_id) {
+ $object->assignToCategory($category_id);
+ }
+
+ $remove_categories = array_diff($existing_categories, $process_categories);
+ foreach ($remove_categories as $category_id) {
+ $object->removeFromCategory($category_id);
+ }
+ }
+
+ /**
+ * Creates category item & redirects to confirmation template (front-end only)
+ *
+ * @param kEvent $event
+ */
+ function OnUpdate(&$event)
+ {
+ $use_pending = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
+ if ($this->Application->IsAdmin() || !$use_pending) {
+ parent::OnUpdate($event);
+ $this->SetFrontRedirectTemplate($event, 'modify');
+ return ;
+ }
+
+ $object =& $event->getObject(Array('skip_autoload' => true));
+ /* @var $object kCatDBItem */
+
+ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
+ if ($items_info) {
+ $perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ foreach ($items_info as $id => $field_values) {
+ $object->Load($id);
+ $edit_perm = $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix);
+
+ if ($use_pending && !$object->GetDBField('OrgId') && ($edit_perm == STATUS_PENDING)) {
+ // pending editing enabled + not pending copy -> get/create pending copy & save changes to it
+ $original_id = $object->GetID();
+ $original_resource_id = $object->GetDBField('ResourceId');
+ $file_helper->PreserveItemFiles($field_values);
+
+ $object->Load($original_id, 'OrgId');
+ if (!$object->isLoaded()) {
+ // 1. user has no pending copy of live item -> clone live item
+ $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($original_id), null, null, null, true);
+
+ $object->Load($cloned_ids[0]);
+ $object->SetFieldsFromHash($field_values);
+
+ // 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
+ $ci_table = $this->Application->getUnitOption('ci', 'TableName');
+ $sql = 'DELETE FROM '.$ci_table.'
+ WHERE ItemResourceId = '.$object->GetDBField('ResourceId').' AND PrimaryCat = 1';
+ $this->Conn->Query($sql);
+
+ // 1b. copy main item categoryitems to cloned item
+ $sql = 'INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
+ SELECT CategoryId, '.$object->GetDBField('ResourceId').' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
+ FROM '.$ci_table.'
+ WHERE ItemResourceId = '.$original_resource_id;
+ $this->Conn->Query($sql);
+
+ // 1c. put cloned id to OrgId field of item being cloned
+ $object->SetDBField('Status', STATUS_PENDING_EDITING);
+ $object->SetDBField('OrgId', $original_id);
+ }
+ else {
+ // 2. user has pending copy of live item -> just update field values
+ $object->SetFieldsFromHash($field_values);
+ }
+
+ // update id in request (used for redirect in mod-rewrite mode)
+ $this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetID());
+ }
+ else {
+ // 3. already editing pending copy -> just update field values
+ $object->SetFieldsFromHash($field_values);
+ }
+
+ if ($object->Update()) {
+ $event->status = erSUCCESS;
+ }
+ else {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ break;
+ }
+ }
+ }
+
+ $this->SetFrontRedirectTemplate($event, 'modify');
+ }
+
+ /**
+ * Sets next template to one required for front-end after adding/modifying item
+ *
+ * @param kEvent $event
+ * @param string $template_key - {suggest,modify}
+ */
+ function SetFrontRedirectTemplate(&$event, $template_key)
+ {
+ if ($this->Application->IsAdmin() || $event->status != erSUCCESS) {
+ return ;
+ }
+
+ // prepare redirect template
+ $object =& $event->getObject();
+ $is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
+
+ $next_template = $is_active ? 'confirm_template' : 'pending_confirm_template';
+ $event->redirect = $this->Application->GetVar($template_key.'_'.$next_template);
+ $event->SetRedirectParam('opener', 's');
+
+ // send email events
+ $perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix');
+ switch ($event->Name) {
+ case 'OnCreate':
+ $event_suffix = $is_active ? 'ADD' : 'ADD.PENDING';
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :(
+ $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField($owner_field));
+ break;
+
+ case 'OnUpdate':
+ $event_suffix = $is_active ? 'MODIFY' : 'MODIFY.PENDING';
+ $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :(
+ $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('ModifiedById'));
+ break;
+ }
+ }
+
+ /**
+ * Apply same processing to each item beeing selected in grid
+ *
+ * @param kEvent $event
+ * @access private
+ */
+ function iterateItems(&$event)
+ {
+ if ($event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline') {
+ return parent::iterateItems($event);
+ }
+
+ if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
+ return;
+ }
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $ids = $this->StoreSelectedIDs($event);
+
+ if ($ids) {
+ foreach ($ids as $id) {
+ $object->Load($id);
+
+ switch ($event->Name) {
+ case 'OnMassApprove':
+ $ret = $object->ApproveChanges();
+ break;
+
+ case 'OnMassDecline':
+ $ret = $object->DeclineChanges();
+ break;
+ }
+
+ if (!$ret) {
+ $event->status = erFAIL;
+ $event->redirect = false;
+ break;
+ }
+ }
+ }
+
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Deletes items & preserves clean env
+ *
+ * @param kEvent $event
+ */
+ function OnDelete(&$event)
+ {
+ parent::OnDelete($event);
+
+ if ($event->status == erSUCCESS && !$this->Application->IsAdmin()) {
+ $event->SetRedirectParam('pass', 'm');
+ $event->SetRedirectParam('m_cat_id', 0);
+ }
+ }
+
+ /**
+ * Checks, that currently loaded item is allowed for viewing (non permission-based)
+ *
+ * @param kEvent $event
+ * @return bool
+ */
+ function checkItemStatus(&$event)
+ {
+ $object =& $event->getObject();
+ if (!$object->isLoaded()) {
+ $this->_errorNotFound($event);
+
+ return true;
+ }
+
+ $status = $object->GetDBField('Status');
+ $user_id = $this->Application->RecallVar('user_id');
+ $owner_field = $this->getOwnerField($event->Prefix);
+
+ if (($status == -2 || $status == STATUS_PENDING) && ($object->GetDBField($owner_field) == $user_id)) {
+ return true;
+ }
+
+ return $status == STATUS_ACTIVE;
+ }
+
+ /**
+ * Set's correct sorting for list
+ * based on data provided with event
+ *
+ * @param kEvent $event
+ * @access private
+ * @see OnListBuild
+ */
+ function SetSorting(&$event)
+ {
+ if (!$this->Application->IsAdmin()) {
+ $event->setEventParam('same_special', true);
+ }
+
+ parent::SetSorting($event);
+ }
+
+ /**
+ * Returns current per-page setting for list
+ *
+ * @param kEvent $event
+ * @return int
+ */
+ function getPerPage(&$event)
+ {
+ if (!$this->Application->IsAdmin()) {
+ $event->setEventParam('same_special', true);
+ }
+
+ return parent::getPerPage($event);
+ }
+
+ function getOwnerField($prefix)
+ {
+ $owner_field = $this->Application->getUnitOption($prefix, 'OwnerField');
+ if (!$owner_field) {
+ $owner_field = 'CreatedById';
+ }
+
+ return $owner_field;
+ }
+
+ /**
+ * Creates virtual image fields for item
+ *
+ * @param kEvent $event
+ */
+ function OnAfterConfigRead(&$event)
+ {
+ parent::OnAfterConfigRead($event);
+
+ if (defined('IS_INSTALL') && IS_INSTALL) {
+ return ;
+ }
+
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ $file_helper->createItemFiles($event->Prefix, true); // create image fields
+ $file_helper->createItemFiles($event->Prefix, false); // create file fields
+
+ // add EditorsPick to ForcedSorting if needed
+ $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
+ if (array_key_exists('ForceEditorPick', $config_mapping) && $this->Application->ConfigValue($config_mapping['ForceEditorPick'])) {
+ $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings');
+
+ $new_forced_sorting = Array ('EditorsPick' => 'DESC');
+
+ if (array_key_exists('ForcedSorting', $list_sortings[''])) {
+ foreach ($list_sortings['']['ForcedSorting'] as $sort_field => $sort_order) {
+ $new_forced_sorting[$sort_field] = $sort_order;
+ }
+ }
+ $list_sortings['']['ForcedSorting'] = $new_forced_sorting;
+
+ $this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
+ }
+
+ // add grids for advanced view (with primary category column)
+ $grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
+ $process_grids = Array ('Default', 'Radio');
+ foreach ($process_grids as $process_grid) {
+ $grid_data = $grids[$process_grid];
+ $grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_primary_category_td', 'filter_block' => 'grid_like_filter');
+ $grids[$process_grid . 'ShowAll'] = $grid_data;
+ }
+ $this->Application->setUnitOption($this->Prefix, 'Grids', $grids);
+
+ // add options for CategoryId field (quick way to select item's primary category)
+ $category_helper =& $this->Application->recallObject('CategoryHelper');
+ /* @var $category_helper CategoryHelper */
+
+ $virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
+
+ $virtual_fields['CategoryId']['default'] = (int)$this->Application->GetVar('m_cat_id');
+ $virtual_fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions();
+
+ $this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
+ }
+
+ /**
+ * Returns file contents associated with item
+ *
+ * @param kEvent $event
+ */
+ function OnDownloadFile(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $event->status = erSTOP;
+
+ $field = $this->Application->GetVar('field');
+ if (!preg_match('/^File([\d]+)/', $field)) {
+ return ;
+ }
+
+ $file_helper =& $this->Application->recallObject('FileHelper');
+ /* @var $file_helper FileHelper */
+
+ $filename = $object->GetField($field, 'full_path');
+ $file_helper->DownloadFile($filename);
+ }
+
+ /**
+ * Saves user's vote
+ *
+ * @param kEvent $event
+ */
+ function OnMakeVote(&$event)
+ {
+ $event->status = erSTOP;
+
+ if ($this->Application->GetVar('ajax') != 'yes') {
+ // this is supposed to call from AJAX only
+ return ;
+ }
+
+ $rating_helper =& $this->Application->recallObject('RatingHelper');
+ /* @var $rating_helper RatingHelper */
+
+ $object =& $event->getObject( Array ('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $object->Load( $this->Application->GetVar('id') );
+
+ echo $rating_helper->makeVote($object);
+ }
+}
\ No newline at end of file
Property changes on: branches/5.0.x/core/kernel/db/cat_event_handler.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.97.2.36
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/kernel/db/cat_dblist.php
===================================================================
--- branches/5.0.x/core/kernel/db/cat_dblist.php (nonexistent)
+++ branches/5.0.x/core/kernel/db/cat_dblist.php (revision 12343)
@@ -0,0 +1,37 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ class kCatDBList extends kDBList {
+
+ /**
+ * Select items from current category or from all categories
+ *
+ * @var bool
+ */
+ var $Scope = true;
+
+ /*function GetWhereClause($for_counting=false,$system_filters_only=false)
+ {
+ switch ($this->Special)
+ {
+ case 'showall':
+ $this->clearFilters(false,true,false,false);
+ break;
+ }
+ return parent::GetWhereClause($for_counting,$system_filters_only);
+ }*/
+
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/kernel/db/cat_dblist.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.4
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/kernel/application.php
===================================================================
--- branches/5.0.x/core/kernel/application.php (revision 12342)
+++ branches/5.0.x/core/kernel/application.php (revision 12343)
@@ -1,2905 +1,2896 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
/**
* Basic class for Kernel4-based Application
*
* This class is a Facade for any other class which needs to deal with Kernel4 framework.<br>
* The class incapsulates the main run-cycle of the script, provide access to all other objects in the framework.<br>
* <br>
* The class is a singleton, which means that there could be only one instance of kApplication in the script.<br>
* This could be 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.<br>
* See singleton pattern by GOF.
* @package kernel4
*/
defined('FULL_PATH') or die('restricted access!');
class kApplication {
/**
* Is true, when Init method was called already, prevents double initialization
*
* @var bool
*/
var $InitDone = false;
/**
* Holds internal NParser object
* @access private
* @var NParser
*/
var $Parser;
/**
* Holds parser output buffer
* @access private
* @var string
*/
var $HTML;
/**
* Prevents request from beeing proceeded twice in case if application init is called mere then one time
*
* @var bool
* @todo This is not good anyway (by Alex)
*/
var $RequestProcessed = false;
/**
* The main Factory used to create
* almost any class of kernel and
* modules
*
* @access private
* @var kFactory
*/
var $Factory;
/**
* All ConfigurationValues table content (hash) here
*
* @var Array
* @access private
*/
var $ConfigHash = Array();
/**
* Ids of config variables used in current run (for caching)
*
* @var Array
* @access private
*/
var $ConfigCacheIds = array();
/**
* Template names, that will be used instead of regular templates
*
* @var Array
*/
var $ReplacementTemplates = Array ();
/**
* Mod-Rewrite listeners used during url building and parsing
*
* @var Array
*/
var $RewriteListeners = Array ();
/**
* Reference to debugger
*
* @var Debugger
*/
var $Debugger = null;
/**
* Holds all phrases used
* in code and template
*
* @var PhrasesCache
*/
var $Phrases;
/**
* Modules table content, key - module name
*
* @var Array
*/
var $ModuleInfo = Array();
/**
* Holds DBConnection
*
* @var kDBConnection
*/
var $Conn = null;
/**
* Maintains list of user-defined error handlers
*
* @var Array
*/
var $errorHandlers = Array();
// performance needs:
/**
* Holds a refererence to httpquery
*
* @var kHttpQuery
*/
var $HttpQuery = null;
/**
* Holds a reference to UnitConfigReader
*
* @var kUnitConfigReader
*/
var $UnitConfigReader = null;
/**
* Holds a reference to Session
*
* @var Session
*/
var $Session = null;
/**
* Holds a ref to kEventManager
*
* @var kEventManager
*/
var $EventManager = null;
/**
* Ref to itself, needed because everybody used to write $this->Application, even inside kApplication
*
* @var kApplication
*/
var $Application = null;
/**
* Ref for TemplatesChache
*
* @var TemplatesCache
*/
var $TemplatesCache = null;
var $CompilationCache = array(); //used when compiling templates
var $CachedProcessors = array(); //used when running compiled templates
var $LambdaElements = 1; // for autonumbering unnamed RenderElements [any better place for this prop? KT]
/**
* Holds current NParser tag while parsing, can be used in error messages to display template file and line
*
* @var _BlockTag
*/
var $CurrentNTag = null;
/**
* Memcache object pointer
*
* @var Memcache
*/
var $Memcached = null;
/**
* 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.
* Anywhere in the script you could write:
* <code>
* $application =& kApplication::Instance();
* </code>
* or in an object:
* <code>
* $this->Application =& kApplication::Instance();
* </code>
* to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class.
* To use descendand 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.
* @static
* @access public
* @return kApplication
*/
function &Instance()
{
static $instance = false;
if(!$instance)
{
safeDefine('APPLICATION_CLASS', 'kApplication');
$class = APPLICATION_CLASS;
$instance = new $class();
$instance->Application =& $instance;
}
return $instance;
}
function InitMemcached()
{
return ;
$memcached_servers = 'localhost:11211'; // $this->Application->ConfigValue('MemcachedServers');
if ($memcached_servers && class_exists('Memcache')) {
$this->Memcached = new Memcache();
$servers = explode(';', $memcached_servers);
foreach ($servers as $server) {
list ($server, $port) = strpos($server, ':') !== false ? explode(':', $server, 2) : Array ($server, 11211);
$this->Memcached->addServer($server, $port);
}
}
//try to set something to cache, if not working - set $this->Memcached to null
}
function CacheSet($name, $value, $expiration)
{
if (isset($this->Memcached)) {
return $this->Memcached->set($name, $value, 0, $expiration);
}
return false;
}
function CacheGet($name)
{
if (isset($this->Memcached)) {
return $this->Memcached->get($name);
}
return false;
}
/**
* Initializes the Application
*
* @access public
* @see kHTTPQuery
* @see Session
* @see TemplatesCache
* @return bool Was Init actually made now or before
*/
function Init()
{
if($this->InitDone) return false;
$this->InitMemcached();
if (!constOn('SKIP_OUT_COMPRESSION')) {
ob_start(); // collect any output from method (other then tags) into buffer
}
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Init:');
}
if (!$this->isDebugMode() && !constOn('DBG_ZEND_PRESENT')) {
error_reporting(0);
ini_set('display_errors', 0);
}
if (!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;
}
}
$this->Conn = new kDBConnection(SQL_TYPE, Array(&$this, 'handleSQLError') );
$this->Conn->debugMode = $this->isDebugMode();
$this->Conn->Connect(SQL_SERVER, SQL_USER, SQL_PASS, SQL_DB);
$this->Factory = new kFactory();
$this->registerDefaultClasses();
$this->Phrases = new PhrasesCache();
$this->EventManager =& $this->Factory->makeClass('EventManager');
$this->Factory->Storage['EventManager'] =& $this->EventManager;
$this->RegisterDefaultBuildEvents();
$this->SetDefaultConstants();
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Before UnitConfigReader');
}
$this->UnitConfigReader =& $this->recallObject('kUnitConfigReader');
$this->UnitConfigReader->scanModules(MODULES_PATH);
$this->registerModuleConstants();
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('After UnitConfigReader');
}
$rewrite_on = $this->ConfigValue('UseModRewrite');
// admin=1 - when front is browsed using admin session
$admin_on = getArrayValue($_REQUEST, 'admin') || $this->IsAdmin();
define('MOD_REWRITE', $rewrite_on && !$admin_on ? 1 : 0);
$this->HttpQuery =& $this->recallObject('HTTPQuery');
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Processed HTTPQuery initial');
}
$this->Session =& $this->recallObject('Session');
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Processed Session');
}
if (!$this->RecallVar('UserGroups')) {
$user_groups = trim($this->Session->GetField('GroupList'), ',');
if (!$user_groups) {
$user_groups = $this->ConfigValue('User_GuestGroup');
}
$this->Session->SetField('GroupList', $user_groups);
$this->StoreVar('UserGroups', $user_groups);
}
$this->HttpQuery->AfterInit();
$this->Session->ValidateExpired();
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit');
}
$this->LoadCache();
$this->InitConfig();
$this->Phrases->Init('phrases');
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Loaded cache and phrases');
}
$this->UnitConfigReader->AfterConfigRead();
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendTimestamp('Processed AfterConfigRead');
}
/*// Module items are recalled during url parsing & PhrasesCache is needed already there,
// because it's used in their build events. That's why phrases cache initialization is
// called from kHTTPQuery in case when mod_rewrite is used
if (!$this->RewriteURLs()) {
$this->Phrases = new PhrasesCache();
}*/
if ($this->GetVar('m_cat_id') === false) $this->SetVar('m_cat_id', 0);
if( !$this->RecallVar('curr_iso') ) $this->StoreVar('curr_iso', $this->GetPrimaryCurrency() );
$this->SetVar('visits_id', $this->RecallVar('visit_id') );
$language =& $this->recallObject( 'lang.current', null, Array('live_table' => true) );
if (preg_match('/utf-8/', $language->GetDBField('Charset'))) {
setlocale(LC_ALL, 'en_US.UTF-8');
mb_internal_encoding('UTF-8');
}
$this->ValidateLogin();
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->profileFinish('kernel4_startup');
}
$this->InitDone = true;
$this->HandleEvent( new kEvent('adm:OnStartup') );
return true;
}
/**
* Returns module information. Searches module by requested field
*
* @param string $field
* @param mixed $value
* @param string field value to returns, if not specified, then return all fields
* @param string field to return
* @return Array
*/
function findModule($field, $value, $return_field = null)
{
$found = false;
foreach ($this->ModuleInfo as $module_name => $module_info) {
if (strtolower($module_info[$field]) == strtolower($value)) {
$found = true;
break;
}
}
if ($found) {
return isset($return_field) ? $module_info[$return_field] : $module_info;
}
return false;
}
function refreshModuleInfo()
{
if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules')) {
$this->registerModuleConstants();
return false;
}
$modules_helper =& $this->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Modules
WHERE Loaded = 1
ORDER BY LoadOrder';
$this->ModuleInfo = $this->Conn->Query($sql, 'Name');
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'Modules
WHERE '.$modules_helper->getWhereClause().'
ORDER BY LoadOrder';
$this->ModuleInfo = $this->Conn->Query($sql, 'Name');
$this->registerModuleConstants();
}
/**
* Checks if passed language id if valid and sets it to primary otherwise
*
*/
function VerifyLanguageId()
{
$language_id = $this->GetVar('m_lang');
if (!$language_id) {
$language_id = 'default';
}
$this->SetVar('lang.current_id', $language_id );
$this->SetVar('m_lang', $language_id );
$lang_mode = $this->GetVar('lang_mode');
$this->SetVar('lang_mode', '');
$lang =& $this->recallObject('lang.current');
if ( !$lang->IsLoaded() || (!$this->Application->IsAdmin() && !$lang->GetDBField('Enabled')) ) {
if (!defined('IS_INSTALL')) $this->ApplicationDie('Unknown or disabled language');
}
$this->SetVar('lang_mode',$lang_mode);
}
/**
* Checks if passed theme id if valid and sets it to primary otherwise
*
*/
function VerifyThemeId()
{
if ($this->Application->IsAdmin()) {
safeDefine('THEMES_PATH', '/core/admin_templates');
return;
}
$path = $this->GetFrontThemePath();
if ($path === false) {
$this->ApplicationDie('No Primary Theme Selected or Current Theme is Unknown or Disabled');
}
safeDefine('THEMES_PATH', $path);
/*$theme_id = $this->GetVar('m_theme');
if (!$theme_id) {
$theme_id = $this->GetDefaultThemeId();
if (!$theme_id) {
if (!defined('IS_INSTALL')) $this->ApplicationDie('No Primary Theme Selected');
}
}
$this->SetVar('m_theme', $theme_id);
$this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId
$theme =& $this->recallObject('theme.current');
if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) {
if (!defined('IS_INSTALL')) $this->ApplicationDie('Unknown or disabled theme');
}
safeDefine('THEMES_PATH', '/themes/'.$theme->GetDBField('Name'));*/
}
function GetFrontThemePath($force=0)
{
static $path=null;
if (!$force && isset($path)) return $path;
$theme_id = $this->GetVar('m_theme');
if (!$theme_id) {
// $theme_id = $this->GetDefaultThemeId(1); //1 to force front-end mode!
$theme_id = 'default';
}
$this->SetVar('m_theme', $theme_id);
$this->SetVar('theme.current_id', $theme_id ); // KOSTJA: this is to fool theme' getPassedId
$theme =& $this->recallObject('theme.current');
if (!$theme->IsLoaded() || !$theme->GetDBField('Enabled')) {
return false;
}
$path = '/themes/'.$theme->GetDBField('Name');
return $path;
}
function GetDefaultLanguageId()
{
static $language_id = 0;
if ($language_id > 0) {
return $language_id;
}
$table = $this->getUnitOption('lang', 'TableName');
$id_field = $this->getUnitOption('lang', 'IDField');
$sql = 'SELECT '.$id_field.'
FROM '.$table.'
WHERE (PrimaryLang = 1) AND (Enabled = 1)';
$language_id = $this->Conn->GetOne($sql);
if (!$language_id && defined('IS_INSTALL') && IS_INSTALL) {
$language_id = 1;
}
return $language_id;
}
function GetDefaultThemeId($force_front=0)
{
static $theme_id = 0;
if ($theme_id > 0) {
return $theme_id;
}
if (constOn('DBG_FORCE_THEME')) {
$theme_id = DBG_FORCE_THEME;
}
elseif (!$force_front && $this->IsAdmin()) {
$theme_id = 999;
}
else {
$table = $this->getUnitOption('theme','TableName');
$id_field = $this->getUnitOption('theme','IDField');
$sql = 'SELECT '.$id_field.'
FROM '.$table.'
WHERE (PrimaryTheme = 1) AND (Enabled = 1)';
$theme_id = $this->Conn->GetOne($sql);
}
return $theme_id;
}
function GetPrimaryCurrency()
{
if ($this->isModuleEnabled('In-Commerce')) {
$table = $this->getUnitOption('curr', 'TableName');
return $this->Conn->GetOne('SELECT ISO FROM '.$table.' WHERE IsPrimary = 1');
}
else {
return 'USD';
}
}
/**
* Registers default classes such as ItemController, GridController and LoginController
*
* Called automatically while initializing Application
* @access private
* @return void
*/
function RegisterDefaultClasses()
{
- $this->registerClass('kTempTablesHandler', KERNEL_PATH.'/utility/temp_handler.php');
- $this->registerClass('kEventManager', KERNEL_PATH.'/event_manager.php', 'EventManager');
- $this->registerClass('kUnitConfigReader', KERNEL_PATH.'/utility/unit_config_reader.php');
+ $this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php');
+ $this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager');
+ $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php');
+
+ $this->registerClass('kArray', KERNEL_PATH . '/utility/params.php');
+ $this->registerClass('Params', KERNEL_PATH . '/utility/params.php');
+ $this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions');
+ $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'Cache', 'Params');
+ $this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery', 'Params');
+
+ $this->registerClass('kHelper', KERNEL_PATH . '/kbase.php');
+ $this->registerClass('kMultipleFilter', KERNEL_PATH . '/utility/filters.php');
+
+ $this->registerClass('Session', KERNEL_PATH . '/session/session.php');
+ $this->registerClass('SessionStorage', KERNEL_PATH . '/session/session.php');
+ $this->registerClass('InpSession', KERNEL_PATH . '/session/inp_session.php', 'Session');
+ $this->registerClass('InpSessionStorage', KERNEL_PATH . '/session/inp_session.php', 'SessionStorage');
+
+ $this->registerClass('kTagProcessor', KERNEL_PATH . '/processors/tag_processor.php');
+ $this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php','m_TagProcessor', 'kTagProcessor');
+
+ $this->registerClass('kDBList', KERNEL_PATH . '/db/dblist.php');
+ $this->registerClass('kDBItem', KERNEL_PATH . '/db/dbitem.php');
+ $this->registerClass('kDBEventHandler', KERNEL_PATH . '/db/db_event_handler.php');
+ $this->registerClass('kDBTagProcessor', KERNEL_PATH . '/db/db_tag_processor.php', null, 'kTagProcessor');
+ $this->registerClass('kCatDBItem', KERNEL_PATH . '/db/cat_dbitem.php');
+ $this->registerClass('kCatDBList', KERNEL_PATH . '/db/cat_dblist.php');
+ $this->registerClass('kCatDBEventHandler', KERNEL_PATH . '/db/cat_event_handler.php');
+ $this->registerClass('kCatDBTagProcessor', KERNEL_PATH . '/db/cat_tag_processor.php');
+
+ $this->registerClass('NParser', KERNEL_PATH . '/nparser/nparser.php');
+ $this->registerClass('TemplatesCache', KERNEL_PATH . '/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor'));
+
+ $this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender', 'kHelper');
+ $this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket');
- $this->registerClass('kArray', KERNEL_PATH.'/utility/params.php');
- $this->registerClass('Params', KERNEL_PATH.'/utility/params.php');
- $this->registerClass('kHelper', KERNEL_PATH.'/kbase.php');
-
- $this->registerClass('kCache', KERNEL_PATH.'/utility/cache.php', 'Cache', 'Params');
- $this->registerClass('kHTTPQuery', KERNEL_PATH.'/utility/http_query.php', 'HTTPQuery', 'Params');
-
- $this->registerClass('Session', KERNEL_PATH.'/session/session.php');
- $this->registerClass('SessionStorage', KERNEL_PATH.'/session/session.php');
-
- $this->registerClass('Params', KERNEL_PATH.'/utility/params.php', 'kActions');
-
- $this->registerClass('kMultipleFilter', KERNEL_PATH.'/utility/filters.php');
- $this->registerClass('kDBList', KERNEL_PATH.'/db/dblist.php');
- $this->registerClass('kDBItem', KERNEL_PATH.'/db/dbitem.php');
- $this->registerClass('kDBEventHandler', KERNEL_PATH.'/db/db_event_handler.php');
-
- $this->registerClass('kTagProcessor', KERNEL_PATH.'/processors/tag_processor.php');
- $this->registerClass('kMainTagProcessor', KERNEL_PATH.'/processors/main_processor.php','m_TagProcessor', 'kTagProcessor');
- $this->registerClass('kDBTagProcessor', KERNEL_PATH.'/db/db_tag_processor.php', null, 'kTagProcessor');
-
- $this->registerClass('TemplatesCache', KERNEL_PATH.'/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor'));
- $this->registerClass('NParser', KERNEL_PATH.'/nparser/nparser.php');
-
- $this->registerClass('kEmailSendingHelper', KERNEL_PATH.'/utility/email_send.php', 'EmailSender', 'kHelper');
- $this->registerClass('kSocket', KERNEL_PATH.'/utility/socket.php', 'Socket');
-
- if (file_exists(MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php')) {
- $this->registerClass('kCurrencyRates', MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php');
+ if (file_exists(MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php')) {
+ $this->registerClass('kCurrencyRates', MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php');
}
- /* Moved from MyApplication */
-
- $this->registerClass('InpSession',KERNEL_PATH.'/../units/general/inp_ses_storage.php', 'Session');
- $this->registerClass('InpSessionStorage',KERNEL_PATH.'/../units/general/inp_ses_storage.php', 'SessionStorage');
-
- $this->registerClass('kCatDBItem',KERNEL_PATH.'/../units/general/cat_dbitem.php');
- $this->registerClass('kCatDBItemExportHelper',KERNEL_PATH.'/../units/general/cat_dbitem_export.php', 'CatItemExportHelper');
- $this->registerClass('kCatDBList',KERNEL_PATH.'/../units/general/cat_dblist.php');
- $this->registerClass('kCatDBEventHandler',KERNEL_PATH.'/../units/general/cat_event_handler.php');
- $this->registerClass('kCatDBTagProcessor',KERNEL_PATH.'/../units/general/cat_tag_processor.php');
-
- // Do not move to config - this helper is used before configs are read
- $this->registerClass('kModulesHelper', KERNEL_PATH.'/../units/helpers/modules_helper.php', 'ModulesHelper');
-
- /* End moved */
-
+ // do not move to config - this helper is used before configs are read
+ $this->registerClass('kModulesHelper', KERNEL_PATH . '/../units/helpers/modules_helper.php', 'ModulesHelper');
}
function RegisterDefaultBuildEvents()
{
$event_manager =& $this->recallObject('EventManager');
$event_manager->registerBuildEvent('kTempTablesHandler', 'OnTempHandlerBuild');
}
/**
* Returns item's filename that corresponds id passed. If possible, then get it from cache
*
* @param string $prefix
* @param int $id
* @return string
*/
function getFilename($prefix, $id, $category_id=null)
{
$filename = $this->getCache('filenames', $prefix.'_'.$id);
if ($filename === false) {
$table = $this->getUnitOption($prefix, 'TableName');
$id_field = $this->getUnitOption($prefix, 'IDField');
if ($prefix == 'c') {
if(!$id) {
$this->setCache('filenames', $prefix.'_'.$id, '');
return '';
}
// this allows to save 2 sql queries for each category
$sql = 'SELECT NamedParentPath, CachedTemplate, TreeLeft, TreeRight
FROM '.$table.'
WHERE '.$id_field.' = '.$this->Conn->qstr($id);
$category_data = $this->Conn->GetRow($sql);
// only direct links to category pages work (symlinks, container pages and so on won't work)
$filename = $category_data['NamedParentPath'];
$this->setCache('category_templates', $id, $filename);
$this->setCache('category_designs', $id, ltrim($category_data['CachedTemplate'], '/'));
$this->setCache('category_tree', $id, $category_data['TreeLeft'] . ';' . $category_data['TreeRight']);
}
else {
$resource_id = $this->Conn->GetOne('SELECT ResourceId FROM '.$table.' WHERE '.$id_field.' = '.$this->Conn->qstr($id));
if (is_null($category_id)) $category_id = $this->GetVar('m_cat_id');
$sql = 'SELECT Filename FROM '.TABLE_PREFIX.'CategoryItems WHERE ItemResourceId = '.$resource_id.' AND CategoryId = '.$category_id;
$filename = $this->Conn->GetOne($sql);
/*if (!$filename) {
$sql = 'SELECT Filename FROM '.TABLE_PREFIX.'CategoryItems WHERE ItemResourceId = '.$resource_id.' AND PrimaryCat = 1';
$filename = $this->Conn->GetOne($sql);
}*/
/*$sql = 'SELECT Filename
FROM '.$table.'
WHERE '.$id_field.' = '.$this->Conn->qstr($id);
$filename = $this->Conn->GetOne($sql);*/
}
$this->setCache('filenames', $prefix.'_'.$id, $filename);
}
return $filename;
}
/**
* Adds new value to cache $cache_name and identified by key $key
*
* @param string $cache_name cache name
* @param int $key key name to add to cache
* @param mixed $value value of chached record
*/
function setCache($cache_name, $key, $value, $expiration=3600)
{
$cache =& $this->recallObject('Cache');
/* @var $cache kCache */
return $cache->setCache($cache_name, $key, $value, $expiration);
}
/**
* Returns cached $key value from cache named $cache_name
*
* @param string $cache_name cache name
* @param int $key key name from cache
* @return mixed
*/
function getCache($cache_name, $key)
{
$cache =& $this->recallObject('Cache');
return $cache->getCache($cache_name, $key);
}
/**
* Defines default constants if it's not defined before - in config.php
*
* @access private
*/
function SetDefaultConstants() // it's defined in startup.php - can be removed??
{
safeDefine('SERVER_NAME', $_SERVER['HTTP_HOST']);
}
/**
* Registers each module specific constants if any found
*
*/
function registerModuleConstants()
{
if (file_exists(KERNEL_PATH.'/constants.php')) {
k4_include_once(KERNEL_PATH.'/constants.php');
}
if (!$this->ModuleInfo) return false;
foreach($this->ModuleInfo as $module_name => $module_info)
{
$module_path = '/'.$module_info['Path'];
$contants_file = FULL_PATH.$module_path.'constants.php';
if( file_exists($contants_file) ) k4_include_once($contants_file);
}
return true;
}
function ProcessRequest()
{
$event_manager =& $this->recallObject('EventManager');
/* @var $event_manager kEventManager */
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_SHOW_HTTPQUERY')) {
$this->Debugger->appendHTML('HTTPQuery:');
$this->Debugger->dumpVars($this->HttpQuery->_Params);
}
$event_manager->ProcessRequest();
$event_manager->RunRegularEvents(reBEFORE);
$this->RequestProcessed = true;
}
/**
* Actually runs the parser against current template and stores parsing result
*
* This method gets t variable passed to the script, loads the template given in t variable and
* parses it. The result is store in {@link $this->HTML} property.
* @access public
* @return void
*/
function Run()
{
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Run:');
}
if ($this->IsAdmin()) {
// for permission checking in events & templates
$this->LinkVar('module'); // for common configuration templates
$this->LinkVar('module_key'); // for common search templates
$this->LinkVar('section'); // for common configuration templates
if ($this->GetVar('m_opener') == 'p') {
$this->LinkVar('main_prefix'); // window prefix, that opened selector
$this->LinkVar('dst_field'); // field to set value choosed in selector
// $this->LinkVar('return_template'); // template to go, when something was coosen from popup (from finalizePopup)
// $this->LinkVar('return_m'); // main env part to restore after popup will be closed (from finalizePopup)
}
if ($this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax')) {
// hide debug output from ajax requests automatically
define('DBG_SKIP_REPORTING', 1);
}
}
elseif ($this->GetVar('admin')) {
// viewing front-end through admin's frame
$admin_session =& $this->Application->recallObject('Session.admin');
$user = (int)$admin_session->RecallVar('user_id'); // in case, when no valid admin session found
$perm_helper =& $this->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
if ($perm_helper->CheckUserPermission($user, 'CATEGORY.MODIFY', 0, 0)) {
// user can edit cms blocks
$editing_mode = $this->GetVar('editing_mode');
define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_BROWSE);
$this->Phrases->setPhraseEditing();
}
}
safeDefine('EDITING_MODE', ''); // user can't edit anything
if (!$this->RequestProcessed) $this->ProcessRequest();
$this->InitParser();
$t = $this->GetVar('t');
if (!$this->TemplatesCache->TemplateExists($t) && !$this->IsAdmin()) {
$cms_handler =& $this->recallObject('st_EventHandler');
/* @var $cms_handler CategoriesEventHandler */
$t = ltrim($cms_handler->GetDesignTemplate(), '/');
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->Debugger->appendHTML('<strong>Design Template</strong>: ' . $t . '; <strong>CategoryID</strong>: ' . $this->GetVar('m_cat_id'));
}
}
/*else {
$cms_handler->SetCatByTemplate();
}*/
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Parsing:');
}
$this->HTML = $this->Parser->Run($t);
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application after Parsing:');
}
}
function InitParser($theme_name = false)
{
if( !is_object($this->Parser) ) {
$this->Parser =& $this->recallObject('NParser');
$this->TemplatesCache =& $this->recallObject('TemplatesCache');
}
$this->TemplatesCache->forceThemeName = $theme_name;
}
/**
* Send the parser results to browser
*
* Actually send everything stored in {@link $this->HTML}, to the browser by echoing it.
* @access public
* @return void
*/
function Done()
{
$this->HandleEvent( new kEvent('adm:OnBeforeShutdown') );
if (defined('DEBUG_MODE') && $this->isDebugMode() && constOn('DBG_PROFILE_MEMORY')) {
$this->Debugger->appendMemoryUsage('Application before Done:');
}
if (defined('DEBUG_MODE') && $this->isDebugMode()) {
$this->EventManager->RunRegularEvents(reAFTER);
$this->Session->SaveData();
if (constOn('DBG_CACHE')) {
$cache =& $this->recallObject('Cache');
$cache->printStatistics();
}
$this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true);
}
else {
$this->HTML = ob_get_clean().$this->HTML;
}
if ($this->UseOutputCompression()) {
header('Content-Encoding: gzip');
$compression_level = $this->ConfigValue('OutputCompressionLevel');
if ($compression_level < 0 || $compression_level > 9) $compression_level = 7;
echo gzencode($this->HTML, $compression_level);
}
else {
echo $this->HTML;
}
$this->UpdateCache();
flush();
if (!$this->isDebugMode()) {
$this->EventManager->RunRegularEvents(reAFTER);
$this->Session->SaveData();
}
if (defined('DBG_CAPTURE_STATISTICS') && DBG_CAPTURE_STATISTICS && !$this->IsAdmin()) {
$this->_storeStatistics();
}
}
/**
* Stores script execution statistics to database
*
*/
function _storeStatistics()
{
global $start;
$script_time = getmicrotime() - $start;
$query_statistics = $this->Conn->getQueryStatistics(); // time & count
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'StatisticsCapture
WHERE TemplateName = "' . $this->GetVar('t') . '"';
$data = $this->Conn->GetRow($sql);
if ($data) {
$this->_updateAverageStatistics($data, 'ScriptTime', $script_time);
$this->_updateAverageStatistics($data, 'SqlTime', $query_statistics['time']);
$this->_updateAverageStatistics($data, 'SqlCount', $query_statistics['count']);
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'StatisticsCapture', 'StatisticsId = ' . $data['StatisticsId']);
}
else {
$data['ScriptTimeMin'] = $data['ScriptTimeAvg'] = $data['ScriptTimeMax'] = $script_time;
$data['SqlTimeMin'] = $data['SqlTimeAvg'] = $data['SqlTimeMax'] = $query_statistics['time'];
$data['SqlCountMin'] = $data['SqlCountAvg'] = $data['SqlCountMax'] = $query_statistics['count'];
$data['TemplateName'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'StatisticsCapture');
}
}
/**
* Calculates average time for statistics
*
* @param Array $data
* @param string $field_prefix
* @param float $current_value
*/
function _updateAverageStatistics(&$data, $field_prefix, $current_value)
{
$data[$field_prefix . 'Avg'] = (($data['Hits'] * $data[$field_prefix . 'Avg']) + $current_value) / ($data['Hits'] + 1);
if ($current_value < $data[$field_prefix . 'Min']) {
$data[$field_prefix . 'Min'] = $current_value;
}
if ($current_value > $data[$field_prefix . 'Max']) {
$data[$field_prefix . 'Max'] = $current_value;
}
}
function logSlowQuery($slow_sql, $time)
{
$query_crc = crc32($slow_sql);
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'SlowSqlCapture
WHERE QueryCrc = ' . $query_crc;
$data = $this->Conn->Query($sql, null, true);
if ($data) {
$this->_updateAverageStatistics($data, 'Time', $time);
$template_names = explode(',', $data['TemplateNames']);
array_push($template_names, $this->GetVar('t'));
$data['TemplateNames'] = implode(',', array_unique($template_names));
$data['Hits']++;
$data['LastHit'] = adodb_mktime();
$this->Conn->doUpdate($data, TABLE_PREFIX . 'SlowSqlCapture', 'CaptureId = ' . $data['CaptureId']);
}
else {
$data['TimeMin'] = $data['TimeAvg'] = $data['TimeMax'] = $time;
$data['SqlQuery'] = $slow_sql;
$data['QueryCrc'] = $query_crc;
$data['TemplateNames'] = $this->GetVar('t');
$data['Hits'] = 1;
$data['LastHit'] = adodb_mktime();
$this->Conn->doInsert($data, TABLE_PREFIX . 'SlowSqlCapture');
}
}
/**
* Checks if output compression options is available
*
* @return string
*/
function UseOutputCompression()
{
if (constOn('IS_INSTALL') || constOn('DBG_ZEND_PRESENT') || constOn('SKIP_OUT_COMPRESSION')) return false;
return $this->ConfigValue('UseOutputCompression') && function_exists('gzencode') && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
}
// Facade
/**
* Returns current session id (SID)
* @access public
* @return longint
*/
function GetSID()
{
$session =& $this->recallObject('Session');
return $session->GetID();
}
function DestroySession()
{
$session =& $this->recallObject('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)
{
return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default;
}
/**
* Returns ALL variables passed to the script as GET/POST/COOKIE
*
* @access public
* @return array
*/
function GetVars()
{
return $this->HttpQuery->GetParams();
}
/**
* Set the variable 'as it was passed to the script through GET/POST/COOKIE'
*
* This could be useful to set the variable when you know that
* other objects would relay on variable passed from GET/POST/COOKIE
* or you could use SetVar() / GetVar() pairs to pass the values between different objects.<br>
*
* This method is formerly known as $this->Session->SetProperty.
* @param string $var Variable name to set
* @param mixed $val Variable value
* @access public
* @return void
*/
function SetVar($var,$val)
{
return $this->HttpQuery->Set($var, $val);
}
/**
* Deletes kHTTPQuery variable
*
* @param string $var
* @todo think about method name
*/
function DeleteVar($var)
{
return $this->HttpQuery->Remove($var);
}
/**
* Deletes Session variable
*
* @param string $var
*/
function RemoveVar($var)
{
return $this->Session->RemoveVar($var);
}
function RemovePersistentVar($var)
{
return $this->Session->RemovePersistentVar($var);
}
/**
* Restores Session variable to it's db version
*
* @param string $var
*/
function RestoreVar($var)
{
return $this->Session->RestoreVar($var);
}
/**
* Returns session variable value
*
* Return value of $var variable stored in Session. An optional default value could be passed as second parameter.
*
* @see SimpleSession
* @access public
* @param string $var Variable name
* @param mixed $default Default value to return if no $var variable found in session
* @return mixed
*/
function RecallVar($var,$default=false)
{
return $this->Session->RecallVar($var,$default);
}
function RecallPersistentVar($var, $default = false)
{
return $this->Session->RecallPersistentVar($var, $default);
}
/**
* Stores variable $val in session under name $var
*
* Use this method to store variable in session. Later this variable could be recalled.
* @see RecallVar
* @access public
* @param string $var Variable name
* @param mixed $val Variable value
*/
function StoreVar($var, $val, $optional = false)
{
$session =& $this->recallObject('Session');
$this->Session->StoreVar($var, $val, $optional);
}
function StorePersistentVar($var, $val)
{
$this->Session->StorePersistentVar($var, $val);
}
function StoreVarDefault($var, $val, $optional=false)
{
$session =& $this->recallObject('Session');
$this->Session->StoreVarDefault($var, $val, $optional);
}
/**
* Links HTTP Query variable with session variable
*
* If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session.
* This method could be used for making sure that GetVar will return query or session value for given
* variable, when query variable should overwrite session (and be stored there for later use).<br>
* This could be used for passing item's ID into popup with multiple tab -
* in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id').
* After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session
* @access public
* @param string $var HTTP Query (GPC) variable name
* @param mixed $ses_var Session variable name
* @param mixed $default Default variable value
*/
function LinkVar($var, $ses_var = null, $default = '', $optional = false)
{
if (!isset($ses_var)) $ses_var = $var;
if ($this->GetVar($var) !== false) {
$this->StoreVar($ses_var, $this->GetVar($var), $optional);
}
else {
$this->SetVar($var, $this->RecallVar($ses_var, $default));
}
}
/**
* Returns variable from HTTP Query, or from session if not passed in HTTP Query
*
* The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed.
* Returns the default value if variable does not exist in session and was not passed in HTTP Query
*
* @see LinkVar
* @access public
* @param string $var HTTP Query (GPC) variable name
* @param mixed $ses_var Session variable name
* @param mixed $default Default variable value
* @return mixed
*/
function GetLinkedVar($var, $ses_var = null, $default = '')
{
$this->LinkVar($var, $ses_var, $default);
return $this->GetVar($var);
}
function AddBlock($name, $tpl)
{
$this->cache[$name] = $tpl;
}
function ProcessParsedTag($prefix, $tag, $params)
{
$processor = $this->Parser->GetProcessor($prefix);
return $processor->ProcessParsedTag($tag, $params, $prefix);
}
/**
* Return ADODB Connection object
*
* Returns ADODB Connection object already connected to the project database, configurable in config.php
* @access public
* @return kDBConnection
*/
function &GetADODBConnection()
{
return $this->Conn;
}
/**
* Allows to parse given block name or include template
*
* @param Array $params Parameters to pass to block/template. Reserved parameter "name" used to specify block/template name.
* @param Array $pass_params Forces to pass current parser params to this block/template. Use with cauntion, because you can accidently pass "block_no_data" parameter.
* @param bool $as_template
* @return string
*/
function ParseBlock($params, $pass_params = 0, $as_template = false)
{
if (substr($params['name'], 0, 5) == 'html:') {
return substr($params['name'], 6);
}
return $this->Parser->ParseBlock($params, $pass_params, $as_template);
}
/**
* Returns index file, that could be passed as parameter to method, as parameter to tag and as constant or not passed at all
*
* @param string $prefix
* @param string $index_file
* @param Array $params
* @return string
*/
function getIndexFile($prefix, $index_file, &$params)
{
if (isset($params['index_file'])) {
$index_file = $params['index_file'];
unset($params['index_file']);
return $index_file;
}
if (isset($index_file)) {
return $index_file;
}
if (defined('INDEX_FILE')) {
return INDEX_FILE;
}
$cut_prefix = trim(BASE_PATH, '/').'/'.trim($prefix, '/');
return trim(preg_replace('/'.preg_quote($cut_prefix, '/').'(.*)/', '\\1', $_SERVER['PHP_SELF']), '/');
}
/**
* Return href for template
*
* @access public
* @param string $t Template path
* @var string $prefix index.php prefix - could be blank, 'admin'
*/
function HREF($t, $prefix='', $params=null, $index_file=null)
{
if(!$t) $t = $this->GetVar('t'); // moved from kMainTagProcessor->T()
$t = preg_replace('/^Content\//i', '', $t);
/*if ($this->GetVar('skip_last_template')) {
$params['opener'] = 'p';
$this->SetVar('m_opener', 'p');
}
if ($t == 'incs/close_popup') {
// because this template closes the popup and we don't need popup mark here anymore
$params['m_opener'] = 's';
}*/
if( substr($t, -4) == '.tpl' ) $t = substr($t, 0, strlen($t) - 4 );
if ( $this->IsAdmin() && $prefix == '') $prefix = ADMIN_DIRECTORY;
if ( $this->IsAdmin() && $prefix == '_FRONT_END_') $prefix = '';
$index_file = $this->getIndexFile($prefix, $index_file, $params);
if (isset($params['_auto_prefix_'])) {
unset($params['_auto_prefix_']); // this is parser-related param, do not need to pass it here
}
$ssl = isset($params['__SSL__']) ? $params['__SSL__'] : null;
if ($ssl !== null) {
$session =& $this->recallObject('Session');
$cookie_url = trim($session->CookieDomain.$session->CookiePath, '/.');
if ($ssl) {
$target_url = defined('ADMIN') && ADMIN ? $this->ConfigValue('AdminSSL_URL') : false;
if (!$target_url) {
$target_url = $this->ConfigValue('SSL_URL');
}
}
else {
$target_url = 'http://'.DOMAIN.$this->ConfigValue('Site_Path');
}
if (!preg_match('#'.preg_quote($cookie_url).'#', $target_url)) {
$session->SetMode(smGET_ONLY);
}
}
if (isset($params['opener']) && $params['opener'] == 'u') {
$wid = $this->Application->GetVar('m_wid');
$stack_name = rtrim('opener_stack_'.$wid, '_');
$opener_stack = $this->RecallVar($stack_name);
if ($opener_stack && $opener_stack != serialize(Array())) {
$opener_stack = unserialize($opener_stack);
list($index_file, $env) = explode('|', $opener_stack[count($opener_stack) - 1]);
$ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.ENV_VAR_NAME.'='.$env;
if ( getArrayValue($params,'escape') ) $ret = addslashes($ret);
if (isset($params['m_opener']) && $params['m_opener'] == 'u') {
array_pop($opener_stack);
if (!$opener_stack) {
$this->RemoveVar($stack_name);
// remove popups last templates, because popup is closing now
$this->RemoveVar('last_template_'.$wid);
$this->RemoveVar('last_template_popup_'.$wid);
// don't save popups last templates again :)
$this->SetVar('skip_last_template', 1);
}
else {
$this->StoreVar($stack_name, serialize($opener_stack));
}
/*// store window relations
$window_relations = $this->Application->RecallVar('window_relations');
$window_relations = $window_relations ? unserialize($window_relations) : Array ();
if (array_key_exists($wid, $window_relations)) {
unset($window_relations[$wid]);
$this->Application->StoreVar('window_relations', serialize($window_relations));
}*/
}
return $ret;
}
else {
//define('DBG_REDIRECT', 1);
$t = $this->GetVar('t');
}
}
$pass = isset($params['pass']) ? $params['pass'] : '';
$pass_events = isset($params['pass_events']) ? $params['pass_events'] : false; // pass events with url
$map_link = '';
if( isset($params['anchor']) )
{
$map_link = '#'.$params['anchor'];
unset($params['anchor']);
}
if ( isset($params['no_amp']) )
{
$params['__URLENCODE__'] = $params['no_amp'];
unset($params['no_amp']);
}
$no_rewrite = false;
if( isset($params['__NO_REWRITE__']) )
{
$no_rewrite = true;
unset($params['__NO_REWRITE__']);
}
$force_rewrite = false;
if( isset($params['__MOD_REWRITE__']) )
{
$force_rewrite = true;
unset($params['__MOD_REWRITE__']);
}
$force_no_sid = false;
if( isset($params['__NO_SID__']) )
{
$force_no_sid = true;
unset($params['__NO_SID__']);
}
// append pass through variables to each link to be build
// $params = array_merge_recursive2($this->getPassThroughVariables($params), $params);
$params = array_merge($this->getPassThroughVariables($params), $params);
if ($force_rewrite || ($this->RewriteURLs($ssl) && !$no_rewrite)) {
static $rewrite_listeners_done = false;
if (!$rewrite_listeners_done) {
$mod_rewrite_helper =& $this->recallObject('ModRewriteHelper');
/* @var $mod_rewrite_helper kModRewriteHelper */
$mod_rewrite_helper->initRewriteListeners();
$rewrite_listeners_done = true;
}
$session =& $this->recallObject('Session');
if ($session->NeedQueryString() && !$force_no_sid) {
$params['sid'] = $this->GetSID();
}
$url = $this->BuildEnv_NEW($t, $params, $pass, $pass_events);
$ret = $this->BaseURL($prefix, $ssl).$url.$map_link;
}
else {
unset($params['pass_category']); // we don't need to pass it when mod_rewrite is off
$env = $this->BuildEnv($t, $params, $pass, $pass_events);
$ret = $this->BaseURL($prefix, $ssl).$index_file.'?'.$env.$map_link;
}
return $ret;
}
/**
* Returns variables with values that should be passed throught with this link + variable list
*
* @param Array $params
* @return Array
*/
function getPassThroughVariables(&$params)
{
static $cached_pass_through = null;
if (isset($params['no_pass_through']) && $params['no_pass_through']) {
unset($params['no_pass_through']);
return Array();
}
// because pass through is not changed during script run, then we can cache it
if (is_null($cached_pass_through)) {
$cached_pass_through = Array();
$pass_through = $this->Application->GetVar('pass_through');
if ($pass_through) {
// names of variables to pass to each link
$cached_pass_through['pass_through'] = $pass_through;
$pass_through = explode(',', $pass_through);
foreach ($pass_through as $pass_through_var) {
$cached_pass_through[$pass_through_var] = $this->Application->GetVar($pass_through_var);
}
}
}
return $cached_pass_through;
}
/**
* Returns sorted array of passed prefixes (to build url from)
*
* @param string $pass
* @return Array
*/
function getPassInfo($pass = 'all')
{
if (!$pass) $pass = 'all';
$pass = trim(
preg_replace(
'/(?<=,|\\A)all(?=,|\\z)/',
trim($this->GetVar('passed'), ','),
trim($pass, ',')
),
',');
if (!$pass) {
return Array();
}
$pass_info = array_unique( explode(',', $pass) ); // array( prefix[.special], prefix[.special] ...
// we need to keep that sorting despite the sorting below, because this sorts prefixes with same priority by name
sort($pass_info, SORT_STRING); // to be prefix1,prefix1.special1,prefix1.special2,prefix3.specialX
foreach ($pass_info as $prefix) {
list($prefix_only) = explode('.', $prefix, 1);
$sorted[$prefix] = $this->getUnitOption($prefix_only, 'RewritePriority', 0);
}
arsort($sorted);
$pass_info = array_keys($sorted);
// ensure that "m" prefix is at the beginning
$main_index = array_search('m', $pass_info);
if ($main_index !== false) {
unset($pass_info[$main_index]);
array_unshift($pass_info, 'm');
}
return $pass_info;
}
function BuildEnv_NEW($t, $params, $pass='all', $pass_events = false)
{
// $session =& $this->recallObject('Session');
$force_admin = getArrayValue($params,'admin') || $this->GetVar('admin');
// if($force_admin) $sid = $this->GetSID();
$ret = '';
$env = '';
$encode = false;
if (isset($params['__URLENCODE__'])) {
$encode = $params['__URLENCODE__'];
unset($params['__URLENCODE__']);
}
if (isset($params['__SSL__'])) {
unset($params['__SSL__']);
}
$catalog_item_found = false;
$pass_info = $this->getPassInfo($pass);
if ($pass_info) {
if ($pass_info[0] == 'm') {
array_shift($pass_info);
}
$inject_parts = Array (); // url parts for beginning of url
$params['t'] = $t; // make template available for rewrite listeners
$params['pass_template'] = true; // by default we keep given template in resulting url
if (!array_key_exists('pass_category', $params)) {
$params['pass_category'] = false; // by default we don't keep categories in url
}
foreach ($pass_info as $pass_index => $pass_element) {
list ($prefix) = explode('.', $pass_element);
$catalog_item = $this->findModule('Var', $prefix) && $this->getUnitOption($prefix, 'CatalogItem');
if (array_key_exists($prefix, $this->RewriteListeners)) {
// if next prefix is same as current, but with special => exclude current prefix from url
$next_prefix = array_key_exists($pass_index + 1, $pass_info) ? $pass_info[$pass_index + 1] : false;
if ($next_prefix) {
$next_prefix = substr($next_prefix, 0, strlen($prefix) + 1);
if ($prefix . '.' == $next_prefix) {
continue;
}
}
// rewrited url part
$url_part = $this->BuildModuleEnv_NEW($pass_element, $params, $pass_events);
if (is_string($url_part) && $url_part) {
$ret .= $url_part . '/';
if ($catalog_item) {
// pass category later only for catalog items
$catalog_item_found = true;
}
}
elseif (is_array($url_part)) {
// rewrite listener want to insert something at the beginning of url too
if ($url_part[0]) {
$inject_parts[] = $url_part[0];
}
if ($url_part[1]) {
$ret .= $url_part[1] . '/';
}
if ($catalog_item) {
// pass category later only for catalog items
$catalog_item_found = true;
}
} elseif ($url_part === false) {
// rewrite listener decided not to rewrite given $pass_element
$env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events);
}
}
else {
$env .= ':' . $this->BuildModuleEnv($pass_element, $params, $pass_events);
}
}
if ($catalog_item_found || preg_match('/c\.[-\d]*/', implode(',', $pass_info))) {
// "c" prefix is present -> keep category
$params['pass_category'] = true;
}
$params['inject_parts'] = $inject_parts;
$ret = $this->BuildModuleEnv_NEW('m', $params, $pass_events) . '/' . $ret;
$cat_processed = array_key_exists('category_processed', $params) && $params['category_processed'];
// remove tempporary parameters used by listeners
unset($params['t'], $params['inject_parts'], $params['pass_template'], $params['pass_category'], $params['category_processed']);
if ($catalog_item_found || !$cat_processed || !defined('EXP_DIR_URLS')) {
// this catalog item detail page OR there is no category given
$ret = trim($ret, '/') . '.html';
}
else {
// url ends with "/" and not with ".html"
$ret = trim($ret, '/') . '/';
}
if ($env) {
$params[ENV_VAR_NAME] = ltrim($env, ':');
}
}
unset($params['pass'], $params['opener'], $params['m_event']);
if ($force_admin) {
$params['admin'] = 1;
}
if (array_key_exists('escape', $params) && $params['escape']) {
$ret = addslashes($ret);
unset($params['escape']);
}
$ret = str_replace('%2F', '/', urlencode($ret));
$params_str = '';
$join_string = $encode ? '&' : '&amp;';
foreach ($params as $param => $value) {
$params_str .= $join_string . $param . '=' . $value;
}
if ($params_str) {
$ret .= '?' . substr($params_str, strlen($join_string));
}
if ($encode) {
$ret = str_replace('\\', '%5C', $ret);
}
return $ret;
}
function BuildModuleEnv_NEW($prefix_special, &$params, $keep_events = false)
{
list ($prefix) = explode('.', $prefix_special);
$url_parts = Array ();
$listener = $this->RewriteListeners[$prefix];
$ret = $listener[0]->$listener[1](REWRITE_MODE_BUILD, $prefix_special, $params, $url_parts, $keep_events);
return $ret;
}
/**
* Builds env part that corresponds prefix passed
*
* @param string $prefix_special item's prefix & [special]
* @param Array $params url params
* @param bool $pass_events
*/
function BuildModuleEnv($prefix_special, &$params, $pass_events = false)
{
list($prefix) = explode('.', $prefix_special);
$query_vars = $this->getUnitOption($prefix, 'QueryString');
//if pass events is off and event is not implicity passed
if( !$pass_events && !isset($params[$prefix_special.'_event']) ) {
$params[$prefix_special.'_event'] = ''; // remove event from url if requested
//otherwise it will use value from get_var
}
if(!$query_vars) return '';
$tmp_string = Array(0 => $prefix_special);
foreach($query_vars as $index => $var_name)
{
//if value passed in params use it, otherwise use current from application
$var_name = $prefix_special.'_'.$var_name;
$tmp_string[$index] = isset( $params[$var_name] ) ? $params[$var_name] : $this->GetVar($var_name);
if ( isset($params[$var_name]) ) unset( $params[$var_name] );
}
$escaped = array();
foreach ($tmp_string as $tmp_val) {
$escaped[] = str_replace(Array('-',':'), Array('\-','\:'), $tmp_val);
}
$ret = implode('-', $escaped);
if ($this->getUnitOption($prefix, 'PortalStyleEnv') == true)
{
$ret = preg_replace('/^([a-zA-Z]+)-([0-9]+)-(.*)/','\\1\\2-\\3', $ret);
}
return $ret;
}
function BuildEnv($t, $params, $pass='all', $pass_events = false, $env_var = true)
{
$session =& $this->recallObject('Session');
$ssl = isset($params['__SSL__']) ? $params['__SSL__'] : 0;
$sid = $session->NeedQueryString() && !$this->RewriteURLs($ssl) ? $this->GetSID() : '';
// if (getArrayValue($params,'admin') == 1) $sid = $this->GetSID();
$ret = '';
if ($env_var) {
$ret = ENV_VAR_NAME.'=';
}
$ret .= $sid . '-'; // SID-TEMPLATE
$encode = false;
if (isset($params['__URLENCODE__'])) {
$encode = $params['__URLENCODE__'];
unset($params['__URLENCODE__']);
}
if (isset($params['__SSL__'])) {
unset($params['__SSL__']);
}
$env_string = '';
$category_id = isset($params['m_cat_id']) ? $params['m_cat_id'] : $this->GetVar('m_cat_id');
$item_id = false;
$pass_info = $this->getPassInfo($pass);
if ($pass_info) {
if ($pass_info[0] == 'm') array_shift($pass_info);
foreach ($pass_info as $pass_element) {
list($prefix) = explode('.', $pass_element);
$require_rewrite = $this->findModule('Var', $prefix);
if ($require_rewrite) {
$item_id = isset($params[$pass_element.'_id']) ? $params[$pass_element.'_id'] : $this->GetVar($pass_element.'_id');
}
$env_string .= ':'.$this->BuildModuleEnv($pass_element, $params, $pass_events);
}
}
if (strtolower($t) == '__default__') {
// to put category & item templates into cache
$filename = $this->getFilename('c', $category_id);
if (is_numeric($item_id)) {
$mod_rw_helper =& $this->Application->recallObject('ModRewriteHelper');
/* @var $mod_rw_helper kModRewriteHelper */
$t = $mod_rw_helper->GetItemTemplate($category_id, $pass_element); // $pass_element should be the last processed element
// $t = $this->getCache('item_templates', $category_id);
}
elseif ($category_id) {
$t = strtolower( preg_replace('/^Content\//i', '', $this->getCache('category_templates', $category_id)) );
}
else {
$t = 'index';
}
}
$ret .= $t.':'.$this->BuildModuleEnv('m', $params, $pass_events).$env_string;
unset($params['pass'], $params['opener'], $params['m_event']);
if ($this->GetVar('admin') && !isset($params['admin'])) {
$params['admin'] = 1;
if (!array_key_exists('editing_mode', $params)) {
$params['editing_mode'] = EDITING_MODE;
}
}
if (array_key_exists('escape', $params) && $params['escape']) {
$ret = addslashes($ret);
unset($params['escape']);
}
$join_string = $encode ? '&' : '&amp;';
$params_str = '';
foreach ($params as $param => $value)
{
$params_str .= $join_string.$param.'='.$value;
}
$ret .= $params_str;
if ($encode) {
$ret = str_replace('\\', '%5C', $ret);
}
return $ret;
}
function BaseURL($prefix='', $ssl=null)
{
if ($ssl === null) {
return PROTOCOL.SERVER_NAME.(defined('PORT')?':'.PORT : '').rtrim(BASE_PATH, '/').$prefix.'/';
}
else {
if ($ssl) {
$base_url = defined('ADMIN') && ADMIN ? $this->ConfigValue('AdminSSL_URL') : false;
if (!$base_url) {
$base_url = $this->ConfigValue('SSL_URL');
}
return rtrim($base_url, '/').$prefix.'/';
}
else {
return 'http://'.DOMAIN.(defined('PORT')?':'.PORT : '').rtrim( $this->ConfigValue('Site_Path'), '/').$prefix.'/';
}
}
}
function Redirect($t='', $params=null, $prefix='', $index_file=null)
{
$js_redirect = getArrayValue($params, 'js_redirect');
if (preg_match("/external:(.*)/", $t, $rets)) {
$location = $rets[1];
}
else {
if ($t == '' || $t === true) $t = $this->GetVar('t');
// pass prefixes and special from previous url
if( isset($params['js_redirect']) ) unset($params['js_redirect']);
if (!isset($params['pass'])) $params['pass'] = 'all';
if ($this->GetVar('ajax') == 'yes' && $t == $this->GetVar('t')) {
// redirects to the same template as current
$params['ajax'] = 'yes';
}
$params['__URLENCODE__'] = 1;
$location = $this->HREF($t, $prefix, $params, $index_file);
//echo " location : $location <br>";
}
$a_location = $location;
$location = "Location: $location";
if ($this->isDebugMode() && constOn('DBG_REDIRECT')) {
$this->Debugger->appendTrace();
echo "<b>Debug output above!!!</b> Proceed to redirect: <a href=\"$a_location\">$a_location</a><br>";
}
else {
if ($js_redirect) {
$this->SetVar('t', 'redirect');
$this->SetVar('redirect_to_js', addslashes($a_location) );
$this->SetVar('redirect_to', $a_location);
return true;
}
else {
if ($this->GetVar('ajax') == 'yes' && $t != $this->GetVar('t')) {
// redirection to other then current template during ajax request
echo '#redirect#'.$a_location;
}
elseif (headers_sent() != '') {
// some output occured -> redirect using javascript
echo '<script type="text/javascript">window.location.href = \''.$a_location.'\';</script>';
}
else {
// no output before -> redirect using HTTP header
// header('HTTP/1.1 302 Found');
header("$location");
}
}
}
ob_end_flush();
// session expiration is called from session initialization,
// that's why $this->Session may be not defined here
$session =& $this->Application->recallObject('Session');
/* @var $session Session */
$this->HandleEvent( new kEvent('adm:OnBeforeShutdown') );
$session->SaveData();
exit;
}
function Phrase($label, $allow_editing = true)
{
return $this->Phrases->GetPhrase($label, $allow_editing);
}
/**
* Replace language tags in exclamation marks found in text
*
* @param string $text
* @param bool $force_escape force escaping, not escaping of resulting string
* @return string
* @access public
*/
function ReplaceLanguageTags($text, $force_escape=null)
{
// !!!!!!!!
// if( !is_object($this->Phrases) ) $this->Debugger->appendTrace();
return $this->Phrases->ReplaceLanguageTags($text,$force_escape);
}
/**
* Checks if user is logged in, and creates
* user object if so. User object can be recalled
* later using "u.current" prefix_special. Also you may
* get user id by getting "u.current_id" variable.
*
* @access private
*/
function ValidateLogin()
{
$session =& $this->recallObject('Session');
$user_id = $session->GetField('PortalUserId');
if (!$user_id && $user_id != -1) $user_id = -2;
$this->SetVar('u.current_id', $user_id);
if (!$this->IsAdmin()) {
// needed for "profile edit", "registration" forms ON FRONT ONLY
$this->SetVar('u_id', $user_id);
}
$this->StoreVar('user_id', $user_id);
if ($this->GetVar('expired') == 1) {
// this parameter is set only from admin
$user =& $this->recallObject('u.current');
$user->SetError('ValidateLogin', 'session_expired', 'la_text_sess_expired');
}
if (($user_id != -2) && constOn('DBG_REQUREST_LOG') ) {
$http_query =& $this->recallObject('HTTPQuery');
$http_query->writeRequestLog(DBG_REQUREST_LOG);
}
if ($user_id != -2) {
// normal users + root
$this->LoadPersistentVars();
}
}
/**
* Loads current user persistent session data
*
*/
function LoadPersistentVars()
{
$this->Session->LoadPersistentVars();
}
function LoadCache() {
$cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->IsAdmin();
$query = sprintf("SELECT PhraseList, ConfigVariables FROM %s WHERE Template = %s",
TABLE_PREFIX.'PhraseCache',
$this->Conn->qstr(md5($cache_key)));
$res = $this->Conn->GetRow($query);
if ($res) {
$this->Caches['PhraseList'] = $res['PhraseList'] ? explode(',', $res['PhraseList']) : array();
$config_ids = $res['ConfigVariables'] ? explode(',', $res['ConfigVariables']) : array();
if (isset($this->Caches['ConfigVariables'])) {
$config_ids = array_diff($config_ids, $this->Caches['ConfigVariables']);
}
}
else {
$config_ids = array();
}
$this->Caches['ConfigVariables'] = $config_ids;
$this->ConfigCacheIds = $config_ids;
}
function UpdateCache()
{
$update = false;
//something changed
$update = $update || $this->Phrases->NeedsCacheUpdate();
$update = $update || (count($this->ConfigCacheIds) && $this->ConfigCacheIds != $this->Caches['ConfigVariables']);
if ($update) {
$cache_key = $this->GetVar('t').$this->GetVar('m_theme').$this->GetVar('m_lang').$this->IsAdmin();
$query = sprintf("REPLACE %s (PhraseList, CacheDate, Template, ConfigVariables)
VALUES (%s, %s, %s, %s)",
TABLE_PREFIX.'PhraseCache',
$this->Conn->Qstr(join(',', $this->Phrases->Ids)),
adodb_mktime(),
$this->Conn->Qstr(md5($cache_key)),
$this->Conn->qstr(implode(',', array_unique($this->ConfigCacheIds))));
$this->Conn->Query($query);
}
}
function InitConfig()
{
if (isset($this->Caches['ConfigVariables']) && count($this->Caches['ConfigVariables']) > 0) {
$this->ConfigHash = array_merge($this->ConfigHash, $this->Conn->GetCol(
'SELECT VariableValue, VariableName FROM '.TABLE_PREFIX.'ConfigurationValues
WHERE VariableId IN ('.implode(',', $this->Caches['ConfigVariables']).')', 'VariableName'));
}
}
/**
* Returns configuration option value by name
*
* @param string $name
* @return string
*/
function ConfigValue($name)
{
$res = array_key_exists($name, $this->ConfigHash) ? $this->ConfigHash[$name] : false;
if ($res !== false) {
return $res;
}
if (defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('ConfigurationValues')) {
return false;
}
$sql = 'SELECT VariableId, VariableValue
FROM '.TABLE_PREFIX.'ConfigurationValues
WHERE VariableName = '.$this->Conn->qstr($name);
$res = $this->Conn->GetRow($sql);
if ($res !== false) {
$this->ConfigHash[$name] = $res['VariableValue'];
$this->ConfigCacheIds[] = $res['VariableId'];
return $res['VariableValue'];
}
return false;
}
function UpdateConfigCache()
{
if ($this->ConfigCacheIds) {
}
}
/**
* Allows to process any type of event
*
* @param kEvent $event
* @access public
* @author Alex
*/
function HandleEvent(&$event, $params=null, $specificParams=null)
{
if ( isset($params) ) {
$event = new kEvent( $params, $specificParams );
}
if (!isset($this->EventManager)) {
$this->EventManager =& $this->recallObject('EventManager');
}
$this->EventManager->HandleEvent($event);
}
/**
* Registers new class in the factory
*
* @param string $real_class Real name of class as in class declaration
* @param string $file Filename in what $real_class is declared
* @param string $pseudo_class Name under this class object will be accessed using getObject method
* @param Array $dependecies List of classes required for this class functioning
* @access public
* @author Alex
*/
function registerClass($real_class, $file, $pseudo_class = null, $dependecies = Array() )
{
$this->Factory->registerClass($real_class, $file, $pseudo_class, $dependecies);
}
/**
* Add $class_name to required classes list for $depended_class class.
* All required class files are included before $depended_class file is included
*
* @param string $depended_class
* @param string $class_name
* @author Alex
*/
function registerDependency($depended_class, $class_name)
{
$this->Factory->registerDependency($depended_class, $class_name);
}
/**
* Registers Hook from subprefix event to master prefix event
*
* @param string $hookto_prefix
* @param string $hookto_special
* @param string $hookto_event
* @param string $mode
* @param string $do_prefix
* @param string $do_special
* @param string $do_event
* @param string $conditional
* @access public
* @todo take care of a lot parameters passed
* @author Kostja
*/
function registerHook($hookto_prefix, $hookto_special, $hookto_event, $mode, $do_prefix, $do_special, $do_event, $conditional)
{
$event_manager =& $this->recallObject('EventManager');
$event_manager->registerHook($hookto_prefix, $hookto_special, $hookto_event, $mode, $do_prefix, $do_special, $do_event, $conditional);
}
/**
* Allows one TagProcessor tag act as other TagProcessor tag
*
* @param Array $tag_info
* @author Kostja
*/
function registerAggregateTag($tag_info)
{
$aggregator =& $this->recallObject('TagsAggregator', 'kArray');
$aggregator->SetArrayValue($tag_info['AggregateTo'], $tag_info['AggregatedTagName'], Array($tag_info['LocalPrefix'], $tag_info['LocalTagName'], getArrayValue($tag_info, 'LocalSpecial')));
}
/**
* Returns object using params specified,
* creates it if is required
*
* @param string $name
* @param string $pseudo_class
* @param Array $event_params
* @return Object
* @author Alex
*/
function &recallObject($name,$pseudo_class=null,$event_params=Array())
{
$result =& $this->Factory->getObject($name, $pseudo_class, $event_params);
return $result;
}
/**
* Returns object using Variable number of params,
* all params starting with 4th are passed to object consturctor
*
* @param string $name
* @param string $pseudo_class
* @param Array $event_params
* @return Object
* @author Alex
*/
function &recallObjectP($name,$pseudo_class=null,$event_params=Array())
{
$func_args = func_get_args();
$result =& ref_call_user_func_array( Array(&$this->Factory, 'getObjectP'), $func_args );
return $result;
}
/**
* Returns tag processor for prefix specified
*
* @param string $prefix
* @return kDBTagProcessor
*/
function &recallTagProcessor($prefix)
{
$this->InitParser(); // because kDBTagProcesor is in NParser dependencies
$result =& $this->recallObject($prefix . '_TagProcessor');
return $result;
}
/**
* Checks if object with prefix passes was already created in factory
*
* @param string $name object presudo_class, prefix
* @return bool
* @author Kostja
*/
function hasObject($name)
{
return isset($this->Factory->Storage[$name]);
}
/**
* Removes object from storage by given name
*
* @param string $name Object's name in the Storage
* @author Kostja
*/
function removeObject($name)
{
$this->Factory->DestroyObject($name);
}
/**
* Get's real class name for pseudo class,
* includes class file and creates class
* instance
*
* @param string $pseudo_class
* @return Object
* @access public
* @author Alex
*/
function &makeClass($pseudo_class)
{
$func_args = func_get_args();
$result =& ref_call_user_func_array( Array(&$this->Factory, 'makeClass'), $func_args);
return $result;
}
/**
* Checks if application is in debug mode
*
* @param bool $check_debugger check if kApplication debugger is initialized too, not only for defined DEBUG_MODE constant
* @return bool
* @author Alex
* @access public
*/
function isDebugMode($check_debugger = true)
{
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
if ($check_debugger) {
$debug_mode = $debug_mode && is_object($this->Debugger);
}
return $debug_mode;
}
/**
* Checks if it is admin
*
* @return bool
* @author Alex
*/
function IsAdmin()
{
return constOn('ADMIN');
}
/**
* Apply url rewriting used by mod_rewrite or not
*
* @param bool $ssl Force ssl link to be build
* @return bool
*/
function RewriteURLs($ssl = false)
{
// case #1,#4:
// we want to create https link from http mode
// we want to create https link from https mode
// conditions: ($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')
// case #2,#3:
// we want to create http link from https mode
// we want to create http link from http mode
// conditions: !$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')
$allow_rewriting =
(!$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')) // always allow mod_rewrite for http
|| // or allow rewriting for redirect TO httpS or when already in httpS
(($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')); // but only if it's allowed in config!
return constOn('MOD_REWRITE') && $allow_rewriting;
}
/**
* Reads unit (specified by $prefix)
* option specified by $option
*
* @param string $prefix
* @param string $option
* @param mixed $default
* @return string
* @access public
* @author Alex
*/
function getUnitOption($prefix, $option, $default = false)
{
/*if (!isset($this->UnitConfigReader)) {
$this->UnitConfigReader =& $this->recallObject('kUnitConfigReader');
}*/
return $this->UnitConfigReader->getUnitOption($prefix, $option, $default);
}
/**
* Set's new unit option value
*
* @param string $prefix
* @param string $name
* @param string $value
* @author Alex
* @access public
*/
function setUnitOption($prefix, $option, $value)
{
// $unit_config_reader =& $this->recallObject('kUnitConfigReader');
return $this->UnitConfigReader->setUnitOption($prefix,$option,$value);
}
/**
* Read all unit with $prefix options
*
* @param string $prefix
* @return Array
* @access public
* @author Alex
*/
function getUnitOptions($prefix)
{
// $unit_config_reader =& $this->recallObject('kUnitConfigReader');
return $this->UnitConfigReader->getUnitOptions($prefix);
}
/**
* Returns true if config exists and is allowed for reading
*
* @param string $prefix
* @return bool
*/
function prefixRegistred($prefix)
{
/*if (!isset($this->UnitConfigReader)) {
$this->UnitConfigReader =& $this->recallObject('kUnitConfigReader');
}*/
return $this->UnitConfigReader->prefixRegistred($prefix);
}
/**
* Splits any mixing of prefix and
* special into correct ones
*
* @param string $prefix_special
* @return Array
* @access public
* @author Alex
*/
function processPrefix($prefix_special)
{
return $this->Factory->processPrefix($prefix_special);
}
/**
* Set's new event for $prefix_special
* passed
*
* @param string $prefix_special
* @param string $event_name
* @access public
*/
function setEvent($prefix_special,$event_name)
{
$event_manager =& $this->recallObject('EventManager');
$event_manager->setEvent($prefix_special,$event_name);
}
/**
* SQL Error Handler
*
* @param int $code
* @param string $msg
* @param string $sql
* @return bool
* @access private
* @author Alex
*/
function handleSQLError($code, $msg, $sql)
{
if ( isset($this->Debugger) )
{
$errorLevel = constOn('DBG_SQL_FAILURE') && !defined('IS_INSTALL') ? E_USER_ERROR : E_USER_WARNING;
$this->Debugger->appendTrace();
$error_msg = '<span class="debug_error">'.$msg.' ('.$code.')</span><br><a href="javascript:$Debugger.SetClipboard(\''.htmlspecialchars($sql).'\');"><b>SQL</b></a>: '.$this->Debugger->formatSQL($sql);
$long_id = $this->Debugger->mapLongError($error_msg);
trigger_error( mb_substr($msg.' ('.$code.') ['.$sql.']',0,1000).' #'.$long_id, $errorLevel);
return true;
}
else
{
//$errorLevel = constOn('IS_INSTALL') ? E_USER_WARNING : E_USER_ERROR;
$errorLevel = E_USER_WARNING;
trigger_error('<b>SQL Error</b> in sql: '.$sql.', code <b>'.$code.'</b> ('.$msg.')', $errorLevel);
/*echo '<b>xProcessing SQL</b>: '.$sql.'<br>';
echo '<b>Error ('.$code.'):</b> '.$msg.'<br>';*/
return $errorLevel == E_USER_ERROR ? false : true;
}
}
/**
* Default error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array $errcontext
*/
function handleError($errno, $errstr, $errfile = '', $errline = '', $errcontext = '')
{
if (defined('SILENT_LOG') && SILENT_LOG) {
if ( !(defined('DBG_IGNORE_STRICT_ERRORS') && DBG_IGNORE_STRICT_ERRORS && defined('E_STRICT') && ($errno == E_STRICT)) ) {
$fp = fopen(FULL_PATH.'/silent_log.txt','a');
$time = adodb_date('d/m/Y H:i:s');
fwrite($fp, '['.$time.'] #'.$errno.': '.strip_tags($errstr).' in ['.$errfile.'] on line '.$errline."\n");
fclose($fp);
}
}
$debug_mode = defined('DEBUG_MODE') && DEBUG_MODE;
$skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING;
if (!$this->errorHandlers || ($debug_mode && $skip_reporting)) {
// when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request)
$ignore_fatal_errors = defined('DBG_IGNORE_FATAL_ERRORS') && DBG_IGNORE_FATAL_ERRORS;
if (($errno == E_USER_ERROR) && !$ignore_fatal_errors) {
echo (' <div style="background-color: #FEFFBF; margin: auto; padding: 10px; border: 2px solid red; text-align: center">
<strong>Fatal Error: </strong>'."$errstr in $errfile on line $errline".'
</div>');
exit;
}
if (!$this->errorHandlers) {
return true;
}
}
$res = false;
$i = 0; // while (not foreach) because it is array of references in some cases
$eh_count = count($this->errorHandlers);
while ($i < $eh_count) {
if ( is_array($this->errorHandlers[$i]) ) {
$object =& $this->errorHandlers[$i][0];
$method = $this->errorHandlers[$i][1];
$res = $object->$method($errno, $errstr, $errfile, $errline, $errcontext);
}
else {
$function = $this->errorHandlers[$i];
$res = $function($errno, $errstr, $errfile, $errline, $errcontext);
}
$i++;
}
return $res;
}
/**
* Returns & blocks next ResourceId available in system
*
* @return int
* @access public
* @author Alex
*/
function NextResourceId()
{
$table_name = TABLE_PREFIX.'IdGenerator';
$this->Conn->Query('LOCK TABLES '.$table_name.' WRITE');
$this->Conn->Query('UPDATE '.$table_name.' SET lastid = lastid + 1');
$id = $this->Conn->GetOne('SELECT lastid FROM '.$table_name);
if($id === false)
{
$this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)');
$id = 2;
}
$this->Conn->Query('UNLOCK TABLES');
return $id - 1;
}
/**
* Returns genealogical main prefix for subtable prefix passes
* OR prefix, that has been found in REQUEST and some how is parent of passed subtable prefix
*
* @param string $current_prefix
* @param string $real_top if set to true will return real topmost prefix, regardless of its id is passed or not
* @return string
* @access public
* @author Kostja / Alex
*/
function GetTopmostPrefix($current_prefix, $real_top = false)
{
// 1. get genealogical tree of $current_prefix
$prefixes = Array ($current_prefix);
while ( $parent_prefix = $this->getUnitOption($current_prefix, 'ParentPrefix') ) {
if (!$this->prefixRegistred($parent_prefix)) {
// stop searching, when parent prefix is not registered
break;
}
$current_prefix = $parent_prefix;
array_unshift($prefixes, $current_prefix);
}
if ($real_top) {
return $current_prefix;
}
// 2. find what if parent is passed
$passed = explode(',', $this->GetVar('all_passed'));
foreach ($prefixes as $a_prefix) {
if (in_array($a_prefix, $passed)) {
return $a_prefix;
}
}
return $current_prefix;
}
/**
* Triggers email event of type Admin
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return unknown
*/
function &EmailEventAdmin($email_event_name, $to_user_id = -1, $send_params = false)
{
$event =& $this->EmailEvent($email_event_name, 1, $to_user_id, $send_params);
return $event;
}
/**
* Triggers email event of type User
*
* @param string $email_event_name
* @param int $to_user_id
* @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return unknown
*/
function &EmailEventUser($email_event_name, $to_user_id = -1, $send_params = false)
{
$event =& $this->EmailEvent($email_event_name, 0, $to_user_id, $send_params);
return $event;
}
/**
* Triggers general email event
*
* @param string $email_event_name
* @param int $email_event_type ( 0 for User, 1 for Admin)
* @param int $to_user_id
* @param array $send_params associative array of direct send params,
* possible keys: to_email, to_name, from_email, from_name, message, message_text
* @return unknown
*/
function &EmailEvent($email_event_name, $email_event_type, $to_user_id = -1, $send_params = false)
{
$params = array(
'EmailEventName' => $email_event_name,
'EmailEventToUserId' => $to_user_id,
'EmailEventType' => $email_event_type,
);
if ($send_params) {
$params['DirectSendParams'] = $send_params;
}
$event_str = isset($send_params['use_special']) ? 'emailevents.'.$send_params['use_special'].':OnEmailEvent' : 'emailevents:OnEmailEvent';
$this->HandleEvent($event, $event_str, $params);
return $event;
}
/**
* Allows to check if user in this session is logged in or not
*
* @return bool
*/
function LoggedIn()
{
// no session during expiration process
return is_null($this->Session) ? false : $this->Session->LoggedIn();
}
/**
* Check current user permissions based on it's group permissions in specified category
*
* @param string $name permission name
* @param int $cat_id category id, current used if not specified
* @param int $type permission type {1 - system, 0 - per category}
* @return int
*/
function CheckPermission($name, $type = 1, $cat_id = null)
{
$perm_helper =& $this->recallObject('PermissionsHelper');
return $perm_helper->CheckPermission($name, $type, $cat_id);
}
/**
* Set's any field of current visit
*
* @param string $field
* @param mixed $value
*/
function setVisitField($field, $value)
{
$visit =& $this->recallObject('visits');
$visit->SetDBField($field, $value);
$visit->Update();
}
/**
* Allows to check if in-portal is installed
*
* @return bool
*/
function isInstalled()
{
return $this->InitDone && (count($this->ModuleInfo) > 0);
}
/**
* Allows to determine if module is installed & enabled
*
* @param string $module_name
* @return bool
*/
function isModuleEnabled($module_name)
{
return $this->findModule('Name', $module_name) !== false;
}
function reportError($class, $method)
{
$this->Debugger->appendTrace();
trigger_error('depricated method <b>'.$class.'->'.$method.'(...)</b>', E_USER_ERROR);
}
/**
* Returns Window ID of passed prefix main prefix (in edit mode)
*
* @param string $prefix
* @return mixed
*/
function GetTopmostWid($prefix)
{
$top_prefix = $this->GetTopmostPrefix($prefix);
$mode = $this->GetVar($top_prefix.'_mode');
return $mode != '' ? substr($mode, 1) : '';
}
/**
* Get temp table name
*
* @param string $table
* @param mixed $wid
* @return string
*/
function GetTempName($table, $wid = '')
{
if (preg_match('/prefix:(.*)/', $wid, $regs)) {
$wid = $this->GetTopmostWid($regs[1]);
}
return TABLE_PREFIX.'ses_'.$this->GetSID().($wid ? '_'.$wid : '').'_edit_'.$table;
}
function GetTempTablePrefix($wid = '')
{
if (preg_match('/prefix:(.*)/', $wid, $regs)) {
$wid = $this->GetTopmostWid($regs[1]);
}
return TABLE_PREFIX.'ses_'.$this->GetSID().($wid ? '_'.$wid : '').'_edit_';
}
function IsTempTable($table)
{
return preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$table);
}
/**
* Checks, that given prefix is in temp mode
*
* @param string $prefix
* @return bool
*/
function IsTempMode($prefix, $special = '')
{
$top_prefix = $this->Application->GetTopmostPrefix($prefix);
$var_names = Array (
$top_prefix,
rtrim($top_prefix . '_' . $special, '_'), // from post
rtrim($top_prefix . '.' . $special, '.'), // assembled locally
);
$var_names = array_unique($var_names);
$temp_mode = false;
foreach ($var_names as $var_name) {
$value = $this->Application->GetVar($var_name . '_mode');
if ($value && (substr($value, 0, 1) == 't')) {
$temp_mode = true;
break;
}
}
return $temp_mode;
}
/**
* Return live table name based on temp table name
*
* @param string $temp_table
* @return string
*/
function GetLiveName($temp_table)
{
if( preg_match('/'.TABLE_PREFIX.'ses_'.$this->GetSID().'(_[\d]+){0,1}_edit_(.*)/',$temp_table, $rets) )
{
// cut wid from table end if any
return $rets[2];
}
else
{
return $temp_table;
}
}
function CheckProcessors($processors)
{
foreach ($processors as $a_processor)
{
if (!isset($this->CachedProcessors[$a_processor])) {
$this->CachedProcessors[$a_processor] =& $this->recallObject($a_processor.'_TagProcessor');
}
}
}
function TimeZoneAdjustment($time_zone = null)
{
if ($time_zone == 'GMT') {
return (-1) * adodb_date('Z');
}
$target_zone = isset($time_zone) ? $time_zone : $this->ConfigValue('Config_Site_Time');
return 3600 * ($target_zone - $this->ConfigValue('Config_Server_Time'));
}
function ApplicationDie($message = '')
{
$message = ob_get_clean().$message;
if ($this->isDebugMode()) {
$message .= $this->Debugger->printReport(true);
}
echo $this->UseOutputCompression() ? gzencode($message, DBG_COMPRESSION_LEVEL) : $message;
exit;
}
/* moved from MyApplication */
function getUserGroups($user_id)
{
switch($user_id)
{
case -1:
$user_groups = $this->ConfigValue('User_LoggedInGroup');
break;
case -2:
$user_groups = $this->ConfigValue('User_LoggedInGroup');
$user_groups .= ','.$this->ConfigValue('User_GuestGroup');
break;
default:
$sql = 'SELECT GroupId FROM '.TABLE_PREFIX.'UserGroup WHERE PortalUserId = '.$user_id;
$res = $this->Conn->GetCol($sql);
$user_groups = Array( $this->ConfigValue('User_LoggedInGroup') );
if(is_array($res))
{
$user_groups = array_merge($user_groups, $res);
}
$user_groups = implode(',', $user_groups);
}
return $user_groups;
}
/**
* Allows to detect if page is browsed by spider (293 agents supported)
*
* @return bool
*/
function IsSpider()
{
static $is_spider = null;
if (!isset($is_spider)) {
$user_agent = trim($_SERVER['HTTP_USER_AGENT']);
$robots = file(FULL_PATH.'/core/robots_list.txt');
foreach ($robots as $robot_info) {
$robot_info = explode("\t", $robot_info, 3);
if ($user_agent == trim($robot_info[2])) {
$is_spider = true;
break;
}
}
}
return $is_spider;
}
/**
* Allows to detect table's presense in database
*
* @param string $table_name
* @return bool
*/
function TableFound($table_name)
{
return $this->Conn->TableFound($table_name);
}
/**
* Returns counter value
*
* @param string $name counter name
* @param Array $params counter parameters
* @param string $query_name specify query name directly (don't generate from parmeters)
* @param bool $multiple_results
* @return mixed
*/
function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false)
{
$count_helper =& $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
return $count_helper->getCounter($name, $params, $query_name, $multiple_results);
}
/**
* Resets counter, whitch are affected by one of specified tables
*
* @param string $tables comma separated tables list used in counting sqls
*/
function resetCounters($tables)
{
if (constOn('IS_INSTALL')) {
return ;
}
$count_helper =& $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
return $count_helper->resetCounters($tables);
}
/**
* Sends XML header + optionally displays xml heading
*
* @param string $xml_version
* @return string
* @author Alex
*/
function XMLHeader($xml_version = false)
{
$lang =& $this->recallObject('lang.current');
header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
return $xml_version ? '<?xml version="'.$xml_version.'" encoding="'.$lang->GetDBField('Charset').'"?>' : '';
}
/**
* Returns category tree
*
* @param int $category_id
* @return Array
*/
function getTreeIndex($category_id)
{
$category_template = $this->getFilename('c', $category_id); // to rebuild "category_tree" cache
$tree_index = $this->getCache('category_tree', $category_id);
if ($tree_index) {
$ret = Array ();
list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index);
return $ret;
}
return false;
}
}
\ No newline at end of file
Index: branches/5.0.x/core/units/sections/site_config_tp.php
===================================================================
--- branches/5.0.x/core/units/sections/site_config_tp.php (revision 12342)
+++ branches/5.0.x/core/units/sections/site_config_tp.php (revision 12343)
@@ -1,61 +1,61 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
- class SiteConfigTagProcessor extends TagProcessor {
+ class SiteConfigTagProcessor extends kTagProcessor {
function PrintEditingModes($params)
{
$editing_modes = Array (
EDITING_MODE_BROWSE => Array ('image' => 'show_structure', 'title' => 'Browse Mode'),
EDITING_MODE_CONTENT => Array ('image' => 'content_mode', 'title' => 'Content Mode'),
EDITING_MODE_DESIGN => Array ('image' => 'show_all', 'title' => 'Design Mode'),
);
$preset_name = $this->Application->ConfigValue('AdminConsoleInterface');
$base_path = FULL_PATH . ADMIN_DIRECTORY . '/system_presets/' . $preset_name;
if (file_exists($base_path . DIRECTORY_SEPARATOR . 'settings.php')) {
include_once $base_path . DIRECTORY_SEPARATOR . 'settings.php'; // will get $visible_editing_modes
foreach ($editing_modes as $editing_mode => $data) {
if (!in_array($editing_mode, $visible_editing_modes)) {
unset($editing_modes[$editing_mode]);
}
}
if (count($editing_modes) == 1) {
// don't show buttons, when there only one left
return '';
}
}
$ret = '';
$i = 1;
$count = count($editing_modes);
$block_params = Array ('name' => $params['render_as']);
foreach ($editing_modes as $editing_mode => $data) {
$block_params = array_merge($block_params, $data);
$block_params['editing_mode'] = $editing_mode;
$block_params['is_last'] = $i == $count;
$ret .= $this->Application->ParseBlock($block_params);
$i++;
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php
===================================================================
--- branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php (nonexistent)
+++ branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php (revision 12343)
@@ -0,0 +1,1444 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.net/license/ for copyright notices and details.
+*/
+
+ defined('FULL_PATH') or die('restricted access!');
+
+ define('EXPORT_STEP', 100); // export by 200 items (e.g. links)
+ define('IMPORT_STEP', 20); // export by 200 items (e.g. links)
+ define('IMPORT_CHUNK', 10240); // 10240); //30720); //50120); // 5 KB
+
+ define('IMPORT_TEMP', 1);
+ define('IMPORT_LIVE', 2);
+
+ class kCatDBItemExportHelper extends kHelper {
+
+ var $false = false;
+
+ var $cache = Array();
+
+ /**
+ * Allows to find out what items are new in cache
+ *
+ * @var Array
+ */
+ var $cacheStatus = Array();
+
+ var $cacheTable = '';
+
+ var $exportFields = Array();
+
+ /**
+ * Export options
+ *
+ * @var Array
+ */
+ var $exportOptions = Array();
+
+ /**
+ * Item beeing currenly exported
+ *
+ * @var kCatDBItem
+ */
+ var $curItem = null;
+
+ /**
+ * Dummy category object
+ *
+ * @var CategoriesItem
+ */
+ var $dummyCategory = null;
+
+ /**
+ * Pointer to opened file
+ *
+ * @var resource
+ */
+ var $filePointer = null;
+
+ /**
+ * Custom fields definition of current item
+ *
+ * @var Array
+ */
+ var $customFields = Array();
+
+ function kCatDBItemExportHelper()
+ {
+ parent::kHelper();
+ $this->cacheTable = TABLE_PREFIX.'ImportCache';
+ }
+
+ /**
+ * Returns value from cache if found or false otherwise
+ *
+ * @param string $type
+ * @param int $key
+ * @return mixed
+ */
+ function getFromCache($type, $key)
+ {
+ return getArrayValue($this->cache, $type, $key);
+ }
+
+ /**
+ * Adds value to be cached
+ *
+ * @param string $type
+ * @param int $key
+ * @param mixed $value
+ */
+ function addToCache($type, $key, $value, $is_new = true)
+ {
+// if (!isset($this->cache[$type])) $this->cache[$type] = Array();
+ $this->cache[$type][$key] = $value;
+ if ($is_new) {
+ $this->cacheStatus[$type][$key] = true;
+ }
+ }
+
+ function storeCache($cache_types)
+ {
+ $cache_types = explode(',', $cache_types);
+
+ $values_sql = '';
+ foreach ($cache_types as $cache_type) {
+ $sql_mask = '('.$this->Conn->qstr($cache_type).',%s,%s),';
+ $cache = getArrayValue($this->cacheStatus, $cache_type);
+ if (!$cache) $cache = Array();
+ foreach ($cache as $var_name => $cache_status) {
+ $var_value = $this->cache[$cache_type][$var_name];
+ $values_sql .= sprintf($sql_mask, $this->Conn->qstr($var_name), $this->Conn->qstr($var_value) );
+ }
+ }
+ $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql);
+ if ($values_sql) {
+ $sql = 'INSERT INTO '.$this->cacheTable.'(`CacheName`,`VarName`,`VarValue`) VALUES '.$values_sql;
+ $this->Conn->Query($sql);
+ }
+
+ }
+
+ function loadCache()
+ {
+ $sql = 'SELECT * FROM '.$this->cacheTable;
+ $records = $this->Conn->Query($sql);
+
+ $this->cache = Array();
+ foreach ($records as $record) {
+ $this->addToCache($record['CacheName'], $record['VarName'], $record['VarValue'], false);
+ }
+ }
+
+ /**
+ * Fill required fields with dummy values
+ *
+ * @param kEvent $event
+ */
+ function fillRequiredFields(&$event, &$object, $set_status = false)
+ {
+ if ($object == $this->false) {
+ $object =& $event->getObject();
+ }
+
+ $has_empty = false;
+ $fields = array_keys($object->Fields);
+ foreach ($fields as $field_name)
+ {
+ $field_options =& $object->Fields[$field_name];
+ if (isset($object->VirtualFields[$field_name]) || !getArrayValue($field_options, 'required') ) continue;
+ if ( $object->GetDBField($field_name) ) continue;
+
+ $formatter_class = getArrayValue($field_options, 'formatter');
+ if ($formatter_class) // not tested
+ {
+ $formatter =& $this->Application->recallObject($formatter_class);
+ $sample_value = $formatter->GetSample($field_name, $field_options, $object);
+ }
+
+ $has_empty = true;
+ $object->SetField($field_name, isset($sample_value) && $sample_value ? $sample_value : 'no value');
+ }
+ $object->UpdateFormattersSubFields();
+
+ if ($set_status && $has_empty) {
+ $object->SetDBField('Status', 0);
+ }
+ }
+
+ /**
+ * Verifies that all user entered export params are correct
+ *
+ * @param kEvent $event
+ */
+ function verifyOptions(&$event)
+ {
+ if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid'))
+ {
+ $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 0);
+ return false;
+ }
+
+ $this->fillRequiredFields($event, $this->false);
+
+ $object =& $event->getObject();
+ $cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy');
+ if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field
+ {
+ $object->setRequired('CategorySeparator', true);
+ $cross_unique_fields[] = 'CategorySeparator';
+ }
+
+ $ret = $object->Validate();
+
+ // check if cross unique fields has no same values
+ foreach ($cross_unique_fields as $field_index => $field_name)
+ {
+ if (getArrayValue($object->FieldErrors, $field_name, 'pseudo') == 'required') continue;
+
+ $check_fields = $cross_unique_fields;
+ unset($check_fields[$field_index]);
+
+ foreach ($check_fields as $check_field)
+ {
+ if ($object->GetDBField($field_name) == $object->GetDBField($check_field))
+ {
+ $object->SetError($check_field, 'unique');
+ }
+ }
+ }
+
+ if ($event->Special == 'import')
+ {
+ $this->exportOptions = $this->loadOptions($event);
+
+ $automatic_fields = ($object->GetDBField('FieldTitles') == 1);
+ $object->setRequired('ExportColumns', !$automatic_fields);
+ $category_prefix = '__CATEGORY__';
+ if ( $automatic_fields && ($this->exportOptions['SkipFirstRow']) ) {
+ $this->openFile($event);
+ $this->exportOptions['ExportColumns'] = $this->readRecord();
+
+ if (!$this->exportOptions['ExportColumns']) {
+ $this->exportOptions['ExportColumns'] = Array ();
+ }
+
+ $this->closeFile();
+
+ // remove additional (non-parseble columns)
+ foreach ($this->exportOptions['ExportColumns'] as $field_index => $field_name) {
+ if (!$this->validateField($field_name, $object)) {
+ unset($this->exportOptions['ExportColumns'][$field_index]);
+ }
+ }
+ $category_prefix = '';
+ }
+
+ // 1. check, that we have column definitions
+ if (!$this->exportOptions['ExportColumns']) {
+ $object->setError('ExportColumns', 'required');
+ $ret = false;
+ }
+ else {
+ // 1.1. check that all required fields are present in imported file
+ $missing_columns = Array();
+ foreach ($object->Fields as $field_name => $field_options) {
+ if ($object->skipField($field_name)) continue;
+ if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) {
+ $missing_columns[] = $field_name;
+ $object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing');
+ $ret = false;
+ }
+ }
+
+ if (!$ret && $this->Application->isDebugMode()) {
+ $this->Application->Debugger->appendHTML('Missing required for import/export:');
+ $this->Application->Debugger->dumpVars($missing_columns);
+ }
+ }
+
+
+ // 2. check, that we have only mixed category field or only separated category fields
+ $category_found['mixed'] = false;
+ $category_found['separated'] = false;
+
+ foreach ($this->exportOptions['ExportColumns'] as $import_field) {
+ if (preg_match('/^'.$category_prefix.'Category(Path|[0-9]+)/', $import_field, $rets)) {
+ $category_found[$rets[1] == 'Path' ? 'mixed' : 'separated'] = true;
+ }
+ }
+ if ($category_found['mixed'] && $category_found['separated']) {
+ $object->SetError('ExportColumns', 'unique_category', 'la_error_unique_category_field');
+ $ret = false;
+ }
+
+ // 3. check, that duplicates check fields are selected & present in imported fields
+ if ($this->exportOptions['ReplaceDuplicates']) {
+ if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
+ $check_fields = Array($object->IDField);
+ }
+ else {
+ $check_fields = $this->exportOptions['DuplicateCheckFields'] ? explode('|', substr($this->exportOptions['DuplicateCheckFields'], 1, -1)) : Array();
+ $object =& $event->getObject();
+
+ $language_id = $this->Application->GetDefaultLanguageId();
+ foreach ($check_fields as $index => $check_field) {
+ foreach ($object->Fields as $field_name => $field_options) {
+ if ($field_name == 'l'.$language_id.'_'.$check_field) {
+ $check_fields[$index] = 'l'.$language_id.'_'.$check_field;
+ break;
+ }
+ }
+ }
+ }
+ $this->exportOptions['DuplicateCheckFields'] = $check_fields;
+
+ if (!$check_fields) {
+ $object->setError('CheckDuplicatesMethod', 'required');
+ $ret = false;
+ }
+ else {
+ foreach ($check_fields as $check_field) {
+ $check_field = preg_replace('/^cust_(.*)/', 'Custom_\\1', $check_field);
+ if (!in_array($check_field, $this->exportOptions['ExportColumns'])) {
+ $object->setError('ExportColumns', 'required');
+ $ret = false;
+ break;
+ }
+ }
+ }
+ }
+ $this->saveOptions($event);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Returns filename to read import data from
+ *
+ * @return string
+ */
+ function getImportFilename()
+ {
+ if ($this->exportOptions['ImportSource'] == 1)
+ {
+ $ret = $this->exportOptions['ImportFilename']; // ['name']; commented by Kostja
+ }
+ else {
+ $ret = $this->exportOptions['ImportLocalFilename'];
+ }
+ return EXPORT_PATH.'/'.$ret;
+ }
+
+ /**
+ * Returns filename to write export data to
+ *
+ * @return string
+ */
+ function getExportFilename()
+ {
+ return EXPORT_PATH.'/'.$this->exportOptions['ExportFilename'].'.'.$this->getFileExtension();
+ }
+
+ /**
+ * Opens file required for export/import operations
+ *
+ * @param kEvent $event
+ */
+ function openFile(&$event)
+ {
+ if ($event->Special == 'export') {
+ $write_mode = ($this->exportOptions['start_from'] == 0) ? 'w' : 'a';
+ $this->filePointer = fopen($this->getExportFilename(), $write_mode);
+ }
+ else {
+ $this->filePointer = fopen($this->getImportFilename(), 'r');
+ }
+
+ // skip UTF-8 BOM Modifier
+ $first_chars = fread($this->filePointer, 3);
+ if (bin2hex($first_chars) != 'efbbbf') {
+ fseek($this->filePointer, 0);
+ }
+ }
+
+ /**
+ * Closes opened file
+ *
+ */
+ function closeFile()
+ {
+ fclose($this->filePointer);
+ }
+
+ function getCustomSQL()
+ {
+ $ml_formatter =& $this->Application->recallObject('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.', ';
+ }
+
+ return preg_replace('/(.*), /', '\\1', $custom_sql);
+ }
+
+ function getPlainExportSQL($count_only = false) {
+ if ($count_only && isset($this->exportOptions['ForceCountSQL'])) {
+ $sql = $this->exportOptions['ForceCountSQL'];
+ }
+ elseif (!$count_only && isset($this->exportOptions['ForceSelectSQL'])) {
+ $sql = $this->exportOptions['ForceSelectSQL'];
+ }
+ else {
+ $items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List');
+ $items_list->SetPerPage(-1);
+
+ if ($options['export_ids'] != '') {
+ $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')');
+ }
+
+ if ($count_only) {
+ $sql = $items_list->getCountSQL( $items_list->GetSelectSQL(true,false) );
+ }
+ else {
+ $sql = $items_list->GetSelectSQL();
+ }
+ }
+
+ if (!$count_only)
+ {
+ $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
+ }
+// else {
+// $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
+// }
+
+ return $sql;
+ }
+
+ function getExportSQL($count_only = false)
+ {
+ if (!$this->Application->getUnitOption($this->curItem->Prefix, 'CatalogItem')) {
+ return $this->GetPlainExportSQL($count_only); // in case this is not a CategoryItem
+ }
+
+ if ($this->exportOptions['export_ids'] === false)
+ {
+ // get links from current category & all it's subcategories
+ $join_clauses = Array();
+
+ $custom_sql = $this->getCustomSQL();
+ if ($custom_sql) {
+ $custom_table = $this->Application->getUnitOption($this->curItem->Prefix.'-cdata', 'TableName');
+ $join_clauses[$custom_table.' custom_data'] = 'custom_data.ResourceId = item_table.ResourceId';
+ }
+
+ $join_clauses[TABLE_PREFIX.'CategoryItems ci'] = 'ci.ItemResourceId = item_table.ResourceId';
+ $join_clauses[TABLE_PREFIX.'Category c'] = 'c.CategoryId = ci.CategoryId';
+
+ $sql = 'SELECT item_table.*, ci.CategoryId'.($custom_sql ? ', '.$custom_sql : '').'
+ FROM '.$this->curItem->TableName.' item_table';
+
+ foreach ($join_clauses as $table_name => $join_expression) {
+ $sql .= ' LEFT JOIN '.$table_name.' ON '.$join_expression;
+ }
+ $sql .= ' WHERE ';
+
+ if ($this->exportOptions['export_cats_ids'][0] == 0)
+ {
+ $sql .= '1';
+ }
+ else {
+ foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
+ $sql .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
+ }
+ $sql = preg_replace('/(.*) OR $/', '\\1', $sql);
+ }
+
+ $sql .= ' ORDER BY ci.PrimaryCat DESC'; // NEW
+ }
+ else {
+ // get only selected links
+ $sql = 'SELECT item_table.*, '.$this->exportOptions['export_cats_ids'][0].' AS CategoryId
+ FROM '.$this->curItem->TableName.' item_table
+ WHERE '.$this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
+ }
+
+ if (!$count_only)
+ {
+ $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
+ }
+ else {
+ $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
+ }
+
+ return $sql;
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function performExport(&$event)
+ {
+ $this->exportOptions = $this->loadOptions($event);
+ $this->exportFields = $this->exportOptions['ExportColumns'];
+ $this->curItem =& $event->getObject( Array('skip_autoload' => true) );
+ $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
+ $this->openFile($event);
+
+ if ($this->exportOptions['start_from'] == 0) // first export step
+ {
+ if (!getArrayValue($this->exportOptions, 'IsBaseCategory')) {
+ $this->exportOptions['IsBaseCategory'] = 0;
+ }
+
+ if ($this->exportOptions['IsBaseCategory'] ) {
+ $sql = 'SELECT ParentPath
+ FROM '.TABLE_PREFIX.'Category
+ WHERE CategoryId = '.$this->Application->GetVar('m_cat_id');
+ $parent_path = $this->Conn->GetOne($sql);
+ $parent_path = explode('|', substr($parent_path, 1, -1));
+ if ($parent_path && $parent_path[0] == $this->Application->findModule('Name', 'Core', 'RootCat')) {
+ array_shift($parent_path);
+ }
+
+ $this->exportOptions['BaseLevel'] = count($parent_path); // level to cut from other categories
+ }
+
+ // 1. export field titles if required
+ if ($this->exportOptions['IncludeFieldTitles'])
+ {
+ $data_array = Array();
+ foreach ($this->exportFields as $export_field)
+ {
+ $data_array = array_merge($data_array, $this->getFieldCaption($export_field));
+ }
+ $this->writeRecord($data_array);
+ }
+ $this->exportOptions['total_records'] = $this->Conn->GetOne( $this->getExportSQL(true) );
+ }
+
+ // 2. export data
+ $records = $this->Conn->Query( $this->getExportSQL() );
+ $records_exported = 0;
+ foreach ($records as $record_info) {
+ $this->curItem->Clear();
+ $this->curItem->SetDBFieldsFromHash($record_info);
+ $this->setCurrentID();
+ $this->curItem->raiseEvent('OnAfterItemLoad', $this->curItem->GetID() );
+
+ $data_array = Array();
+ foreach ($this->exportFields as $export_field)
+ {
+ $data_array = array_merge($data_array, $this->getFieldValue($export_field) );
+ }
+ $this->writeRecord($data_array);
+ $records_exported++;
+ }
+ $this->closeFile();
+
+ $this->exportOptions['start_from'] += $records_exported;
+ $this->saveOptions($event);
+
+ return $this->exportOptions;
+ }
+
+ function getItemFields()
+ {
+ // just in case dummy user selected automtic mode & moved columns too :(
+ return array_merge($this->curItem->Fields['AvailableColumns']['options'], $this->curItem->Fields['ExportColumns']['options']);
+ }
+
+ /**
+ * Checks if field really belongs to importable field list
+ *
+ * @param string $field_name
+ * @param kCatDBItem $object
+ * @return bool
+ */
+ function validateField($field_name, &$object)
+ {
+ // 1. convert custom field
+ $field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name);
+
+ // 2. convert category field (mixed version & serparated version)
+ $field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name);
+
+ $valid_fields = $object->getPossibleExportColumns();
+ return isset($valid_fields[$field_name]) || isset($valid_fields['__VIRTUAL__'.$field_name]);
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function performImport(&$event)
+ {
+ if (!$this->exportOptions) {
+ // load import options in case if not previously loaded in verification function
+ $this->exportOptions = $this->loadOptions($event);
+ }
+
+ $backup_category_id = $this->Application->GetVar('m_cat_id');
+ $this->Application->SetVar('m_cat_id', (int)$this->Application->RecallVar('ImportCategory') );
+
+ $this->openFile($event);
+
+ $bytes_imported = 0;
+ if ($this->exportOptions['start_from'] == 0) // first export step
+ {
+ // 1st time run
+ if ($this->exportOptions['SkipFirstRow']) {
+ $this->readRecord();
+ $this->exportOptions['start_from'] = ftell($this->filePointer);
+ $bytes_imported = ftell($this->filePointer);
+ }
+
+ $current_category_id = $this->Application->GetVar('m_cat_id');
+ if ($current_category_id > 0) {
+ $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$current_category_id;
+ $this->exportOptions['ImportCategoryPath'] = $this->Conn->GetOne($sql);
+ }
+ else {
+ $this->exportOptions['ImportCategoryPath'] = '';
+ }
+ $this->exportOptions['total_records'] = filesize($this->getImportFilename());
+ }
+ else {
+ $this->loadCache();
+ }
+
+ $this->exportFields = $this->exportOptions['ExportColumns'];
+ $this->addToCache('category_parent_path', $this->Application->GetVar('m_cat_id'), $this->exportOptions['ImportCategoryPath']);
+
+ // 2. import data
+ $this->dummyCategory =& $this->Application->recallObject('c.-tmpitem', 'c', Array('skip_autoload' => true));
+ fseek($this->filePointer, $this->exportOptions['start_from']);
+
+ $items_processed = 0;
+ while (($bytes_imported < IMPORT_CHUNK && $items_processed < IMPORT_STEP) && !feof($this->filePointer)) {
+ $data = $this->readRecord();
+ if ($data) {
+ if ($this->exportOptions['ReplaceDuplicates']) {
+ // set fields used as keys for replace duplicates code
+ $this->resetImportObject($event, IMPORT_TEMP, $data);
+ }
+
+ $this->processCurrentItem($event, $data);
+ }
+ $bytes_imported = ftell($this->filePointer) - $this->exportOptions['start_from'];
+ $items_processed++;
+ }
+
+ $this->closeFile();
+ $this->Application->SetVar('m_cat_id', $backup_category_id);
+
+ $this->exportOptions['start_from'] += $bytes_imported;
+ $this->storeCache('new_ids');
+
+ $this->saveOptions($event);
+
+ if ($this->exportOptions['start_from'] == $this->exportOptions['total_records']) {
+ $this->Conn->Query('TRUNCATE TABLE '.$this->cacheTable);
+ }
+
+ return $this->exportOptions;
+ }
+
+ function setCurrentID()
+ {
+ $this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) );
+ }
+
+ function setFieldValue($field_index, $value)
+ {
+ if (empty($value)) {
+ $value = null;
+ }
+
+ $field_name = getArrayValue($this->exportFields, $field_index);
+ if ($field_name == 'ResourceId') {
+ return false;
+ }
+
+ 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 (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, 11) == '__VIRTUAL__') {
+ $field_name = substr($field_name, 11);
+ $this->curItem->SetField($field_name, $value);
+ }
+ else {
+ $this->curItem->SetField($field_name, $value);
+ }
+
+ $pseudo_error = getArrayValue($this->curItem->FieldErrors, $field_name, 'pseudo');
+ if ($pseudo_error) {
+ $this->curItem->SetDBField($field_name, null);
+ unset($this->curItem->FieldErrors[$field_name]);
+ }
+ }
+
+ function resetImportObject(&$event, $object_type, $record_data = null)
+ {
+ switch ($object_type) {
+ case IMPORT_TEMP:
+ $this->curItem =& $event->getObject( Array('skip_autoload' => true) );
+ break;
+
+ case IMPORT_LIVE:
+ $this->curItem =& $this->Application->recallObject($event->Prefix.'.-tmpitem'.$event->Special, $event->Prefix, Array('skip_autoload' => true));
+ break;
+ }
+ $this->curItem->Clear();
+ $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
+
+ if (isset($record_data)) {
+ $this->setImportData($record_data);
+ }
+ }
+
+ function setImportData($record_data)
+ {
+ foreach ($record_data as $field_index => $field_value) {
+ $this->setFieldValue($field_index, $field_value);
+ }
+ $this->setCurrentID();
+ }
+
+
+ function getItemCategory()
+ {
+ static $lang_prefix = null;
+ $backup_category_id = $this->Application->GetVar('m_cat_id');
+
+ $category_id = $this->getFromCache('category_names', implode(':', $this->curItem->CategoryPath));
+ if ($category_id) {
+ $this->Application->SetVar('m_cat_id', $category_id);
+ return $category_id;
+ }
+
+ if (is_null($lang_prefix)) {
+ $lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
+ }
+
+ foreach ($this->curItem->CategoryPath as $category_index => $category_name) {
+ if (!$category_name) continue;
+ $category_key = crc32( implode(':', array_slice($this->curItem->CategoryPath, 0, $category_index + 1) ) );
+
+ $category_id = $this->getFromCache('category_names', $category_key);
+ if ($category_id === false) {
+ // get parent category path to search only in it
+ $current_category_id = $this->Application->GetVar('m_cat_id');
+// $parent_path = $this->getParentPath($current_category_id);
+
+ // get category id from database by name
+ $sql = 'SELECT CategoryId
+ FROM '.TABLE_PREFIX.'Category
+ WHERE ('.$lang_prefix.'Name = '.$this->Conn->qstr($category_name).') AND (ParentId = '.$current_category_id.')';
+ $category_id = $this->Conn->GetOne($sql);
+
+ if ($category_id === false) {
+ // category not in db -> create
+ $category_fields = Array( $lang_prefix.'Name' => $category_name, $lang_prefix.'Description' => $category_name,
+ 'Status' => STATUS_ACTIVE, 'ParentId' => $current_category_id, 'AutomaticFilename' => 1
+ );
+ $this->dummyCategory->SetDBFieldsFromHash($category_fields);
+ if ($this->dummyCategory->Create()) {
+ $category_id = $this->dummyCategory->GetID();
+ $this->addToCache('category_parent_path', $category_id, $this->dummyCategory->GetDBField('ParentPath'));
+ $this->addToCache('category_names', $category_key, $category_id);
+ }
+ }
+ else {
+ $this->addToCache('category_names', $category_key, $category_id);
+ }
+ }
+
+ if ($category_id) {
+ $this->Application->SetVar('m_cat_id', $category_id);
+ }
+ }
+ if (!$this->curItem->CategoryPath) {
+ $category_id = $backup_category_id;
+ }
+
+ return $category_id;
+ }
+
+ /**
+ * Enter description here...
+ *
+ * @param kEvent $event
+ */
+ function processCurrentItem(&$event, $record_data)
+ {
+ $save_method = 'Create';
+ $load_keys = Array();
+
+ // create/update categories
+ $backup_category_id = $this->Application->GetVar('m_cat_id');
+
+ // perform replace duplicates code
+ if ($this->exportOptions['ReplaceDuplicates']) {
+ // get replace keys first, then reset current item to empty one
+ $category_id = $this->getItemCategory();
+ if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
+ if ($this->curItem->GetID()) {
+ $load_keys = Array($this->curItem->IDField => $this->curItem->GetID());
+ }
+ }
+ else {
+ $key_fields = $this->exportOptions['DuplicateCheckFields'];
+ foreach ($key_fields as $key_field) {
+ $load_keys[$key_field] = $this->curItem->GetDBField($key_field);
+ }
+ }
+
+ $this->resetImportObject($event, IMPORT_LIVE);
+
+ if (count($load_keys)) {
+ $where_clause = '';
+ foreach ($load_keys as $field_name => $field_value) {
+ if (preg_match('/^cust_(.*)/', $field_name, $regs)) {
+ $custom_id = array_search($regs[1], $this->customFields);
+ $field_name = 'l'.$this->Application->GetVar('m_lang').'_cust_'.$custom_id;
+ $where_clause .= '(custom_data.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
+ }
+ else {
+ $where_clause .= '(item_table.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
+ }
+
+ }
+ $where_clause = preg_replace('/(.*) AND $/', '\\1', $where_clause);
+
+ $item_id = $this->getFromCache('new_ids', crc32($where_clause));
+ if (!$item_id) {
+ if ($this->exportOptions['CheckDuplicatesMethod'] == 2) {
+ // by other fields
+ $parent_path = $this->getParentPath($category_id);
+ $where_clause = '(c.ParentPath LIKE "'.$parent_path.'%") AND '.$where_clause;
+ }
+
+ $cdata_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
+ $sql = 'SELECT '.$this->curItem->IDField.'
+ FROM '.$this->curItem->TableName.' item_table
+ LEFT JOIN '.$cdata_table.' custom_data ON custom_data.ResourceId = item_table.ResourceId
+ LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId
+ LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
+ WHERE '.$where_clause;
+ $item_id = $this->Conn->GetOne($sql);
+ }
+ $save_method = $item_id && $this->curItem->Load($item_id) ? 'Update' : 'Create';
+ if ($save_method == 'Update') {
+ // replace id from csv file with found id (only when ID is found in cvs file)
+ if (in_array($this->curItem->IDField, $this->exportFields)) {
+ $record_data[ array_search($this->curItem->IDField, $this->exportFields) ] = $item_id;
+ }
+ }
+ }
+
+ $this->setImportData($record_data);
+ }
+ else {
+ $this->resetImportObject($event, IMPORT_LIVE, $record_data);
+ $category_id = $this->getItemCategory();
+ }
+
+ // create main record
+ if ($save_method == 'Create') {
+ $this->fillRequiredFields($this->false, $this->curItem, true);
+ }
+
+// $sql_start = getmicrotime();
+ if (!$this->curItem->$save_method()) {
+ $this->Application->SetVar('m_cat_id', $backup_category_id);
+ return false;
+ }
+// $sql_end = getmicrotime();
+// $this->saveLog('SQL ['.$save_method.'] Time: '.($sql_end - $sql_start).'s');
+
+ if ($load_keys && ($save_method == 'Create') && $this->exportOptions['ReplaceDuplicates']) {
+ // map new id to old id
+ $this->addToCache('new_ids', crc32($where_clause), $this->curItem->GetID() );
+ }
+
+ // assign item to categories
+ $this->curItem->assignToCategory($category_id, false);
+
+ $this->Application->SetVar('m_cat_id', $backup_category_id);
+ return true;
+ }
+
+ /*function saveLog($msg)
+ {
+ static $first_time = true;
+
+ $fp = fopen(FULL_PATH.'/sqls.log', $first_time ? 'w' : 'a');
+ fwrite($fp, $msg."\n");
+ fclose($fp);
+
+ $first_time = false;
+ }*/
+
+ /**
+ * Returns category parent path, if possible, then from cache
+ *
+ * @param int $category_id
+ * @return string
+ */
+ function getParentPath($category_id)
+ {
+ $parent_path = $this->getFromCache('category_parent_path', $category_id);
+ if ($parent_path === false) {
+ $sql = 'SELECT ParentPath
+ FROM '.TABLE_PREFIX.'Category
+ WHERE CategoryId = '.$category_id;
+ $parent_path = $this->Conn->GetOne($sql);
+ $this->addToCache('category_parent_path', $category_id, $parent_path);
+ }
+ return $parent_path;
+ }
+
+ function getFileExtension()
+ {
+ return $this->exportOptions['ExportFormat'] == 1 ? 'csv' : 'xml';
+ }
+
+ function getLineSeparator($option = 'LineEndings')
+ {
+ return $this->exportOptions[$option] == 1 ? "\r\n" : "\n";
+ }
+
+ /**
+ * Returns field caption for any exported field
+ *
+ * @param string $field
+ * @return string
+ */
+ function getFieldCaption($field)
+ {
+ if (substr($field, 0, 10) == '__CUSTOM__')
+ {
+ $ret = 'Custom_'.substr($field, 10, strlen($field) );
+ }
+ elseif (substr($field, 0, 12) == '__CATEGORY__')
+ {
+ return $this->getCategoryTitle();
+ }
+ elseif (substr($field, 0, 11) == '__VIRTUAL__') {
+ $ret = substr($field, 11);
+ }
+ else
+ {
+ $ret = $field;
+ }
+
+ return Array($ret);
+ }
+
+ /**
+ * Returns requested field value (including custom fields and category fields)
+ *
+ * @param string $field
+ * @return string
+ */
+ function getFieldValue($field)
+ {
+ if (substr($field, 0, 10) == '__CUSTOM__') {
+ $field = 'cust_'.substr($field, 10, strlen($field));
+ $ret = $this->curItem->GetField($field);
+ }
+ elseif (substr($field, 0, 12) == '__CATEGORY__') {
+ return $this->getCategoryPath();
+ }
+ elseif (substr($field, 0, 11) == '__VIRTUAL__') {
+ $field = substr($field, 11);
+ $ret = $this->curItem->GetField($field);
+ }
+ else
+ {
+ $ret = $this->curItem->GetField($field);
+ }
+
+ $ret = str_replace("\r\n", $this->getLineSeparator('LineEndingsInside'), $ret);
+ return Array($ret);
+ }
+
+ /**
+ * Returns category field(-s) caption based on export mode
+ *
+ * @return string
+ */
+ function getCategoryTitle()
+ {
+ // category path in separated fields
+ $category_count = $this->getMaxCategoryLevel();
+ if ($this->exportOptions['CategoryFormat'] == 1)
+ {
+ // category path in one field
+ return $category_count ? Array('CategoryPath') : Array();
+ }
+ else
+ {
+ $i = 0;
+ $ret = Array();
+ while ($i < $category_count) {
+ $ret[] = 'Category'.($i + 1);
+ $i++;
+ }
+ return $ret;
+ }
+ }
+
+ /**
+ * Returns category path in required format for current link
+ *
+ * @return string
+ */
+ function getCategoryPath()
+ {
+ $category_id = $this->curItem->GetDBField('CategoryId');
+ $category_path = $this->getFromCache('category_path', $category_id);
+ if (!$category_path)
+ {
+ $ml_formatter =& $this->Application->recallObject('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') {
+ array_shift($category_path);
+ }
+
+ if ($this->exportOptions['IsBaseCategory']) {
+ $i = $this->exportOptions['BaseLevel'];
+ while ($i > 0) {
+ array_shift($category_path);
+ $i--;
+ }
+ }
+
+ $category_count = $this->getMaxCategoryLevel();
+ if ($this->exportOptions['CategoryFormat'] == 1) {
+ // category path in single field
+ $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)
+ {
+ $i = 0;
+ while ($i < $category_count - $levels_used) {
+ $category_path[] = '';
+ $i++;
+ }
+ }
+ }
+ $this->addToCache('category_path', $category_id, $category_path);
+ }
+
+ return $category_path;
+ }
+
+ /**
+ * Get maximal category deep level from links beeing exported
+ *
+ * @return int
+ */
+ function getMaxCategoryLevel()
+ {
+ static $max_level = -1;
+
+ if ($max_level != -1)
+ {
+ return $max_level;
+ }
+
+ $sql = 'SELECT IF(c.CategoryId IS NULL, 0, MAX( LENGTH(c.ParentPath) - LENGTH( REPLACE(c.ParentPath, "|", "") ) - 1 ))
+ FROM '.$this->curItem->TableName.' item_table
+ LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON item_table.ResourceId = ci.ItemResourceId
+ LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
+ WHERE (ci.PrimaryCat = 1) AND ';
+
+ $where_clause = '';
+ if ($this->exportOptions['export_ids'] === false) {
+ // get links from current category & all it's subcategories
+ if ($this->exportOptions['export_cats_ids'][0] == 0) {
+ $where_clause = 1;
+ }
+ else {
+ foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
+ $where_clause .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
+ }
+ $where_clause = preg_replace('/(.*) OR $/', '\\1', $where_clause);
+ }
+ }
+ else {
+ // get only selected links
+ $where_clause = $this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
+ }
+
+ $max_level = $this->Conn->GetOne($sql.'('.$where_clause.')');
+
+ if ($this->exportOptions['IsBaseCategory'] ) {
+ $max_level -= $this->exportOptions['BaseLevel'];
+ }
+
+ return $max_level;
+ }
+
+ /**
+ * Saves one record to export file
+ *
+ * @param Array $fields_hash
+ */
+ function writeRecord($fields_hash)
+ {
+ fputcsv2($this->filePointer, $fields_hash, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy'], $this->getLineSeparator() );
+ }
+
+ function readRecord()
+ {
+ return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']);
+ }
+
+ function saveOptions(&$event, $options = null)
+ {
+ if (!isset($options)) {
+ $options = $this->exportOptions;
+ }
+ $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) );
+ }
+
+ function loadOptions(&$event)
+ {
+ return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options'));
+ }
+
+ /**
+ * Sets correct available & export fields
+ *
+ * @param kEvent $event
+ */
+ function prepareExportColumns(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+
+ if (!array_key_exists('ExportColumns', $object->Fields)) {
+ // import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported
+ return ;
+ }
+
+ $available_columns = Array();
+
+ if ($this->Application->getUnitOption($event->Prefix, 'CatalogItem')) {
+ // category field (mixed)
+ $available_columns['__CATEGORY__CategoryPath'] = 'CategoryPath';
+
+ if ($event->Special == 'import') {
+ // category field (separated fields)
+ $max_level = $this->Application->ConfigValue('MaxImportCategoryLevels');
+ $i = 0;
+ while ($i < $max_level) {
+ $available_columns['__CATEGORY__Category'.($i + 1)] = 'Category'.($i + 1);
+ $i++;
+ }
+ }
+ }
+
+ // db fields
+ foreach ($object->Fields as $field_name => $field_options)
+ {
+ if (!$object->skipField($field_name))
+ {
+ $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : '');
+ }
+ }
+
+ $handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
+ $available_columns = array_merge_recursive2($available_columns, $handler->getCustomExportColumns($event));
+
+ // custom fields
+ foreach ($object->customFields as $custom_id => $custom_name)
+ {
+ $available_columns['__CUSTOM__'.$custom_name] = $custom_name;
+ }
+
+ // columns already in use
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info)
+ {
+ list($item_id, $field_values) = each($items_info);
+ $export_keys = $field_values['ExportColumns'];
+ $export_keys = $export_keys ? explode('|', substr($export_keys, 1, -1) ) : Array();
+ }
+ else {
+ $export_keys = Array();
+ }
+
+ $export_columns = Array();
+ foreach ($export_keys as $field_key)
+ {
+ $field_name = $this->getExportField($field_key);
+ $export_columns[$field_key] = $field_name;
+ unset($available_columns[$field_key]);
+ }
+
+ $options = $object->GetFieldOptions('ExportColumns');
+ $options['options'] = $export_columns;
+ $object->SetFieldOptions('ExportColumns', $options);
+
+ $options = $object->GetFieldOptions('AvailableColumns');
+ $options['options'] = $available_columns;
+ $object->SetFieldOptions('AvailableColumns', $options);
+
+ $this->updateImportFiles($event);
+ $this->PrepareExportPresets($event);
+ }
+
+ function PrepareExportPresets(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ $options = $object->GetFieldOptions('ExportPresets');
+
+ $export_settings = $this->Application->RecallPersistentVar('export_settings');
+ if (!$export_settings) return ;
+ $export_settings = unserialize($export_settings);
+
+ if (!isset($export_settings[$event->Prefix])) return ;
+
+
+ $export_presets = array(''=>'');
+ foreach ($export_settings[$event->Prefix] as $key => $val) {
+ $export_presets[implode('|', $val['ExportColumns'])] = $key;
+ }
+
+ $options['options'] = $export_presets;
+ $object->SetFieldOptions('ExportPresets', $options);
+ }
+
+ function getExportField($field_key)
+ {
+ $prepends = Array('__CUSTOM__', '__CATEGORY__');
+ foreach ($prepends as $prepend)
+ {
+ if (substr($field_key, 0, strlen($prepend) ) == $prepend)
+ {
+ $field_key = substr($field_key, strlen($prepend), strlen($field_key) );
+ break;
+ }
+ }
+ return $field_key;
+ }
+
+ /**
+ * Updates uploaded files list
+ *
+ * @param kEvent $event
+ */
+ function updateImportFiles(&$event)
+ {
+ if ($event->Special != 'import') {
+ return false;
+ }
+
+ $object =& $event->getObject();
+
+ $import_filenames = Array();
+
+ 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 = formatSize( filesize(EXPORT_PATH.'/'.$file) );
+ $import_filenames[$file] = $file.' ('.$file_size.')';
+ }
+ closedir($folder_handle);
+ }
+
+ $options = $object->GetFieldOptions('ImportLocalFilename');
+ $options['options'] = $import_filenames;
+ $object->SetFieldOptions('ImportLocalFilename', $options);
+ }
+
+ /**
+ * Returns module folder
+ *
+ * @param kEvent $event
+ * @return string
+ */
+ function getModuleFolder(&$event)
+ {
+ return $this->Application->getUnitOption($event->Prefix, 'ModuleFolder');
+ }
+
+ /**
+ * Export form validation & processing
+ *
+ * @param kEvent $event
+ */
+ function OnExportBegin(&$event)
+ {
+ $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->SetFieldsFromHash($field_values);
+ $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
+
+ $object->setID($item_id);
+ $this->setRequiredFields($event);
+
+ $export_object =& $this->Application->recallObject('CatItemExportHelper');
+
+ // 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');
+
+ // 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['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));
+ $field_values = $nevent->getEventParam('options');
+
+ $export_object->saveOptions($event, $field_values);
+
+ if( $export_object->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[$event->Prefix][$name] = $field_values;
+ $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
+ }
+
+ $progress_t = $this->Application->RecallVar('export_progress_t');
+ if ($progress_t) {
+ $this->Application->RemoveVar('export_progress_t');
+ }
+ else {
+ $progress_t = $export_object->getModuleFolder($event).'/'.$event->Special.'_progress';
+ }
+ $event->redirect = $progress_t;
+
+ if ($event->Special == 'import') {
+ $import_category = (int)$this->Application->RecallVar('ImportCategory');
+
+ // in future could use module root category if import category will be unavailable :)
+ $event->SetRedirectParam('m_cat_id', $import_category); // for template permission checking
+ $this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking
+ }
+ }
+ else
+ {
+ // make uploaded file local & change source selection
+ $filename = getArrayValue($field_values, 'ImportFilename');
+ if ($filename) {
+ $export_object->updateImportFiles($event);
+ $object->SetDBField('ImportSource', 2);
+ $field_values['ImportSource'] = 2;
+ $object->SetDBField('ImportLocalFilename', $filename);
+ $field_values['ImportLocalFilename'] = $filename;
+ $export_object->saveOptions($event, $field_values);
+ }
+
+ $event->status = erFAIL;
+ $event->redirect = false;
+ }
+ }
+
+ /**
+ * Returns export save preset name, when used at all
+ *
+ * @param kDBItem $object
+ * @return string
+ */
+ function _getExportSavePreset(&$object)
+ {
+ if (!array_key_exists('ExportSavePreset', $object->Fields)) {
+ return '';
+ }
+
+ return $object->GetDBField('ExportSavePreset');
+ }
+
+ /**
+ * set required fields based on import or export params
+ *
+ * @param kEvent $event
+ */
+ function setRequiredFields(&$event)
+ {
+ $required_fields['common'] = Array('FieldsSeparatedBy', 'LineEndings', 'CategoryFormat');
+
+ $required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns');
+
+ $object =& $event->getObject();
+ if ($this->_getExportSavePreset($object)) {
+ $required_fields['export'][] = 'ExportPresetName';
+ }
+
+ $required_fields['import'] = Array('FieldTitles', 'ImportSource', 'CheckDuplicatesMethod'); // ImportFilename, ImportLocalFilename
+
+ if ($event->Special == 'import')
+ {
+ $import_source = Array(1 => 'ImportFilename', 2 => 'ImportLocalFilename');
+ $used_field = $import_source[ $object->GetDBField('ImportSource') ];
+
+ $required_fields[$event->Special][] = $used_field;
+ $object->Fields[$used_field]['error_field'] = 'ImportSource';
+
+ if ($object->GetDBField('FieldTitles') == 2) $required_fields[$event->Special][] = 'ExportColumns'; // manual field titles
+ }
+
+ $required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]);
+ foreach ($required_fields as $required_field) {
+ $object->setRequired($required_field, true);
+ }
+ }
+
+ }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php
___________________________________________________________________
Added: cvs2svn:cvs-rev
## -0,0 +1 ##
+1.24.2.5
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property
Index: branches/5.0.x/core/units/helpers/helpers_config.php
===================================================================
--- branches/5.0.x/core/units/helpers/helpers_config.php (revision 12342)
+++ branches/5.0.x/core/units/helpers/helpers_config.php (revision 12343)
@@ -1,58 +1,59 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array (
'Prefix' => 'helpers',
'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
'RegisterClasses' => Array (
Array ('pseudo' => 'kMultiLanguageHelper', 'class' => 'kMultiLanguageHelper', 'file' => 'multilanguage_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SearchHelper', 'class' => 'kSearchHelper', 'file' => 'search_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SectionsHelper', 'class' => 'kSectionsHelper', 'file' => 'sections_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PermissionsHelper', 'class' => 'kPermissionsHelper', 'file' => 'permissions_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModulesHelper', 'class' => 'kModulesHelper', 'file' => 'modules_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ModRewriteHelper', 'class' => 'kModRewriteHelper', 'file' => 'mod_rewrite_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RecursiveHelper', 'class' => 'kRecursiveHelper', 'file' => 'recursive_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FilenamesHelper', 'class' => 'kFilenamesHelper', 'file' => 'filenames_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ClipboardHelper', 'class' => 'kClipboardHelper', 'file' => 'clipboard_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ColumnPickerHelper', 'class' => 'kColumnPickerHelper', 'file' => 'col_picker_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ThemesHelper', 'class' => 'kThemesHelper', 'file' => 'themes_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CaptchaHelper', 'class' => 'kCaptchaHelper', 'file' => 'captcha_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'PriorityHelper', 'class' => 'kPriorityHelper', 'file' => 'priority_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CurlHelper', 'class' => 'kCurlHelper', 'file' => 'curl_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CountHelper', 'class' => 'kCountHelper', 'file' => 'count_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ImageHelper', 'class' => 'ImageHelper', 'file' => 'image_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FileHelper', 'class' => 'FileHelper', 'file' => 'file_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CategoryHelper', 'class' => 'CategoryHelper', 'file' => 'category_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'CSVHelper', 'class' => 'kCSVHelper', 'file' => 'csv_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'ChartHelper', 'class' => 'kChartHelper', 'file' => 'chart_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'RatingHelper', 'class' => 'RatingHelper', 'file' => 'rating_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'FCKHelper', 'class' => 'fckFCKHelper', 'file' => 'fck_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SpamHelper', 'class' => 'SpamHelper', 'file' => 'spam_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'TemplateHelper', 'class' => 'TemplateHelper', 'file' => 'template_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'MailingListHelper', 'class' => 'MailingListHelper', 'file' => 'mailing_list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kBracketsHelper', 'pseudo' => 'BracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('class' => 'kXMLHelper', 'pseudo' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('class' => 'kCatDBItemExportHelper', 'pseudo' => 'CatItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
),
);
\ No newline at end of file
Index: branches/5.0.x/core/units/general/inp_ses_storage.php
===================================================================
--- branches/5.0.x/core/units/general/inp_ses_storage.php (revision 12342)
+++ branches/5.0.x/core/units/general/inp_ses_storage.php (nonexistent)
@@ -1,148 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
- defined('FULL_PATH') or die('restricted access!');
-
- class InpSession extends Session
- {
- function Init($prefix,$special)
- {
- $this->SessionTimeout = $this->Application->ConfigValue('SessionTimeout');
-
- $path = (BASE_PATH == '') ? '/' : BASE_PATH;
-// if ( $this->Application->IsAdmin() ) $path = rtrim($path, '/').'/admin';
- $this->SetCookiePath($path);
-
- $cookie_name = $this->Application->ConfigValue('SessionCookieName');
- if (!$cookie_name) $cookie_name = 'sid';
- if (($this->Application->IsAdmin() && $special !== 'front') || $special == 'admin' ) { // || $this->Application->GetVar('admin') == 1
- $cookie_name = 'adm_'.$cookie_name;
- }
- $this->SetCookieName($cookie_name);
-
- $this->SetCookieDomain(SERVER_NAME);
-
- if( $this->Application->IsAdmin()) { // && $this->Application->GetVar('admin') != 1
- $mode = smAUTO;
- }
- elseif (constOn('IS_INSTALL')) {
- $mode = smCOOKIES_ONLY;
- }
- else {
- $ses_mode = $this->Application->ConfigValue('CookieSessions');
- if ($ses_mode == 2) $mode = smAUTO;
- if ($ses_mode == 1) $mode = smCOOKIES_ONLY;
- if ($ses_mode == 0) $mode = smGET_ONLY;
- }
- $this->SetMode($mode);
-
- parent::Init($prefix,$special);
-
- if( !$this->Application->IsAdmin() && $this->GetField('PortalUserId') <= 0 )
- {
- $group_list = $this->Application->ConfigValue('User_GuestGroup').','.$this->Application->ConfigValue('User_LoggedInGroup');
- $this->SetField('GroupId', $this->Application->ConfigValue('User_GuestGroup'));
- $this->SetField('GroupList', $group_list);
- }
- }
-
- function Destroy()
- {
- $this->Storage->DeleteSession($this);
- $this->Storage->DeleteEditTables();
- $this->Data = new Params();
- $this->SID = $this->CachedSID = '';
- if ($this->CookiesEnabled) $this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty
-
- $this->SetSession(); //will create a new session
- }
-
- }
-
-class InpSessionStorage extends SessionStorage {
-
- function Init($prefix,$special)
- {
- parent::Init($prefix,$special);
- $this->setTableName(TABLE_PREFIX.'UserSession');
- $this->SessionDataTable = TABLE_PREFIX.'SessionData';
- $this->setIDField('SessionKey');
- $this->TimestampField = 'LastAccessed';
- $this->DataValueField = 'VariableValue';
- $this->DataVarField = 'VariableName';
- }
-
- function LocateSession($sid)
- {
- $res = parent::LocateSession($sid);
- if ($res) {
- $this->Expiration += $this->SessionTimeout;
- }
- return $res;
- }
-
- function UpdateSession(&$session)
- {
- $time = adodb_mktime();
- // Update LastAccessed only if it's newer than 1/10 of session timeout - perfomance optimization to eliminate needless updates on every click
-// if ($time - $this->DirectVars['LastAccessed'] > $this->SessionTimeout/10) {
- $this->SetField($session, $this->TimestampField, $time + $this->SessionTimeout);
-// }
- }
-
-
- function StoreSession(&$session, $additional_fields = Array())
- {
- $fields_hash = Array (
- 'PortalUserId' => $this->Application->IsAdmin() ? 0 : -2, // Guest
- 'Language' => $this->Application->GetDefaultLanguageId(),
- 'Theme' => $this->Application->GetDefaultThemeId(),
- 'IpAddress' => $_SERVER['REMOTE_ADDR'],
- 'GroupId' => $this->Application->ConfigValue('User_GuestGroup'),
- 'GroupList' => $this->Application->ConfigValue('User_GuestGroup'),
- 'CurrentTempKey'=> $session->SID,
- );
-
- parent::StoreSession($session, $fields_hash);
- }
-
- function GetExpiredSIDs()
- {
- $query = ' SELECT '.$this->IDField.' FROM '.$this->TableName.' WHERE '.$this->TimestampField.' < '.(adodb_mktime());
- $ret = $this->Conn->GetCol($query);
- if($ret) {
- $this->DeleteEditTables();
- }
- return $ret;
-
- }
-
- function DeleteEditTables()
- {
- $tables = $this->Conn->GetCol('SHOW TABLES');
- $mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_(.*)/';
- $mask_search_table = '/'.TABLE_PREFIX.'ses_(.*?)_(.*)/';
-
- $sql='SELECT COUNT(*) FROM '.$this->TableName.' WHERE '.$this->IDField.' = \'%s\'';
- foreach($tables as $table)
- {
- if( preg_match($mask_edit_table,$table,$rets) || preg_match($mask_search_table,$table,$rets) )
- {
- $sid = preg_replace('/(.*)_(.*)/', '\\1', $rets[1]); // remove popup's wid from sid
- $is_alive = $this->Conn->GetOne( sprintf($sql,$sid) );
- if(!$is_alive) $this->Conn->Query('DROP TABLE IF EXISTS '.$table);
- }
- }
- }
-}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/inp_ses_storage.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.23.2.4
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/cat_tag_processor.php
===================================================================
--- branches/5.0.x/core/units/general/cat_tag_processor.php (revision 12342)
+++ branches/5.0.x/core/units/general/cat_tag_processor.php (nonexistent)
@@ -1,789 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
- defined('FULL_PATH') or die('restricted access!');
-
- class kCatDBTagProcessor extends kDBTagProcessor {
-
- /**
- * Permission Helper
- *
- * @var kPermissionsHelper
- */
- var $PermHelper = null;
-
- function kCatDBTagProcessor()
- {
- parent::kDBTagProcessor();
- $this->PermHelper = $this->Application->recallObject('PermissionsHelper');
- }
-
- function ItemIcon($params)
- {
- $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params);
-
- $grids = $this->Application->getUnitOption($this->Prefix,'Grids');
- $icons =& $grids[ $params['grid'] ]['Icons'];
-
- $status_fields = $this->Application->getUnitOption($this->Prefix,'StatusField');
- if (!$status_fields) return $icons['default'];
-
- $value = $object->GetDBField($status_fields[0]); // sets base status icon
- /* @var $object kDBItem */
- if ($value == STATUS_ACTIVE) {
- if( $object->HasField('IsPop') && $object->GetDBField('IsPop') ) $value = 'POP';
- if( $object->HasField('IsHot') && $object->GetDBField('IsHot') ) $value = 'HOT';
- if( $object->HasField('IsNew') && $object->GetDBField('IsNew') ) $value = 'NEW';
- if( $object->HasField('EditorsPick') && $object->GetDBField('EditorsPick') ) $value = 'PICK';
- }
-
- return isset($icons[$value]) ? $icons[$value] : $icons['default'];
- }
-
- /**
- * Allows to create valid mod-rewrite compatible link to module item
- *
- * @param Array $params
- * @param string $id_prefix
- * @return string
- */
- function ItemLink($params, $id_prefix = null)
- {
- if (!isset($params['pass'])) {
- $params['pass'] = 'm,'.$this->Prefix;
- }
-
- $item_id = isset($params[$id_prefix.'_id']) && $params[$id_prefix.'_id'];
- if (!$item_id) {
- $item_id = $this->Application->GetVar($this->getPrefixSpecial().'_id');
- if (!$item_id) {
- $item_id = $this->Application->GetVar($this->Prefix.'_id');
- }
- }
- $params[$this->Prefix.'_id'] = $item_id;
-
- $object =& $this->getObject($params);
- $params['m_cat_id'] = $object->GetDBField('CategoryId');
- $params['m_cat_page'] = 1;
- $params['pass_category'] = 1;
-
- return $this->Application->ProcessParsedTag('m', 't', $params);
- }
-
- function CategoryPath($params)
- {
- if ($this->Application->IsAdmin()) {
- // path for module root category in admin
- if (!isset($params['cat_id'])) {
- $params['cat_id'] = $this->Application->RecallVar($params['session_var'], 0);
- }
- }
- else {
- // path for category item category in front-end
- $object =& $this->getObject($params);
- $params['cat_id'] = $object->GetDBField('CategoryId');
- }
-
- return $this->Application->ProcessParsedTag('c', 'CategoryPath', $params);
- }
-
- function BuildListSpecial($params)
- {
- if ($this->Special != '') return $this->Special;
- if ( isset($params['parent_cat_id']) ) {
- $parent_cat_id = $params['parent_cat_id'];
- }
- else {
- $parent_cat_id = $this->Application->GetVar('c_id');
- if (!$parent_cat_id) {
- $parent_cat_id = $this->Application->GetVar('m_cat_id');
- }
- }
-
- $recursive = isset($params['recursive']);
-
- $list_unique_key = $this->getUniqueListKey($params).$recursive;
- if ($list_unique_key == '') {
- return parent::BuildListSpecial($params);
- }
-
- return crc32($parent_cat_id.$list_unique_key);
- }
-
- function CatalogItemCount($params)
- {
- $params['skip_quering'] = true;
- $object =& $this->GetList($params);
-
- if (!$object->Counted) {
- $object->CountRecs();
- }
-
- return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount;
- }
-
- function ListReviews($params)
- {
- $prefix = $this->Prefix.'-rev';
- $review_tag_processor =& $this->Application->recallObject($prefix.'.item_TagProcessor');
- return $review_tag_processor->PrintList($params);
- }
-
- function ReviewCount($params)
- {
- $review_tag_processor =& $this->Application->recallObject('rev.item_TagProcessor');
- return $review_tag_processor->TotalRecords($params);
- }
-
- function InitCatalogTab($params)
- {
- $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible
- $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab
- $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid
-
- // set default params (same as in catalog)
- if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi';
- if ($tab_params['special'] === false) $tab_params['special'] = '';
- if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes';
-
- // pass params to block with tab content
- $params['name'] = $params['render_as'];
- $special = $tab_params['special'] ? $tab_params['special'] : $this->Special;
-
- $params['prefix'] = trim($this->Prefix.'.'.$special, '.');
-
- $prefix_append = $this->Application->GetVar('prefix_append');
- if ($prefix_append) {
- $params['prefix'] .= $prefix_append;
- }
-
- $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default';
- $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio';
-
-
- $params['cat_prefix'] = trim('c.'.$special, '.');
- $params['tab_mode'] = $tab_params['mode'];
- $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid;
- $params['tab_dependant'] = $tab_params['dependant'];
- $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name
-
- if ($special == 'showall' || $special == 'user') {
- $params['grid_name'] .= 'ShowAll';
- }
-
- return $this->Application->ParseBlock($params, 1);
- }
-
- /**
- * Show CachedNavbar of current item primary category
- *
- * @param Array $params
- * @return string
- */
- function CategoryName($params)
- {
- // show category cachednavbar of
- $object =& $this->getObject($params);
- $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId');
-
- $category_path = $this->Application->getCache('category_paths', $category_id);
- if ($category_path === false) {
- // not chached
- if ($category_id > 0) {
- $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $object->GetField('CachedNavbar'));
- $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > ');
- }
- else {
- $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') );
- }
- $this->Application->setCache('category_paths', $category_id, $category_path);
- }
- return $category_path;
- }
-
- /**
- * Allows to determine if original value should be shown
- *
- * @param Array $params
- * @return bool
- */
- function DisplayOriginal($params)
- {
- // original id found & greather then zero + show original
- $display_original = isset($params['display_original']) && $params['display_original'];
-
- $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
- if (!$owner_field) {
- $owner_field = 'CreatedById';
- }
-
- $object =& $this->getObject($params);
- $perm_value = $this->PermHelper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $this->Prefix);
-
- return $display_original && ($perm_value == 1) && $this->Application->GetVar($this->Prefix.'.original_id');
- }
-
- /**
- * Checks if user have one of required permissions
- *
- * @param Array $params
- * @return bool
- */
- function HasPermission($params)
- {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- $params['raise_warnings'] = 0;
- $object =& $this->getObject($params);
- /* @var $object kCatDBItem */
-
- // 1. category restriction
- $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id');
-
- // 2. owner restriction
- $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
- if (!$owner_field) {
- $owner_field = 'CreatedById';
- }
- $is_owner = $object->GetDBField($owner_field) == $this->Application->RecallVar('user_id');
-
- return $perm_helper->TagPermissionCheck($params, $is_owner);
- }
-
- /**
- * Creates link to current category or to module root category, when current category is home
- *
- * @param Array $params
- * @return string
- */
- function SuggestItemLink($params)
- {
- if (!isset($params['cat_id'])) {
- $params['cat_id'] = $this->Application->GetVar('m_cat_id');
- }
-
- if ($params['cat_id'] == 0) {
- $params['cat_id'] = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
- }
-
- $params['m_cat_page'] = 1;
-
- return $this->Application->ProcessParsedTag('c', 'CategoryLink', $params);
- }
-
- /**
- * Allows to detect if item has any additional images available
- *
- * @param Array $params
- * @return string
- */
- function HasAdditionalImages($params)
- {
- $object =& $this->getObject($params);
- $sql = 'SELECT ImageId
- FROM '.$this->Application->getUnitOption('img', 'TableName').'
- WHERE ResourceId = '.$object->GetDBField('ResourceId').' AND DefaultImg != 1 AND Enabled = 1';
- return $this->Conn->GetOne($sql) ? 1 : 0;
- }
-
- /**
- * Checks that item is pending
- *
- * @param Array $params
- * @return bool
- */
- function IsPending($params)
- {
- $object =& $this->getObject($params);
-
- $pending_status = Array (STATUS_PENDING, STATUS_PENDING_EDITING);
- return in_array($object->GetDBField('Status'), $pending_status);
- }
-
- function IsFavorite($params)
- {
- static $favorite_status = Array ();
-
- $object =& $this->getObject($params);
- /* @var $object kDBList */
-
- if (!isset($favorite_status[$this->Special])) {
- $resource_ids = $object->GetCol('ResourceId');
-
- $user_id = $this->Application->RecallVar('user_id');
- $sql = 'SELECT FavoriteId, ResourceId
- FROM '.$this->Application->getUnitOption('fav', 'TableName').'
- WHERE (PortalUserId = '.$user_id.') AND (ResourceId IN ('.implode(',', $resource_ids).'))';
- $favorite_status[$this->Special] = $this->Conn->GetCol($sql, 'ResourceId');
- }
-
- return isset($favorite_status[$this->Special][$object->GetDBField('ResourceId')]);
- }
-
- /**
- * Returns item's editors pick status (using not formatted value)
- *
- * @param Array $params
- * @return bool
- */
- function IsEditorsPick($params)
- {
- $object =& $this->getObject($params);
-
- return $object->GetDBField('EditorsPick') == 1;
- }
-
- function FavoriteToggleLink($params)
- {
- $fav_prefix = $this->Prefix.'-fav';
-
- $params['pass'] = implode(',', Array('m', $this->Prefix, $fav_prefix));
- $params[$fav_prefix.'_event'] = 'OnFavoriteToggle';
-
- return $this->ItemLink($params);
- }
-
- /**
- * Checks if item is passed in url
- *
- * @param Array $params
- * @return bool
- */
- function ItemAvailable($params)
- {
- return $this->Application->GetVar($this->getPrefixSpecial().'_id') > 0;
- }
-
- function SortingSelected($params)
- {
- $list =& $this->GetList($params);
- $user_sorting_start = $this->getUserSortIndex();
-
- $sorting_field = $list->GetOrderField($user_sorting_start);
- $sorting = strtolower($sorting_field . '|' . $list->GetOrderDirection($user_sorting_start));
-
- $field_options = $list->GetFieldOptions($sorting_field);
- if (array_key_exists('formatter', $field_options) && $field_options['formatter'] == 'kMultiLanguage') {
- // remove language prefix
- $sorting = preg_replace('/^l[\d]+_(.*)/', '\\1', $sorting);
- $params['sorting'] = preg_replace('/^l[\d]+_(.*)/', '\\1', $params['sorting']);
- }
-
- return $sorting == strtolower($params['sorting']) ? $params['selected'] : '';
- }
-
- function CombinedSortingDropDownName($params)
- {
- return $this->Prefix.'_CombinedSorting';
- }
-
- /**
- * Prepares name for field with event in it (used only on front-end)
- *
- * @param Array $params
- * @return string
- */
- function SubmitName($params)
- {
- return 'events['.$this->Prefix.']['.$params['event'].']';
- }
-
- /**
- * Returns prefix + any word (used for shared between categories per page settings)
- *
- * @param Array $params
- * @return string
- */
- function VarName($params)
- {
- return $this->Prefix.'_'.$params['type'];
- }
-
- /**
- * Checks if we are viewing module root category
- *
- * @param Array $params
- * @return bool
- */
- function IsModuleHome($params)
- {
- $root_category = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
-
- return $root_category == $this->Application->GetVar('m_cat_id');
- }
-
- /**
- * Dynamic votes indicator
- *
- * @param Array $params
- *
- * @return string
- */
- function VotesIndicator($params)
- {
- $object =& $this->getObject($params);
- /* @var $object kDBItem */
-
- $rating_helper =& $this->Application->recallObject('RatingHelper');
- /* @var $rating_helper RatingHelper */
-
- $small_style = array_key_exists('small_style', $params) ? $params['small_style'] : false;
-
- return $rating_helper->ratingBar($object, true, '', $small_style);
- }
-
- function RelevanceIndicator($params)
- {
- $object =& $this->getObject($params);
-
- $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
- $sql = 'SELECT Relevance
- FROM '.$search_results_table.'
- WHERE ResourceId = '.$object->GetDBField('ResourceId');
-
- $percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql)));
- $percents_off = ($percents_off < 0) ? 0 : $percents_off;
- if ($percents_off) {
- $params['percent_off'] = $percents_off;
- $params['percent_on'] = 100 - $percents_off;
- $params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal');
- }
- else {
- $params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full');
- }
- return $this->Application->ParseBlock($params);
- }
-
- function SearchResultField($params)
- {
- $ret = $this->Field($params);
-
- $keywords = unserialize( $this->Application->RecallVar('highlight_keywords') );
- $opening = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_opening_render_as,block_highlight_opening')) );
- $closing = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_closing_render_as,block_highlight_closing')) );
-
- foreach ($keywords as $index => $keyword) {
- $keywords[$index] = preg_quote($keyword, '/');
- }
-
- return preg_replace('/('.implode('|', $keywords).')/i', $opening.'\\1'.$closing, $ret);
- }
-
- /**
- * Shows keywords, that user searched
- *
- * @param Array $params
- * @return bool
- */
- function SearchKeywords($params)
- {
- $keywords = $this->Application->GetVar('keywords');
- $sub_search = $this->Application->GetVar('search_type') == 'subsearch';
-
- return ($keywords !== false) && !$sub_search ? $keywords : $this->Application->RecallVar('keywords');
- }
-
- function AdvancedSearchForm($params)
- {
- $search_table = $this->Application->getUnitOption('confs', 'TableName');
- $module_name = $this->Application->findModule('Var', $this->Prefix, 'Name');
-
- $sql = 'SELECT *
- FROM '.$search_table.'
- WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)
- ORDER BY DisplayOrder';
- $search_config = $this->Conn->Query($sql);
-
- $ret = '';
- foreach ($search_config as $record) {
- $params['name'] = $this->SelectParam($params, 'and_or_render_as,and_or_block');
- $params['field'] = $record['FieldName'];
- $params['andor'] = $this->Application->ParseBlock($params);
-
- $params['name'] = $this->SelectParam($params, $record['FieldType'].'_render_as,'.$record['FieldType'].'_block');
- $params['caption'] = $this->Application->Phrase($record['DisplayName']);
- $ret .= $this->Application->ParseBlock($params);
- }
- return $ret;
- }
-
- /**
- * Returns last modification date of items in category / system
- *
- * @param Array $params
- * @return string
- */
- function LastUpdated($params)
- {
- $category_id = $this->Application->GetVar('m_cat_id');
- $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName');
-
- if (isset($params['local']) && $params['local'] && $category_id > 0) {
- // scan only current category & it's children
- $sql = 'SELECT TreeLeft, TreeRight
- FROM '.TABLE_PREFIX.'Category
- WHERE CategoryId = '.$category_id;
- $tree_info = $this->Conn->GetRow($sql);
-
- $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate
- FROM '.$table_name.' item_table
- LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId)
- LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
- WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight'];
- }
- else {
- // scan all categories in system
- $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate
- FROM '.$table_name;
- }
-
- $row_data = $this->Conn->GetRow($sql);
- if (!$row_data) {
- return '';
- }
-
- $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ];
-
- // format date
- $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat';
- if (preg_match("/_regional_(.*)/", $format, $regs)) {
- $lang =& $this->Application->recallObject('lang.current');
- if ($regs[1] == 'DateTimeFormat') {
- // combined format
- $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat');
- }
- else {
- // simple format
- $format = $lang->GetDBField($regs[1]);
- }
- }
-
- return adodb_date($format, $date);
- }
-
- /**
- * Counts category item count in system (not category-dependent)
- *
- * @param Array $params
- * @return int
- */
- function ItemCount($params)
- {
- $count_helper =& $this->Application->recallObject('CountHelper');
- /* @var $count_helper kCountHelper */
-
- $today_only = isset($params['today']) && $params['today'];
- return $count_helper->ItemCount($this->Prefix, $today_only);
- }
-
- function CategorySelector($params)
- {
- $category_id = isset($params['category_id']) && is_numeric($params['category_id']) ? $params['category_id'] : false;
- if ($category_id === false) {
- // if category id not given use module root category
- $category_id = $this->Application->findModule('Var', $this->Prefix, 'RootCat');
- }
-
- $id_field = $this->Application->getUnitOption('c', 'IDField');
- $title_field = $this->Application->getUnitOption('c', 'TitleField');
- $table_name = $this->Application->getUnitOption('c', 'TableName');
-
- $count_helper =& $this->Application->recallObject('CountHelper');
- /* @var $count_helper kCountHelper */
-
- list ($view_perm, $view_filter) = $count_helper->GetPermissionClause('c', 'perm_cache');
-
- // get category list (permission based)
- $sql = 'SELECT c.'.$title_field.', c.'.$id_field.'
- FROM '.$table_name.' c
- INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId
- WHERE (ParentId = '.$category_id.') AND ('.$view_filter.') AND (perm_cache.PermId = '.$view_perm.') AND (c.Status = '.STATUS_ACTIVE.')
- ORDER BY c.'.$title_field.' ASC';
- $categories = $this->Conn->GetCol($sql, $id_field);
-
- $block_params = $this->prepareTagParams($params);
- $block_params['name'] = $params['render_as'];
- $block_params['strip_nl'] = 2;
-
- $ret = '';
- foreach ($categories as $category_id => $category_name) {
- // print category
- $block_params['separator'] = isset($params['category_id']) ? $params['separator'] : ''; // return original separator, remove separator for top level categories
- $block_params['category_id'] = $category_id;
- $block_params['category_name'] = $category_name;
- $ret .= $this->Application->ParseBlock($block_params);
-
- // print it's children
- $block_params['separator'] = '&nbsp;&nbsp;&nbsp;'.$params['separator'];
- $ret .= $this->CategorySelector($block_params);
- }
-
- return $ret;
- }
-
- function PrintMoreCategories($params)
- {
- $object =& $this->getObject();
- /* @var $object kDBItem */
-
- $category_ids = $this->Field($params);
- if (!$category_ids) {
- return '';
- }
-
- $category_ids = explode('|', substr($category_ids, 1, -1));
-
- $id_field = $this->Application->getUnitOption('c', 'IDField');
- $title_field = $this->Application->getUnitOption('c', 'TitleField');
- $table_name = $this->Application->getUnitOption('c', 'TableName');
-
- $sql = 'SELECT '.$title_field.', '.$id_field.'
- FROM '.$table_name.'
- WHERE '.$id_field.' IN ('.implode(',', $category_ids).')';
- $categories = $this->Conn->GetCol($sql, $id_field);
-
- $block_params = $this->prepareTagParams($params);
- $block_params['name'] = $params['render_as'];
-
- $ret = '';
- foreach ($categories as $category_id => $category_name) {
- $block_params['category_id'] = $category_id;
- $block_params['category_name'] = $category_name;
- $ret .= $this->Application->ParseBlock($block_params);
- }
-
- return $ret;
- }
-
- function DownloadFileLink($params)
- {
- $params[$this->getPrefixSpecial().'_event'] = 'OnDownloadFile';
-
- return $this->ItemLink($params);
- }
-
- function ImageSrc($params)
- {
- list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial());
- return $tag_processed ? $ret : false;
- }
-
- /**
- * Registers hit for item (one time per session)
- *
- * @param Array $params
- */
- function RegisterHit($params)
- {
- $object =& $this->getObject();
- /* @var $object kCatDBItem */
-
- if ($object->isLoaded()) {
- $object->RegisterHit();
- }
- }
-
- /**
- * Returns link to item's author public profile
- *
- * @param Array $params
- * @return string
- */
- function ProfileLink($params)
- {
- $object =& $this->getObject($params);
- $owner_field = array_key_exists('owner_field', $params) ? $params['owner_field'] : 'CreatedById';
- $params['user_id'] = $object->GetDBField($owner_field);
- unset($params['owner_field']);
-
- return $this->Application->ProcessParsedTag('m', 'Link', $params);
- }
-
- /**
- * Checks, that "view in browse mode" functionality available
- *
- * @param Array $params
- * @return bool
- */
- function BrowseModeAvailable($params)
- {
- $valid_special = $valid_special = $params['Special'] != 'user';
- $not_selector = $this->Application->GetVar('type') != 'item_selector';
-
- return $valid_special && $not_selector;
- }
-
- /**
- * Returns a link for editing product
- *
- * @param Array $params
- * @return string
- */
- function ItemEditLink($params)
- {
- $object =& $this->getObject();
- /* @var $object kDBList */
-
- $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit';
-
- $url_params = Array (
- 'm_opener' => 'd',
- $this->Prefix.'_mode' => 't',
- $this->Prefix.'_event' => 'OnEdit',
- $this->Prefix.'_id' => $object->GetID(),
- 'm_cat_id' => $object->GetDBField('CategoryId'),
- 'pass' => 'all,'.$this->Prefix,
- 'no_pass_through' => 1,
- );
-
- return $this->Application->HREF($edit_template,'', $url_params);
- }
-
- function LanguageVisible($params)
- {
- $field = $this->SelectParam($params, 'name,field');
-
- preg_match('/l([\d]+)_(.*)/', $field, $regs);
- $params['name'] = $regs[2];
-
- return $this->HasLanguageError($params) || $this->Application->GetVar('m_lang') == $regs[1];
- }
-
- function HasLanguageError($params)
- {
- static $languages = null;
-
- if (!isset($languages)) {
- $sql = 'SELECT ' . $this->Application->getUnitOption('lang', 'IDField') . '
- FROM ' . $this->Application->getUnitOption('lang', 'TableName') . '
- WHERE Enabled = 1';
- $languages = $this->Conn->GetCol($sql);
- }
-
- $field = $this->SelectParam($params, 'name,field');
-
- $object =& $this->getObject($params);
- /* @var $object kDBItem */
-
- foreach ($languages as $language_id) {
- $check_field = 'l' . $language_id . '_' . $field;
- if ($object->GetErrorMsg($check_field, false)) {
- return true;
- }
- }
-
- return false;
- }
- }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/cat_tag_processor.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.38.2.25
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/cat_dbitem_export.php
===================================================================
--- branches/5.0.x/core/units/general/cat_dbitem_export.php (revision 12342)
+++ branches/5.0.x/core/units/general/cat_dbitem_export.php (nonexistent)
@@ -1,1444 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
- defined('FULL_PATH') or die('restricted access!');
-
- define('EXPORT_STEP', 100); // export by 200 items (e.g. links)
- define('IMPORT_STEP', 20); // export by 200 items (e.g. links)
- define('IMPORT_CHUNK', 10240); // 10240); //30720); //50120); // 5 KB
-
- define('IMPORT_TEMP', 1);
- define('IMPORT_LIVE', 2);
-
- class kCatDBItemExportHelper extends kHelper {
-
- var $false = false;
-
- var $cache = Array();
-
- /**
- * Allows to find out what items are new in cache
- *
- * @var Array
- */
- var $cacheStatus = Array();
-
- var $cacheTable = '';
-
- var $exportFields = Array();
-
- /**
- * Export options
- *
- * @var Array
- */
- var $exportOptions = Array();
-
- /**
- * Item beeing currenly exported
- *
- * @var kCatDBItem
- */
- var $curItem = null;
-
- /**
- * Dummy category object
- *
- * @var CategoriesItem
- */
- var $dummyCategory = null;
-
- /**
- * Pointer to opened file
- *
- * @var resource
- */
- var $filePointer = null;
-
- /**
- * Custom fields definition of current item
- *
- * @var Array
- */
- var $customFields = Array();
-
- function kCatDBItemExportHelper()
- {
- parent::kHelper();
- $this->cacheTable = TABLE_PREFIX.'ImportCache';
- }
-
- /**
- * Returns value from cache if found or false otherwise
- *
- * @param string $type
- * @param int $key
- * @return mixed
- */
- function getFromCache($type, $key)
- {
- return getArrayValue($this->cache, $type, $key);
- }
-
- /**
- * Adds value to be cached
- *
- * @param string $type
- * @param int $key
- * @param mixed $value
- */
- function addToCache($type, $key, $value, $is_new = true)
- {
-// if (!isset($this->cache[$type])) $this->cache[$type] = Array();
- $this->cache[$type][$key] = $value;
- if ($is_new) {
- $this->cacheStatus[$type][$key] = true;
- }
- }
-
- function storeCache($cache_types)
- {
- $cache_types = explode(',', $cache_types);
-
- $values_sql = '';
- foreach ($cache_types as $cache_type) {
- $sql_mask = '('.$this->Conn->qstr($cache_type).',%s,%s),';
- $cache = getArrayValue($this->cacheStatus, $cache_type);
- if (!$cache) $cache = Array();
- foreach ($cache as $var_name => $cache_status) {
- $var_value = $this->cache[$cache_type][$var_name];
- $values_sql .= sprintf($sql_mask, $this->Conn->qstr($var_name), $this->Conn->qstr($var_value) );
- }
- }
- $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql);
- if ($values_sql) {
- $sql = 'INSERT INTO '.$this->cacheTable.'(`CacheName`,`VarName`,`VarValue`) VALUES '.$values_sql;
- $this->Conn->Query($sql);
- }
-
- }
-
- function loadCache()
- {
- $sql = 'SELECT * FROM '.$this->cacheTable;
- $records = $this->Conn->Query($sql);
-
- $this->cache = Array();
- foreach ($records as $record) {
- $this->addToCache($record['CacheName'], $record['VarName'], $record['VarValue'], false);
- }
- }
-
- /**
- * Fill required fields with dummy values
- *
- * @param kEvent $event
- */
- function fillRequiredFields(&$event, &$object, $set_status = false)
- {
- if ($object == $this->false) {
- $object =& $event->getObject();
- }
-
- $has_empty = false;
- $fields = array_keys($object->Fields);
- foreach ($fields as $field_name)
- {
- $field_options =& $object->Fields[$field_name];
- if (isset($object->VirtualFields[$field_name]) || !getArrayValue($field_options, 'required') ) continue;
- if ( $object->GetDBField($field_name) ) continue;
-
- $formatter_class = getArrayValue($field_options, 'formatter');
- if ($formatter_class) // not tested
- {
- $formatter =& $this->Application->recallObject($formatter_class);
- $sample_value = $formatter->GetSample($field_name, $field_options, $object);
- }
-
- $has_empty = true;
- $object->SetField($field_name, isset($sample_value) && $sample_value ? $sample_value : 'no value');
- }
- $object->UpdateFormattersSubFields();
-
- if ($set_status && $has_empty) {
- $object->SetDBField('Status', 0);
- }
- }
-
- /**
- * Verifies that all user entered export params are correct
- *
- * @param kEvent $event
- */
- function verifyOptions(&$event)
- {
- if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid'))
- {
- $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 0);
- return false;
- }
-
- $this->fillRequiredFields($event, $this->false);
-
- $object =& $event->getObject();
- $cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy');
- if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field
- {
- $object->setRequired('CategorySeparator', true);
- $cross_unique_fields[] = 'CategorySeparator';
- }
-
- $ret = $object->Validate();
-
- // check if cross unique fields has no same values
- foreach ($cross_unique_fields as $field_index => $field_name)
- {
- if (getArrayValue($object->FieldErrors, $field_name, 'pseudo') == 'required') continue;
-
- $check_fields = $cross_unique_fields;
- unset($check_fields[$field_index]);
-
- foreach ($check_fields as $check_field)
- {
- if ($object->GetDBField($field_name) == $object->GetDBField($check_field))
- {
- $object->SetError($check_field, 'unique');
- }
- }
- }
-
- if ($event->Special == 'import')
- {
- $this->exportOptions = $this->loadOptions($event);
-
- $automatic_fields = ($object->GetDBField('FieldTitles') == 1);
- $object->setRequired('ExportColumns', !$automatic_fields);
- $category_prefix = '__CATEGORY__';
- if ( $automatic_fields && ($this->exportOptions['SkipFirstRow']) ) {
- $this->openFile($event);
- $this->exportOptions['ExportColumns'] = $this->readRecord();
-
- if (!$this->exportOptions['ExportColumns']) {
- $this->exportOptions['ExportColumns'] = Array ();
- }
-
- $this->closeFile();
-
- // remove additional (non-parseble columns)
- foreach ($this->exportOptions['ExportColumns'] as $field_index => $field_name) {
- if (!$this->validateField($field_name, $object)) {
- unset($this->exportOptions['ExportColumns'][$field_index]);
- }
- }
- $category_prefix = '';
- }
-
- // 1. check, that we have column definitions
- if (!$this->exportOptions['ExportColumns']) {
- $object->setError('ExportColumns', 'required');
- $ret = false;
- }
- else {
- // 1.1. check that all required fields are present in imported file
- $missing_columns = Array();
- foreach ($object->Fields as $field_name => $field_options) {
- if ($object->skipField($field_name)) continue;
- if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) {
- $missing_columns[] = $field_name;
- $object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing');
- $ret = false;
- }
- }
-
- if (!$ret && $this->Application->isDebugMode()) {
- $this->Application->Debugger->appendHTML('Missing required for import/export:');
- $this->Application->Debugger->dumpVars($missing_columns);
- }
- }
-
-
- // 2. check, that we have only mixed category field or only separated category fields
- $category_found['mixed'] = false;
- $category_found['separated'] = false;
-
- foreach ($this->exportOptions['ExportColumns'] as $import_field) {
- if (preg_match('/^'.$category_prefix.'Category(Path|[0-9]+)/', $import_field, $rets)) {
- $category_found[$rets[1] == 'Path' ? 'mixed' : 'separated'] = true;
- }
- }
- if ($category_found['mixed'] && $category_found['separated']) {
- $object->SetError('ExportColumns', 'unique_category', 'la_error_unique_category_field');
- $ret = false;
- }
-
- // 3. check, that duplicates check fields are selected & present in imported fields
- if ($this->exportOptions['ReplaceDuplicates']) {
- if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
- $check_fields = Array($object->IDField);
- }
- else {
- $check_fields = $this->exportOptions['DuplicateCheckFields'] ? explode('|', substr($this->exportOptions['DuplicateCheckFields'], 1, -1)) : Array();
- $object =& $event->getObject();
-
- $language_id = $this->Application->GetDefaultLanguageId();
- foreach ($check_fields as $index => $check_field) {
- foreach ($object->Fields as $field_name => $field_options) {
- if ($field_name == 'l'.$language_id.'_'.$check_field) {
- $check_fields[$index] = 'l'.$language_id.'_'.$check_field;
- break;
- }
- }
- }
- }
- $this->exportOptions['DuplicateCheckFields'] = $check_fields;
-
- if (!$check_fields) {
- $object->setError('CheckDuplicatesMethod', 'required');
- $ret = false;
- }
- else {
- foreach ($check_fields as $check_field) {
- $check_field = preg_replace('/^cust_(.*)/', 'Custom_\\1', $check_field);
- if (!in_array($check_field, $this->exportOptions['ExportColumns'])) {
- $object->setError('ExportColumns', 'required');
- $ret = false;
- break;
- }
- }
- }
- }
- $this->saveOptions($event);
- }
-
- return $ret;
- }
-
- /**
- * Returns filename to read import data from
- *
- * @return string
- */
- function getImportFilename()
- {
- if ($this->exportOptions['ImportSource'] == 1)
- {
- $ret = $this->exportOptions['ImportFilename']; // ['name']; commented by Kostja
- }
- else {
- $ret = $this->exportOptions['ImportLocalFilename'];
- }
- return EXPORT_PATH.'/'.$ret;
- }
-
- /**
- * Returns filename to write export data to
- *
- * @return string
- */
- function getExportFilename()
- {
- return EXPORT_PATH.'/'.$this->exportOptions['ExportFilename'].'.'.$this->getFileExtension();
- }
-
- /**
- * Opens file required for export/import operations
- *
- * @param kEvent $event
- */
- function openFile(&$event)
- {
- if ($event->Special == 'export') {
- $write_mode = ($this->exportOptions['start_from'] == 0) ? 'w' : 'a';
- $this->filePointer = fopen($this->getExportFilename(), $write_mode);
- }
- else {
- $this->filePointer = fopen($this->getImportFilename(), 'r');
- }
-
- // skip UTF-8 BOM Modifier
- $first_chars = fread($this->filePointer, 3);
- if (bin2hex($first_chars) != 'efbbbf') {
- fseek($this->filePointer, 0);
- }
- }
-
- /**
- * Closes opened file
- *
- */
- function closeFile()
- {
- fclose($this->filePointer);
- }
-
- function getCustomSQL()
- {
- $ml_formatter =& $this->Application->recallObject('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.', ';
- }
-
- return preg_replace('/(.*), /', '\\1', $custom_sql);
- }
-
- function getPlainExportSQL($count_only = false) {
- if ($count_only && isset($this->exportOptions['ForceCountSQL'])) {
- $sql = $this->exportOptions['ForceCountSQL'];
- }
- elseif (!$count_only && isset($this->exportOptions['ForceSelectSQL'])) {
- $sql = $this->exportOptions['ForceSelectSQL'];
- }
- else {
- $items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List');
- $items_list->SetPerPage(-1);
-
- if ($options['export_ids'] != '') {
- $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')');
- }
-
- if ($count_only) {
- $sql = $items_list->getCountSQL( $items_list->GetSelectSQL(true,false) );
- }
- else {
- $sql = $items_list->GetSelectSQL();
- }
- }
-
- if (!$count_only)
- {
- $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
- }
-// else {
-// $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
-// }
-
- return $sql;
- }
-
- function getExportSQL($count_only = false)
- {
- if (!$this->Application->getUnitOption($this->curItem->Prefix, 'CatalogItem')) {
- return $this->GetPlainExportSQL($count_only); // in case this is not a CategoryItem
- }
-
- if ($this->exportOptions['export_ids'] === false)
- {
- // get links from current category & all it's subcategories
- $join_clauses = Array();
-
- $custom_sql = $this->getCustomSQL();
- if ($custom_sql) {
- $custom_table = $this->Application->getUnitOption($this->curItem->Prefix.'-cdata', 'TableName');
- $join_clauses[$custom_table.' custom_data'] = 'custom_data.ResourceId = item_table.ResourceId';
- }
-
- $join_clauses[TABLE_PREFIX.'CategoryItems ci'] = 'ci.ItemResourceId = item_table.ResourceId';
- $join_clauses[TABLE_PREFIX.'Category c'] = 'c.CategoryId = ci.CategoryId';
-
- $sql = 'SELECT item_table.*, ci.CategoryId'.($custom_sql ? ', '.$custom_sql : '').'
- FROM '.$this->curItem->TableName.' item_table';
-
- foreach ($join_clauses as $table_name => $join_expression) {
- $sql .= ' LEFT JOIN '.$table_name.' ON '.$join_expression;
- }
- $sql .= ' WHERE ';
-
- if ($this->exportOptions['export_cats_ids'][0] == 0)
- {
- $sql .= '1';
- }
- else {
- foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
- $sql .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
- }
- $sql = preg_replace('/(.*) OR $/', '\\1', $sql);
- }
-
- $sql .= ' ORDER BY ci.PrimaryCat DESC'; // NEW
- }
- else {
- // get only selected links
- $sql = 'SELECT item_table.*, '.$this->exportOptions['export_cats_ids'][0].' AS CategoryId
- FROM '.$this->curItem->TableName.' item_table
- WHERE '.$this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
- }
-
- if (!$count_only)
- {
- $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP;
- }
- else {
- $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql);
- }
-
- return $sql;
- }
-
- /**
- * Enter description here...
- *
- * @param kEvent $event
- */
- function performExport(&$event)
- {
- $this->exportOptions = $this->loadOptions($event);
- $this->exportFields = $this->exportOptions['ExportColumns'];
- $this->curItem =& $event->getObject( Array('skip_autoload' => true) );
- $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
- $this->openFile($event);
-
- if ($this->exportOptions['start_from'] == 0) // first export step
- {
- if (!getArrayValue($this->exportOptions, 'IsBaseCategory')) {
- $this->exportOptions['IsBaseCategory'] = 0;
- }
-
- if ($this->exportOptions['IsBaseCategory'] ) {
- $sql = 'SELECT ParentPath
- FROM '.TABLE_PREFIX.'Category
- WHERE CategoryId = '.$this->Application->GetVar('m_cat_id');
- $parent_path = $this->Conn->GetOne($sql);
- $parent_path = explode('|', substr($parent_path, 1, -1));
- if ($parent_path && $parent_path[0] == $this->Application->findModule('Name', 'Core', 'RootCat')) {
- array_shift($parent_path);
- }
-
- $this->exportOptions['BaseLevel'] = count($parent_path); // level to cut from other categories
- }
-
- // 1. export field titles if required
- if ($this->exportOptions['IncludeFieldTitles'])
- {
- $data_array = Array();
- foreach ($this->exportFields as $export_field)
- {
- $data_array = array_merge($data_array, $this->getFieldCaption($export_field));
- }
- $this->writeRecord($data_array);
- }
- $this->exportOptions['total_records'] = $this->Conn->GetOne( $this->getExportSQL(true) );
- }
-
- // 2. export data
- $records = $this->Conn->Query( $this->getExportSQL() );
- $records_exported = 0;
- foreach ($records as $record_info) {
- $this->curItem->Clear();
- $this->curItem->SetDBFieldsFromHash($record_info);
- $this->setCurrentID();
- $this->curItem->raiseEvent('OnAfterItemLoad', $this->curItem->GetID() );
-
- $data_array = Array();
- foreach ($this->exportFields as $export_field)
- {
- $data_array = array_merge($data_array, $this->getFieldValue($export_field) );
- }
- $this->writeRecord($data_array);
- $records_exported++;
- }
- $this->closeFile();
-
- $this->exportOptions['start_from'] += $records_exported;
- $this->saveOptions($event);
-
- return $this->exportOptions;
- }
-
- function getItemFields()
- {
- // just in case dummy user selected automtic mode & moved columns too :(
- return array_merge($this->curItem->Fields['AvailableColumns']['options'], $this->curItem->Fields['ExportColumns']['options']);
- }
-
- /**
- * Checks if field really belongs to importable field list
- *
- * @param string $field_name
- * @param kCatDBItem $object
- * @return bool
- */
- function validateField($field_name, &$object)
- {
- // 1. convert custom field
- $field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name);
-
- // 2. convert category field (mixed version & serparated version)
- $field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name);
-
- $valid_fields = $object->getPossibleExportColumns();
- return isset($valid_fields[$field_name]) || isset($valid_fields['__VIRTUAL__'.$field_name]);
- }
-
- /**
- * Enter description here...
- *
- * @param kEvent $event
- */
- function performImport(&$event)
- {
- if (!$this->exportOptions) {
- // load import options in case if not previously loaded in verification function
- $this->exportOptions = $this->loadOptions($event);
- }
-
- $backup_category_id = $this->Application->GetVar('m_cat_id');
- $this->Application->SetVar('m_cat_id', (int)$this->Application->RecallVar('ImportCategory') );
-
- $this->openFile($event);
-
- $bytes_imported = 0;
- if ($this->exportOptions['start_from'] == 0) // first export step
- {
- // 1st time run
- if ($this->exportOptions['SkipFirstRow']) {
- $this->readRecord();
- $this->exportOptions['start_from'] = ftell($this->filePointer);
- $bytes_imported = ftell($this->filePointer);
- }
-
- $current_category_id = $this->Application->GetVar('m_cat_id');
- if ($current_category_id > 0) {
- $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$current_category_id;
- $this->exportOptions['ImportCategoryPath'] = $this->Conn->GetOne($sql);
- }
- else {
- $this->exportOptions['ImportCategoryPath'] = '';
- }
- $this->exportOptions['total_records'] = filesize($this->getImportFilename());
- }
- else {
- $this->loadCache();
- }
-
- $this->exportFields = $this->exportOptions['ExportColumns'];
- $this->addToCache('category_parent_path', $this->Application->GetVar('m_cat_id'), $this->exportOptions['ImportCategoryPath']);
-
- // 2. import data
- $this->dummyCategory =& $this->Application->recallObject('c.-tmpitem', 'c', Array('skip_autoload' => true));
- fseek($this->filePointer, $this->exportOptions['start_from']);
-
- $items_processed = 0;
- while (($bytes_imported < IMPORT_CHUNK && $items_processed < IMPORT_STEP) && !feof($this->filePointer)) {
- $data = $this->readRecord();
- if ($data) {
- if ($this->exportOptions['ReplaceDuplicates']) {
- // set fields used as keys for replace duplicates code
- $this->resetImportObject($event, IMPORT_TEMP, $data);
- }
-
- $this->processCurrentItem($event, $data);
- }
- $bytes_imported = ftell($this->filePointer) - $this->exportOptions['start_from'];
- $items_processed++;
- }
-
- $this->closeFile();
- $this->Application->SetVar('m_cat_id', $backup_category_id);
-
- $this->exportOptions['start_from'] += $bytes_imported;
- $this->storeCache('new_ids');
-
- $this->saveOptions($event);
-
- if ($this->exportOptions['start_from'] == $this->exportOptions['total_records']) {
- $this->Conn->Query('TRUNCATE TABLE '.$this->cacheTable);
- }
-
- return $this->exportOptions;
- }
-
- function setCurrentID()
- {
- $this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) );
- }
-
- function setFieldValue($field_index, $value)
- {
- if (empty($value)) {
- $value = null;
- }
-
- $field_name = getArrayValue($this->exportFields, $field_index);
- if ($field_name == 'ResourceId') {
- return false;
- }
-
- 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 (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, 11) == '__VIRTUAL__') {
- $field_name = substr($field_name, 11);
- $this->curItem->SetField($field_name, $value);
- }
- else {
- $this->curItem->SetField($field_name, $value);
- }
-
- $pseudo_error = getArrayValue($this->curItem->FieldErrors, $field_name, 'pseudo');
- if ($pseudo_error) {
- $this->curItem->SetDBField($field_name, null);
- unset($this->curItem->FieldErrors[$field_name]);
- }
- }
-
- function resetImportObject(&$event, $object_type, $record_data = null)
- {
- switch ($object_type) {
- case IMPORT_TEMP:
- $this->curItem =& $event->getObject( Array('skip_autoload' => true) );
- break;
-
- case IMPORT_LIVE:
- $this->curItem =& $this->Application->recallObject($event->Prefix.'.-tmpitem'.$event->Special, $event->Prefix, Array('skip_autoload' => true));
- break;
- }
- $this->curItem->Clear();
- $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
-
- if (isset($record_data)) {
- $this->setImportData($record_data);
- }
- }
-
- function setImportData($record_data)
- {
- foreach ($record_data as $field_index => $field_value) {
- $this->setFieldValue($field_index, $field_value);
- }
- $this->setCurrentID();
- }
-
-
- function getItemCategory()
- {
- static $lang_prefix = null;
- $backup_category_id = $this->Application->GetVar('m_cat_id');
-
- $category_id = $this->getFromCache('category_names', implode(':', $this->curItem->CategoryPath));
- if ($category_id) {
- $this->Application->SetVar('m_cat_id', $category_id);
- return $category_id;
- }
-
- if (is_null($lang_prefix)) {
- $lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_';
- }
-
- foreach ($this->curItem->CategoryPath as $category_index => $category_name) {
- if (!$category_name) continue;
- $category_key = crc32( implode(':', array_slice($this->curItem->CategoryPath, 0, $category_index + 1) ) );
-
- $category_id = $this->getFromCache('category_names', $category_key);
- if ($category_id === false) {
- // get parent category path to search only in it
- $current_category_id = $this->Application->GetVar('m_cat_id');
-// $parent_path = $this->getParentPath($current_category_id);
-
- // get category id from database by name
- $sql = 'SELECT CategoryId
- FROM '.TABLE_PREFIX.'Category
- WHERE ('.$lang_prefix.'Name = '.$this->Conn->qstr($category_name).') AND (ParentId = '.$current_category_id.')';
- $category_id = $this->Conn->GetOne($sql);
-
- if ($category_id === false) {
- // category not in db -> create
- $category_fields = Array( $lang_prefix.'Name' => $category_name, $lang_prefix.'Description' => $category_name,
- 'Status' => STATUS_ACTIVE, 'ParentId' => $current_category_id, 'AutomaticFilename' => 1
- );
- $this->dummyCategory->SetDBFieldsFromHash($category_fields);
- if ($this->dummyCategory->Create()) {
- $category_id = $this->dummyCategory->GetID();
- $this->addToCache('category_parent_path', $category_id, $this->dummyCategory->GetDBField('ParentPath'));
- $this->addToCache('category_names', $category_key, $category_id);
- }
- }
- else {
- $this->addToCache('category_names', $category_key, $category_id);
- }
- }
-
- if ($category_id) {
- $this->Application->SetVar('m_cat_id', $category_id);
- }
- }
- if (!$this->curItem->CategoryPath) {
- $category_id = $backup_category_id;
- }
-
- return $category_id;
- }
-
- /**
- * Enter description here...
- *
- * @param kEvent $event
- */
- function processCurrentItem(&$event, $record_data)
- {
- $save_method = 'Create';
- $load_keys = Array();
-
- // create/update categories
- $backup_category_id = $this->Application->GetVar('m_cat_id');
-
- // perform replace duplicates code
- if ($this->exportOptions['ReplaceDuplicates']) {
- // get replace keys first, then reset current item to empty one
- $category_id = $this->getItemCategory();
- if ($this->exportOptions['CheckDuplicatesMethod'] == 1) {
- if ($this->curItem->GetID()) {
- $load_keys = Array($this->curItem->IDField => $this->curItem->GetID());
- }
- }
- else {
- $key_fields = $this->exportOptions['DuplicateCheckFields'];
- foreach ($key_fields as $key_field) {
- $load_keys[$key_field] = $this->curItem->GetDBField($key_field);
- }
- }
-
- $this->resetImportObject($event, IMPORT_LIVE);
-
- if (count($load_keys)) {
- $where_clause = '';
- foreach ($load_keys as $field_name => $field_value) {
- if (preg_match('/^cust_(.*)/', $field_name, $regs)) {
- $custom_id = array_search($regs[1], $this->customFields);
- $field_name = 'l'.$this->Application->GetVar('m_lang').'_cust_'.$custom_id;
- $where_clause .= '(custom_data.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
- }
- else {
- $where_clause .= '(item_table.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND ';
- }
-
- }
- $where_clause = preg_replace('/(.*) AND $/', '\\1', $where_clause);
-
- $item_id = $this->getFromCache('new_ids', crc32($where_clause));
- if (!$item_id) {
- if ($this->exportOptions['CheckDuplicatesMethod'] == 2) {
- // by other fields
- $parent_path = $this->getParentPath($category_id);
- $where_clause = '(c.ParentPath LIKE "'.$parent_path.'%") AND '.$where_clause;
- }
-
- $cdata_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
- $sql = 'SELECT '.$this->curItem->IDField.'
- FROM '.$this->curItem->TableName.' item_table
- LEFT JOIN '.$cdata_table.' custom_data ON custom_data.ResourceId = item_table.ResourceId
- LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId
- LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
- WHERE '.$where_clause;
- $item_id = $this->Conn->GetOne($sql);
- }
- $save_method = $item_id && $this->curItem->Load($item_id) ? 'Update' : 'Create';
- if ($save_method == 'Update') {
- // replace id from csv file with found id (only when ID is found in cvs file)
- if (in_array($this->curItem->IDField, $this->exportFields)) {
- $record_data[ array_search($this->curItem->IDField, $this->exportFields) ] = $item_id;
- }
- }
- }
-
- $this->setImportData($record_data);
- }
- else {
- $this->resetImportObject($event, IMPORT_LIVE, $record_data);
- $category_id = $this->getItemCategory();
- }
-
- // create main record
- if ($save_method == 'Create') {
- $this->fillRequiredFields($this->false, $this->curItem, true);
- }
-
-// $sql_start = getmicrotime();
- if (!$this->curItem->$save_method()) {
- $this->Application->SetVar('m_cat_id', $backup_category_id);
- return false;
- }
-// $sql_end = getmicrotime();
-// $this->saveLog('SQL ['.$save_method.'] Time: '.($sql_end - $sql_start).'s');
-
- if ($load_keys && ($save_method == 'Create') && $this->exportOptions['ReplaceDuplicates']) {
- // map new id to old id
- $this->addToCache('new_ids', crc32($where_clause), $this->curItem->GetID() );
- }
-
- // assign item to categories
- $this->curItem->assignToCategory($category_id, false);
-
- $this->Application->SetVar('m_cat_id', $backup_category_id);
- return true;
- }
-
- /*function saveLog($msg)
- {
- static $first_time = true;
-
- $fp = fopen(FULL_PATH.'/sqls.log', $first_time ? 'w' : 'a');
- fwrite($fp, $msg."\n");
- fclose($fp);
-
- $first_time = false;
- }*/
-
- /**
- * Returns category parent path, if possible, then from cache
- *
- * @param int $category_id
- * @return string
- */
- function getParentPath($category_id)
- {
- $parent_path = $this->getFromCache('category_parent_path', $category_id);
- if ($parent_path === false) {
- $sql = 'SELECT ParentPath
- FROM '.TABLE_PREFIX.'Category
- WHERE CategoryId = '.$category_id;
- $parent_path = $this->Conn->GetOne($sql);
- $this->addToCache('category_parent_path', $category_id, $parent_path);
- }
- return $parent_path;
- }
-
- function getFileExtension()
- {
- return $this->exportOptions['ExportFormat'] == 1 ? 'csv' : 'xml';
- }
-
- function getLineSeparator($option = 'LineEndings')
- {
- return $this->exportOptions[$option] == 1 ? "\r\n" : "\n";
- }
-
- /**
- * Returns field caption for any exported field
- *
- * @param string $field
- * @return string
- */
- function getFieldCaption($field)
- {
- if (substr($field, 0, 10) == '__CUSTOM__')
- {
- $ret = 'Custom_'.substr($field, 10, strlen($field) );
- }
- elseif (substr($field, 0, 12) == '__CATEGORY__')
- {
- return $this->getCategoryTitle();
- }
- elseif (substr($field, 0, 11) == '__VIRTUAL__') {
- $ret = substr($field, 11);
- }
- else
- {
- $ret = $field;
- }
-
- return Array($ret);
- }
-
- /**
- * Returns requested field value (including custom fields and category fields)
- *
- * @param string $field
- * @return string
- */
- function getFieldValue($field)
- {
- if (substr($field, 0, 10) == '__CUSTOM__') {
- $field = 'cust_'.substr($field, 10, strlen($field));
- $ret = $this->curItem->GetField($field);
- }
- elseif (substr($field, 0, 12) == '__CATEGORY__') {
- return $this->getCategoryPath();
- }
- elseif (substr($field, 0, 11) == '__VIRTUAL__') {
- $field = substr($field, 11);
- $ret = $this->curItem->GetField($field);
- }
- else
- {
- $ret = $this->curItem->GetField($field);
- }
-
- $ret = str_replace("\r\n", $this->getLineSeparator('LineEndingsInside'), $ret);
- return Array($ret);
- }
-
- /**
- * Returns category field(-s) caption based on export mode
- *
- * @return string
- */
- function getCategoryTitle()
- {
- // category path in separated fields
- $category_count = $this->getMaxCategoryLevel();
- if ($this->exportOptions['CategoryFormat'] == 1)
- {
- // category path in one field
- return $category_count ? Array('CategoryPath') : Array();
- }
- else
- {
- $i = 0;
- $ret = Array();
- while ($i < $category_count) {
- $ret[] = 'Category'.($i + 1);
- $i++;
- }
- return $ret;
- }
- }
-
- /**
- * Returns category path in required format for current link
- *
- * @return string
- */
- function getCategoryPath()
- {
- $category_id = $this->curItem->GetDBField('CategoryId');
- $category_path = $this->getFromCache('category_path', $category_id);
- if (!$category_path)
- {
- $ml_formatter =& $this->Application->recallObject('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') {
- array_shift($category_path);
- }
-
- if ($this->exportOptions['IsBaseCategory']) {
- $i = $this->exportOptions['BaseLevel'];
- while ($i > 0) {
- array_shift($category_path);
- $i--;
- }
- }
-
- $category_count = $this->getMaxCategoryLevel();
- if ($this->exportOptions['CategoryFormat'] == 1) {
- // category path in single field
- $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)
- {
- $i = 0;
- while ($i < $category_count - $levels_used) {
- $category_path[] = '';
- $i++;
- }
- }
- }
- $this->addToCache('category_path', $category_id, $category_path);
- }
-
- return $category_path;
- }
-
- /**
- * Get maximal category deep level from links beeing exported
- *
- * @return int
- */
- function getMaxCategoryLevel()
- {
- static $max_level = -1;
-
- if ($max_level != -1)
- {
- return $max_level;
- }
-
- $sql = 'SELECT IF(c.CategoryId IS NULL, 0, MAX( LENGTH(c.ParentPath) - LENGTH( REPLACE(c.ParentPath, "|", "") ) - 1 ))
- FROM '.$this->curItem->TableName.' item_table
- LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON item_table.ResourceId = ci.ItemResourceId
- LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId
- WHERE (ci.PrimaryCat = 1) AND ';
-
- $where_clause = '';
- if ($this->exportOptions['export_ids'] === false) {
- // get links from current category & all it's subcategories
- if ($this->exportOptions['export_cats_ids'][0] == 0) {
- $where_clause = 1;
- }
- else {
- foreach ($this->exportOptions['export_cats_ids'] as $category_id) {
- $where_clause .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR ';
- }
- $where_clause = preg_replace('/(.*) OR $/', '\\1', $where_clause);
- }
- }
- else {
- // get only selected links
- $where_clause = $this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')';
- }
-
- $max_level = $this->Conn->GetOne($sql.'('.$where_clause.')');
-
- if ($this->exportOptions['IsBaseCategory'] ) {
- $max_level -= $this->exportOptions['BaseLevel'];
- }
-
- return $max_level;
- }
-
- /**
- * Saves one record to export file
- *
- * @param Array $fields_hash
- */
- function writeRecord($fields_hash)
- {
- fputcsv2($this->filePointer, $fields_hash, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy'], $this->getLineSeparator() );
- }
-
- function readRecord()
- {
- return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']);
- }
-
- function saveOptions(&$event, $options = null)
- {
- if (!isset($options)) {
- $options = $this->exportOptions;
- }
- $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) );
- }
-
- function loadOptions(&$event)
- {
- return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options'));
- }
-
- /**
- * Sets correct available & export fields
- *
- * @param kEvent $event
- */
- function prepareExportColumns(&$event)
- {
- $object =& $event->getObject( Array('skip_autoload' => true) );
-
- if (!array_key_exists('ExportColumns', $object->Fields)) {
- // import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported
- return ;
- }
-
- $available_columns = Array();
-
- if ($this->Application->getUnitOption($event->Prefix, 'CatalogItem')) {
- // category field (mixed)
- $available_columns['__CATEGORY__CategoryPath'] = 'CategoryPath';
-
- if ($event->Special == 'import') {
- // category field (separated fields)
- $max_level = $this->Application->ConfigValue('MaxImportCategoryLevels');
- $i = 0;
- while ($i < $max_level) {
- $available_columns['__CATEGORY__Category'.($i + 1)] = 'Category'.($i + 1);
- $i++;
- }
- }
- }
-
- // db fields
- foreach ($object->Fields as $field_name => $field_options)
- {
- if (!$object->skipField($field_name))
- {
- $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : '');
- }
- }
-
- $handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
- $available_columns = array_merge_recursive2($available_columns, $handler->getCustomExportColumns($event));
-
- // custom fields
- foreach ($object->customFields as $custom_id => $custom_name)
- {
- $available_columns['__CUSTOM__'.$custom_name] = $custom_name;
- }
-
- // columns already in use
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info)
- {
- list($item_id, $field_values) = each($items_info);
- $export_keys = $field_values['ExportColumns'];
- $export_keys = $export_keys ? explode('|', substr($export_keys, 1, -1) ) : Array();
- }
- else {
- $export_keys = Array();
- }
-
- $export_columns = Array();
- foreach ($export_keys as $field_key)
- {
- $field_name = $this->getExportField($field_key);
- $export_columns[$field_key] = $field_name;
- unset($available_columns[$field_key]);
- }
-
- $options = $object->GetFieldOptions('ExportColumns');
- $options['options'] = $export_columns;
- $object->SetFieldOptions('ExportColumns', $options);
-
- $options = $object->GetFieldOptions('AvailableColumns');
- $options['options'] = $available_columns;
- $object->SetFieldOptions('AvailableColumns', $options);
-
- $this->updateImportFiles($event);
- $this->PrepareExportPresets($event);
- }
-
- function PrepareExportPresets(&$event)
- {
- $object =& $event->getObject( Array('skip_autoload' => true) );
- $options = $object->GetFieldOptions('ExportPresets');
-
- $export_settings = $this->Application->RecallPersistentVar('export_settings');
- if (!$export_settings) return ;
- $export_settings = unserialize($export_settings);
-
- if (!isset($export_settings[$event->Prefix])) return ;
-
-
- $export_presets = array(''=>'');
- foreach ($export_settings[$event->Prefix] as $key => $val) {
- $export_presets[implode('|', $val['ExportColumns'])] = $key;
- }
-
- $options['options'] = $export_presets;
- $object->SetFieldOptions('ExportPresets', $options);
- }
-
- function getExportField($field_key)
- {
- $prepends = Array('__CUSTOM__', '__CATEGORY__');
- foreach ($prepends as $prepend)
- {
- if (substr($field_key, 0, strlen($prepend) ) == $prepend)
- {
- $field_key = substr($field_key, strlen($prepend), strlen($field_key) );
- break;
- }
- }
- return $field_key;
- }
-
- /**
- * Updates uploaded files list
- *
- * @param kEvent $event
- */
- function updateImportFiles(&$event)
- {
- if ($event->Special != 'import') {
- return false;
- }
-
- $object =& $event->getObject();
-
- $import_filenames = Array();
-
- 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 = formatSize( filesize(EXPORT_PATH.'/'.$file) );
- $import_filenames[$file] = $file.' ('.$file_size.')';
- }
- closedir($folder_handle);
- }
-
- $options = $object->GetFieldOptions('ImportLocalFilename');
- $options['options'] = $import_filenames;
- $object->SetFieldOptions('ImportLocalFilename', $options);
- }
-
- /**
- * Returns module folder
- *
- * @param kEvent $event
- * @return string
- */
- function getModuleFolder(&$event)
- {
- return $this->Application->getUnitOption($event->Prefix, 'ModuleFolder');
- }
-
- /**
- * Export form validation & processing
- *
- * @param kEvent $event
- */
- function OnExportBegin(&$event)
- {
- $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->SetFieldsFromHash($field_values);
- $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
-
- $object->setID($item_id);
- $this->setRequiredFields($event);
-
- $export_object =& $this->Application->recallObject('CatItemExportHelper');
-
- // 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');
-
- // 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['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));
- $field_values = $nevent->getEventParam('options');
-
- $export_object->saveOptions($event, $field_values);
-
- if( $export_object->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[$event->Prefix][$name] = $field_values;
- $this->Application->StorePersistentVar('export_settings', serialize($export_settings));
- }
-
- $progress_t = $this->Application->RecallVar('export_progress_t');
- if ($progress_t) {
- $this->Application->RemoveVar('export_progress_t');
- }
- else {
- $progress_t = $export_object->getModuleFolder($event).'/'.$event->Special.'_progress';
- }
- $event->redirect = $progress_t;
-
- if ($event->Special == 'import') {
- $import_category = (int)$this->Application->RecallVar('ImportCategory');
-
- // in future could use module root category if import category will be unavailable :)
- $event->SetRedirectParam('m_cat_id', $import_category); // for template permission checking
- $this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking
- }
- }
- else
- {
- // make uploaded file local & change source selection
- $filename = getArrayValue($field_values, 'ImportFilename');
- if ($filename) {
- $export_object->updateImportFiles($event);
- $object->SetDBField('ImportSource', 2);
- $field_values['ImportSource'] = 2;
- $object->SetDBField('ImportLocalFilename', $filename);
- $field_values['ImportLocalFilename'] = $filename;
- $export_object->saveOptions($event, $field_values);
- }
-
- $event->status = erFAIL;
- $event->redirect = false;
- }
- }
-
- /**
- * Returns export save preset name, when used at all
- *
- * @param kDBItem $object
- * @return string
- */
- function _getExportSavePreset(&$object)
- {
- if (!array_key_exists('ExportSavePreset', $object->Fields)) {
- return '';
- }
-
- return $object->GetDBField('ExportSavePreset');
- }
-
- /**
- * set required fields based on import or export params
- *
- * @param kEvent $event
- */
- function setRequiredFields(&$event)
- {
- $required_fields['common'] = Array('FieldsSeparatedBy', 'LineEndings', 'CategoryFormat');
-
- $required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns');
-
- $object =& $event->getObject();
- if ($this->_getExportSavePreset($object)) {
- $required_fields['export'][] = 'ExportPresetName';
- }
-
- $required_fields['import'] = Array('FieldTitles', 'ImportSource', 'CheckDuplicatesMethod'); // ImportFilename, ImportLocalFilename
-
- if ($event->Special == 'import')
- {
- $import_source = Array(1 => 'ImportFilename', 2 => 'ImportLocalFilename');
- $used_field = $import_source[ $object->GetDBField('ImportSource') ];
-
- $required_fields[$event->Special][] = $used_field;
- $object->Fields[$used_field]['error_field'] = 'ImportSource';
-
- if ($object->GetDBField('FieldTitles') == 2) $required_fields[$event->Special][] = 'ExportColumns'; // manual field titles
- }
-
- $required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]);
- foreach ($required_fields as $required_field) {
- $object->setRequired($required_field, true);
- }
- }
-
- }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/cat_dbitem_export.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.24.2.5
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/cat_dbitem.php
===================================================================
--- branches/5.0.x/core/units/general/cat_dbitem.php (revision 12342)
+++ branches/5.0.x/core/units/general/cat_dbitem.php (nonexistent)
@@ -1,598 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
-defined('FULL_PATH') or die('restricted access!');
-
-class kCatDBItem extends kDBItem {
-
- /**
- * Category path, needed for import
- *
- * @var Array
- */
- var $CategoryPath = Array();
-
- /**
- * Use automatic filename generation
- *
- * @var bool
- */
- var $useFilenames = true;
-
- /**
- * Use pending editing abilities during item (delegated by permissions)
- *
- * @var bool
- */
- var $usePendingEditing = false;
-
- function Clear($new_id = null)
- {
- parent::Clear($new_id);
- $this->CategoryPath = Array();
- }
-
- /**
- * Set's prefix and special
- *
- * @param string $prefix
- * @param string $special
- * @access public
- */
- function Init($prefix, $special, $event_params = null)
- {
- parent::Init($prefix, $special, $event_params);
- $this->usePendingEditing = $this->Application->getUnitOption($this->Prefix, 'UsePendingEditing');
- }
-
- function Create($force_id = false, $system_create = false)
- {
- // TODO: move to OnBeforeItemCreate method
- if ($this->Validate()) {
- // TODO: such approach will not respect changes from OnBeforeItemCreate event
- $this->SetDBField('ResourceId', $this->Application->NextResourceId());
- }
-
- $this->SetDBField('Modified_date', adodb_mktime() );
- $this->SetDBField('Modified_time', adodb_mktime() );
-
- if ($this->mode != 't' && !$this->Application->IsAdmin()) {
- $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
- if (!$owner_field) {
- $owner_field = 'CreatedById';
- }
- $this->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
- }
-
- if ($this->useFilenames) {
- $this->checkFilename();
- $this->generateFilename();
- }
-
- $ret = parent::Create($force_id, $system_create);
-
- if ($ret) {
- // TODO: move to OnAfterItemCreate method
- $this->assignPrimaryCategory();
- }
- return $ret;
- }
-
- function assignPrimaryCategory()
- {
- $primary_category = $this->GetDBField('CategoryId') > 0 ? $this->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
- $this->assignToCategory($primary_category, true);
- }
-
- function Update($id=null, $system_update=false)
- {
- $this->VirtualFields['ResourceId'] = Array();
- $this->SetDBField('Modified', adodb_mktime() );
- $this->UpdateFormattersSubFields(array('Modified'));
- $this->SetDBField('ModifiedById', $this->Application->RecallVar('user_id'));
-
- if ($this->useFilenames) {
- $this->checkFilename();
- $this->generateFilename();
- }
-
- $ret = parent::Update($id, $system_update);
-
- if ($ret) {
- $filename = $this->useFilenames ? $this->GetDBField('Filename') : '';
- $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;
- }
-
- /**
- * Returns CategoryItems table based on current item mode (temp/live)
- *
- * @return string
- */
- function CategoryItemsTable()
- {
- $table = TABLE_PREFIX.'CategoryItems';
- if ($this->Application->IsTempTable($this->TableName)) {
- $table = $this->Application->GetTempName($table, 'prefix:'.$this->Prefix);
- }
-
- return $table;
- }
-
-
- function checkFilename()
- {
- if( !$this->GetDBField('AutomaticFilename') )
- {
- $filename = $this->GetDBField('Filename');
- $this->SetDBField('Filename', $this->stripDisallowed($filename) );
- }
- }
-
- function Copy($cat_id=null)
- {
- if (!isset($cat_id)) $cat_id = $this->Application->GetVar('m_cat_id');
- $this->NameCopy($cat_id);
- return $this->Create($cat_id);
- }
-
- function NameCopy($master=null, $foreign_key=null)
- {
- $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
- if (!$title_field) return;
-
- $new_name = $this->GetDBField($title_field);
- $cat_id = $this->Application->GetVar('m_cat_id');
- $original_checked = false;
- do {
- if ( preg_match('/Copy ([0-9]*) *of (.*)/', $new_name, $regs) ) {
- $new_name = 'Copy '.( (int)$regs[1] + 1 ).' of '.$regs[2];
- }
- elseif ($original_checked) {
- $new_name = 'Copy of '.$new_name;
- }
- $query = 'SELECT '.$title_field.' FROM '.$this->TableName.'
- LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON
- ('.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$this->TableName.'.ResourceId)
- WHERE ('.TABLE_PREFIX.'CategoryItems.CategoryId = '.$cat_id.') AND '.
- $title_field.' = '.$this->Conn->qstr($new_name);
- $res = $this->Conn->GetOne($query);
- $original_checked = true;
- } while ($res !== false);
- $this->SetDBField($title_field, $new_name);
-
- // this is needed, because Create will create items in its own CategoryId (if it's set),
- // but we need to create it in target Paste category @see{kCatDBItem::Create} and its primary_category detection
- $this->SetDBField('CategoryId', $cat_id);
- }
-
- /**
- * Changes item primary category to given/current category
- *
- * @param int $category_id
- */
- function MoveToCat($category_id = null)
- {
-// $this->NameCopy();
- if (!isset($category_id)) {
- $category_id = $this->Application->GetVar('m_cat_id');
- }
-
- $table_name = TABLE_PREFIX . 'CategoryItems';
- if ($this->IsTempTable()) {
- $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix);
- }
-
- // check if the item already exists in destination category
- $sql = 'SELECT PrimaryCat
- FROM ' . $table_name . '
- WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
- $is_primary = $this->Conn->GetOne($sql);
-
- // if it's not found is_primary will be FALSE, if it's found but not primary it will be int 0
- $exists = $is_primary !== false;
-
- if ($exists) {
- // if the item already exists in destination category
- if ($is_primary) {
- // do nothing when we paste to primary
- return ;
- }
-
- // if it's not primary - delete it from destination category, as we will move it from current primary below
- $sql = 'DELETE FROM ' . $table_name . '
- WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')';
- $this->Conn->Query($sql);
- }
-
- // change category id in existing primary category record
- $sql = 'UPDATE ' . $table_name . '
- SET CategoryId = ' . $category_id . '
- WHERE (ItemResourceId = ' . $this->GetDBField('ResourceId') . ') AND (PrimaryCat = 1)';
- $this->Conn->Query($sql);
-
- $this->Update();
- }
-
- /**
- * When item is deleted, then also delete it from all categories
- *
- * @param int $id
- * @return bool
- */
- function Delete($id = null)
- {
- if( isset($id) ) {
- $this->setID($id);
- }
-
- $this->Load($this->GetID());
-
- $ret = parent::Delete();
-
- if ($ret) {
- // TODO: move to OnAfterItemDelete method
- $query = ' DELETE FROM ' . $this->CategoryItemsTable() . '
- WHERE ItemResourceId = ' . $this->GetDBField('ResourceId');
- $this->Conn->Query($query);
- }
-
- return $ret;
- }
-
- /**
- * Deletes item from categories
- *
- * @param Array $delete_category_ids
- * @author Alex
- */
- function DeleteFromCategories($delete_category_ids)
- {
- $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); // because item was loaded before by ResourceId
-
- $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)';
-
- $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);
- }
- 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 ) );
- }
- }
- }
-
- /**
- * replace not allowed symbols with "_" chars + remove duplicate "_" chars in result
- *
- * @param string $string
- * @return string
- */
- function stripDisallowed($filename)
- {
- $filenames_helper =& $this->Application->recallObject('FilenamesHelper');
- $table = $this->mode == 't' ? $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems', 'prefix:'.$this->Prefix) : TABLE_PREFIX.'CategoryItems';
-
- return $filenames_helper->stripDisallowed($table, 'ItemResourceId', $this->GetDBField('ResourceId'), $filename);
- }
-
- /* commented out because it's called only from stripDisallowed body, which is moved to helper
-
- function checkAutoFilename($filename)
- {
- $filenames_helper =& $this->Application->recallObject('FilenamesHelper');
- return $filenames_helper->checkAutoFilename($this->TableName, $this->IDField, $this->GetID(), $filename);
- }*/
-
- /**
- * Generate item's filename based on it's title field value
- *
- * @return string
- */
- function generateFilename()
- {
- if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) return false;
-
- $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField');
- 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];
- }
- $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 (!$res) {
- $this->SetError($field, 'required');
- }
- return $res;
- }
-
- /**
- * Adds item to other category
- *
- * @param int $category_id
- * @param bool $is_primary
- */
- function assignToCategory($category_id, $is_primary = false)
- {
- $table = $this->CategoryItemsTable();
- $key_clause = '(ItemResourceId = '.$this->GetDBField('ResourceId').')';
-
- // get all cateories, 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;
- }
- }
-
- if ($primary_found && ($item_category_id == $category_id) && !$is_primary) {
- // want to make primary category as non-primary :(
- return true;
- }
- else if (!$primary_found) {
- $is_primary = true;
- }
-
- if ($is_primary && $item_categories) {
- // reset primary mark from all other categories
- $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.')';
- $this->Conn->Query($sql);
- }
- else {
- $fields_hash = Array(
- 'CategoryId' => $category_id,
- 'ItemResourceId' => $this->GetField('ResourceId'),
- 'PrimaryCat' => $is_primary ? 1 : 0,
- 'ItemPrefix' => $this->Prefix,
- 'Filename' => $this->useFilenames ? $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();
- }
-
- /**
- * Removes item from category specified
- *
- * @param int $category_id
- */
- function removeFromCategory($category_id)
- {
- $sql = 'DELETE FROM '.TABLE_PREFIX.'CategoryItems WHERE (CategoryId = %s) AND (ItemResourceId = %s)';
- $this->Conn->Query( sprintf($sql, $category_id, $this->GetDBField('ResourceId')) );
- }
-
- /**
- * Returns list of columns, that could exist in imported file
- *
- * @return Array
- */
- function getPossibleExportColumns()
- {
- static $columns = null;
- if (!is_array($columns)) {
- $columns = array_merge($this->Fields['AvailableColumns']['options'], $this->Fields['ExportColumns']['options']);
- }
- return $columns;
- }
-
- /**
- * Returns item's primary image data
- *
- * @return Array
- */
- function getPrimaryImageData()
- {
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'Images
- WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (DefaultImg = 1)';
- $image_data = $this->Conn->GetRow($sql);
- if (!$image_data) {
- // 2. no primary image, then get image with name "main"
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'Images
- WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (Name = "main")';
- $image_data = $this->Conn->GetRow($sql);
- }
- return $image_data;
- }
-
- function ChangeStatus($new_status)
- {
- $status_field = array_shift( $this->Application->getUnitOption($this->Prefix,'StatusField') );
- if ($new_status != $this->GetDBField($status_field)) {
- // status was changed
- $this->sendEmailEvents($new_status);
- }
- $this->SetDBField($status_field, $new_status);
-
- return $this->Update();
- }
-
- function sendEmailEvents($new_status)
- {
- $perm_prefix = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix');
- $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField');
- if (!$owner_field) {
- $owner_field = 'CreatedById';
- }
-
- $event_name = $perm_prefix.'.'.($new_status == STATUS_ACTIVE ? 'APPROVE' : 'DENY');
- $this->Application->EmailEventUser($event_name, $this->GetDBField($owner_field));
- }
-
- /**
- * Approves changes made to category item
- *
- * @return bool
- */
- function ApproveChanges()
- {
- $original_id = $this->GetDBField('OrgId');
-
- 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))) {
- // 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));
-
- $this->SetDBField('OrgId', 0);
- return $this->ChangeStatus(STATUS_ACTIVE);
- }
-
- return false;
- }
-
- /**
- * Decline changes made to category item
- *
- * @return bool
- */
- function DeclineChanges()
- {
- $original_id = $this->GetDBField('OrgId');
-
- 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()));
-
- // original item is not changed here, because it is already enabled (thrus pending copy is visible to item's owner or admin with permission)
- return true;
- }
-
- function RegisterHit()
- {
- $already_viewed = $this->Application->RecallVar($this->getPrefixSpecial().'_already_viewed');
- $already_viewed = $already_viewed ? unserialize($already_viewed) : Array ();
-
- $id = $this->GetID();
- if (!in_array($id, $already_viewed)) {
- $property_map = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
- if (!$property_map) {
- return ;
- }
- $hits_field = $property_map['ClickField'];
- $new_hits = $this->GetDBField($hits_field) + 1;
-
- $sql = 'SELECT MAX('.$hits_field.')
- FROM '.$this->TableName.'
- WHERE FLOOR('.$hits_field.') = '.$new_hits;
- $max_hits = $this->Conn->GetOne($sql);
- if ($max_hits) {
- $new_hits = $max_hits + 0.000001;
- }
-
- $fields_hash = Array (
- $hits_field => $new_hits,
- );
- $this->Conn->doUpdate($fields_hash, $this->TableName, $this->IDField.' = '.$id);
-
- array_push($already_viewed, $id);
- $this->Application->StoreVar($this->getPrefixSpecial().'_already_viewed', serialize($already_viewed));
- }
- }
-
- /**
- * 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)
- {
- if ($method == 'load') {
- // for item with many categories makes primary to load
- $ci_table = TABLE_PREFIX.'CategoryItems';
- if ($this->IsTempTable()) {
- $ci_table = $this->Application->GetTempName($ci_table, 'prefix:'.$this->Prefix);
- }
- $keys_hash = Array(
- $this->IDField => $this->ID,
- '`'.$ci_table.'`.`PrimaryCat`' => 1,
- );
- }
- return parent::GetKeyClause($method, $keys_hash);
- }
-
-}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/cat_dbitem.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.40.2.6
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/cat_dblist.php
===================================================================
--- branches/5.0.x/core/units/general/cat_dblist.php (revision 12342)
+++ branches/5.0.x/core/units/general/cat_dblist.php (nonexistent)
@@ -1,37 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
- defined('FULL_PATH') or die('restricted access!');
-
- class kCatDBList extends kDBList {
-
- /**
- * Select items from current category or from all categories
- *
- * @var bool
- */
- var $Scope = true;
-
- /*function GetWhereClause($for_counting=false,$system_filters_only=false)
- {
- switch ($this->Special)
- {
- case 'showall':
- $this->clearFilters(false,true,false,false);
- break;
- }
- return parent::GetWhereClause($for_counting,$system_filters_only);
- }*/
-
- }
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/cat_dblist.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.4
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/cat_event_handler.php
===================================================================
--- branches/5.0.x/core/units/general/cat_event_handler.php (revision 12342)
+++ branches/5.0.x/core/units/general/cat_event_handler.php (nonexistent)
@@ -1,2653 +0,0 @@
-<?php
-/**
-* @version $Id$
-* @package In-Portal
-* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
-* @license GNU/GPL
-* In-Portal is Open Source software.
-* This means that this software may have been modified pursuant
-* the GNU General Public License, and as distributed it includes
-* or is derivative of works licensed under the GNU General Public License
-* or other free or open source software licenses.
-* See http://www.in-portal.net/license/ for copyright notices and details.
-*/
-
-defined('FULL_PATH') or die('restricted access!');
-
-class kCatDBEventHandler extends kDBEventHandler {
-
- /**
- * Allows to override standart permission mapping
- *
- */
- function mapPermissions()
- {
- parent::mapPermissions();
- $permissions = Array(
- 'OnSaveSettings' => Array ('self' => 'add|edit|advanced:import'),
- 'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'),
- 'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
-
- 'OnCopy' => Array ('self' => true),
- 'OnDownloadFile' => Array ('self' => 'view'),
- 'OnCancelAction' => Array ('self' => true),
- 'OnItemBuild' => Array ('self' => true),
- 'OnMakeVote' => Array ('self' => true),
- );
-
- $this->permMapping = array_merge($this->permMapping, $permissions);
- }
-
- /**
- * Load item if id is available
- *
- * @param kEvent $event
- */
- function LoadItem(&$event)
- {
- $object =& $event->getObject();
- $id = $this->getPassedID($event);
- if ($object->Load($id)) {
- $actions =& $this->Application->recallObject('kActions');
- $actions->Set($event->Prefix_Special.'_id', $object->GetID() );
-
- $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
- if ($use_pending_editing && $event->Special != 'original') {
- $this->Application->SetVar($event->Prefix.'.original_id', $object->GetDBField('OrgId'));
- }
- }
- else {
- $object->setID($id);
- }
- }
-
- /**
- * Checks permissions of user
- *
- * @param kEvent $event
- */
- function CheckPermission(&$event)
- {
- if (!$this->Application->IsAdmin()) {
- if ($event->Name == 'OnSetSortingDirect') {
- // allow sorting on front event without view permission
- return true;
- }
- }
-
- if ($event->Name == 'OnExport') {
- // save category_id before doing export
- $this->Application->LinkVar('m_cat_id');
- }
-
- if (in_array($event->Name, $this->_getMassPermissionEvents())) {
- $items = $this->_getPermissionCheckInfo($event);
-
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- if (($event->Name == 'OnSave') && array_key_exists(0, $items)) {
- // adding new item (ID = 0)
- $perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0;
- }
- else {
- // leave only items, that can be edited
- $ids = Array ();
- $check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
- foreach ($items as $item_id => $item_data) {
- if ($perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0) {
- $ids[] = $item_id;
- }
- }
-
- if (!$ids) {
- // no items left for editing -> no permission
- return $perm_helper->finalizePermissionCheck($event, false);
- }
-
- $perm_value = true;
- $event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
- }
-
- return $perm_helper->finalizePermissionCheck($event, $perm_value);
- }
-
- $export_events = Array ('OnSaveSettings', 'OnResetSettings', 'OnExportBegin');
- if (in_array($event->Name, $export_events)) {
- // when import settings before selecting target import category
- return $this->Application->CheckPermission('in-portal:main_import.view');
- }
-
- if ($event->Name == 'OnProcessSelected') {
- if ($this->Application->RecallVar('dst_field') == 'ImportCategory') {
- // when selecting target import category
- return $this->Application->CheckPermission('in-portal:main_import.view');
- }
- }
-
- return parent::CheckPermission($event);
- }
-
- /**
- * Returns events, that require item-based (not just event-name based) permission check
- *
- * @return Array
- */
- function _getMassPermissionEvents()
- {
- return Array (
- 'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
- 'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
- 'OnCut',
- );
- }
-
- /**
- * Returns category item IDs, that require permission checking
- *
- * @param kEvent $event
- * @return string
- */
- function _getPermissionCheckIDs(&$event)
- {
- if ($event->Name == 'OnSave') {
- $selected_ids = implode(',', $this->getSelectedIDs($event, true));
- if (!$selected_ids) {
- $selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
- }
- }
- else {
- // OnEdit, OnMassDelete events, when items are checked in grid
- $selected_ids = implode(',', $this->StoreSelectedIDs($event));
- }
-
- return $selected_ids;
- }
-
- /**
- * Returns information used in permission checking
- *
- * @param kEvent $event
- * @return Array
- */
- function _getPermissionCheckInfo(&$event)
- {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- // when saving data from temp table to live table check by data from temp table
- $item_ids = $this->_getPermissionCheckIDs($event);
- $items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave');
-
- if (!$items) {
- // when item not present in temp table, then permission is not checked, because there are no data in db to check
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- list ($id, $fields_hash) = each($items_info);
-
- if (array_key_exists('CategoryId', $fields_hash)) {
- $item_category = $fields_hash['CategoryId'];
- }
- else {
- $item_category = $this->Application->GetVar('m_cat_id');
- }
-
- $items[$id] = Array (
- 'CreatedById' => $this->Application->RecallVar('use_id'),
- 'CategoryId' => $item_category,
- );
- }
-
- return $items;
- }
-
- /**
- * Add selected items to clipboard with mode = COPY (CLONE)
- *
- * @param kEvent $event
- */
- function OnCopy(&$event)
- {
- $this->Application->RemoveVar('clipboard');
- $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
- $clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
- $this->clearSelectedIDs($event);
- }
-
- /**
- * Add selected items to clipboard with mode = CUT
- *
- * @param kEvent $event
- */
- function OnCut(&$event)
- {
- $this->Application->RemoveVar('clipboard');
- $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
- $clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
- $this->clearSelectedIDs($event);
- }
-
- /**
- * Checks permission for OnPaste event
- *
- * @param kEvent $event
- * @return bool
- */
- function _checkPastePermission(&$event)
- {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- $category_id = $this->Application->GetVar('m_cat_id');
- if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
- // no items left for editing -> no permission
- return $perm_helper->finalizePermissionCheck($event, false);
- }
-
- return true;
- }
-
- /**
- * Performs category item paste
- *
- * @param kEvent $event
- */
- function OnPaste(&$event)
- {
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) {
- return;
- }
-
- $clipboard_data = $event->getEventParam('clipboard_data');
-
- if (!$clipboard_data['cut'] && !$clipboard_data['copy']) {
- return false;
- }
-
- if ($clipboard_data['copy']) {
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- /* @var $temp kTempTablesHandler */
-
- $this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone"
- $temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']);
- }
-
- if ($clipboard_data['cut']) {
- $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix, Array('skip_autoload' => true));
-
- foreach ($clipboard_data['cut'] as $id) {
- $object->Load($id);
- $object->MoveToCat();
- }
- }
- }
-
- /**
- * 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
- */
- function OnMassDelete(&$event)
- {
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
- return;
- }
-
- $event->status=erSUCCESS;
-
- $ids = $this->StoreSelectedIDs($event);
-
- $to_delete = array();
- if ($recycle_bin = $this->Application->ConfigValue('RecycleBinFolder')) {
- $rb =& $this->Application->recallObject('c.recycle', null, array('skip_autoload' => true));
- $rb->Load($recycle_bin);
- $object =& $this->Application->recallObject($event->Prefix.'.recycleitem', null, Array ('skip_autoload' => true));
- foreach ($ids as $id) {
- $object->Load($id);
- if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $object->GetDBField('ParentPath'))) {
- $to_delete[] = $id;
- continue;
- }
- $object->MoveToCat($recycle_bin);
- }
- $ids = $to_delete;
- }
-
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
-
- $event->setEventParam('ids', $ids);
- $this->customProcessing($event, 'before');
- $ids = $event->getEventParam('ids');
-
- if($ids)
- {
- $temp->DeleteItems($event->Prefix, $event->Special, $ids);
- }
- $this->clearSelectedIDs($event);
- }
-
-
- /**
- * Return type clauses for list bulding on front
- *
- * @param kEvent $event
- * @return Array
- */
- function getTypeClauses(&$event)
- {
- $types = $event->getEventParam('types');
- $types = $types ? explode(',', $types) : Array ();
-
- $except_types = $event->getEventParam('except');
- $except_types = $except_types ? explode(',', $except_types) : Array ();
-
- $type_clauses = Array();
-
- $user_id = $this->Application->RecallVar('user_id');
- $owner_field = $this->getOwnerField($event->Prefix);
-
- $type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id;
- $type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id;
- $type_clauses['my_items']['having_filter'] = false;
-
- $type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
- $type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
- $type_clauses['pick']['having_filter'] = false;
-
- $type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1';
- $type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1';
- $type_clauses['hot']['having_filter'] = true;
-
- $type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1';
- $type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1';
- $type_clauses['pop']['having_filter'] = true;
-
- $type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1';
- $type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1';
- $type_clauses['new']['having_filter'] = true;
-
- $type_clauses['displayed']['include'] = '';
- $displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids');
- if ($displayed) {
- $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
- $type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')';
- }
- else {
- $type_clauses['displayed']['except'] = '';
- }
- $type_clauses['displayed']['having_filter'] = false;
-
- if (in_array('search', $types) || in_array('search', $except_types)) {
- $event_mapping = Array(
- 'simple' => 'OnSimpleSearch',
- 'subsearch' => 'OnSubSearch',
- 'advanced' => 'OnAdvancedSearch');
- if($this->Application->GetVar('INPORTAL_ON') && $this->Application->GetVar('Action') == 'm_simple_subsearch')
- {
- $type = 'subsearch';
- }
- else
- {
- $type = $this->Application->GetVar('search_type') ? $this->Application->GetVar('search_type') : 'simple';
- }
-
- if($keywords = $event->getEventParam('keyword_string')) // processing keyword_string param of ListProducts tag
- {
- $this->Application->SetVar('keywords', $keywords);
- $type = 'simple';
- }
- $search_event = $event_mapping[$type];
- $this->$search_event($event);
-
- $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
- $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
- if ($this->Conn->Query($sql)) {
- $search_res_ids = $this->Conn->GetCol('SELECT ResourceId FROM '.$search_table);
- }
-
- if (isset($search_res_ids) && $search_res_ids) {
- $type_clauses['search']['include'] = '%1$s.ResourceId IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
- $type_clauses['search']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
- }
- else {
- $type_clauses['search']['include'] = '0';
- $type_clauses['search']['except'] = '1';
- }
- $type_clauses['search']['having_filter'] = false;
- }
-
- if (in_array('related', $types) || in_array('related', $except_types)) {
-
- $related_to = $event->getEventParam('related_to');
- if (!$related_to) {
- $related_prefix = $event->Prefix;
- }
- else {
- $sql = 'SELECT Prefix
- FROM '.TABLE_PREFIX.'ItemTypes
- WHERE ItemName = '.$this->Conn->qstr($related_to);
- $related_prefix = $this->Conn->GetOne($sql);
- }
-
- $rel_table = $this->Application->getUnitOption('rel', 'TableName');
- $item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
-
- if ($item_type == 0) {
- trigger_error('<strong>ItemType</strong> not defined for prefix <strong>' . $event->Prefix . '</strong>', E_USER_WARNING);
- }
-
- // process case, then this list is called inside another list
- $prefix_special = $event->getEventParam('PrefixSpecial');
- if (!$prefix_special) {
- $prefix_special = $this->Application->Parser->GetParam('PrefixSpecial');
- }
-
- $id = false;
- if ($prefix_special !== false) {
- $processed_prefix = $this->Application->processPrefix($prefix_special);
- if ($processed_prefix['prefix'] == $related_prefix) {
- // printing related categories within list of items (not on details page)
- $list =& $this->Application->recallObject($prefix_special);
- /* @var $list kDBList */
-
- $id = $list->GetID();
- }
- }
-
- if ($id === false) {
- // printing related categories for single item (possibly on details page)
- if ($related_prefix == 'c') {
- $id = $this->Application->GetVar('m_cat_id');
- }
- else {
- $id = $this->Application->GetVar($related_prefix . '_id');
- }
- }
-
- $p_item =& $this->Application->recallObject($related_prefix.'.current', null, Array('skip_autoload' => true));
- $p_item->Load( (int)$id );
-
- $p_resource_id = $p_item->GetDBField('ResourceId');
-
- $sql = 'SELECT SourceId, TargetId FROM '.$rel_table.'
- WHERE
- (Enabled = 1)
- AND (
- (Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
- OR
- (Type = 1
- AND (
- (SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.')
- OR
- (TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.')
- )
- )
- )';
-
- $related_ids_array = $this->Conn->Query($sql);
- $related_ids = Array();
-
- foreach ($related_ids_array as $key => $record) {
- $related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ];
- }
-
- if (count($related_ids) > 0) {
- $type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
- $type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).') AND PrimaryCat = 1';
- }
- else {
- $type_clauses['related']['include'] = '0';
- $type_clauses['related']['except'] = '1';
- }
- $type_clauses['related']['having_filter'] = false;
- }
-
- if (in_array('favorites', $types) || in_array('favorites', $except_types)) {
- $sql = 'SELECT ResourceId
- FROM '.$this->Application->getUnitOption('fav', 'TableName').'
- WHERE PortalUserId = '.$this->Application->RecallVar('user_id');
- $favorite_ids = $this->Conn->GetCol($sql);
- if ($favorite_ids) {
- $type_clauses['favorites']['include'] = '%1$s.ResourceId IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
- $type_clauses['favorites']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1';
- }
- else {
- $type_clauses['favorites']['include'] = 0;
- $type_clauses['favorites']['except'] = 1;
- }
- $type_clauses['favorites']['having_filter'] = false;
- }
-
- return $type_clauses;
- }
-
- /**
- * Returns SQL clause, that will help to select only data from specified category & it's children
- *
- * @param int $category_id
- * @return string
- */
- function getCategoryLimitClause($category_id)
- {
- if (!$category_id) {
- return false;
- }
-
- $tree_indexes = $this->Application->getTreeIndex($category_id);
- if (!$tree_indexes) {
- // id of non-existing category was given
- return 'FALSE';
- }
-
- return TABLE_PREFIX.'Category.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight'];
- }
-
- /**
- * Apply filters to list
- *
- * @param kEvent $event
- */
- function SetCustomQuery(&$event)
- {
- parent::SetCustomQuery($event);
-
- $object =& $event->getObject();
- /* @var $object kDBList */
-
- // add category filter if needed
- if ($event->Special != 'showall' && $event->Special != 'user') {
- if ($event->getEventParam('parent_cat_id') !== false) {
- $parent_cat_id = $event->getEventParam('parent_cat_id');
- }
- else {
- $parent_cat_id = $this->Application->GetVar('c_id');
- if (!$parent_cat_id) {
- $parent_cat_id = $this->Application->GetVar('m_cat_id');
- }
- if (!$parent_cat_id) {
- $parent_cat_id = 0;
- }
- }
-
- if ("$parent_cat_id" == '0') {
- // replace "0" category with "Content" category id (this way template
- $parent_cat_id = $this->Application->findModule('Name', 'Core', 'RootCat');
- }
-
- if ((string)$parent_cat_id != 'any') {
- if ($event->getEventParam('recursive')) {
- $filter_clause = $this->getCategoryLimitClause($parent_cat_id);
- if ($filter_clause !== false) {
- $object->addFilter('category_filter', $filter_clause);
- }
-
- $object->addFilter('primary_filter', 'PrimaryCat = 1');
- }
- else {
- $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id );
- }
- }
- else {
- $object->addFilter('primary_filter', 'PrimaryCat = 1');
- }
- }
- else {
- $object->addFilter('primary_filter', 'PrimaryCat = 1');
-
- // if using recycle bin don't show items from there
- $recycle_bin = $this->Application->ConfigValue('RecycleBinFolder');
- if ($recycle_bin) {
- $object->addFilter('recyclebin_filter', TABLE_PREFIX.'CategoryItems.CategoryId <> '.$recycle_bin);
- }
- }
-
- if ($event->Special == 'user') {
- $editable_user = $this->Application->GetVar('u_id');
- $object->addFilter('owner_filter', '%1$s.'.$this->getOwnerField($event->Prefix).' = '.$editable_user);
- }
-
- // add permission filter
- if ($this->Application->RecallVar('user_id') == -1) {
- // for "root" CATEGORY.VIEW permission is checked for items lists too
- $view_perm = 1;
- }
- else {
- // for any real user itemlist view permission is checked instead of CATEGORY.VIEW
- $count_helper =& $this->Application->recallObject('CountHelper');
- /* @var $count_helper kCountHelper */
-
- list ($view_perm, $view_filter) = $count_helper->GetPermissionClause($event->Prefix, 'perm');
- $object->addFilter('perm_filter2', $view_filter);
- }
-
- $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm);
-
-
- $types = $event->getEventParam('types');
- $this->applyItemStatusFilter($object, $types);
-
- $except_types = $event->getEventParam('except');
- $type_clauses = $this->getTypeClauses($event);
-
- // convert prepared type clauses into list filters
- $includes_or_filter =& $this->Application->makeClass('kMultipleFilter');
- $includes_or_filter->setType(FLT_TYPE_OR);
-
- $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter');
- $excepts_and_filter->setType(FLT_TYPE_AND);
-
- $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter');
- $includes_or_filter_h->setType(FLT_TYPE_OR);
-
- $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter');
- $excepts_and_filter_h->setType(FLT_TYPE_AND);
-
- if ($types) {
- $types_array = explode(',', $types);
- for ($i = 0; $i < sizeof($types_array); $i++) {
- $type = trim($types_array[$i]);
- if (isset($type_clauses[$type])) {
- if ($type_clauses[$type]['having_filter']) {
- $includes_or_filter_h->removeFilter('filter_'.$type);
- $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']);
- }else {
- $includes_or_filter->removeFilter('filter_'.$type);
- $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']);
- }
- }
- }
- }
-
- if ($except_types) {
- $except_types_array = explode(',', $except_types);
- for ($i = 0; $i < sizeof($except_types_array); $i++) {
- $type = trim($except_types_array[$i]);
- if (isset($type_clauses[$type])) {
- if ($type_clauses[$type]['having_filter']) {
- $excepts_and_filter_h->removeFilter('filter_'.$type);
- $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']);
- }else {
- $excepts_and_filter->removeFilter('filter_'.$type);
- $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']);
- }
- }
- }
- }
-
- /*if ( !$this->Application->IsAdmin() ) {
- $object->addFilter('expire_filter', '%1$s.Expire IS NULL OR %1$s.Expire > UNIX_TIMESTAMP()');
- }*/
-
- /*$list_type = $event->getEventParam('ListType');
- switch($list_type)
- {
- case 'favorites':
- $fav_table = $this->Application->getUnitOption('fav','TableName');
- $user_id =& $this->Application->RecallVar('user_id');
-
- $sql = 'SELECT DISTINCT f.ResourceId
- FROM '.$fav_table.' f
- LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId
- WHERE f.PortalUserId = '.$user_id;
- $ids = $this->Conn->GetCol($sql);
- if(!$ids) $ids = Array(-1);
- $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1');
- $object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
- break;
- case 'search':
- $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
- $sql = ' SELECT DISTINCT ResourceId
- FROM '.$search_results_table.'
- WHERE ItemType=11';
- $ids = $this->Conn->GetCol($sql);
- if(!$ids) $ids = Array(-1);
- $object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')');
- break;
- } */
-
- $object->addFilter('includes_filter', $includes_or_filter);
- $object->addFilter('excepts_filter', $excepts_and_filter);
-
- $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER);
- $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER);
- }
-
- /**
- * Adds filter that filters out items with non-required statuses
- *
- * @param kDBList $object
- * @param string $types
- */
- function applyItemStatusFilter(&$object, $types)
- {
- // Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID]
- $pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing');
-
- if ( !$this->Application->IsAdmin() ) {
- $types = explode(',', $types);
- if (in_array('my_items', $types)) {
- $allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING);
- $object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')');
-
- if ($pending_editing) {
- $user_id = $this->Application->RecallVar('user_id');
- $this->applyPendingEditingFilter($object, $user_id);
- }
- }
- else {
- $object->addFilter('status_filter', '(%1$s.Status = ' . STATUS_ACTIVE . ') AND (' . TABLE_PREFIX . 'Category.Status = ' . STATUS_ACTIVE . ')');
- if ($pending_editing) {
- // if category item uses pending editing abilities, then in no cases show pending copies on front
- $object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL');
- }
- }
- }
- else {
- if ($pending_editing) {
- $this->applyPendingEditingFilter($object);
- }
- }
- }
-
- /**
- * Adds filter, that removes live items if they have pending editing copies
- *
- * @param kDBList $object
- * @param int $user_id
- */
- function applyPendingEditingFilter(&$object, $user_id = null)
- {
- $sql = 'SELECT OrgId
- FROM '.$object->TableName.'
- WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL';
-
- if (isset($user_id)) {
- $owner_field = $this->getOwnerField($object->Prefix);
- $sql .= ' AND '.$owner_field.' = '.$user_id;
- }
-
- $pending_ids = $this->Conn->GetCol($sql);
- if ($pending_ids) {
- $object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')');
- }
- }
-
- /**
- * Adds calculates fields for item statuses
- *
- * @param kCatDBItem $object
- * @param kEvent $event
- */
- function prepareObject(&$object, &$event)
- {
- $this->prepareItemStatuses($event);
-
- $object->addCalculatedField('CachedNavbar', 'l'.$this->Application->GetVar('m_lang').'_CachedNavbar');
-
- if ($event->Special == 'export' || $event->Special == 'import') {
- $export_helper =& $this->Application->recallObject('CatItemExportHelper');
- $export_helper->prepareExportColumns($event);
- }
- }
-
- /**
- * Creates calculated fields for all item statuses based on config settings
- *
- * @param kEvent $event
- */
- function prepareItemStatuses(&$event)
- {
- $object =& $event->getObject( Array('skip_autoload' => true) );
-
- $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
- if (!$property_map) {
- return ;
- }
-
- // new items
- $object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2,
- IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '.
- $this->Application->ConfigValue($property_map['NewDays']).
- '*3600*24), 1, 0),
- %1$s.NewItem
- )');
-
- // hot items (cache updated every hour)
- $sql = 'SELECT Data
- FROM '.TABLE_PREFIX.'Cache
- WHERE (VarName = "'.$property_map['HotLimit'].'") AND (Cached >'.(adodb_mktime() - 3600).')';
- $hot_limit = $this->Conn->GetOne($sql);
- if ($hot_limit === false) {
- $hot_limit = $this->CalculateHotLimit($event);
- }
- $object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2,
- IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0),
- %1$s.HotItem
- )');
-
- // popular items
- $object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2,
- IF(%1$s.CachedVotesQty >= '.
- $this->Application->ConfigValue($property_map['MinPopVotes']).
- ' AND %1$s.CachedRating >= '.
- $this->Application->ConfigValue($property_map['MinPopRating']).
- ', 1, 0),
- %1$s.PopItem)');
-
- }
-
- function CalculateHotLimit(&$event)
- {
- $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
- if (!$property_map) {
- return;
- }
- $click_field = $property_map['ClickField'];
-
- $last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1;
- $sql = 'SELECT '.$click_field.' FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
- ORDER BY '.$click_field.' DESC
- LIMIT '.$last_hot.', 1';
- $res = $this->Conn->GetCol($sql);
- $hot_limit = (double)array_shift($res);
- $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("'.$property_map['HotLimit'].'", "'.$hot_limit.'", '.adodb_mktime().')');
- return $hot_limit;
-
- return 0;
- }
-
- /**
- * Moves item to preferred category, updates item hits
- *
- * @param kEvent $event
- */
- function OnBeforeItemUpdate(&$event)
- {
- parent::OnBeforeItemUpdate($event);
-
- // update hits field
- $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings');
- if ($property_map) {
- $click_field = $property_map['ClickField'];
-
- $object =& $event->getObject();
- /* @var $object kCatDBItem */
-
- if( $this->Application->IsAdmin() && ($this->Application->GetVar($click_field.'_original') !== false) &&
- floor($this->Application->GetVar($click_field.'_original')) != $object->GetDBField($click_field) )
- {
- $sql = 'SELECT MAX('.$click_field.') FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').'
- WHERE FLOOR('.$click_field.') = '.$object->GetDBField($click_field);
- $hits = ( $res = $this->Conn->GetOne($sql) ) ? $res + 0.000001 : $object->GetDBField($click_field);
- $object->SetDBField($click_field, $hits);
- }
- }
-
- // change category
- $target_category = $object->GetDBField('CategoryId');
- if ($object->GetOriginalField('CategoryId') != $target_category) {
- $object->MoveToCat($target_category);
- }
- }
-
- /**
- * Load price from temp table if product mode is temp table
- *
- * @param kEvent $event
- */
- function OnAfterItemLoad(&$event)
- {
- $special = substr($event->Special, -6);
-
- $object =& $event->getObject();
- /* @var $object kCatDBItem */
-
- if ($special == 'import' || $special == 'export') {
- $image_data = $object->getPrimaryImageData();
-
- if ($image_data) {
- $thumbnail_image = $image_data[$image_data['LocalThumb'] ? 'ThumbPath' : 'ThumbUrl'];
- if ($image_data['SameImages']) {
- $full_image = '';
- }
- else {
- $full_image = $image_data[$image_data['LocalImage'] ? 'LocalPath' : 'Url'];
- }
- $object->SetDBField('ThumbnailImage', $thumbnail_image);
- $object->SetDBField('FullImage', $full_image);
- $object->SetDBField('ImageAlt', $image_data['AltName']);
- }
- }
-
- // substituiting pending status value for pending editing
- if ($object->HasField('OrgId') && $object->GetDBField('OrgId') > 0 && $object->GetDBField('Status') == -2) {
- $options = $object->Fields['Status']['options'];
- foreach ($options as $key => $val) {
- if ($key == 2) $key = -2;
- $new_options[$key] = $val;
- }
- $object->Fields['Status']['options'] = $new_options;
- }
-
- // linking existing images for item with virtual fields
- $image_helper =& $this->Application->recallObject('ImageHelper');
- /* @var $image_helper ImageHelper */
-
- $image_helper->LoadItemImages($object);
-
- // linking existing files for item with virtual fields
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- $file_helper->LoadItemFiles($object);
-
- // set item's additional categories to virtual field (used in editing)
- $item_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
- $object->SetDBField('MoreCategories', $item_categories ? '|'.implode('|', $item_categories).'|' : '');
- }
-
- function OnAfterItemUpdate(&$event)
- {
- $this->CalculateHotLimit($event);
-
- if ( substr($event->Special, -6) == 'import') {
- $this->setCustomExportColumns($event);
- }
-
- if (!$this->Application->IsAdmin()) {
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- $image_helper =& $this->Application->recallObject('ImageHelper');
- /* @var $image_helper ImageHelper */
-
- // process image upload in virtual fields
- $image_helper->SaveItemImages($object);
-
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- // process file upload in virtual fields
- $file_helper->SaveItemFiles($object);
-
- if ($event->Special != '-item') {
- // don't touch categories during cloning
- $this->processAdditionalCategories($object, 'update');
- }
- }
- }
-
- /**
- * sets values for import process
- *
- * @param kEvent $event
- */
- function OnAfterItemCreate(&$event)
- {
- if ( substr($event->Special, -6) == 'import') {
- $this->setCustomExportColumns($event);
- }
-
- if (!$this->Application->IsAdmin()) {
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- $image_helper =& $this->Application->recallObject('ImageHelper');
- /* @var $image_helper ImageHelper */
-
- // process image upload in virtual fields
- $image_helper->SaveItemImages($object);
-
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- // process file upload in virtual fields
- $file_helper->SaveItemFiles($object);
-
- if ($event->Special != '-item') {
- // don't touch categories during cloning
- $this->processAdditionalCategories($object, 'create');
- }
- }
- }
-
- /**
- * Make record to search log
- *
- * @param string $keywords
- * @param int $search_type 0 - simple search, 1 - advanced search
- */
- function saveToSearchLog($keywords, $search_type = 0)
- {
- // don't save keywords for each module separately, just one time
- // static variable can't help here, because each module uses it's own class instance !
- if (!$this->Application->GetVar('search_logged')) {
- $sql = 'UPDATE '.TABLE_PREFIX.'SearchLog
- SET Indices = Indices + 1
- WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search
- $this->Conn->Query($sql);
- if ($this->Conn->getAffectedRows() == 0) {
- $fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type);
- $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLog');
- }
-
- $this->Application->SetVar('search_logged', 1);
- }
- }
-
- /**
- * Makes simple search for products
- * based on keywords string
- *
- * @param kEvent $event
- * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
- */
- function OnSimpleSearch(&$event)
- {
- if($this->Application->GetVar('INPORTAL_ON') && !($this->Application->GetVar('Action') == 'm_simple_search'))
- {
- return;
- }
-
- $event->redirect = false;
- $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
-
- $keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) );
-
- $query_object =& $this->Application->recallObject('HTTPQuery');
- $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
-
- if(!isset($query_object->Get['keywords']) &&
- !isset($query_object->Post['keywords']) &&
- $this->Conn->Query($sql))
- {
- return; // used when navigating by pages or changing sorting in search results
- }
- if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length'))
- {
- $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
- $this->Application->SetVar('keywords_too_short', 1);
- return; // if no or too short keyword entered, doing nothing
- }
-
- $this->Application->StoreVar('keywords', $keywords);
- if (!$this->Application->GetVar('INPORTAL_ON')) {
- // don't save search log, because in-portal already saved it
- $this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search
- }
-
- $keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_'));
-
- $event->setPseudoClass('_List');
-
- $object =& $event->getObject();
- /* @var $object kDBList */
-
- $this->Application->SetVar($event->getPrefixSpecial().'_Page', 1);
- $lang = $this->Application->GetVar('m_lang');
- $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
- $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
-
- $sql = 'SELECT *
- FROM ' . $this->Application->getUnitOption('confs', 'TableName') . '
- WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1';
- $search_config = $this->Conn->Query($sql, 'FieldName');
-
- $field_list = array_keys($search_config);
-
- $join_clauses = Array();
-
- // field processing
- $weight_sum = 0;
-
- $alias_counter = 0;
-
- $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
- if ($custom_fields) {
- $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
- $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
- }
-
- // what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table))
- $search_config_map = Array();
-
- foreach ($field_list as $key => $field) {
- $options = $object->getFieldOptions($field);
- $local_table = TABLE_PREFIX.$search_config[$field]['TableName'];
- $weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause
-
- // processing multilingual fields
- if (getArrayValue($options, 'formatter') == 'kMultiLanguage') {
- $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
- $field_list[$key] = 'l'.$lang.'_'.$field;
-
- if (!isset($search_config[$field]['ForeignField'])) {
- $field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary'];
- $search_config_map[ $field_list[$key.'_primary'] ] = $field;
- }
- }
-
- // processing fields from other tables
- if ($foreign_field = $search_config[$field]['ForeignField']) {
- $exploded = explode(':', $foreign_field, 2);
- if ($exploded[0] == 'CALC') {
- // ignoring having type clauses in simple search
- unset($field_list[$key]);
- continue;
- }
- else {
- $multi_lingual = false;
- if ($exploded[0] == 'MULTI') {
- $multi_lingual = true;
- $foreign_field = $exploded[1];
- }
-
- $exploded = explode('.', $foreign_field); // format: table.field_name
- $foreign_table = TABLE_PREFIX.$exploded[0];
-
- $alias_counter++;
- $alias = 't'.$alias_counter;
-
- if ($multi_lingual) {
- $field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1];
- $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field;
- $search_config_map[ $field_list[$key] ] = $field;
- $search_config_map[ $field_list[$key.'_primary'] ] = $field;
- }
- else {
- $field_list[$key] = $alias.'.'.$exploded[1];
- $search_config_map[ $field_list[$key] ] = $field;
- }
-
- $join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']);
- $join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
-
- $join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.'
- ON '.$join_clause;
- }
- }
- else {
- // processing fields from local table
- if ($search_config[$field]['CustomFieldId']) {
- $local_table = 'custom_data';
-
- // search by custom field value on current language
- $custom_field_id = array_search($field_list[$key], $custom_fields);
- $field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id;
-
- // search by custom field value on primary language
- $field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id;
- $search_config_map[ $field_list[$key.'_primary'] ] = $field;
- }
-
- $field_list[$key] = $local_table.'.'.$field_list[$key];
- $search_config_map[ $field_list[$key] ] = $field;
- }
- }
-
- // keyword string processing
- $search_helper =& $this->Application->recallObject('SearchHelper');
- /* @var $search_helper kSearchHelper */
-
- $where_clause = Array ();
- foreach ($field_list as $field) {
- if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) {
- // local real field
- $filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false);
- if ($filter_data) {
- $where_clause[] = $filter_data['value'];
- }
- }
- elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) {
- $custom_field_name = 'cust_' . $search_config_map[$field];
- $filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false);
- if ($filter_data) {
- $where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']);
- }
- }
- else {
- $where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field));
- }
- }
-
- $where_clause = '(' . implode(') OR (', $where_clause) . ')';
-
- $search_scope = $this->Application->GetVar('search_scope');
- if ($search_scope == 'category') {
- $category_id = $this->Application->GetVar('m_cat_id');
- $category_filter = $this->getCategoryLimitClause($category_id);
- if ($category_filter !== false) {
- $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON '.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$items_table.'.ResourceId';
- $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'Category ON '.TABLE_PREFIX.'Category.CategoryId = '.TABLE_PREFIX.'CategoryItems.CategoryId';
-
- $where_clause = '('.$this->getCategoryLimitClause($category_id).') AND '.$where_clause;
- }
- }
-
- $where_clause = $where_clause.' AND '.$items_table.'.Status=1';
-
- if($this->Application->GetVar('Action') == 'm_simple_subsearch') // subsearch, In-portal
- {
- if( $event->getEventParam('ResultIds') )
- {
- $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->specificParams['ResultIds']).')';
- }
- }
- if( $event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild' ) // subsearch, k4
- {
- if( $event->MasterEvent->getEventParam('ResultIds') )
- {
- $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')';
- }
- }
-
- // making relevance clause
- $positive_words = $search_helper->getPositiveKeywords($keywords);
- $this->Application->StoreVar('highlight_keywords', serialize($positive_words));
- $revelance_parts = Array();
- reset($search_config);
-
- foreach ($positive_words as $keyword_index => $positive_word) {
- $positive_words[$keyword_index] = mysql_real_escape_string($positive_word);
- }
-
- foreach ($field_list as $field) {
-
- if (!array_key_exists($field, $search_config_map)) {
- $map_key = $search_config_map[$items_table . '.' . $field];
- }
- else {
- $map_key = $search_config_map[$field];
- }
-
- $config_elem = $search_config[ $map_key ];
- $weight = $config_elem['Priority'];
- $revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)';
- foreach ($positive_words as $keyword) {
- $revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$weight.', 0)';
- }
- }
- $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
- $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
- $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
- $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
- $relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords;
- if ($rel_pop && isset($object->Fields['Hits'])) {
- $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
- }
- if ($rel_rating && isset($object->Fields['CachedRating'])) {
- $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
- }
-
- // building final search query
- if (!$this->Application->GetVar('do_not_drop_search_table') && !$this->Application->GetVar('INPORTAL_ON')) {
- $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event
- $this->Application->SetVar('do_not_drop_search_table', true);
- }
-
-
- $search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"');
- if ($search_table_exists) {
- $select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) ';
- }
- else {
- $select_intro = 'CREATE TABLE '.$search_table.' AS ';
- }
-
- $edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0';
-
-
- $sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance,
- '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId,
- '.$items_table.'.ResourceId,
- '.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType,
- '.$edpick_clause.' AS EdPick
- FROM '.$object->TableName.'
- '.implode(' ', $join_clauses).'
- WHERE '.$where_clause.'
- GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField');
-
- $res = $this->Conn->Query($sql);
- }
-
- /**
- * Enter description here...
- *
- * @param kEvent $event
- */
- function OnSubSearch(&$event)
- {
- $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
- $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
- if($this->Conn->Query($sql))
- {
- $sql = 'SELECT DISTINCT ResourceId FROM '.$search_table;
- $ids = $this->Conn->GetCol($sql);
- }
- $event->setEventParam('ResultIds', $ids);
- $event->CallSubEvent('OnSimpleSearch');
- }
-
- /**
- * Enter description here...
- *
- * @param kEvent $event
- * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!!
- */
- function OnAdvancedSearch(&$event)
- {
- $query_object =& $this->Application->recallObject('HTTPQuery');
- if(!isset($query_object->Post['andor']))
- {
- return; // used when navigating by pages or changing sorting in search results
- }
-
- $this->Application->RemoveVar('keywords');
- $this->Application->RemoveVar('Search_Keywords');
-
- $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name');
-
- $sql = 'SELECT *
- FROM '.$this->Application->getUnitOption('confs', 'TableName').'
- WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)';
- $search_config = $this->Conn->Query($sql);
-
- $lang = $this->Application->GetVar('m_lang');
- $object =& $event->getObject();
- $object->SetPage(1);
-
- $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
-
- $search_keywords = $this->Application->GetVar('value'); // will not be changed
-
- $keywords = $this->Application->GetVar('value'); // will be changed down there
- $verbs = $this->Application->GetVar('verb');
- $glues = $this->Application->GetVar('andor');
-
- $and_conditions = Array();
- $or_conditions = Array();
- $and_having_conditions = Array();
- $or_having_conditions = Array();
- $join_clauses = Array();
- $highlight_keywords = Array();
- $relevance_parts = Array();
-
- $alias_counter = 0;
-
- $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields');
- if ($custom_fields) {
- $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName');
- $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId';
- }
-
- $search_log = '';
- $weight_sum = 0;
-
- // processing fields and preparing conditions
- foreach ($search_config as $record) {
- $field = $record['FieldName'];
- $join_clause = '';
- $condition_mode = 'WHERE';
-
- // field processing
-
- $options = $object->getFieldOptions($field);
- $local_table = TABLE_PREFIX.$record['TableName'];
- $weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause
-
- // processing multilingual fields
- if (getArrayValue($options, 'formatter') == 'kMultiLanguage') {
- $field_name = 'l'.$lang.'_'.$field;
- }
- else {
- $field_name = $field;
- }
-
- // processing fields from other tables
- if ($foreign_field = $record['ForeignField']) {
- $exploded = explode(':', $foreign_field, 2);
- if($exploded[0] == 'CALC')
- {
- $user_groups = $this->Application->RecallVar('UserGroups');
- $field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]);
- $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']);
- $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause);
- $join_clause = ' LEFT JOIN '.$join_clause;
-
- $condition_mode = 'HAVING';
- }
- else {
- $exploded = explode('.', $foreign_field);
- $foreign_table = TABLE_PREFIX.$exploded[0];
-
- if($record['CustomFieldId']) {
- $exploded[1] = 'l'.$lang.'_'.$exploded[1];
- }
-
- $alias_counter++;
- $alias = 't'.$alias_counter;
-
- $field_name = $alias.'.'.$exploded[1];
- $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']);
- $join_clause = str_replace('{LocalTable}', $items_table, $join_clause);
-
- if($record['CustomFieldId'])
- {
- $join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId'];
- }
- $join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.'
- ON '.$join_clause;
- }
- }
- else
- {
- // processing fields from local table
- if ($record['CustomFieldId']) {
- $local_table = 'custom_data';
- $field_name = 'l'.$lang.'_cust_'.array_search($field_name, $custom_fields);
- }
-
- $field_name = $local_table.'.'.$field_name;
- }
-
- $condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
- if ($record['CustomFieldId'] && strlen($condition)) {
- // search in primary value of custom field + value in current language
- $field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields);
- $primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords);
- $condition = '('.$condition.' OR '.$primary_condition.')';
- }
-
- if ($condition) {
- if ($join_clause) {
- $join_clauses[] = $join_clause;
- }
-
- $relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)';
- if ($glues[$field] == 1) { // and
- if ($condition_mode == 'WHERE') {
- $and_conditions[] = $condition;
- }
- else {
- $and_having_conditions[] = $condition;
- }
- }
- else { // or
- if ($condition_mode == 'WHERE') {
- $or_conditions[] = $condition;
- }
- else {
- $or_having_conditions[] = $condition;
- }
- }
-
- // create search log record
- $search_log_data = Array('search_config' => $record, 'verb' => getArrayValue($verbs, $field), 'value' => ($record['FieldType'] == 'range') ? $search_keywords[$field.'_from'].'|'.$search_keywords[$field.'_to'] : $search_keywords[$field]);
- $search_log[] = $this->Application->Phrase('la_Field').' "'.$this->getHuman('Field', $search_log_data).'" '.$this->getHuman('Verb', $search_log_data).' '.$this->Application->Phrase('la_Value').' '.$this->getHuman('Value', $search_log_data).' '.$this->Application->Phrase($glues[$field] == 1 ? 'lu_And' : 'lu_Or');
- }
- }
-
- if ($search_log) {
- $search_log = implode('<br />', $search_log);
- $search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log);
- $this->saveToSearchLog($search_log, 1); // advanced search
- }
-
- $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords));
-
- // making relevance clause
- if($relevance_parts)
- {
- $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix');
- $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100;
- $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100;
- $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100;
- $relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords;
- $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop;
- $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating;
- }
- else
- {
- $relevance_clause = '0';
- }
-
- // building having clause
- if($or_having_conditions)
- {
- $and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')';
- }
- $having_clause = implode(' AND ', $and_having_conditions);
- $having_clause = $having_clause ? ' HAVING '.$having_clause : '';
-
- // building where clause
- if($or_conditions)
- {
- $and_conditions[] = '('.implode(' OR ', $or_conditions).')';
- }
-// $and_conditions[] = $items_table.'.Status = 1';
- $where_clause = implode(' AND ', $and_conditions);
- if(!$where_clause)
- {
- if($having_clause)
- {
- $where_clause = '1';
- }
- else
- {
- $where_clause = '0';
- $this->Application->SetVar('adv_search_error', 1);
- }
- }
- $where_clause .= ' AND '.$items_table.'.Status = 1';
-
- // building final search query
- $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
-
- $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table);
-
- $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
- $fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
- $pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0';
-
- $sql = ' CREATE TABLE '.$search_table.'
- SELECT '.$relevance_clause.' AS Relevance,
- '.$items_table.'.'.$id_field.' AS ItemId,
- '.$items_table.'.ResourceId AS ResourceId,
- 11 AS ItemType,
- '.$pick_field.' AS EdPick
- FROM '.$items_table.'
- '.implode(' ', $join_clauses).'
- WHERE '.$where_clause.'
- GROUP BY '.$items_table.'.'.$id_field.
- $having_clause;
-
- $res = $this->Conn->Query($sql);
- }
-
- function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords)
- {
- $field = $record['FieldName'];
-
- $condition_patterns = Array (
- 'any' => '%s LIKE %s',
- 'contains' => '%s LIKE %s',
- 'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)',
- 'is' => '%s = %s',
- 'isnot' => '(%1$s != %2$s OR %1$s IS NULL)'
- );
-
- $condition = '';
- switch ($record['FieldType']) {
- case 'select':
- $keywords[$field] = unhtmlentities( $keywords[$field] );
- if ($keywords[$field]) {
- $condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] ));
- }
- break;
-
- case 'multiselect':
- $keywords[$field] = unhtmlentities( $keywords[$field] );
- if ($keywords[$field]) {
- $condition = Array ();
- $values = explode('|', substr($keywords[$field], 1, -1));
- foreach ($values as $selected_value) {
- $condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%'));
- }
- $condition = '('.implode(' OR ', $condition).')';
- }
- break;
-
- case 'text':
- $keywords[$field] = unhtmlentities( $keywords[$field] );
-
- if (mb_strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) {
- $highlight_keywords[] = $keywords[$field];
- if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) {
- $keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%';
- }
- $condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] ));
- }
- break;
-
- case 'boolean':
- if ($keywords[$field] != -1) {
- $property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings');
- $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
-
- switch ($field) {
- case 'HotItem':
- $hot_limit_var = getArrayValue($property_mappings, 'HotLimit');
- if ($hot_limit_var) {
- $sql = 'SELECT Data
- FROM '.TABLE_PREFIX.'Cache
- WHERE VarName = "'.$hot_limit_var.'"';
- $hot_limit = (int)$this->Conn->GetOne($sql);
-
- $condition = 'IF('.$items_table.'.HotItem = 2,
- IF('.$items_table.'.Hits >= '.
- $hot_limit.
- ', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field];
- }
- break;
-
- case 'PopItem':
- $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop');
- $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop');
- if ($votes2pop_var && $rating2pop_var) {
- $condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '.
- $this->Application->ConfigValue($votes2pop_var).
- ' AND '.$items_table.'.CachedRating >= '.
- $this->Application->ConfigValue($rating2pop_var).
- ', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field];
- }
- break;
-
- case 'NewItem':
- $new_days_var = getArrayValue($property_mappings, 'NewDays');
- if ($new_days_var) {
- $condition = 'IF('.$items_table.'.NewItem = 2,
- IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '.
- $this->Application->ConfigValue($new_days_var).
- '*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field];
- }
- break;
-
- case 'EditorsPick':
- $condition = $items_table.'.EditorsPick = '.$keywords[$field];
- break;
- }
- }
- break;
-
- case 'range':
- $range_conditions = Array();
- if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) {
- $range_conditions[] = $field_name.' >= '.$keywords[$field.'_from'];
- }
- if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) {
- $range_conditions[] = $field_name.' <= '.$keywords[$field.'_to'];
- }
- if ($range_conditions) {
- $condition = implode(' AND ', $range_conditions);
- }
- break;
-
- case 'date':
- if ($keywords[$field]) {
- if (in_array($keywords[$field], Array('today', 'yesterday'))) {
- $current_time = getdate();
- $day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']);
- $time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400));
- $min_time = $time_mapping[$keywords[$field]];
- }
- else {
- $time_mapping = Array (
- 'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000,
- 'last_6_months' => 15768000, 'last_year' => 31536000,
- );
- $min_time = adodb_mktime() - $time_mapping[$keywords[$field]];
- }
- $condition = $field_name.' > '.$min_time;
- }
- break;
- }
-
- return $condition;
- }
-
- function getHuman($type, $search_data)
- {
- $type = ucfirst(strtolower($type));
- extract($search_data);
-
- switch ($type) {
- case 'Field':
- return $this->Application->Phrase($search_config['DisplayName']);
- break;
-
- case 'Verb':
- return $verb ? $this->Application->Phrase('lu_advsearch_'.$verb) : '';
- break;
-
- case 'Value':
- switch ($search_config['FieldType']) {
- case 'date':
- $values = Array(0 => 'lu_comm_Any', 'today' => 'lu_comm_Today',
- 'yesterday' => 'lu_comm_Yesterday', 'last_week' => 'lu_comm_LastWeek',
- 'last_month' => 'lu_comm_LastMonth', 'last_3_months' => 'lu_comm_Last3Months',
- 'last_6_months' => 'lu_comm_Last6Months', 'last_year' => 'lu_comm_LastYear');
- $ret = $this->Application->Phrase($values[$value]);
- break;
-
- case 'range':
- $value = explode('|', $value);
- return $this->Application->Phrase('lu_comm_From').' "'.$value[0].'" '.$this->Application->Phrase('lu_comm_To').' "'.$value[1].'"';
- break;
-
- case 'boolean':
- $values = Array(1 => 'lu_comm_Yes', 0 => 'lu_comm_No', -1 => 'lu_comm_Both');
- $ret = $this->Application->Phrase($values[$value]);
- break;
-
- default:
- $ret = $value;
- break;
-
- }
- return '"'.$ret.'"';
- break;
- }
- }
-
-
-
- /**
- * Set's correct page for list
- * based on data provided with event
- *
- * @param kEvent $event
- * @access private
- * @see OnListBuild
- */
- function SetPagination(&$event)
- {
- // get PerPage (forced -> session -> config -> 10)
- $per_page = $this->getPerPage($event);
-
-
- $object =& $event->getObject();
- $object->SetPerPage($per_page);
- $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1);
-
- $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page');
- if (!$page)
- {
- $page = $this->Application->GetVar($event->getPrefixSpecial(true).'_Page');
- }
-
- if (!$page)
- {
- if( $this->Application->RewriteURLs() )
- {
- $page = $this->Application->GetVar($event->Prefix.'_Page');
- if (!$page)
- {
- $page = $this->Application->RecallVar($event->Prefix.'_Page');
- }
- if($page) $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page);
- }
- else
- {
- $page = $this->Application->RecallVar($event->getPrefixSpecial().'_Page');
- }
- }
- else {
- $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page);
- }
-
- if( !$event->getEventParam('skip_counting') )
- {
- $pages = $object->GetTotalPages();
- if($page > $pages)
- {
- $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1);
- $page = 1;
- }
- }
-
- /*$cur_per_page = $per_page;
- $per_page = $event->getEventParam('per_page');
- if ($per_page == 'list_next') {
-
- $cur_page = $page;
-
- $object =& $this->Application->recallObject($event->Prefix);
- $object->SetPerPage(1);
- $cur_item_index = $object->CurrentIndex;
-
- $page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1;
- $object->SetPerPage(1);
- }*/
-
- $object->SetPage($page);
- }
-
-/* === RELATED TO IMPORT/EXPORT: BEGIN === */
-
- /**
- * Shows export dialog
- *
- * @param kEvent $event
- */
- function OnExport(&$event)
- {
- $selected_ids = $this->StoreSelectedIDs($event);
- if (implode(',', $selected_ids) == '') {
- // K4 fix when no ids found bad selected ids array is formed
- $selected_ids = false;
- }
-
- $selected_cats_ids = $this->Application->GetVar('export_categories');
-
- $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
- $this->Application->StoreVar($event->Prefix.'_export_cats_ids', $selected_cats_ids);
-
- $export_helper =& $this->Application->recallObject('CatItemExportHelper');
- /* @var $export_helper kCatDBItemExportHelper */
-
- $redirect_params = Array (
- $this->Prefix.'.export_event' => 'OnNew',
- 'pass' => 'all,'.$this->Prefix.'.export'
- );
-
- $event->setRedirectParams($redirect_params);
- }
-
- /**
- * Performs each export step & displays progress percent
- *
- * @param kEvent $event
- */
- function OnExportProgress(&$event)
- {
- $export_object =& $this->Application->recallObject('CatItemExportHelper');
- /* @var $export_object kCatDBItemExportHelper */
-
- $event = new kEvent($event->getPrefixSpecial().':OnDummy');
-
- $action_method = 'perform'.ucfirst($event->Special);
- $field_values = $export_object->$action_method($event);
-
- // finish code is done from JS now
- if ($field_values['start_from'] == $field_values['total_records']) {
- if ($event->Special == 'import') {
- $this->Application->StoreVar('PermCache_UpdateRequired', 1);
- $url_params = Array(
- 't' => 'catalog/catalog',
- 'm_cat_id' => $this->Application->RecallVar('ImportCategory'),
- 'anchor' => 'tab-' . $event->Prefix,
- );
- $this->Application->EventManager->openerStackChange($url_params);
-
- $event->SetRedirectParam('opener', 'u');
- }
- elseif ($event->Special == 'export') {
- $event->redirect = $this->Application->getUnitOption($event->Prefix, 'ModuleFolder') . '/' . $event->Special . '_finish';
- $event->SetRedirectParam('pass', 'all');
- }
-
- return ;
- }
-
- $export_options = $export_object->loadOptions($event);
- echo $export_options['start_from'] * 100 / $export_options['total_records'];
-
- $event->status = erSTOP;
- }
-
- /**
- * Returns specific to each item type columns only
- *
- * @param kEvent $event
- * @return Array
- */
- function getCustomExportColumns(&$event)
- {
- return Array( '__VIRTUAL__ThumbnailImage' => 'ThumbnailImage',
- '__VIRTUAL__FullImage' => 'FullImage',
- '__VIRTUAL__ImageAlt' => 'ImageAlt');
- }
-
- /**
- * Sets non standart virtual fields (e.g. to other tables)
- *
- * @param kEvent $event
- */
- function setCustomExportColumns(&$event)
- {
- $this->restorePrimaryImage($event);
- }
-
- /**
- * Create/Update primary image record in info found in imported data
- *
- * @param kEvent $event
- */
- function restorePrimaryImage(&$event)
- {
- $object =& $event->getObject();
-
- $has_image_info = $object->GetDBField('ImageAlt') && ($object->GetDBField('ThumbnailImage') || $object->GetDBField('FullImage'));
- if (!$has_image_info) {
- return false;
- }
-
- $image_data = $object->getPrimaryImageData();
-
- $image =& $this->Application->recallObject('img', null, Array('skip_autoload' => true));
- if ($image_data) {
- $image->Load($image_data['ImageId']);
- }
- else {
- $image->Clear();
- $image->SetDBField('Name', 'main');
- $image->SetDBField('DefaultImg', 1);
- $image->SetDBField('ResourceId', $object->GetDBField('ResourceId'));
- }
-
- $image->SetDBField('AltName', $object->GetDBField('ImageAlt'));
-
- if ($object->GetDBField('ThumbnailImage')) {
- $thumbnail_field = $this->isURL( $object->GetDBField('ThumbnailImage') ) ? 'ThumbUrl' : 'ThumbPath';
- $image->SetDBField($thumbnail_field, $object->GetDBField('ThumbnailImage') );
- $image->SetDBField('LocalThumb', $thumbnail_field == 'ThumbPath' ? 1 : 0);
- }
-
- if (!$object->GetDBField('FullImage')) {
- $image->SetDBField('SameImages', 1);
- }
- else {
- $image->SetDBField('SameImages', 0);
- $full_field = $this->isURL( $object->GetDBField('FullImage') ) ? 'Url' : 'LocalPath';
- $image->SetDBField($full_field, $object->GetDBField('FullImage') );
- $image->SetDBField('LocalImage', $full_field == 'LocalPath' ? 1 : 0);
- }
-
- if ($image->isLoaded()) {
- $image->Update();
- }
- else {
- $image->Create();
- }
- }
-
- function isURL($path)
- {
- return preg_match('#(http|https)://(.*)#', $path);
- }
-
- /**
- * Prepares item for import/export operations
- *
- * @param kEvent $event
- */
- function OnNew(&$event)
- {
- parent::OnNew($event);
-
- if ($event->Special == 'import' || $event->Special == 'export') {
- $export_helper =& $this->Application->recallObject('CatItemExportHelper');
- $export_helper->setRequiredFields($event);
- }
- }
-
- /**
- * Process items selected in item_selector
- *
- * @param kEvent $event
- */
- function OnProcessSelected(&$event)
- {
- $selected_ids = $this->Application->GetVar('selected_ids');
-
- $dst_field = $this->Application->RecallVar('dst_field');
-
- if ($dst_field == 'ItemCategory') {
- // Item Edit -> Categories Tab -> New Categories
- $object =& $event->getObject();
- $category_ids = explode(',', $selected_ids['c']);
- foreach ($category_ids as $category_id) {
- $object->assignToCategory($category_id);
- }
- }
-
- if ($dst_field == 'ImportCategory') {
- // Tools -> Import -> Item Import -> Select Import Category
- $this->Application->StoreVar('ImportCategory', $selected_ids['c']);
-// $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 1); // not to loose import/export values on form refresh
-
- $url_params = Array (
- $event->getPrefixSpecial() . '_id' => 0,
- $event->getPrefixSpecial() . '_event' => 'OnExportBegin',
-// 'm_opener' => 's',
- );
-
- $this->Application->EventManager->openerStackChange($url_params);
- }
-
- $event->SetRedirectParam('opener', 'u');
- }
-
- /**
- * Saves Import/Export settings to session
- *
- * @param kEvent $event
- */
- function OnSaveSettings(&$event)
- {
- $event->redirect = false;
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- if ($items_info) {
- list($id, $field_values) = each($items_info);
-
- $object =& $event->getObject( Array('skip_autoload' => true) );
- $object->SetFieldsFromHash($field_values);
- $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!!
- $field_values['ImportSource'] = 2;
- $field_values['ImportLocalFilename'] = $object->GetDBField('ImportFilename');
- $items_info[$id] = $field_values;
-
- $this->Application->StoreVar($event->getPrefixSpecial().'_ItemsInfo', serialize($items_info));
- }
- }
-
- /**
- * Saves Import/Export settings to session
- *
- * @param kEvent $event
- */
- function OnResetSettings(&$event)
- {
- $this->Application->StoreVar('ImportCategory', $this->Application->findModule('Name', 'Core', 'RootCat'));
- }
-
- function OnCancelAction(&$event)
- {
- $event->redirect_params = Array('pass' => 'all,'.$event->GetPrefixSpecial());
- $event->redirect = $this->Application->GetVar('cancel_template');
- }
-
-/* === RELATED TO IMPORT/EXPORT: END === */
-
- /**
- * Stores item's owner login into separate field together with id
- *
- * @param kEvent $event
- * @param string $id_field
- * @param string $cached_field
- */
- function cacheItemOwner(&$event, $id_field, $cached_field)
- {
- $object =& $event->getObject();
-
- $user_id = $object->GetDBField($id_field);
- $options = $object->GetFieldOptions($id_field);
- if (isset($options['options'][$user_id])) {
- $object->SetDBField($cached_field, $options['options'][$user_id]);
- }
- else {
- $id_field = $this->Application->getUnitOption('u', 'IDField');
- $table_name = $this->Application->getUnitOption('u', 'TableName');
-
- $sql = 'SELECT Login
- FROM '.$table_name.'
- WHERE '.$id_field.' = '.$user_id;
- $object->SetDBField($cached_field, $this->Conn->GetOne($sql));
- }
- }
-
- /**
- * Saves item beeing edited into temp table
- *
- * @param kEvent $event
- */
- function OnPreSave(&$event)
- {
- parent::OnPreSave($event);
- $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
- if ($event->status == erSUCCESS && $use_pending_editing) {
- // decision: clone or not clone
-
- $object =& $event->getObject();
- if ($object->GetID() == 0 || $object->GetDBField('OrgId') > 0) {
- // new items or cloned items shouldn't be cloned again
- return true;
- }
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- $owner_field = $this->getOwnerField($event->Prefix);
-
- if ($perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix) == 2) {
-
- // 1. clone original item
- $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($object->GetID()), null, null, null, true);
- $ci_table = $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems');
-
- // 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
- $sql = 'SELECT ResourceId
- FROM '.$object->TableName.'
- WHERE '.$object->IDField.' = '.$cloned_ids[0];
- $clone_resource_id = $this->Conn->GetOne($sql);
-
- $sql = 'DELETE FROM '.$ci_table.'
- WHERE ItemResourceId = '.$clone_resource_id.' AND PrimaryCat = 1';
- $this->Conn->Query($sql);
-
- // 3. copy main item categoryitems to cloned item
- $sql = ' INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
- SELECT CategoryId, '.$clone_resource_id.' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
- FROM '.$ci_table.'
- WHERE ItemResourceId = '.$object->GetDBField('ResourceId');
- $this->Conn->Query($sql);
-
- // 4. put cloned id to OrgId field of item being cloned
- $sql = 'UPDATE '.$object->TableName.'
- SET OrgId = '.$object->GetID().'
- WHERE '.$object->IDField.' = '.$cloned_ids[0];
- $this->Conn->Query($sql);
-
- // 5. substitute id of item being cloned with clone id
- $this->Application->SetVar($event->getPrefixSpecial().'_id', $cloned_ids[0]);
-
- $selected_ids = $this->getSelectedIDs($event, true);
- $selected_ids[ array_search($object->GetID(), $selected_ids) ] = $cloned_ids[0];
- $this->StoreSelectedIDs($event, $selected_ids);
-
- // 6. delete original item from temp table
- $temp_handler->DeleteItems($event->Prefix, $event->Special, Array($object->GetID()));
- }
- }
- }
-
- /**
- * Sets default expiration based on module setting
- *
- * @param kEvent $event
- */
- function OnPreCreate(&$event)
- {
- parent::OnPreCreate($event);
-
- if ($event->status == erSUCCESS) {
- $object =& $event->getObject();
- $owner_field = $this->getOwnerField($event->Prefix);
-
- $object->SetDBField($owner_field, $this->Application->RecallVar('user_id'));
- }
- }
-
- /**
- * Occures before original item of item in pending editing got deleted (for hooking only)
- *
- * @param kEvent $event
- */
- function OnBeforeDeleteOriginal(&$event)
- {
-
- }
-
- /**
- * 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!
- *
- * @param kEvent $event
- */
- function OnBeforeClone(&$event)
- {
- if ($this->Application->GetVar('ResetCatBeforeClone')) {
- $object =& $event->getObject();
- $object->SetDBField('CategoryId', null);
- }
- }
-
- /**
- * Set status for new category item based on user permission in category
- *
- * @param kEvent $event
- */
- function OnBeforeItemCreate(&$event)
- {
- if ($this->Application->IsAdmin()) {
- return true;
- }
-
- $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
- if ($use_pending_editing) {
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- $primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
- $item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix);
- if ($item_status == STATUS_DISABLED) {
- $event->status = erFAIL;
- return false;
- }
- else {
- $object->SetDBField('Status', $item_status);
- }
- }
- }
-
- /**
- * Creates category item & redirects to confirmation template (front-end only)
- *
- * @param kEvent $event
- */
- function OnCreate(&$event)
- {
- parent::OnCreate($event);
- $this->SetFrontRedirectTemplate($event, 'suggest');
- }
-
- /**
- * Returns item's categories (allows to exclude primary category)
- *
- * @param int $resource_id
- * @param bool $with_primary
- * @return Array
- */
- function getItemCategories($resource_id, $with_primary = false)
- {
- $sql = 'SELECT CategoryId
- FROM '.TABLE_PREFIX.'CategoryItems
- WHERE (ItemResourceId = '.$resource_id.')';
-
- if (!$with_primary) {
- $sql .= ' AND (PrimaryCat = 0)';
- }
-
- return $this->Conn->GetCol($sql);
- }
-
- /**
- * Adds new and removes old additional categories from category item
- *
- * @param kCatDBItem $object
- */
- function processAdditionalCategories(&$object, $mode)
- {
- $process_categories = $object->GetDBField('MoreCategories');
- if ($process_categories === '') {
- // field was not in submit & have default value (when no categories submitted, then value is null)
- return ;
- }
-
- if ($mode == 'create') {
- // prevents first additional category to become primary
- $object->assignPrimaryCategory();
- }
-
- $process_categories = $process_categories ? explode('|', substr($process_categories, 1, -1)) : Array ();
- $existing_categories = $this->getItemCategories($object->GetDBField('ResourceId'));
-
- $add_categories = array_diff($process_categories, $existing_categories);
- foreach ($add_categories as $category_id) {
- $object->assignToCategory($category_id);
- }
-
- $remove_categories = array_diff($existing_categories, $process_categories);
- foreach ($remove_categories as $category_id) {
- $object->removeFromCategory($category_id);
- }
- }
-
- /**
- * Creates category item & redirects to confirmation template (front-end only)
- *
- * @param kEvent $event
- */
- function OnUpdate(&$event)
- {
- $use_pending = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
- if ($this->Application->IsAdmin() || !$use_pending) {
- parent::OnUpdate($event);
- $this->SetFrontRedirectTemplate($event, 'modify');
- return ;
- }
-
- $object =& $event->getObject(Array('skip_autoload' => true));
- /* @var $object kCatDBItem */
-
- $items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
- if ($items_info) {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- /* @var $temp_handler kTempTablesHandler */
-
- $owner_field = $this->getOwnerField($event->Prefix);
-
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- foreach ($items_info as $id => $field_values) {
- $object->Load($id);
- $edit_perm = $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix);
-
- if ($use_pending && !$object->GetDBField('OrgId') && ($edit_perm == STATUS_PENDING)) {
- // pending editing enabled + not pending copy -> get/create pending copy & save changes to it
- $original_id = $object->GetID();
- $original_resource_id = $object->GetDBField('ResourceId');
- $file_helper->PreserveItemFiles($field_values);
-
- $object->Load($original_id, 'OrgId');
- if (!$object->isLoaded()) {
- // 1. user has no pending copy of live item -> clone live item
- $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($original_id), null, null, null, true);
-
- $object->Load($cloned_ids[0]);
- $object->SetFieldsFromHash($field_values);
-
- // 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem
- $ci_table = $this->Application->getUnitOption('ci', 'TableName');
- $sql = 'DELETE FROM '.$ci_table.'
- WHERE ItemResourceId = '.$object->GetDBField('ResourceId').' AND PrimaryCat = 1';
- $this->Conn->Query($sql);
-
- // 1b. copy main item categoryitems to cloned item
- $sql = 'INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename)
- SELECT CategoryId, '.$object->GetDBField('ResourceId').' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename
- FROM '.$ci_table.'
- WHERE ItemResourceId = '.$original_resource_id;
- $this->Conn->Query($sql);
-
- // 1c. put cloned id to OrgId field of item being cloned
- $object->SetDBField('Status', STATUS_PENDING_EDITING);
- $object->SetDBField('OrgId', $original_id);
- }
- else {
- // 2. user has pending copy of live item -> just update field values
- $object->SetFieldsFromHash($field_values);
- }
-
- // update id in request (used for redirect in mod-rewrite mode)
- $this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetID());
- }
- else {
- // 3. already editing pending copy -> just update field values
- $object->SetFieldsFromHash($field_values);
- }
-
- if ($object->Update()) {
- $event->status = erSUCCESS;
- }
- else {
- $event->status = erFAIL;
- $event->redirect = false;
- break;
- }
- }
- }
-
- $this->SetFrontRedirectTemplate($event, 'modify');
- }
-
- /**
- * Sets next template to one required for front-end after adding/modifying item
- *
- * @param kEvent $event
- * @param string $template_key - {suggest,modify}
- */
- function SetFrontRedirectTemplate(&$event, $template_key)
- {
- if ($this->Application->IsAdmin() || $event->status != erSUCCESS) {
- return ;
- }
-
- // prepare redirect template
- $object =& $event->getObject();
- $is_active = ($object->GetDBField('Status') == STATUS_ACTIVE);
-
- $next_template = $is_active ? 'confirm_template' : 'pending_confirm_template';
- $event->redirect = $this->Application->GetVar($template_key.'_'.$next_template);
- $event->SetRedirectParam('opener', 's');
-
- // send email events
- $perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix');
- switch ($event->Name) {
- case 'OnCreate':
- $event_suffix = $is_active ? 'ADD' : 'ADD.PENDING';
- $owner_field = $this->getOwnerField($event->Prefix);
-
- $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :(
- $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField($owner_field));
- break;
-
- case 'OnUpdate':
- $event_suffix = $is_active ? 'MODIFY' : 'MODIFY.PENDING';
- $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :(
- $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('ModifiedById'));
- break;
- }
- }
-
- /**
- * Apply same processing to each item beeing selected in grid
- *
- * @param kEvent $event
- * @access private
- */
- function iterateItems(&$event)
- {
- if ($event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline') {
- return parent::iterateItems($event);
- }
-
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
- return;
- }
-
- $object =& $event->getObject( Array('skip_autoload' => true) );
- $ids = $this->StoreSelectedIDs($event);
-
- if ($ids) {
- foreach ($ids as $id) {
- $object->Load($id);
-
- switch ($event->Name) {
- case 'OnMassApprove':
- $ret = $object->ApproveChanges();
- break;
-
- case 'OnMassDecline':
- $ret = $object->DeclineChanges();
- break;
- }
-
- if (!$ret) {
- $event->status = erFAIL;
- $event->redirect = false;
- break;
- }
- }
- }
-
- $this->clearSelectedIDs($event);
- }
-
- /**
- * Deletes items & preserves clean env
- *
- * @param kEvent $event
- */
- function OnDelete(&$event)
- {
- parent::OnDelete($event);
-
- if ($event->status == erSUCCESS && !$this->Application->IsAdmin()) {
- $event->SetRedirectParam('pass', 'm');
- $event->SetRedirectParam('m_cat_id', 0);
- }
- }
-
- /**
- * Checks, that currently loaded item is allowed for viewing (non permission-based)
- *
- * @param kEvent $event
- * @return bool
- */
- function checkItemStatus(&$event)
- {
- $object =& $event->getObject();
- if (!$object->isLoaded()) {
- $this->_errorNotFound($event);
-
- return true;
- }
-
- $status = $object->GetDBField('Status');
- $user_id = $this->Application->RecallVar('user_id');
- $owner_field = $this->getOwnerField($event->Prefix);
-
- if (($status == -2 || $status == STATUS_PENDING) && ($object->GetDBField($owner_field) == $user_id)) {
- return true;
- }
-
- return $status == STATUS_ACTIVE;
- }
-
- /**
- * Set's correct sorting for list
- * based on data provided with event
- *
- * @param kEvent $event
- * @access private
- * @see OnListBuild
- */
- function SetSorting(&$event)
- {
- if (!$this->Application->IsAdmin()) {
- $event->setEventParam('same_special', true);
- }
-
- parent::SetSorting($event);
- }
-
- /**
- * Returns current per-page setting for list
- *
- * @param kEvent $event
- * @return int
- */
- function getPerPage(&$event)
- {
- if (!$this->Application->IsAdmin()) {
- $event->setEventParam('same_special', true);
- }
-
- return parent::getPerPage($event);
- }
-
- function getOwnerField($prefix)
- {
- $owner_field = $this->Application->getUnitOption($prefix, 'OwnerField');
- if (!$owner_field) {
- $owner_field = 'CreatedById';
- }
-
- return $owner_field;
- }
-
- /**
- * Creates virtual image fields for item
- *
- * @param kEvent $event
- */
- function OnAfterConfigRead(&$event)
- {
- parent::OnAfterConfigRead($event);
-
- if (defined('IS_INSTALL') && IS_INSTALL) {
- return ;
- }
-
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- $file_helper->createItemFiles($event->Prefix, true); // create image fields
- $file_helper->createItemFiles($event->Prefix, false); // create file fields
-
- // add EditorsPick to ForcedSorting if needed
- $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
- if (array_key_exists('ForceEditorPick', $config_mapping) && $this->Application->ConfigValue($config_mapping['ForceEditorPick'])) {
- $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings');
-
- $new_forced_sorting = Array ('EditorsPick' => 'DESC');
-
- if (array_key_exists('ForcedSorting', $list_sortings[''])) {
- foreach ($list_sortings['']['ForcedSorting'] as $sort_field => $sort_order) {
- $new_forced_sorting[$sort_field] = $sort_order;
- }
- }
- $list_sortings['']['ForcedSorting'] = $new_forced_sorting;
-
- $this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings);
- }
-
- // add grids for advanced view (with primary category column)
- $grids = $this->Application->getUnitOption($this->Prefix, 'Grids');
- $process_grids = Array ('Default', 'Radio');
- foreach ($process_grids as $process_grid) {
- $grid_data = $grids[$process_grid];
- $grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_primary_category_td', 'filter_block' => 'grid_like_filter');
- $grids[$process_grid . 'ShowAll'] = $grid_data;
- }
- $this->Application->setUnitOption($this->Prefix, 'Grids', $grids);
-
- // add options for CategoryId field (quick way to select item's primary category)
- $category_helper =& $this->Application->recallObject('CategoryHelper');
- /* @var $category_helper CategoryHelper */
-
- $virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields');
-
- $virtual_fields['CategoryId']['default'] = (int)$this->Application->GetVar('m_cat_id');
- $virtual_fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions();
-
- $this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields);
- }
-
- /**
- * Returns file contents associated with item
- *
- * @param kEvent $event
- */
- function OnDownloadFile(&$event)
- {
- $object =& $event->getObject();
- /* @var $object kDBItem */
-
- $event->status = erSTOP;
-
- $field = $this->Application->GetVar('field');
- if (!preg_match('/^File([\d]+)/', $field)) {
- return ;
- }
-
- $file_helper =& $this->Application->recallObject('FileHelper');
- /* @var $file_helper FileHelper */
-
- $filename = $object->GetField($field, 'full_path');
- $file_helper->DownloadFile($filename);
- }
-
- /**
- * Saves user's vote
- *
- * @param kEvent $event
- */
- function OnMakeVote(&$event)
- {
- $event->status = erSTOP;
-
- if ($this->Application->GetVar('ajax') != 'yes') {
- // this is supposed to call from AJAX only
- return ;
- }
-
- $rating_helper =& $this->Application->recallObject('RatingHelper');
- /* @var $rating_helper RatingHelper */
-
- $object =& $event->getObject( Array ('skip_autoload' => true) );
- /* @var $object kDBItem */
-
- $object->Load( $this->Application->GetVar('id') );
-
- echo $rating_helper->makeVote($object);
- }
-}
\ No newline at end of file
Property changes on: branches/5.0.x/core/units/general/cat_event_handler.php
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.97.2.36
\ No newline at end of property
Deleted: svn:executable
## -1 +0,0 ##
-*
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Id
\ No newline at end of property
Index: branches/5.0.x/core/units/general/general_config.php
===================================================================
--- branches/5.0.x/core/units/general/general_config.php (revision 12342)
+++ branches/5.0.x/core/units/general/general_config.php (revision 12343)
@@ -1,47 +1,46 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.net/license/ for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array (
'Prefix' => 'm',
'EventHandlerClass' => Array ('class' => 'kEventHandler', 'file' => '', 'build_event' => 'OnBuild'),
// 'TagProcessorClass' => Array ('class' => 'kMainTagProcessor', 'file' => '', 'build_event' => 'OnBuild'),
'QueryString' => Array (
1 => 'cat_id',
2 => 'cat_page',
3 => 'lang',
4 => 'theme',
5 => 'opener',
6 => 'wid',
),
'TitleField' => 'CachedNavbar',
'TitlePhrase' => 'la_Text_Category',
'CatalogTabIcon' => 'icon16_folder.gif',
'ItemType' => 1,
'TableName' => TABLE_PREFIX . 'Category',
'CatalogItem' => true,
'PortalStyleEnv' => true,
'RewritePriority' => 100,
'RewriteListener' => 'ModRewriteHelper:MainRewriteListener',
'PermTabText' => 'In-Portal',
'PermSection' => Array ('search' => 'in-portal:configuration_search', 'custom' => 'in-portal:configuration_custom'),
-
);
\ No newline at end of file

Event Timeline