Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Sun, Feb 2, 10:00 PM

in-portal

Index: branches/RC/core/kernel/db/db_tag_processor.php
===================================================================
--- branches/RC/core/kernel/db/db_tag_processor.php (revision 11757)
+++ branches/RC/core/kernel/db/db_tag_processor.php (revision 11758)
@@ -1,2502 +1,2511 @@
<?php
class kDBTagProcessor extends TagProcessor {
/**
* 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 ($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())
+ 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 = array();
$block_params['name'] = $this->SelectParam($params, 'render_as,block');
return $this->Application->ParseBlock($block_params, 1);
}
}
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->getObject($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->RecordsCount > $object->PerPage) || ($object->Page > 1);
+ 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 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/';
}
/**
* 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']);
}
function SetFCKDefaultLanguage()
{
$lang_id = $this->Application->GetDefaultLanguageId();
$sql="SELECT Locale FROM ".TABLE_PREFIX."Language WHERE LanguageId = ".$lang_id;
$lang_prefix = strtolower($this->Conn->GetOne($sql));
$lang_file=strtolower($this->Conn->GetOne($sql)).'.js';
if (file_exists(FULL_PATH.EDITOR_PATH.'/editor/lang/'.$lang_file))
{
return $lang_prefix;
}
$aLangPrefix = explode("-",$lang_prefix);
if (file_exists(FULL_PATH.EDITOR_PATH.'/editor/lang/'.$aLangPrefix[0].'.js'))
{
return $aLangPrefix[0];
}
return 'en';
}
function FCKEditor($params)
{
$params['no_special'] = 1;
$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';
}
$url = '';
$st_id = $this->Application->GetVar('st_id');
if ($st_id) {
$sql = 'SELECT NamedParentPath
FROM ' . $this->Application->getUnitOption('st', 'TableName') . '
WHERE ' . $this->Application->getUnitOption('st', 'IDField') . ' = ' . $st_id;
$tpl = $this->Conn->GetOne($sql);
$url_params = Array ('pass' => 'm', 'm_cat_id' => $st_id, 'index_file' => 'index.php');
$url = $this->Application->HREF($tpl, '_FRONT_END_', $url_params);
}
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 = $st_id ? 'Advanced' : 'Default';
$oFCKeditor->Value = $value;
$oFCKeditor->PreviewUrl = $url;
$oFCKeditor->DefaultLanguage = $this->SetFCKDefaultLanguage();
$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' => $url,
'BaseUrl' => BASE_PATH . '/',
'DefaultLanguage' => $this->SetFCKDefaultLanguage(),
'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/RC/core/kernel/db/db_event_handler.php
===================================================================
--- branches/RC/core/kernel/db/db_event_handler.php (revision 11757)
+++ branches/RC/core/kernel/db/db_event_handler.php (revision 11758)
@@ -1,2470 +1,2472 @@
<?php
define('EH_CUSTOM_PROCESSING_BEFORE',1);
define('EH_CUSTOM_PROCESSING_AFTER',2);
/**
* Note:
* 1. When adressing variables from submit containing
* Prefix_Special as part of their name use
* $event->getPrefixSpecial(true) instead of
* $event->Prefix_Special as usual. This is due PHP
* is converting "." symbols in variable names during
* submit info "_". $event->getPrefixSpecial optional
* 1st parameter returns correct corrent Prefix_Special
* for variables beeing submitted such way (e.g. variable
* name that will be converted by PHP: "users.read_only_id"
* will be submitted as "users_read_only_id".
*
* 2. When using $this->Application-LinkVar on variables submitted
* from form which contain $Prefix_Special then note 1st item. Example:
* LinkVar($event->getPrefixSpecial(true).'_varname',$event->Prefix_Special.'_varname')
*
*/
/**
* EventHandler that is used to process
* any database related events
*
*/
class kDBEventHandler extends kEventHandler {
/**
* Description
*
* @var kDBConnection
* @access public
*/
var $Conn;
/**
* Adds ability to address db connection
*
* @return kDBEventHandler
* @access public
*/
function kDBEventHandler()
{
parent::kBase();
$this->Conn =& $this->Application->GetADODBConnection();
}
/**
* Checks permissions of user
*
* @param kEvent $event
*/
function CheckPermission(&$event)
{
if (!$this->Application->IsAdmin()) {
$allow_events = Array('OnSearch', 'OnSearchReset', 'OnNew');
if (in_array($event->Name, $allow_events)) {
// allow search on front
return true;
}
}
$section = $event->getSection();
if (!preg_match('/^CATEGORY:(.*)/', $section)) {
// only if not category item events
if ((substr($event->Name, 0, 9) == 'OnPreSave') || ($event->Name == 'OnSave')) {
if ($this->isNewItemCreate($event)) {
return $this->Application->CheckPermission($section.'.add', 1);
}
else {
return $this->Application->CheckPermission($section.'.add', 1) || $this->Application->CheckPermission($section.'.edit', 1);
}
}
}
if ($event->Name == 'OnPreCreate') {
// save category_id before item create (for item category selector not to destroy permission checking category)
$this->Application->LinkVar('m_cat_id');
}
if ($event->Name == 'OnSaveWidths') {
return $this->Application->IsAdmin() && $this->Application->LoggedIn();
}
return parent::CheckPermission($event);
}
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnLoad' => Array('self' => 'view', 'subitem' => 'view'),
'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'),
'OnBuild' => Array('self' => true),
'OnNew' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnCreate' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnUpdate' => Array('self' => 'edit', 'subitem' => 'add|edit'),
'OnSetPrimary' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnDeleteAll' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnMassDelete' => Array('self' => 'delete', 'subitem' => 'add|edit'),
'OnMassClone' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnCut' => array('self'=>'edit', 'subitem' => 'edit'),
'OnCopy' => array('self'=>'edit', 'subitem' => 'edit'),
'OnPaste' => array('self'=>'edit', 'subitem' => 'edit'),
'OnSelectItems' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnProcessSelected' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnSelectUser' => Array('self' => 'add|edit', 'subitem' => 'add|edit'),
'OnMassApprove' => Array('self' => 'advanced:approve|edit', 'subitem' => 'advanced:approve|add|edit'),
'OnMassDecline' => Array('self' => 'advanced:decline|edit', 'subitem' => 'advanced:decline|add|edit'),
'OnMassMoveUp' => Array('self' => 'advanced:move_up|edit', 'subitem' => 'advanced:move_up|add|edit'),
'OnMassMoveDown' => Array('self' => 'advanced:move_down|edit', 'subitem' => 'advanced:move_down|add|edit'),
'OnPreCreate' => Array('self' => 'add|add.pending', 'subitem' => 'edit|edit.pending'),
'OnEdit' => Array('self' => 'edit|edit.pending', 'subitem' => 'edit|edit.pending'),
'OnExport' => Array('self' => 'view|advanced:export'),
'OnExportBegin' => Array('self' => 'view|advanced:export'),
'OnExportProgress' => Array('self' => 'view|advanced:export'),
'OnSetAutoRefreshInterval' => Array ('self' => true, 'subitem' => true),
'OnAutoRefreshToggle' => Array ('self' => true, 'subitem' => true),
// theese event do not harm, but just in case check them too :)
'OnCancelEdit' => Array('self' => true, 'subitem' => true),
'OnCancel' => Array('self' => true, 'subitem' => true),
'OnReset' => Array('self' => true, 'subitem' => true),
'OnSetSorting' => Array('self' => true, 'subitem' => true),
'OnSetSortingDirect' => Array('self' => true, 'subitem' => true),
'OnResetSorting' => Array('self' => true, 'subitem' => true),
'OnSetFilter' => Array('self' => true, 'subitem' => true),
'OnApplyFilters' => Array('self' => true, 'subitem' => true),
'OnRemoveFilters' => Array('self' => true, 'subitem' => true),
'OnSetFilterPattern' => Array('self' => true, 'subitem' => true),
'OnSetPerPage' => Array('self' => true, 'subitem' => true),
'OnSearch' => Array('self' => true, 'subitem' => true),
'OnSearchReset' => Array('self' => true, 'subitem' => true),
'OnGoBack' => Array('self' => true, 'subitem' => true),
// it checks permission itself since flash uploader does not send cookies
'OnUploadFile' => Array ('self' => true, 'subitem' => true),
'OnDeleteFile' => Array ('self' => true, 'subitem' => true),
'OnViewFile' => Array ('self' => true, 'subitem' => true),
'OnSaveWidths' => Array ('self' => true, 'subitem' => true),
'OnValidateMInputFields' => Array ('self' => 'view'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function mapEvents()
{
$events_map = Array(
'OnRemoveFilters' => 'FilterAction',
'OnApplyFilters' => 'FilterAction',
'OnMassApprove'=>'iterateItems',
'OnMassDecline'=>'iterateItems',
'OnMassMoveUp'=>'iterateItems',
'OnMassMoveDown'=>'iterateItems',
);
$this->eventMethods = array_merge($this->eventMethods, $events_map);
}
/**
* Returns ID of current item to be edited
* by checking ID passed in get/post as prefix_id
* or by looking at first from selected ids, stored.
* Returned id is also stored in Session in case
* it was explicitly passed as get/post
*
* @param kEvent $event
* @return int
*/
function getPassedID(&$event)
{
if ($event->getEventParam('raise_warnings') === false) {
$event->setEventParam('raise_warnings', 1);
}
if (preg_match('/^auto-(.*)/', $event->Special, $regs) && $this->Application->prefixRegistred($regs[1])) {
// <inp2:lang.auto-phrase_Field name="DateFormat"/> - returns field DateFormat value from language (LanguageId is extracted from current phrase object)
$main_object =& $this->Application->recallObject($regs[1]);
/* @var $main_object kDBItem */
$id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
return $main_object->GetDBField($id_field);
}
// 1. get id from post (used in admin)
$ret = $this->Application->GetVar($event->getPrefixSpecial(true).'_id');
if (($ret !== false) && ($ret != '')) {
return $ret;
}
// 2. get id from env (used in front)
$ret = $this->Application->GetVar($event->getPrefixSpecial().'_id');
if (($ret !== false) && ($ret != '')) {
return $ret;
}
// recall selected ids array and use the first one
$ids = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids');
if ($ids != '') {
$ids = explode(',',$ids);
if ($ids) {
$ret = array_shift($ids);
}
}
else { // if selected ids are not yet stored
$this->StoreSelectedIDs($event);
return $this->Application->GetVar($event->getPrefixSpecial(true).'_id'); // StoreSelectedIDs sets this variable
}
return $ret;
}
/**
* Prepares and stores selected_ids string
* in Session and Application Variables
* by getting all checked ids from grid plus
* id passed in get/post as prefix_id
*
* @param kEvent $event
* @param Array $direct_ids
*
* @return Array ids stored
*/
function StoreSelectedIDs(&$event, $direct_ids = null)
{
$wid = $this->Application->GetTopmostWid($event->Prefix);
$session_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ids = $event->getEventParam('ids');
if (isset($direct_ids) || ($ids !== false)) {
// save ids directly if they given
$this->Application->StoreVar($session_name, implode(',', $direct_ids ? $direct_ids : $ids));
return $ids;
}
$ret = Array();
// May be we don't need this part: ?
$passed = $this->Application->GetVar($event->getPrefixSpecial(true).'_id');
if($passed !== false && $passed != '')
{
array_push($ret, $passed);
}
$ids = Array();
// get selected ids from post & save them to session
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
$id_field = $this->Application->getUnitOption($event->Prefix,'IDField');
foreach($items_info as $id => $field_values)
{
if( getArrayValue($field_values,$id_field) ) array_push($ids,$id);
}
//$ids=array_keys($items_info);
}
$ret = array_unique(array_merge($ret, $ids));
$this->Application->SetVar($event->getPrefixSpecial().'_selected_ids', implode(',',$ret));
$this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids', $session_name);
// This is critical - otherwise getPassedID will return last ID stored in session! (not exactly true)
// this smells... needs to be refactored
$first_id = getArrayValue($ret,0);
if (($first_id === false) && ($event->getEventParam('raise_warnings') == 1)) {
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendTrace();
}
trigger_error('Requested ID for prefix <b>'.$event->getPrefixSpecial().'</b> <span class="debug_error">not passed</span>',E_USER_NOTICE);
}
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $first_id);
return $ret;
}
/**
* Returns stored selected ids as an array
*
* @param kEvent $event
* @param bool $from_session return ids from session (written, when editing was started)
* @return array
*/
function getSelectedIDs(&$event, $from_session = false)
{
if ($from_session) {
$wid = $this->Application->GetTopmostWid($event->Prefix);
$var_name = rtrim($event->getPrefixSpecial().'_selected_ids_'.$wid, '_');
$ret = $this->Application->RecallVar($var_name);
}
else {
$ret = $this->Application->GetVar($event->getPrefixSpecial().'_selected_ids');
}
return explode(',', $ret);
}
/**
* Returs associative array of submitted fields for current item
* Could be used while creating/editing single item -
* meaning on any edit form, except grid edit
*
* @param kEvent $event
*/
function getSubmittedFields(&$event)
{
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
$field_values = $items_info ? array_shift($items_info) : Array();
return $field_values;
}
/**
* Removes any information about current/selected ids
* from Application variables and Session
*
* @param kEvent $event
*/
function clearSelectedIDs(&$event)
{
$prefix_special = $event->getPrefixSpecial();
$ids = implode(',', $this->getSelectedIDs($event, true));
$event->setEventParam('ids', $ids);
$wid = $this->Application->GetTopmostWid($event->Prefix);
$session_name = rtrim($prefix_special.'_selected_ids_'.$wid, '_');
$this->Application->RemoveVar($session_name);
$this->Application->SetVar($prefix_special.'_selected_ids', '');
$this->Application->SetVar($prefix_special.'_id', ''); // $event->getPrefixSpecial(true).'_id' too may be
}
/*function SetSaveEvent(&$event)
{
$this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnUpdate');
$this->Application->LinkVar($event->Prefix_Special.'_SaveEvent');
}*/
/**
* Common builder part for Item & List
*
* @param kDBBase $object
* @param kEvent $event
* @access private
*/
function dbBuild(&$object, &$event)
{
$object->Configure( $event->getEventParam('populate_ml_fields') || $this->Application->getUnitOption($event->Prefix, 'PopulateMlFields') );
$this->PrepareObject($object, $event);
// force live table if specified or is original item
$live_table = $event->getEventParam('live_table') || $event->Special == 'original';
if( $this->UseTempTables($event) && !$live_table )
{
$object->SwitchToTemp();
}
// This strange constuction creates hidden field for storing event name in form submit
// It pass SaveEvent to next screen, otherwise after unsuccsefull create it will try to update rather than create
$current_event = $this->Application->GetVar($event->Prefix_Special.'_event');
// $this->Application->setEvent($event->Prefix_Special, $current_event);
$this->Application->setEvent($event->Prefix_Special, '');
$save_event = $this->UseTempTables($event) && $this->Application->GetTopmostPrefix($event->Prefix) == $event->Prefix ? 'OnSave' : 'OnUpdate';
$this->Application->SetVar($event->Prefix_Special.'_SaveEvent',$save_event);
}
/**
* Checks, that currently loaded item is allowed for viewing (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
$status_fields = $this->Application->getUnitOption($event->Prefix,'StatusField');
if (!$status_fields) {
return true;
}
$status_field = array_shift($status_fields);
if ($status_field == 'Status' || $status_field == 'Enabled') {
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
return $object->GetDBField($status_field) == STATUS_ACTIVE;
}
return true;
}
/**
* Shows not found template content
*
* @param kEvent $event
*
*/
function _errorNotFound(&$event)
{
if ($event->getEventParam('raise_warnings') === 0) {
// when it's possible, that autoload fails do nothing
return ;
}
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendTrace();
}
trigger_error('ItemLoad Permission Failed for prefix [' . $event->getPrefixSpecial() . '] in <strong>checkItemStatus</strong>, leading to "404 Not Found"', E_USER_WARNING);
header('HTTP/1.0 404 Not Found');
while (ob_get_level()) {
ob_end_clean();
}
// object is used inside template parsing, so break out any parsing and return error document
$error_template = $this->Application->ConfigValue('ErrorTemplate');
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
$this->Application->SetVar('t', $error_template);
$this->Application->SetVar('m_cat_id', $themes_helper->getPageByTemplate($error_template));
$this->Application->HTML = $this->Application->ParseBlock( Array ('name' => $error_template) );
$this->Application->Done();
exit;
}
/**
* Builds item (loads if needed)
*
* @param kEvent $event
* @access protected
*/
function OnItemBuild(&$event)
{
$object =& $event->getObject();
$this->dbBuild($object,$event);
$sql = $this->ItemPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
// 2. loads if allowed
$auto_load = $this->Application->getUnitOption($event->Prefix,'AutoLoad');
$skip_autload = $event->getEventParam('skip_autoload');
if ($auto_load && !$skip_autload) {
$perm_status = true;
$user_id = $this->Application->RecallVar('user_id');
$event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
$status_checked = false;
if ($user_id == -1 || $this->CheckPermission($event)) {
// don't autoload item, when user doesn't have view permission
$this->LoadItem($event);
$status_checked = true;
if ($user_id != -1 && !$this->Application->IsAdmin() && !$this->checkItemStatus($event)) {
$perm_status = false;
}
}
else {
$perm_status = false;
}
if (!$perm_status) {
// when no permission to view item -> redirect to no pemrission template
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendTrace();
}
trigger_error('ItemLoad Permission Failed for prefix ['.$event->getPrefixSpecial().'] in <strong>'.($status_checked ? 'checkItemStatus' : 'CheckPermission').'</strong>', E_USER_WARNING);
$next_template = $this->Application->IsAdmin() ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
$this->Application->Redirect($next_template, Array('next_template' => $this->Application->GetVar('t')));
}
}
$actions =& $this->Application->recallObject('kActions');
$actions->Set($event->Prefix_Special.'_GoTab', '');
$actions->Set($event->Prefix_Special.'_GoId', '');
}
/**
* Build subtables array from configs
*
* @param kEvent $event
*/
function OnTempHandlerBuild(&$event)
{
$object =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $object kTempTablesHandler */
$object->BuildTables( $event->Prefix, $this->getSelectedIDs($event) );
}
/**
* Checks, that object used in event should use temp tables
*
* @param kEvent $event
* @return bool
*/
function UseTempTables(&$event)
{
$top_prefix = $this->Application->GetTopmostPrefix($event->Prefix); // passed parent, not always actual
$special = ($top_prefix == $event->Prefix) ? $event->Special : $this->getMainSpecial($event);
return $this->Application->IsTempMode($event->Prefix, $special);
}
/**
* Returns table prefix from event (temp or live)
*
* @param kEvent $event
* @return string
* @todo Needed? Should be refactored (by Alex)
*/
function TablePrefix(&$event)
{
return $this->UseTempTables($event) ? $this->Application->GetTempTablePrefix('prefix:'.$event->Prefix).TABLE_PREFIX : TABLE_PREFIX;
}
/**
* Load item if id is available
*
* @param kEvent $event
*/
function LoadItem(&$event)
{
$object =& $event->getObject();
$id = $this->getPassedID($event);
if ($object->isLoaded() && !is_array($id) && ($object->GetID() == $id)) {
// object is already loaded by same id
return ;
}
if ($object->Load($id)) {
$actions =& $this->Application->recallObject('kActions');
$actions->Set($event->Prefix_Special.'_id', $object->GetID() );
}
else {
$object->setID($id);
}
}
/**
* Builds list
*
* @param kEvent $event
* @access protected
*/
function OnListBuild(&$event)
{
$object =& $event->getObject();
/* @var $object kDBList */
$this->dbBuild($object,$event);
$sql = $this->ListPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
$object->Counted = false; // when requery="1" should re-count records too!
$object->ClearOrderFields(); // prevents duplicate order fields, when using requery="1"
$object->linkToParent( $this->getMainSpecial($event) );
$this->AddFilters($event);
$this->SetCustomQuery($event); // new!, use this for dynamic queries based on specials for ex.
$this->SetPagination($event);
$this->SetSorting($event);
// $object->CalculateTotals(); // Now called in getTotals to avoid extra query
$actions =& $this->Application->recallObject('kActions');
$actions->Set('remove_specials['.$event->Prefix_Special.']', '0');
$actions->Set($event->Prefix_Special.'_GoTab', '');
}
/**
* Get's special of main item for linking with subitem
*
* @param kEvent $event
* @return string
*/
function getMainSpecial(&$event)
{
$main_special = $event->getEventParam('main_special');
if ($main_special === false) {
// main item's special not passed
if (substr($event->Special, -5) == '-item') {
// temp handler added "-item" to given special -> process that here
return substr($event->Special, 0, -5);
}
// by default subitem's special is used for main item searching
return $event->Special;
}
return $main_special;
}
/**
* Apply any custom changes to list's sql query
*
* @param kEvent $event
* @access protected
* @see OnListBuild
*/
function SetCustomQuery(&$event)
{
}
/**
* Set's new perpage for grid
*
* @param kEvent $event
*/
function OnSetPerPage(&$event)
{
$per_page = $this->Application->GetVar($event->getPrefixSpecial(true).'_PerPage');
$this->Application->StoreVar($event->getPrefixSpecial().'_PerPage', $per_page);
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_PerPage.'.$view_name, $per_page);
}
/**
* 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) {
$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;
}
}
/*$per_page = $event->getEventParam('per_page');
if ($per_page == 'list_next') {
$cur_page = $page;
$cur_per_page = $per_page;
$object->SetPerPage(1);
$object =& $this->Application->recallObject($event->Prefix);
$cur_item_index = $object->CurrentIndex;
$page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1;
$object->SetPerPage(1);
}*/
$object->SetPage($page);
}
/**
* Returns current per-page setting for list
*
* @param kEvent $event
* @return int
*/
function getPerPage(&$event)
{
// 1. per-page is passed as tag parameter to PrintList, InitList, etc.
$per_page = $event->getEventParam('per_page');
/*if ($per_page == 'list_next') {
$per_page = '';
}*/
// 2. per-page variable name is store into config variable
$config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
if ($config_mapping) {
switch ( $per_page ){
case 'short_list' :
$per_page = $this->Application->ConfigValue($config_mapping['ShortListPerPage']);
break;
case 'default' :
$per_page = $this->Application->ConfigValue($config_mapping['PerPage']);
break;
}
}
if (!$per_page) {
// per-page is stored to persistent session
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$storage_prefix = $event->getEventParam('same_special') ? $event->Prefix : $event->getPrefixSpecial();
$per_page = $this->Application->RecallPersistentVar($storage_prefix.'_PerPage.'.$view_name, ALLOW_DEFAULT_SETTINGS);
if (!$per_page) {
// per-page is stored to current session
$per_page = $this->Application->RecallVar($storage_prefix.'_PerPage');
}
if (!$per_page) {
if ($config_mapping) {
if (!isset($config_mapping['PerPage'])) {
trigger_error('Incorrect mapping of <span class="debug_error">PerPage</span> key in config for prefix <b>'.$event->Prefix.'</b>', E_USER_WARNING);
}
$per_page = $this->Application->ConfigValue($config_mapping['PerPage']);
}
if (!$per_page) {
// none of checked above per-page locations are useful, then try default value
$default_per_page = $event->getEventParam('default_per_page');
$per_page = is_numeric($default_per_page) ? $default_per_page : 10;
}
}
}
return $per_page;
}
/**
* Set's correct sorting for list
* based on data provided with event
*
* @param kEvent $event
* @access private
* @see OnListBuild
*/
function SetSorting(&$event)
{
$event->setPseudoClass('_List');
$object =& $event->getObject();
$storage_prefix = $event->getEventParam('same_special') ? $event->Prefix : $event->Prefix_Special;
$cur_sort1 = $this->Application->RecallVar($storage_prefix.'_Sort1');
$cur_sort1_dir = $this->Application->RecallVar($storage_prefix.'_Sort1_Dir');
$cur_sort2 = $this->Application->RecallVar($storage_prefix.'_Sort2');
$cur_sort2_dir = $this->Application->RecallVar($storage_prefix.'_Sort2_Dir');
$sorting_configs = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping');
$list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings');
$sorting_prefix = getArrayValue($list_sortings, $event->Special) ? $event->Special : '';
$tag_sort_by = $event->getEventParam('sort_by');
if ($tag_sort_by) {
if ($tag_sort_by == 'random') {
$object->AddOrderField('RAND()', '');
}
else {
$tag_sort_by = explode('|', $tag_sort_by);
foreach ($tag_sort_by as $sorting_element) {
list ($by, $dir) = explode(',', $sorting_element);
$object->AddOrderField($by, $dir);
}
}
}
if ($sorting_configs && isset ($sorting_configs['DefaultSorting1Field'])){
$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']),
);
}
// Use default if not specified
if ( !$cur_sort1 || !$cur_sort1_dir)
{
if ( $sorting = getArrayValue($list_sortings, $sorting_prefix, 'Sorting') ) {
reset($sorting);
$cur_sort1 = key($sorting);
$cur_sort1_dir = current($sorting);
if (next($sorting)) {
$cur_sort2 = key($sorting);
$cur_sort2_dir = current($sorting);
}
}
}
if ( $forced_sorting = getArrayValue($list_sortings, $sorting_prefix, 'ForcedSorting') ) {
foreach ($forced_sorting as $field => $dir) {
$object->AddOrderField($field, $dir);
}
}
if($cur_sort1 != '' && $cur_sort1_dir != '')
{
$object->AddOrderField($cur_sort1, $cur_sort1_dir);
}
if($cur_sort2 != '' && $cur_sort2_dir != '')
{
$object->AddOrderField($cur_sort2, $cur_sort2_dir);
}
}
/**
* Add filters found in session
*
* @param kEvent $event
*/
function AddFilters(&$event)
{
$object =& $event->getObject();
$edit_mark = rtrim($this->Application->GetSID().'_'.$this->Application->GetTopmostWid($event->Prefix), '_');
// add search filter
$filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter');
if ($filter_data) {
$filter_data = unserialize($filter_data);
foreach ($filter_data as $filter_field => $filter_params) {
$filter_type = ($filter_params['type'] == 'having') ? HAVING_FILTER : WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $filter_params['value']);
$object->addFilter($filter_field, $filter_value, $filter_type, FLT_SEARCH);
}
}
// add custom filter
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$custom_filters = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_custom_filter.'.$view_name);
if ($custom_filters) {
$grid_name = $event->getEventParam('grid');
$custom_filters = unserialize($custom_filters);
if (isset($custom_filters[$grid_name])) {
foreach ($custom_filters[$grid_name] as $field_name => $field_options) {
list ($filter_type, $field_options) = each($field_options);
if (isset($field_options['value']) && $field_options['value']) {
$filter_type = ($field_options['sql_filter_type'] == 'having') ? HAVING_FILTER : WHERE_FILTER;
$filter_value = str_replace(EDIT_MARK, $edit_mark, $field_options['value']);
$object->addFilter($field_name, $filter_value, $filter_type, FLT_CUSTOM);
}
}
}
}
$view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
if($view_filter)
{
$view_filter = unserialize($view_filter);
$temp_filter =& $this->Application->makeClass('kMultipleFilter');
$filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
$group_key = 0; $group_count = count($filter_menu['Groups']);
while($group_key < $group_count)
{
$group_info = $filter_menu['Groups'][$group_key];
$temp_filter->setType( constant('FLT_TYPE_'.$group_info['mode']) );
$temp_filter->clearFilters();
foreach ($group_info['filters'] as $flt_id)
{
$sql_key = getArrayValue($view_filter,$flt_id) ? 'on_sql' : 'off_sql';
if ($filter_menu['Filters'][$flt_id][$sql_key] != '')
{
$temp_filter->addFilter('view_filter_'.$flt_id, $filter_menu['Filters'][$flt_id][$sql_key]);
}
}
$object->addFilter('view_group_'.$group_key, $temp_filter, $group_info['type'] , FLT_VIEW);
$group_key++;
}
}
}
/**
* Set's new sorting for list
*
* @param kEvent $event
* @access protected
*/
function OnSetSorting(&$event)
{
$cur_sort1 = $this->Application->RecallVar($event->Prefix_Special.'_Sort1');
$cur_sort1_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort1_Dir');
$use_double_sorting = $this->Application->ConfigValue('UseDoubleSorting');
if ($use_double_sorting) {
$cur_sort2 = $this->Application->RecallVar($event->Prefix_Special.'_Sort2');
$cur_sort2_dir = $this->Application->RecallVar($event->Prefix_Special.'_Sort2_Dir');
}
$passed_sort1 = $this->Application->GetVar($event->getPrefixSpecial(true).'_Sort1');
if ($cur_sort1 == $passed_sort1) {
$cur_sort1_dir = $cur_sort1_dir == 'asc' ? 'desc' : 'asc';
}
else {
if ($use_double_sorting) {
$cur_sort2 = $cur_sort1;
$cur_sort2_dir = $cur_sort1_dir;
}
$cur_sort1 = $passed_sort1;
$cur_sort1_dir = 'asc';
}
$this->Application->StoreVar($event->Prefix_Special.'_Sort1', $cur_sort1);
$this->Application->StoreVar($event->Prefix_Special.'_Sort1_Dir', $cur_sort1_dir);
if ($use_double_sorting) {
$this->Application->StoreVar($event->Prefix_Special.'_Sort2', $cur_sort2);
$this->Application->StoreVar($event->Prefix_Special.'_Sort2_Dir', $cur_sort2_dir);
}
}
/**
* Set sorting directly to session (used for category item sorting (front-end), grid sorting (admin, view menu)
*
* @param kEvent $event
*/
function OnSetSortingDirect(&$event)
{
$combined = $this->Application->GetVar($event->Prefix.'_CombinedSorting');
if ($combined) {
list($field, $dir) = explode('|', $combined);
$this->Application->StoreVar($event->Prefix.'_Sort1', $field);
$this->Application->StoreVar($event->Prefix.'_Sort1_Dir', $dir);
return ;
}
$field_pos = $this->Application->GetVar($event->Prefix.'_SortPos');
$this->Application->LinkVar($event->Prefix.'_Sort'.$field_pos, $event->Prefix.'_Sort'.$field_pos);
$this->Application->LinkVar($event->Prefix.'_Sort'.$field_pos.'_Dir', $event->Prefix.'_Sort'.$field_pos.'_Dir');
}
/**
* Reset grid sorting to default (from config)
*
* @param kEvent $event
*/
function OnResetSorting(&$event)
{
$this->Application->RemoveVar($event->Prefix_Special.'_Sort1');
$this->Application->RemoveVar($event->Prefix_Special.'_Sort1_Dir');
$this->Application->RemoveVar($event->Prefix_Special.'_Sort2');
$this->Application->RemoveVar($event->Prefix_Special.'_Sort2_Dir');
}
/**
* Sets grid refresh interval
*
* @param kEvent $event
*/
function OnSetAutoRefreshInterval(&$event)
{
$refresh_interval = $this->Application->GetVar('refresh_interval');
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_interval);
}
/**
* Changes auto-refresh state for grid
*
* @param kEvent $event
*/
function OnAutoRefreshToggle(&$event)
{
$refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals');
if (!$refresh_intervals) {
return ;
}
$view_name = $this->Application->RecallVar($event->getPrefixSpecial().'_current_view');
$auto_refresh = $this->Application->RecallPersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name);
if ($auto_refresh === false) {
$refresh_intervals = explode(',', $refresh_intervals);
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_refresh_interval.'.$view_name, $refresh_intervals[0]);
}
$this->Application->StorePersistentVar($event->getPrefixSpecial().'_auto_refresh.'.$view_name, $auto_refresh ? 0 : 1);
}
/**
* Creates needed sql query to load item,
* if no query is defined in config for
* special requested, then use default
* query
*
* @param kEvent $event
* @access protected
*/
function ItemPrepareQuery(&$event)
{
$sqls = $this->Application->getUnitOption($event->Prefix, 'ItemSQLs', Array ());
$special = array_key_exists($event->Special, $sqls) ? $event->Special : '';
if (!array_key_exists($special, $sqls)) {
// preferred special not found in ItemSQLs -> use analog from ListSQLs
return $this->ListPrepareQuery($event);
}
return $sqls[$special];
}
/**
* Creates needed sql query to load list,
* if no query is defined in config for
* special requested, then use default
* query
*
* @param kEvent $event
* @access protected
*/
function ListPrepareQuery(&$event)
{
$sqls = $this->Application->getUnitOption($event->Prefix, 'ListSQLs', Array ());
return $sqls[ array_key_exists($event->Special, $sqls) ? $event->Special : '' ];
}
/**
* Apply custom processing to item
*
* @param kEvent $event
*/
function customProcessing(&$event, $type)
{
}
/* Edit Events mostly used in Admin */
/**
* Creates new kDBItem
*
* @param kEvent $event
* @access protected
*/
function OnCreate(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
list($id,$field_values) = each($items_info);
$object->SetFieldsFromHash($field_values);
}
$this->customProcessing($event,'before');
//look at kDBItem' Create for ForceCreateId description, it's rarely used and is NOT set by default
if( $object->Create($event->getEventParam('ForceCreateId')) )
{
if( $object->IsTempTable() ) $object->setTempID();
$this->customProcessing($event,'after');
$event->status=erSUCCESS;
$event->redirect_params = Array('opener'=>'u');
}
else
{
$event->status = erFAIL;
$event->redirect = false;
$this->Application->SetVar($event->Prefix_Special.'_SaveEvent','OnCreate');
$object->setID($id);
}
}
/**
* Updates kDBItem
*
* @param kEvent $event
* @access protected
*/
function OnUpdate(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
foreach($items_info as $id => $field_values)
{
$object->Load($id);
$object->SetFieldsFromHash($field_values);
$this->customProcessing($event, 'before');
if( $object->Update($id) )
{
$this->customProcessing($event, 'after');
$event->status=erSUCCESS;
}
else
{
$event->status=erFAIL;
$event->redirect=false;
break;
}
}
}
$event->redirect_params = Array('opener'=>'u');
}
/**
* Delete's kDBItem object
*
* @param kEvent $event
* @access protected
*/
function OnDelete(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
$temp->DeleteItems($event->Prefix, $event->Special, Array($this->getPassedID($event)));
}
/**
* Deletes all records from table
*
* @param kEvent $event
*/
function OnDeleteAll(&$event)
{
$sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . '
FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName');
$ids = $this->Conn->GetCol($sql);
if ($ids) {
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial() . '_TempHandler', 'kTempTablesHandler');
/* @var $temp_handler kTempTablesHandler */
$temp_handler->DeleteItems($event->Prefix, $event->Special, $ids);
}
}
/**
* Prepares new kDBItem object
*
* @param kEvent $event
* @access protected
*/
function OnNew(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
/* @var $object kDBItem */
$object->Clear(0);
$this->Application->SetVar($event->Prefix_Special.'_SaveEvent', 'OnCreate');
if ($event->getEventParam('top_prefix') != $event->Prefix) {
// this is subitem prefix, so use main item special
$table_info = $object->getLinkedInfo( $this->getMainSpecial($event) );
}
else {
$table_info = $object->getLinkedInfo();
}
$object->SetDBField($table_info['ForeignKey'], $table_info['ParentId']);
$event->redirect = false;
}
/**
* Cancel's kDBItem Editing/Creation
*
* @param kEvent $event
* @access protected
*/
function OnCancel(&$event)
{
$object =& $event->getObject(Array('skip_autoload' => true));
$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
if ($items_info) {
$delete_ids = Array();
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
foreach ($items_info as $id => $field_values) {
$object->Load($id);
// record created for using with selector (e.g. Reviews->Select User), and not validated => Delete it
if ($object->isLoaded() && !$object->Validate() && ($id <= 0) ) {
$delete_ids[] = $id;
}
}
if ($delete_ids) {
$temp->DeleteItems($event->Prefix, $event->Special, $delete_ids);
}
}
$event->redirect_params = Array('opener'=>'u');
}
/**
* Deletes all selected items.
* Automatically recurse into sub-items using temp handler, and deletes sub-items
* by calling its Delete method if sub-item has AutoDelete set to true in its config file
*
* @param kEvent $event
*/
function OnMassDelete(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$event->status=erSUCCESS;
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$ids = $this->StoreSelectedIDs($event);
$event->setEventParam('ids', $ids);
$this->customProcessing($event, 'before');
$ids = $event->getEventParam('ids');
if($ids)
{
$temp->DeleteItems($event->Prefix, $event->Special, $ids);
}
$this->clearSelectedIDs($event);
}
/**
* Sets window id (of first opened edit window) to temp mark in uls
*
* @param kEvent $event
*/
function setTempWindowID(&$event)
{
$prefixes = Array ($event->Prefix, $event->getPrefixSpecial(true));
foreach ($prefixes as $prefix) {
$mode = $this->Application->GetVar($prefix . '_mode');
if ($mode == 't') {
$wid = $this->Application->GetVar('m_wid');
$this->Application->SetVar(str_replace('_', '.', $prefix) . '_mode', 't' . $wid);
break;
}
}
}
/**
* Prepare temp tables and populate it
* with items selected in the grid
*
* @param kEvent $event
*/
function OnEdit(&$event)
{
$this->setTempWindowID($event);
$this->StoreSelectedIDs($event);
$var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
$this->Application->RemoveVar($var_name);
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
$temp->PrepareEdit();
$event->redirect=false;
}
/**
* Saves content of temp table into live and
* redirects to event' default redirect (normally grid template)
*
* @param kEvent $event
*/
function OnSave(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status == erSUCCESS) {
$skip_master = false;
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$changes_var_name = $this->Prefix.'_changes_'.$this->Application->GetTopmostWid($this->Prefix);
if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array());
// Deleteing files scheduled for delete
$var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
$schedule = $this->Application->RecallVar($var_name);
$schedule = $schedule ? unserialize($schedule) : array();
foreach ($schedule as $data) {
if ($data['action'] == 'delete') {
unlink($data['file']);
}
}
if ($live_ids) {
// ensure, that newly created item ids are avalable as if they were selected from grid
// NOTE: only works if main item has subitems !!!
$this->StoreSelectedIDs($event, $live_ids);
}
$this->SaveLoggedChanges($changes_var_name);
}
else {
$this->Application->RemoveVar($changes_var_name);
}
$this->clearSelectedIDs($event);
$event->redirect_params = Array('opener' => 'u');
$this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
// all temp tables are deleted here => all after hooks should think, that it's live mode now
$this->Application->SetVar($event->Prefix.'_mode', '');
}
}
function SaveLoggedChanges($changes_var_name)
{
$ses_log_id = $this->Application->RecallVar('_SessionLogId_');
if (!$ses_log_id) {
return ;
}
$changes = $this->Application->RecallVar($changes_var_name);
$changes = $changes ? unserialize($changes) : Array ();
if (!$changes) {
return ;
}
$add_fields = Array (
'PortalUserId' => $this->Application->RecallVar('user_id'),
'SessionLogId' => $ses_log_id,
);
$changelog_table = $this->Application->getUnitOption('change-log', 'TableName');
$sessionlog_table = $this->Application->getUnitOption('session-log', 'TableName');
foreach ($changes as $rec) {
$this->Conn->doInsert(array_merge($rec, $add_fields), $changelog_table);
}
$sql = 'UPDATE '.$sessionlog_table.'
SET AffectedItems = AffectedItems + '.count($changes).'
WHERE SessionLogId = '.$ses_log_id;
$this->Conn->Query($sql);
$this->Application->RemoveVar($changes_var_name);
}
/**
* Cancels edit
* Removes all temp tables and clears selected ids
*
* @param kEvent $event
*/
function OnCancelEdit(&$event)
{
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$temp->CancelEdit();
$this->clearSelectedIDs($event);
$event->redirect_params = Array('opener'=>'u');
$this->Application->RemoveVar($event->getPrefixSpecial().'_modified');
}
/**
* Allows to determine if we are creating new item or editing already created item
*
* @param kEvent $event
* @return bool
*/
function isNewItemCreate(&$event)
{
$object =& $event->getObject( Array ('raise_warnings' => 0) );
return !$object->IsLoaded();
// $item_id = $this->getPassedID($event);
// return ($item_id == '') ? true : false;
}
/**
* Saves edited item into temp table
* If there is no id, new item is created in temp table
*
* @param kEvent $event
*/
function OnPreSave(&$event)
{
//$event->redirect = false;
// if there is no id - it means we need to create an item
if (is_object($event->MasterEvent)) {
$event->MasterEvent->setEventParam('IsNew',false);
}
if ($this->isNewItemCreate($event)) {
$event->CallSubEvent('OnPreSaveCreated');
if (is_object($event->MasterEvent)) {
$event->MasterEvent->setEventParam('IsNew',true);
}
return;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if ($items_info) {
foreach ($items_info as $id => $field_values) {
$object->SetDefaultValues();
$object->Load($id);
$object->SetFieldsFromHash($field_values);
$this->customProcessing($event, 'before');
if( $object->Update($id) )
{
$this->customProcessing($event, 'after');
$event->status=erSUCCESS;
}
else {
$event->status = erFAIL;
$event->redirect = false;
break;
}
}
}
}
/**
* [HOOK] Saves subitem
*
* @param kEvent $event
*/
function OnPreSaveSubItem(&$event)
{
$not_created = $this->isNewItemCreate($event);
$event->CallSubEvent($not_created ? 'OnCreate' : 'OnUpdate');
if ($event->status == erSUCCESS) {
$object =& $event->getObject();
/* @var $object kDBItem */
$this->Application->SetVar($event->getPrefixSpecial() . '_id', $object->GetID());
}
$event->SetRedirectParam('opener', 's');
}
/**
* Saves edited item in temp table and loads
* item with passed id in current template
* Used in Prev/Next buttons
*
* @param kEvent $event
*/
function OnPreSaveAndGo(&$event)
{
$event->CallSubEvent('OnPreSave');
+
if ($event->status == erSUCCESS) {
- $event->SetRedirectParam($event->getPrefixSpecial(true).'_id', $this->Application->GetVar($event->Prefix_Special.'_GoId'));
+ $id = $this->Application->GetVar($event->getPrefixSpecial(true) . '_GoId');
+ $event->SetRedirectParam($event->getPrefixSpecial() . '_id', $id);
}
}
/**
* Saves edited item in temp table and goes
* to passed tabs, by redirecting to it with OnPreSave event
*
* @param kEvent $event
*/
function OnPreSaveAndGoToTab(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status==erSUCCESS) {
$event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
}
}
/**
* Saves editable list and goes to passed tab,
* by redirecting to it with empty event
*
* @param kEvent $event
*/
function OnUpdateAndGoToTab(&$event)
{
$event->setPseudoClass('_List');
$event->CallSubEvent('OnUpdate');
if ($event->status==erSUCCESS) {
$event->redirect=$this->Application->GetVar($event->getPrefixSpecial(true).'_GoTab');
}
}
/**
* Prepare temp tables for creating new item
* but does not create it. Actual create is
* done in OnPreSaveCreated
*
* @param kEvent $event
*/
function OnPreCreate(&$event)
{
$this->setTempWindowID($event);
$this->clearSelectedIDs($event);
$object =& $event->getObject( Array('skip_autoload' => true) );
$temp =& $this->Application->recallObject($event->Prefix.'_TempHandler', 'kTempTablesHandler');
$temp->PrepareEdit();
$object->setID(0);
$this->Application->SetVar($event->getPrefixSpecial().'_id',0);
$this->Application->SetVar($event->getPrefixSpecial().'_PreCreate', 1);
$event->redirect=false;
}
/**
* Creates a new item in temp table and
* stores item id in App vars and Session on succsess
*
* @param kEvent $event
*/
function OnPreSaveCreated(&$event)
{
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info) $field_values = array_shift($items_info);
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->SetFieldsFromHash($field_values);
$this->customProcessing($event, 'before');
if( $object->Create() )
{
$this->customProcessing($event, 'after');
$event->redirect_params[$event->getPrefixSpecial(true).'_id'] = $object->GetId();
$event->status=erSUCCESS;
}
else
{
$event->status=erFAIL;
$event->redirect=false;
$object->setID(0);
}
}
function OnReset(&$event)
{
//do nothing - should reset :)
if ($this->isNewItemCreate($event)) {
// just reset id to 0 in case it was create
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->setID(0);
$this->Application->SetVar($event->getPrefixSpecial().'_id',0);
}
}
/**
* Apply same processing to each item beeing selected in grid
*
* @param kEvent $event
* @access private
*/
function iterateItems(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') );
$order_field = $this->Application->getUnitOption($event->Prefix,'OrderField');
if (!$order_field) {
$order_field = 'Priority';
}
foreach ($ids as $id) {
$object->Load($id);
switch ($event->Name) {
case 'OnMassApprove':
$object->SetDBField($status_field, 1);
break;
case 'OnMassDecline':
$object->SetDBField($status_field, 0);
break;
case 'OnMassMoveUp':
$object->SetDBField($order_field, $object->GetDBField($order_field) + 1);
break;
case 'OnMassMoveDown':
$object->SetDBField($order_field, $object->GetDBField($order_field) - 1);
break;
}
if ($object->Update()) {
$event->status = erSUCCESS;
}
else {
$event->status = erFAIL;
$event->redirect = false;
break;
}
}
}
$this->clearSelectedIDs($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnMassClone(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
return;
}
$event->status = erSUCCESS;
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$ids = $this->StoreSelectedIDs($event);
if ($ids) {
$temp->CloneItems($event->Prefix, $event->Special, $ids);
}
$this->clearSelectedIDs($event);
}
function check_array($records, $field, $value)
{
foreach ($records as $record) {
if ($record[$field] == $value) {
return true;
}
}
return false;
}
function OnPreSavePopup(&$event)
{
$object =& $event->getObject();
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
$this->finalizePopup($event);
}
/* End of Edit events */
// III. Events that allow to put some code before and after Update,Load,Create and Delete methods of item
/**
* Occurse before loading item, 'id' parameter
* allows to get id of item beeing loaded
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemLoad(&$event)
{
}
/**
* Occurse after loading item, 'id' parameter
* allows to get id of item that was loaded
*
* @param kEvent $event
* @access public
*/
function OnAfterItemLoad(&$event)
{
}
/**
* Occurse before creating item
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemCreate(&$event)
{
}
/**
* Occurse after creating item
*
* @param kEvent $event
* @access public
*/
function OnAfterItemCreate(&$event)
{
}
/**
* Occurse before updating item
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemUpdate(&$event)
{
}
/**
* Occurse after updating item
*
* @param kEvent $event
* @access public
*/
function OnAfterItemUpdate(&$event)
{
}
/**
* Occurse before deleting item, id of item beeing
* deleted is stored as 'id' event param
*
* @param kEvent $event
* @access public
*/
function OnBeforeItemDelete(&$event)
{
}
/**
* Occurse after deleting item, id of deleted item
* is stored as 'id' param of event
*
* @param kEvent $event
* @access public
*/
function OnAfterItemDelete(&$event)
{
}
/**
* Occurs after successful item validation
*
* @param kEvent $event
*/
function OnAfterItemValidate(&$event)
{
}
/**
* Occures after an item has been copied to temp
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterCopyToTemp(&$event)
{
}
/**
* Occures before an item is deleted from live table when copying from temp
* (temp handler deleted all items from live and then copy over all items from temp)
* Id of item being deleted is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnBeforeDeleteFromLive(&$event)
{
}
/**
* Occures before an item is copied to live table (after all foreign keys have been updated)
* Id of item being copied is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnBeforeCopyToLive(&$event)
{
}
/**
* !!! NOT FULLY IMPLEMENTED - SEE TEMP HANDLER COMMENTS (search by event name)!!!
* Occures after an item has been copied to live table
* Id of copied item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterCopyToLive(&$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)
{
}
/**
* Occures after an item has been cloned
* Id of newly created item is passed as event' 'id' param
*
* @param kEvent $event
*/
function OnAfterClone(&$event)
{
}
/**
* Occures after list is queried
*
* @param kEvent $event
*/
function OnAfterListQuery(&$event)
{
}
/**
* Ensures that popup will be closed automatically
* and parent window will be refreshed with template
* passed
*
* @param kEvent $event
* @access public
*/
function finalizePopup(&$event)
{
$event->SetRedirectParam('opener', 'u');
}
/**
* Create search filters based on search query
*
* @param kEvent $event
* @access protected
*/
function OnSearch(&$event)
{
$event->setPseudoClass('_List');
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->performSearch($event);
}
/**
* Clear search keywords
*
* @param kEvent $event
* @access protected
*/
function OnSearchReset(&$event)
{
$search_helper =& $this->Application->recallObject('SearchHelper');
/* @var $search_helper kSearchHelper */
$search_helper->resetSearch($event);
}
/**
* Set's new filter value (filter_id meaning from config)
*
* @param kEvent $event
*/
function OnSetFilter(&$event)
{
$filter_id = $this->Application->GetVar('filter_id');
$filter_value = $this->Application->GetVar('filter_value');
$view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
$view_filter = $view_filter ? unserialize($view_filter) : Array();
$view_filter[$filter_id] = $filter_value;
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
}
function OnSetFilterPattern(&$event)
{
$filters = $this->Application->GetVar($event->getPrefixSpecial(true).'_filters');
if (!$filters) return ;
$view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter');
$view_filter = $view_filter ? unserialize($view_filter) : Array();
$filters = explode(',', $filters);
foreach ($filters as $a_filter) {
list($id, $value) = explode('=', $a_filter);
$view_filter[$id] = $value;
}
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
$event->redirect = false;
}
/**
* Add/Remove all filters applied to list from "View" menu
*
* @param kEvent $event
*/
function FilterAction(&$event)
{
$view_filter = Array();
$filter_menu = $this->Application->getUnitOption($event->Prefix,'FilterMenu');
switch ($event->Name)
{
case 'OnRemoveFilters':
$filter_value = 1;
break;
case 'OnApplyFilters':
$filter_value = 0;
break;
}
foreach($filter_menu['Filters'] as $filter_key => $filter_params)
{
if(!$filter_params) continue;
$view_filter[$filter_key] = $filter_value;
}
$this->Application->StoreVar( $event->getPrefixSpecial().'_view_filter', serialize($view_filter) );
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnPreSaveAndOpenTranslator(&$event)
{
$this->Application->SetVar('allow_translation', true);
$object =& $event->getObject();
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
if ($event->status == erSUCCESS) {
$resource_id = $this->Application->GetVar('translator_resource_id');
if ($resource_id) {
$t_prefixes = explode(',', $this->Application->GetVar('translator_prefixes'));
$cdata =& $this->Application->recallObject($t_prefixes[1], null, Array('skip_autoload' => true));
$cdata->Load($resource_id, 'ResourceId');
if (!$cdata->isLoaded()) {
$cdata->SetDBField('ResourceId', $resource_id);
$cdata->Create();
}
$this->Application->SetVar($cdata->getPrefixSpecial().'_id', $cdata->GetID());
}
$event->redirect = $this->Application->GetVar('translator_t');
$event->redirect_params = Array('pass'=>'all,trans,'.$this->Application->GetVar('translator_prefixes'),
$event->getPrefixSpecial(true).'_id' => $object->GetID(),
'trans_event' => 'OnLoad',
'trans_prefix' => $this->Application->GetVar('translator_prefixes'),
'trans_field' => $this->Application->GetVar('translator_field'),
'trans_multi_line' => $this->Application->GetVar('translator_multi_line'),
);
// 1. SAVE LAST TEMPLATE TO SESSION (really needed here, because of tweaky redirect)
$last_template = $this->Application->RecallVar('last_template');
preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets);
$this->Application->StoreVar('return_template', $this->Application->GetVar('t'));
}
}
function RemoveRequiredFields(&$object)
{
// making all field non-required to achieve successful presave
foreach($object->Fields as $field => $options)
{
if(isset($options['required']))
{
unset($object->Fields[$field]['required']);
}
}
}
/**
* Saves selected user in needed field
*
* @param kEvent $event
*/
function OnSelectUser(&$event)
{
$items_info = $this->Application->GetVar('u');
if ($items_info) {
$user_id = array_shift( array_keys($items_info) );
$object =& $event->getObject();
$this->RemoveRequiredFields($object);
$is_new = !$object->isLoaded();
$is_main = substr($this->Application->GetVar($event->Prefix.'_mode'), 0, 1) == 't';
if ($is_new) {
$new_event = $is_main ? 'OnPreCreate' : 'OnNew';
$event->CallSubEvent($new_event);
$event->redirect = true;
}
$object->SetDBField($this->Application->RecallVar('dst_field'), $user_id);
if ($is_new) {
$object->Create();
if (!$is_main && $object->IsTempTable()) {
$object->setTempID();
}
}
else {
$object->Update();
}
}
$event->SetRedirectParam($event->getPrefixSpecial().'_id', $object->GetID());
$this->finalizePopup($event);
}
/** EXPORT RELATED **/
/**
* 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;
}
$this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' );
$this->Application->LinkVar('export_finish_t');
$this->Application->LinkVar('export_progress_t');
$this->Application->StoreVar('export_oroginal_special', $event->Special);
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/*list ($index_file, $env) = explode('|', $this->Application->RecallVar('last_template'));
$finish_url = $this->Application->BaseURL('/admin').$index_file.'?'.ENV_VAR_NAME.'='.$env;
$this->Application->StoreVar('export_finish_url', $finish_url);*/
$redirect_params = Array (
$this->Prefix . '.export_event' => 'OnNew',
'pass' => 'all,' . $this->Prefix . '.export'
);
$event->setRedirectParams($redirect_params);
}
/**
* Apply some special processing to
* object beeing recalled before using
* it in other events that call prepareObject
*
* @param Object $object
* @param kEvent $event
* @access protected
*/
function prepareObject(&$object, &$event)
{
if ($event->Special == 'export' || $event->Special == 'import')
{
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->prepareExportColumns($event);
}
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
*/
function getCustomExportColumns(&$event)
{
return Array();
}
/**
* Export form validation & processing
*
* @param kEvent $event
*/
function OnExportBegin(&$event)
{
$export_helper =& $this->Application->recallObject('CatItemExportHelper');
/* @var $export_helper kCatDBItemExportHelper */
$export_helper->OnExportBegin($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnExportCancel(&$event)
{
$this->OnGoBack($event);
}
/**
* Allows configuring export options
*
* @param kEvent $event
*/
function OnBeforeExportBegin(&$event)
{
}
function OnDeleteExportPreset(&$event)
{
$object =& $event->GetObject();
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
if($items_info)
{
list($id,$field_values) = each($items_info);
$preset_key = $field_values['ExportPresets'];
$export_settings = $this->Application->RecallPersistentVar('export_settings');
if (!$export_settings) return ;
$export_settings = unserialize($export_settings);
if (!isset($export_settings[$event->Prefix])) return ;
$to_delete = '';
$export_presets = array(''=>'');
foreach ($export_settings[$event->Prefix] as $key => $val) {
if (implode('|', $val['ExportColumns']) == $preset_key) {
$to_delete = $key;
break;
}
}
if ($to_delete) {
unset($export_settings[$event->Prefix][$to_delete]);
$this->Application->StorePersistentVar('export_settings', serialize($export_settings));
}
}
}
/**
* Saves changes & changes language
*
* @param kEvent $event
*/
function OnPreSaveAndChangeLanguage(&$event)
{
$event->CallSubEvent('OnPreSave');
if ($event->status == erSUCCESS) {
$this->Application->SetVar('m_lang', $this->Application->GetVar('language'));
$pass_vars = Array ('st_id', 'cms_id');
foreach ($pass_vars as $pass_var) {
$data = $this->Application->GetVar($pass_var);
if ($data) {
$event->SetRedirectParam($pass_var, $data);
}
}
}
}
/**
* Used to save files uploaded via swfuploader
*
* @param kEvent $event
*/
function OnUploadFile(&$event)
{
$event->status = erSTOP;
define('DBG_SKIP_REPORTING', 1);
echo "Flash requires that we output something or it won't fire the uploadSuccess event";
if (!$this->Application->HttpQuery->Post) {
// Variables {field, id, flashsid} are always submitted through POST!
// When file size is larger, then "upload_max_filesize" (in php.ini),
// then theese variables also are not submitted -> handle such case.
header('HTTP/1.0 413 File size exceeds allowed limit');
return ;
}
if (!$this->_checkFlashUploaderPermission($event)) {
// 403 Forbidden
header('HTTP/1.0 403 You don\'t have permissions to upload');
return ;
}
$value = $this->Application->GetVar('Filedata');
if (!$value || ($value['error'] != UPLOAD_ERR_OK)) {
// 413 Request Entity Too Large (file uploads disabled OR uploaded file was
// to large for web server to accept, see "upload_max_filesize" in php.ini)
header('HTTP/1.0 413 File size exceeds allowed limit');
return ;
}
$tmp_path = defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/';
$fname = $value['name'];
$id = $this->Application->GetVar('id');
if ($id) {
$fname = $id.'_'.$fname;
}
$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');
$upload_dir = $fields[ $this->Application->GetVar('field') ]['upload_dir'];
if (!is_writable($tmp_path) || !is_writable(FULL_PATH . $upload_dir)) {
// 500 Internal Server Error
// check both temp and live upload directory
header('HTTP/1.0 500 Write permissions not set on the server');
return ;
}
move_uploaded_file($value['tmp_name'], $tmp_path.$fname);
}
/**
* Checks, that flash uploader is allowed to perform upload
*
* @param kEvent $event
* @return bool
*/
function _checkFlashUploaderPermission(&$event)
{
// Flash uploader does NOT send correct cookies, so we need to make our own check
$cookie_name = 'adm_' . $this->Application->ConfigValue('SessionCookieName');
$this->Application->HttpQuery->Cookie['cookies_on'] = 1;
$this->Application->HttpQuery->Cookie[$cookie_name] = $this->Application->GetVar('flashsid');
// this prevents session from auto-expiring when KeepSessionOnBrowserClose & FireFox is used
$this->Application->HttpQuery->Cookie[$cookie_name . '_live'] = $this->Application->GetVar('flashsid');
$admin_ses =& $this->Application->recallObject('Session.admin');
/* @var $admin_ses Session */
$backup_user_id = $this->Application->RecallVar('user_id'); // 1. backup user
$this->Application->StoreVar('user_id', $admin_ses->RecallVar('user_id')); // 2. fake user_id
$check_event = new kEvent($event->getPrefixSpecial() . ':OnProcessSelected'); // 3. event, that have "add|edit" rule
$allowed_to_upload = $this->CheckPermission($check_event); // 4. check permission
$this->Application->StoreVar('user_id', $backup_user_id); // 5. restore user id
return $allowed_to_upload;
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnDeleteFile(&$event)
{
$event->status = erSTOP;
if (strpos($this->Application->GetVar('file'), '../') !== false) {
return ;
}
$object =& $event->getObject( Array ('skip_autoload' => true) );
$options = $object->GetFieldOptions( $this->Application->GetVar('field') );
$var_name = $event->getPrefixSpecial() . '_file_pending_actions' . $this->Application->GetVar('m_wid');
$schedule = $this->Application->RecallVar($var_name);
$schedule = $schedule ? unserialize($schedule) : Array ();
$schedule[] = Array ('action' => 'delete', 'file' => $path = FULL_PATH . $options['upload_dir'] . $this->Application->GetVar('file'));
$this->Application->StoreVar($var_name, serialize($schedule));
$this->Application->Session->SaveData();
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnViewFile(&$event)
{
if (strpos($this->Application->GetVar('file'), '../') !== false) return ;
if ($this->Application->GetVar('tmp')) {
$path = (defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/').$this->Application->GetVar('id').'_'.$this->Application->GetVar('file');
}
else {
$object =& $event->getObject(array('skip_autoload'=>true));
$options = $object->GetFieldOptions($this->Application->GetVar('field'));
$path = FULL_PATH.$options['upload_dir'].$this->Application->GetVar('file');
}
$path = str_replace('/', DIRECTORY_SEPARATOR, $path);
$type = mime_content_type($path);
header('Content-Length: '.filesize($path));
header('Content-Type: '.$type);
safeDefine('DBG_SKIP_REPORTING',1);
readfile($path);
exit();
}
/**
* Validates MInput control fields
*
* @param kEvent $event
*/
function OnValidateMInputFields(&$event)
{
$minput_helper =& $this->Application->recallObject('MInputHelper');
/* @var $minput_helper MInputHelper */
$minput_helper->OnValidateMInputFields($event);
}
/**
* Returns auto-complete values for ajax-dropdown
*
* @param kEvent $event
*/
function OnSuggestValues(&$event)
{
$this->Application->XMLHeader();
$field = $this->Application->GetVar('field');
$cur_value = $this->Application->GetVar('cur_value');
if (!$field || !$cur_value) {
exit;
}
$limit = $this->Application->GetVar('limit');
if (!$limit) {
$limit = 20;
}
$object =& $event->getObject();
$sql = 'SELECT DISTINCT '.$field.'
FROM '.$object->TableName.'
WHERE '.$field.' LIKE '.$this->Conn->qstr($cur_value.'%').'
ORDER BY '.$field.'
LIMIT 0,' . $limit;
$data = $this->Conn->GetCol($sql);
echo '<suggestions>';
foreach ($data as $item) {
echo '<item>' . htmlspecialchars($item) . '</item>';
}
echo '</suggestions>';
$event->status = erSTOP;
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnSaveWidths(&$event)
{
$event->status = erSTOP;
$lang =& $this->Application->recallObject('lang.current');
// header('Content-type: text/xml; charset='.$lang->GetDBField('Charset'));
$picker_helper =& $this->Application->RecallObject('ColumnPickerHelper');
/* @var $picker_helper kColumnPickerHelper */
$picker_helper->PreparePicker($event->getPrefixSpecial(), $this->Application->GetVar('grid_name'));
$picker_helper->SaveWidths($event->getPrefixSpecial(), $this->Application->GetVar('widths'));
echo 'OK';
}
/**
* Called from CSV import script after item fields
* are set and validated, but before actual item create/update.
* If event status is erSUCCESS, line will be imported,
* else it will not be imported but added to skipped lines
* and displayed in the end of import.
* Event status is preset from import script.
*
* @param kEvent $event
*/
function OnBeforeCSVLineImport(&$event)
{
// abstract, for hooking
}
}
?>
\ No newline at end of file

Event Timeline