Index: branches/5.0.x/core/kernel/db/db_tag_processor.php =================================================================== --- branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 13232) +++ branches/5.0.x/core/kernel/db/db_tag_processor.php (revision 13233) @@ -1,2561 +1,2561 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ defined('FULL_PATH') or die('restricted access!'); class kDBTagProcessor extends kTagProcessor { /** * Description * * @var kDBConnection * @access public */ var $Conn; function kDBTagProcessor() { parent::kBase(); $this->Conn =& $this->Application->GetADODBConnection(); } /** * Returns true if "new" button was pressed in toolbar * * @param Array $params * @return bool */ function IsNewMode($params) { $object =& $this->getObject($params); return $object->GetID() <= 0; } /** * Returns view menu name for current prefix * * @param Array $params * @return string */ function GetItemName($params) { $item_name = $this->Application->getUnitOption($this->Prefix, 'ViewMenuPhrase'); return $this->Application->Phrase($item_name); } function ViewMenu($params) { $block_params = $params; unset($block_params['block']); $block_params['name'] = $params['block']; $list =& $this->GetList($params); $block_params['PrefixSpecial'] = $list->getPrefixSpecial(); return $this->Application->ParseBlock($block_params); } function SearchKeyword($params) { $list =& $this->GetList($params); return $this->Application->RecallVar($list->getPrefixSpecial() . '_search_keyword'); } /** * Draw filter menu content (for ViewMenu) based on filters defined in config * * @param Array $params * @return string */ function DrawFilterMenu($params) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['spearator_block']; $separator = $this->Application->ParseBlock($block_params); $filter_menu = $this->Application->getUnitOption($this->Prefix,'FilterMenu'); if (!$filter_menu) { trigger_error('<span class="debug_error">no filters defined</span> for prefix <b>'.$this->Prefix.'</b>, but <b>DrawFilterMenu</b> tag used', E_USER_WARNING); return ''; } // Params: label, filter_action, filter_status $block_params['name'] = $params['item_block']; $view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter'); if ($view_filter === false) { $event_params = Array ('prefix' => $this->Prefix, 'special' => $this->Special, 'name' => 'OnRemoveFilters'); $this->Application->HandleEvent( new kEvent($event_params) ); $view_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_view_filter'); } $view_filter = unserialize($view_filter); $filters = Array(); $prefix_special = $this->getPrefixSpecial(); foreach ($filter_menu['Filters'] as $filter_key => $filter_params) { $group_params = isset($filter_params['group_id']) ? $filter_menu['Groups'][ $filter_params['group_id'] ] : Array(); if (!isset($group_params['element_type'])) { $group_params['element_type'] = 'checkbox'; } if (!$filter_params) { $filters[] = $separator; continue; } $block_params['label'] = addslashes( $this->Application->Phrase($filter_params['label']) ); if (getArrayValue($view_filter,$filter_key)) { $submit = 0; if (isset($params['old_style'])) { $status = $group_params['element_type'] == 'checkbox' ? 1 : 2; } else { $status = $group_params['element_type'] == 'checkbox' ? '[\'img/check_on.gif\']' : '[\'img/menu_dot.gif\']'; } } else { $submit = 1; $status = 'null'; } $block_params['filter_action'] = 'set_filter("'.$prefix_special.'","'.$filter_key.'","'.$submit.'",'.$params['ajax'].');'; $block_params['filter_status'] = $status; // 1 - checkbox, 2 - radio, 0 - no image $filters[] = $this->Application->ParseBlock($block_params); } return implode('', $filters); } /** * Draws auto-refresh submenu in View Menu. * * @param Array $params * @return string */ function DrawAutoRefreshMenu($params) { $refresh_intervals = $this->Application->ConfigValue('AutoRefreshIntervals'); if (!$refresh_intervals) { trigger_error('<span class="debug_error">no filters defined</span> for prefix <strong>'.$this->Prefix.'</strong>, but <strong>DrawAutoRefreshMenu</strong> tag used', E_USER_WARNING); return ''; } $refresh_intervals = explode(',', $refresh_intervals); $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); $current_refresh_interval = $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); if ($current_refresh_interval === false) { // if no interval was selected before, then choose 1st interval $current_refresh_interval = $refresh_intervals[0]; } $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($refresh_intervals as $refresh_interval) { $block_params['label'] = $this->_formatInterval($refresh_interval); $block_params['refresh_interval'] = $refresh_interval; $block_params['selected'] = $current_refresh_interval == $refresh_interval; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Tells, that current grid is using auto refresh * * @param Array $params * @return bool */ function UseAutoRefresh($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_auto_refresh.'.$view_name); } /** * Returns current grid refresh interval * * @param Array $params * @return bool */ function AutoRefreshInterval($params) { $view_name = $this->Application->RecallVar($this->getPrefixSpecial().'_current_view'); return $this->Application->RecallPersistentVar($this->getPrefixSpecial().'_refresh_interval.'.$view_name); } /** * Formats time interval using given text for hours and minutes * * @param int $intervalmMinutes * @param string $hour_text Text for hours * @param string $min_text Text for minutes * @return unknown */ function _formatInterval($interval, $hour_text = 'h', $min_text = 'min') { // 65 $minutes = $interval % 60; $hours = ($interval - $minutes) / 60; $ret = ''; if ($hours) { $ret .= $hours.$hour_text.' '; } if ($minutes) { $ret .= $minutes.$min_text; } return $ret; } function IterateGridFields($params) { $mode = $params['mode']; $def_block = isset($params['block']) ? $params['block'] : ''; $force_block = isset($params['force_block']) ? $params['force_block'] : false; $grids = $this->Application->getUnitOption($this->Prefix,'Grids'); $grid_config = $grids[$params['grid']]['Fields']; $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); /* @var $picker_helper kColumnPickerHelper */ $picker_helper->ApplyPicker($this->getPrefixSpecial(), $grid_config, $params['grid']); if ($mode == 'fields') { return "'".join("','", array_keys($grid_config))."'"; } $std_params['pass_params'] = 'true'; $std_params['PrefixSpecial'] = $this->getPrefixSpecial(); $object =& $this->GetList($params); $o = ''; $i = 0; foreach ($grid_config as $field => $options) { $i++; $block_params = Array(); $block_params['name'] = $force_block ? $force_block : (isset($options[$mode.'_block']) ? $options[$mode.'_block'] : $def_block); $block_params['field'] = $field; $block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field; $block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field; $w = $picker_helper->GetWidth($field); if ($w) $options['width'] = $w; /*if (isset($options['filter_width'])) { $block_params['filter_width'] = $options['filter_width']; } elseif (isset($options['width'])) { if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) { if ($options['width'] < 60) { $options['width'] = 60; $block_params['filter_width'] = 20; } else { $block_params['filter_width'] = $options['width'] - 40; } } else { $block_params['filter_width'] = max($options['width']-10, 20); } }*/ /*if (isset($block_params['filter_width'])) $block_params['filter_width'] .= 'px'; if (isset($options['filter_block']) && preg_match('/range/', $options['filter_block'])) { $block_params['filter_width'] = '20px'; } else { $block_params['filter_width'] = '97%'; // $block_params['filter_width'] = max($options['width']-10, 20); }*/ $field_options = $object->GetFieldOptions($field); if (array_key_exists('use_phrases', $field_options)) { $block_params['use_phrases'] = $field_options['use_phrases']; } $block_params['is_last'] = ($i == count($grid_config)); $block_params = array_merge($std_params, $options, $block_params); $o.= $this->Application->ParseBlock($block_params, 1); } return $o; } function PickerCRC($params) { /* @var $picker_helper kColumnPickerHelper */ $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); $picker_helper->SetGridName($params['grid']); $data = $picker_helper->LoadColumns($this->getPrefixSpecial()); return $data['crc']; } function FreezerPosition($params) { /* @var $picker_helper kColumnPickerHelper */ $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); $picker_helper->SetGridName($params['grid']); $data = $picker_helper->LoadColumns($this->getPrefixSpecial()); $freezer_pos = array_search('__FREEZER__', $data['order']); return $freezer_pos === false || in_array('__FREEZER__', $data['hidden_fields']) ? 1 : ++$freezer_pos; } function GridFieldsCount($params) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); $grid_config = $grids[$params['grid']]['Fields']; return count($grid_config); } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList($params) { $params['no_table'] = 1; return $this->PrintList2($params); } function InitList($params) { $list_name = isset($params['list_name']) ? $params['list_name'] : ''; $names_mapping = $this->Application->GetVar('NamesToSpecialMapping'); if( !getArrayValue($names_mapping, $this->Prefix, $list_name) ) { $list =& $this->GetList($params); } } function BuildListSpecial($params) { return $this->Special; } /** * Returns key, that identifies each list on template (used internally, not tag) * * @param Array $params * @return string */ function getUniqueListKey($params) { $types = array_key_exists('types', $params) ? $params['types'] : ''; $except = array_key_exists('except', $params) ? $params['except'] : ''; $list_name = array_key_exists('list_name', $params) ? $params['list_name'] : ''; if (!$list_name) { $list_name = $this->Application->Parser->GetParam('list_name'); } return $types . $except . $list_name; } /** * Enter description here... * * @param Array $params * @return kDBList */ function &GetList($params) { $list_name = $this->SelectParam($params, 'list_name,name'); if (!$list_name) { $list_name = $this->Application->Parser->GetParam('list_name'); } $requery = isset($params['requery']) && $params['requery']; if ($list_name && !$requery) { $names_mapping = $this->Application->GetVar('NamesToSpecialMapping'); $special = is_array($names_mapping) && isset($names_mapping[$this->Prefix]) && isset($names_mapping[$this->Prefix][$list_name]) ? $names_mapping[$this->Prefix][$list_name] : false; // $special = getArrayValue($names_mapping, $this->Prefix, $list_name); if (!$special) { $special = $this->BuildListSpecial($params); } } else { $special = $this->BuildListSpecial($params); } $prefix_special = rtrim($this->Prefix.'.'.$special, '.'); $params['skip_counting'] = true; $list =& $this->Application->recallObject( $prefix_special, $this->Prefix.'_List', $params); /* @var $list kDBList */ if (!array_key_exists('skip_quering', $params) || !$params['skip_quering']) { if ($requery) { $this->Application->HandleEvent($an_event, $prefix_special.':OnListBuild', $params); } if (array_key_exists('offset', $params)) { $list->Offset += $params['offset']; // apply custom offset } $list->Query($requery); if (array_key_exists('offset', $params)) { $list->Offset -= $params['offset']; // remove custom offset } } $this->Special = $special; if ($list_name) { $names_mapping[$this->Prefix][$list_name] = $special; $this->Application->SetVar('NamesToSpecialMapping', $names_mapping); } return $list; } function ListMarker($params) { $list =& $this->GetList($params); $ret = $list->getPrefixSpecial(); if (array_key_exists('as_preg', $params) && $params['as_preg']) { $ret = preg_quote($ret, '/'); } return $ret; } /** * Prepares name for field with event in it (used only on front-end) * * @param Array $params * @return string */ function SubmitName($params) { $list =& $this->GetList($params); $prefix_special = $list->getPrefixSpecial(); return 'events['.$prefix_special.']['.$params['event'].']'; } /** * Prints list content using block specified * * @param Array $params * @return string * @access public */ function PrintList2($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ($per_page !== false) $params['per_page'] = $per_page; $list =& $this->GetList($params); $o = ''; $direction = (isset($params['direction']) && $params['direction']=="H")?"H":"V"; $columns = (isset($params['columns'])) ? $params['columns'] : 1; $id_field = (isset($params['id_field'])) ? $params['id_field'] : $this->Application->getUnitOption($this->Prefix, 'IDField'); if ($columns > 1 && $direction == 'V') { $records_left = array_splice($list->Records, $list->SelectedCount); // because we have 1 more record for "More..." link detection (don't need to sort it) $list->Records = $this->LinearToVertical($list->Records, $columns, $list->GetPerPage()); $list->Records = array_merge($list->Records, $records_left); } $list->GoFirst(); $block_params=$this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['pass_params'] = 'true'; $block_params['column_width'] = $params['column_width'] = 100 / $columns; $block_start_row_params = $this->prepareTagParams($params); $block_start_row_params['name'] = $this->SelectParam($params, 'row_start_render_as,block_row_start,row_start_block'); $block_end_row_params=$this->prepareTagParams($params); $block_end_row_params['name'] = $this->SelectParam($params, 'row_end_render_as,block_row_end,row_end_block'); $block_empty_cell_params = $this->prepareTagParams($params); $block_empty_cell_params['name'] = $this->SelectParam($params, 'empty_cell_render_as,block_empty_cell,empty_cell_block'); $i=0; $backup_id=$this->Application->GetVar($this->Prefix."_id"); $displayed = array(); $column_number = 1; $cache_mod_rw = $this->Application->getUnitOption($this->Prefix, 'CacheModRewrite') && $this->Application->RewriteURLs(); $limit = isset($params['limit']) ? $params['limit'] : false; while (!$list->EOL() && (!$limit || $i<$limit)) { $this->Application->SetVar( $this->getPrefixSpecial().'_id', $list->GetDBField($id_field) ); // for edit/delete links using GET $this->Application->SetVar( $this->Prefix.'_id', $list->GetDBField($id_field) ); $block_params['is_last'] = ($i == $list->SelectedCount - 1); $block_params['last_row'] = ($i + (($i+1) % $columns) >= $list->SelectedCount - 1); $block_params['not_last'] = !$block_params['is_last']; // for front-end if ($cache_mod_rw) { if ($this->Prefix == 'c') { // for listing subcategories in category $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('NamedParentPath')); $this->Application->setCache('category_tree', $list->GetDBField($id_field), $list->GetDBField('TreeLeft') . ';' . $list->GetDBField('TreeRight')); } else { // for listing items in category $this->Application->setCache('filenames', 'c_'.$list->GetDBField('CategoryId'), $list->GetDBField('CategoryFilename')); $this->Application->setCache('filenames', $this->Prefix.'_'.$list->GetDBField($id_field), $list->GetDBField('Filename')); } } if ($i % $columns == 0) { // record in this iteration is first in row, then open row $column_number = 1; $o.= $block_start_row_params['name'] ? $this->Application->ParseBlock($block_start_row_params, 1) : (!isset($params['no_table']) ? '<tr>' : ''); } else { $column_number++; } $block_params['first_col'] = $column_number == 1 ? 1 : 0; $block_params['last_col'] = $column_number == $columns ? 1 : 0; $block_params['column_number'] = $column_number; $block_params['num'] = ($i+1); $this->PrepareListElementParams($list, $block_params); // new, no need to rewrite PrintList $o.= $this->Application->ParseBlock($block_params, 1); array_push($displayed, $list->GetDBField($id_field)); if($direction == 'V' && $list->SelectedCount % $columns > 0 && $column_number == ($columns - 1) && ceil(($i + 1) / $columns) > $list->SelectedCount % ceil($list->SelectedCount / $columns)) { // if vertical output, then draw empty cells vertically, not horizontally $o .= $block_empty_cell_params['name'] ? $this->Application->ParseBlock($block_empty_cell_params, 1) : '<td> </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> </td>'; if (($i+1) % $columns == 0) { // record in next iteration is first in row too, then close this row $o .= $block_end_row_params['name'] ? $this->Application->ParseBlock($block_end_row_params, 1) : '</tr>'; } $i++; } $cur_displayed = $this->Application->GetVar($this->Prefix.'_displayed_ids'); if (!$cur_displayed) { $cur_displayed = Array(); } else { $cur_displayed = explode(',', $cur_displayed); } $displayed = array_unique(array_merge($displayed, $cur_displayed)); $this->Application->SetVar($this->Prefix.'_displayed_ids', implode(',',$displayed)); $this->Application->SetVar( $this->Prefix.'_id', $backup_id); $this->Application->SetVar( $this->getPrefixSpecial().'_id', ''); if (isset($params['more_link_render_as'])) { $block_params = $params; $params['render_as'] = $params['more_link_render_as']; $o .= $this->MoreLink($params); } return $o; } /** * Allows to modify block params & current list record before PrintList parses record * * @param kDBList $object * @param Array $block_params */ function PrepareListElementParams(&$object, &$block_params) { // $fields_hash =& $object->getCurrentRecord(); } function MoreLink($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ($per_page !== false) $params['per_page'] = $per_page; $list =& $this->GetList($params); if ($list->PerPage < $list->RecordsCount) { $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); return $this->Application->ParseBlock($block_params); } } function NotLastItem($params) { $object =& $this->getList($params); // maybe we should use $this->GetList($params) instead return ($object->CurrentIndex < min($object->PerPage == -1 ? $object->RecordsCount : $object->PerPage, $object->RecordsCount) - 1); } function PageLink($params) { $t = isset($params['template']) ? $params['template'] : ''; unset($params['template']); if (!$t) $t = $this->Application->GetVar('t'); if (isset($params['page'])) { $this->Application->SetVar($this->getPrefixSpecial().'_Page', $params['page']); unset($params['page']); } if (!isset($params['pass'])) { $params['pass'] = 'm,'.$this->getPrefixSpecial(); } return $this->Application->HREF($t, '', $params); } function ColumnWidth($params) { $columns = $this->Application->Parser->GetParam('columns'); return round(100/$columns).'%'; } /** * Append prefix and special to tag * params (get them from tagname) like * they were really passed as params * * @param Array $tag_params * @return Array * @access protected */ function prepareTagParams($tag_params = Array()) { $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').' '; 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) { // apply htmlspecialchars on all field values on Front-End $params['no_special'] = 'no_special'; } $object =& $this->getObject($params); if (array_key_exists('db', $params) && $params['db']) { $value = $object->GetDBField($field); } else { if (array_key_exists('currency', $params) && $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 = array_key_exists('format', $params) ? $params['format'] : false; if (!$format || $format == '$format') { $format = null; } $value = $object->GetField($field, $format); if (array_key_exists('negative', $params) && $params['negative']) { if (strpos($value, '-') === 0) { $value = substr($value, 1); } else { $value = '-' . $value; } } if (array_key_exists('currency', $params) && $params['currency']) { $value = $this->AddCurrencySymbol($value, $iso); $params['no_special'] = 1; } } if (!array_key_exists('no_special', $params) || !$params['no_special']) { // when no_special parameter NOT SET apply htmlspecialchars $value = htmlspecialchars($value); } if (array_key_exists('checked', $params) && $params['checked']) { $value = ($value == ( isset($params['value']) ? $params['value'] : 1)) ? 'checked' : ''; } if (array_key_exists('plus_or_as_label', $params) && $params['plus_or_as_label']) { $value = substr($value, 0,1) == '+' ? substr($value, 1) : $this->Application->Phrase($value); } elseif (array_key_exists('as_label', $params) && $params['as_label']) { $value = $this->Application->Phrase($value); } $first_chars = $this->SelectParam($params,'first_chars,cut_first'); if ($first_chars) { $stripped_value = strip_tags($value, $this->SelectParam($params, 'allowed_tags')); if (mb_strlen($stripped_value) > $first_chars) { $value = mb_substr($stripped_value, 0, $first_chars) . ' ...'; } } if (array_key_exists('nl2br', $params) && $params['nl2br']) { $value = nl2br($value); } if ($value != '') { $this->Application->Parser->DataExists = true; } if (array_key_exists('currency', $params) && $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)); } 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 = array_key_exists('except', $params) ? $params['except'] : false; $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 array_key_exists('required', $options) ? $options['required'] : false; } 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 (array_key_exists('has_empty', $params) && $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 = array_key_exists('selected_param', $params) ? $params['selected_param'] : false; if (!$selected_param_name) { $selected_param_name = $params['selected']; } $selected = $params['selected']; $o = ''; if (array_key_exists('no_empty', $params) && $params['no_empty'] && !getArrayValue($options, '')) { // removes empty option, when present (needed?) array_shift($options); } if (strpos($value, '|') !== false) { // multiple checkboxes OR multiselect $value = explode('|', substr($value, 1, -1) ); foreach ($options as $key => $val) { $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = ( in_array($key, $value) ? ' '.$selected : ''); $o .= $this->Application->ParseBlock($block_params, 1); } } else { // single selection radio OR checkboxes OR dropdown foreach ($options as $key => $val) { $block_params['key'] = $key; $block_params['option'] = $val; $block_params[$selected_param_name] = (strlen($key) == strlen($value) && ($key == $value) ? ' '.$selected : ''); $o .= $this->Application->ParseBlock($block_params, 1); } } return $o; } function PredefinedSearchOptions($params) { $object =& $this->GetList($params); /* @var $object kDBList */ $params['value'] = $this->SearchField($params); return $this->PredefinedOptions($params); } function Format($params) { $field = $this->SelectParam($params, 'name,field'); $object =& $this->getObject($params); $options = $object->GetFieldOptions($field); $format = $options[ $this->SelectParam($params, 'input_format') ? 'input_format' : 'format' ]; $formatter_class = array_key_exists('formatter', $options) ? $options['formatter'] : false; if ($formatter_class) { $formatter =& $this->Application->recallObject($formatter_class); $human_format = array_key_exists('human', $params) ? $params['human'] : false; $edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false; $sample = array_key_exists('sample', $params) ? $params['sample'] : false; 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 = array_key_exists('IdField', $params) ? $params['IdField'] : false; $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 (array_key_exists('as_preg', $params) && $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 (array_key_exists('as_preg', $params) && $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); return $object->GetDBField( $this->SelectParam($params, 'name,field') ) == $params['value']; } /** * 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) { $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); $grid = $grids[ $params['grid'] ]; if (!array_key_exists('Icons', $grid)) { return ''; } $icons = $grid['Icons']; if (array_key_exists('name', $params)) { $icon_name = $params['name']; return array_key_exists($icon_name, $icons) ? $icons[$icon_name] : ''; } $status_fields = $this->Application->getUnitOption($this->Prefix, 'StatusField'); if (!$status_fields) { return $icons['default']; } $object =& $this->getObject($params); /* @var $object kDBList */ $icon = ''; foreach ($status_fields as $status_field) { $icon .= $object->GetDBField($status_field) . '_'; } $icon = rtrim($icon, '_'); return array_key_exists($icon, $icons) ? $icons[$icon] : $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 = array_key_exists($preset_name, $title_presets) ? $title_presets[$preset_name] : false; 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 (array_key_exists('default', $title_presets) && $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 = array_key_exists('prefixes', $title_info) ? $title_info['prefixes'] : false; $all_tag_params = array_key_exists('tag_params', $title_info) ? $title_info['tag_params'] : false; 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']; } $first_chars = $this->SelectParam($params, 'first_chars,cut_first'); if ($first_chars && !preg_match('/<a href="(.*)".*>(.*)<\/a>/', $title)) { // don't cut titles, that contain phrase translation links $stripped_title = strip_tags($title, $this->SelectParam($params, 'allowed_tags')); if (mb_strlen($stripped_title) > $first_chars) { $title = mb_substr($stripped_title, 0, $first_chars) . ' ...'; } } return $title; } function getInfo(&$object, $info_type) { switch ($info_type) { case 'titlefield': $field = $this->Application->getUnitOption($object->Prefix,'TitleField'); return $field !== false ? $object->GetField($field) : 'TitleField Missing'; break; case 'recordcount': $of_phrase = $this->Application->Phrase('la_of'); return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' '.$of_phrase.' '.$object->NoFilterCount : $object->RecordsCount; break; default: return $object->GetField($info_type); break; } } function GridInfo($params) { $object =& $this->GetList($params); /* @var $object kDBList */ switch ($params['type']) { case 'filtered': return $object->GetRecordsCount(); case 'total': return $object->GetNoFilterCount(); case 'from': return $object->RecordsCount ? $object->Offset+1 : 0; //0-based case 'to': return $object->PerPage > 0 ? min($object->Offset + $object->PerPage, $object->RecordsCount) : $object->RecordsCount; case 'total_pages': return $object->GetTotalPages(); case 'needs_pagination': return ($object->PerPage != -1) && (($object->RecordsCount > $object->PerPage) || ($object->Page > 1)); } } /** * Parses block depending on its element type. * For radio and select elements values are taken from 'value_list_field' in key1=value1,key2=value2 * format. key=value can be substituted by <SQL>SELECT f1 AS OptionName, f2 AS OptionValue... FROM <PREFIX>TableName </SQL> * where prefix is TABLE_PREFIX * * @param Array $params * @return string */ function ConfigFormElement($params) { $object =& $this->getObject($params); $field = $params['field']; $helper =& $this->Application->recallObject('InpCustomFieldsHelper'); /* @var $helper InpCustomFieldsHelper */ $element_type = $object->GetDBField($params['element_type_field']); if($element_type == 'label') $element_type = 'text'; $params['name'] = $params['blocks_prefix'].$element_type; switch ($element_type) { case 'select': case 'multiselect': case 'radio': $field_options = $object->GetFieldOptions($field, 'options'); if ($object->GetDBField('DirectOptions')) { // used for custom fields $field_options['options'] = $object->GetDBField('DirectOptions'); } else { // used for configuration $field_options['options'] = $helper->GetValuesHash($object->GetDBField($params['value_list_field']), ','); } $object->SetFieldOptions($field, $field_options); break; case 'text': case 'textarea': $params['field_params'] = $helper->ParseConfigSQL($object->GetDBField($params['value_list_field'])); break; case 'password': case 'checkbox': default: break; } return $this->Application->ParseBlock($params, 1); } /** * Get's requested custom field value * * @param Array $params * @return string * @access public */ function CustomField($params) { $params['name'] = 'cust_'.$this->SelectParam($params, 'name,field'); return $this->Field($params); } function CustomFieldLabel($params) { $object =& $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); $sql = 'SELECT FieldLabel FROM '.$this->Application->getUnitOption('cf', 'TableName').' WHERE FieldName = '.$this->Conn->qstr($field); return $this->Application->Phrase($this->Conn->GetOne($sql)); } /** * transposes 1-dimensional array elements for vertical alignment according to given columns and per_page parameters * * @param array $arr * @param int $columns * @param int $per_page * @return array */ function LinearToVertical(&$arr, $columns, $per_page) { $rows = $columns; // in case if after applying per_page limit record count less then // can fill requrested column count, then fill as much as we can $cols = min(ceil($per_page / $columns), ceil(count($arr) / $columns)); $imatrix = array(); for ($row = 0; $row < $rows; $row++) { for ($col = 0; $col < $cols; $col++) { $source_index = $row * $cols + $col; if (!isset($arr[$source_index])) { // in case if source array element count is less then element count in one row continue; } $imatrix[$col * $rows + $row] = $arr[$source_index]; } } ksort($imatrix); return array_values($imatrix); } /** * If data was modfied & is in TempTables mode, then parse block with name passed; * remove modification mark if not in TempTables mode * * @param Array $params * @return string * @access public * @author Alexey */ function SaveWarning($params) { $main_prefix = array_key_exists('main_prefix', $params) ? $params['main_prefix'] : false; if ($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 (!array_key_exists('no_special', $params) || !$params['no_special']) { $ret = htmlspecialchars($ret); } return $ret; } return ''; } /** * Tells, that at least one of search filters is used by now * * @param Array $params * @return bool */ function SearchActive($params) { if ($this->Application->RecallVar($this->getPrefixSpecial() . '_search_keyword')) { // simple search filter is used return true; } $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(); return array_key_exists($params['grid'], $custom_filter); } 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 = array_key_exists('formatter', $options) ? $options['formatter'] : false; if ($formatter_class) { $formatter =& $this->Application->recallObject($formatter_class); $human_format = array_key_exists('human', $params) ? $params['human'] : false; $edit_size = array_key_exists('edit_size', $params) ? $params['edit_size'] : false; $sample = array_key_exists('sample', $params) ? $params['sample'] : false; if ($sample) { return $formatter->GetSample($field, $options, $object); } elseif ($human_format || $edit_size) { $format = $formatter->HumanFormat($format); return $edit_size ? strlen($format) : $format; } } return $format; } /** * Returns error of range field * * @param unknown_type $params * @return unknown */ function SearchError($params) { $field = $this->SelectParam($params, 'field,name'); $error_var_name = $this->getPrefixSpecial().'_'.$field.'_error'; $pseudo = $this->Application->RecallVar($error_var_name); if ($pseudo) { $this->Application->RemoveVar($error_var_name); } $object =& $this->Application->recallObject($this->Prefix.'.'.$this->Special.'-item', null, Array('skip_autoload' => true)); /* @var $object kDBItem */ $object->SetError($field, $pseudo); return $object->GetErrorMsg($field, false); } /** * Returns object used in tag processor * * @access public * @return kDBBase */ function &getObject($params = Array()) { $object =& $this->Application->recallObject($this->getPrefixSpecial(), $this->Prefix, $params); if (isset($params['requery']) && $params['requery']) { $this->Application->HandleEvent($q_event, $this->getPrefixSpecial().':LoadItem', $params); } return $object; } /** * Checks if object propery value matches value passed * * @param Array $params * @return bool */ function PropertyEquals($params) { $object =& $this->getObject($params); $property_name = $this->SelectParam($params, 'name,var,property'); return $object->$property_name == $params['value']; } /** * Group list records by header, saves internal order in group * * @param Array $records * @param string $heading_field */ function groupRecords(&$records, $heading_field) { $sorted = Array(); $i = 0; $record_count = count($records); while ($i < $record_count) { $sorted[ $records[$i][$heading_field] ][] = $records[$i]; $i++; } $records = Array(); foreach ($sorted as $heading => $heading_records) { $records = array_merge_recursive($records, $heading_records); } } function DisplayOriginal($params) { return false; } /*function MultipleEditing($params) { $wid = $this->Application->GetTopmostWid($this->Prefix); $session_name = rtrim($this->getPrefixSpecial().'_selected_ids_'.$wid, '_'); $selected_ids = explode(',', $this->Application->RecallVar($session_name)); $ret = ''; if ($selected_ids) { $selected_ids = explode(',', $selected_ids); $object =& $this->getObject( array_merge_recursive2($params, Array('skip_autoload' => true)) ); $params['name'] = $params['render_as']; foreach ($selected_ids as $id) { $object->Load($id); $ret .= $this->Application->ParseBlock($params); } } return $ret; }*/ /** * Returns import/export process percent * * @param Array $params * @return int * @deprecated Please convert to event-model, not tag based */ function ExportStatus($params) { $export_object =& $this->Application->recallObject('CatItemExportHelper'); $event = new kEvent($this->getPrefixSpecial().':OnDummy'); $action_method = 'perform'.ucfirst($this->Special); $field_values = $export_object->$action_method($event); // finish code is done from JS now if ($field_values['start_from'] >= $field_values['total_records']) { if ($this->Special == 'import') { // this is used? $this->Application->StoreVar('PermCache_UpdateRequired', 1); $this->Application->Redirect('categories/cache_updater', Array('m_opener' => 'r', 'pass' => 'm', 'continue' => 1, 'no_amp' => 1)); } elseif ($this->Special == 'export') { // used for orders export in In-Commerce $finish_t = $this->Application->RecallVar('export_finish_t'); $this->Application->Redirect($finish_t, Array('pass' => 'all')); $this->Application->RemoveVar('export_finish_t'); } } $export_options = $export_object->loadOptions($event); return $export_options['start_from'] * 100 / $export_options['total_records']; } /** * Returns path where exported category items should be saved * * @param Array $params */ function ExportPath($params) { - $ret = EXPORT_PATH.'/'; + $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial().'_options')); + $extension = $export_options['ExportFormat'] == 1 ? 'csv' : 'xml'; + $filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $export_options['ExportFilename']) . '.' . $extension; + $path = EXPORT_PATH . '/'; if (array_key_exists('as_url', $params) && $params['as_url']) { - $ret = str_replace( FULL_PATH.'/', $this->Application->BaseURL(), $ret); + $path = str_replace( FULL_PATH . '/', $this->Application->BaseURL(), $path); } - - $export_options = unserialize($this->Application->RecallVar($this->getPrefixSpecial().'_options')); - $ret .= $export_options['ExportFilename'].'.'.($export_options['ExportFormat'] == 1 ? 'csv' : 'xml'); - - return $ret; + + return $path . $filename; } function FieldTotal($params) { $list =& $this->GetList($params); return $list->GetFormattedTotal($this->SelectParam($params, 'field,name'), $params['function']); } /** * Returns FCKEditor locale, that matches default site language * * @return string */ function _getFCKLanguage() { static $language_code = null; if (!isset($language_code)) { $language_code = 'en'; // defaut value if ($this->Application->isAdmin) { $language_id = $this->Application->Phrases->LanguageId; } else { $language_id = $this->Application->GetDefaultLanguageId(); // $this->Application->GetVar('m_lang'); } $sql = 'SELECT Locale FROM '. $this->Application->getUnitOption('lang', 'TableName') . ' WHERE LanguageId = ' . $language_id; $locale = strtolower( $this->Conn->GetOne($sql) ); if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale . '.js')) { // found language file, that exactly matches locale name (e.g. "en") $language_code = $locale; } else { $locale = explode('-', $locale); if (file_exists(FULL_PATH . EDITOR_PATH . 'editor/lang/' . $locale[0] . '.js')) { // language file matches first part of locale (e.g. "ru-RU") $language_code = $locale[0]; } } } return $language_code; } function FCKEditor($params) { $params['no_special'] = 1; $params['format'] = array_key_exists('format', $params) ? $params['format'] . ';fck_ready' : 'fck_ready'; $value = $this->Field($params); $name = array_key_exists('name', $params) ? $params['name'] : $this->InputName($params); $theme_path = substr($this->Application->GetFrontThemePath(), 1) . '/inc/'; if (!file_exists(FULL_PATH . '/' . $theme_path . 'style.css')) { $theme_path = EDITOR_PATH; } $styles_xml = $this->Application->BaseURL() . $theme_path . 'styles.xml'; $styles_css = $this->Application->BaseURL() . $theme_path . 'style.css'; $bgcolor = array_key_exists('bgcolor', $params) ? $params['bgcolor'] : $this->Application->GetVar('bgcolor'); if (!$bgcolor) { $bgcolor = '#ffffff'; } $preview_url = ''; $page_id = $this->Application->GetVar('c_id'); $content_id = $this->Application->GetVar('content_id'); if ($page_id && $content_id) { // editing content block from Front-End, not category in admin $sql = 'SELECT NamedParentPath FROM ' . $this->Application->getUnitOption('c', 'TableName') . ' WHERE ' . $this->Application->getUnitOption('c', 'IDField') . ' = ' . (int)$page_id; $template = strtolower( $this->Conn->GetOne($sql) ); $url_params = Array ('m_cat_id' => $page_id, 'no_amp' => 1, 'editing_mode' => EDITING_MODE_CONTENT, 'pass' => 'm'); $preview_url = $this->Application->HREF($template, '_FRONT_END_', $url_params, 'index.php'); $preview_url = preg_replace('/&(admin|editing_mode)=[\d]/', '', $preview_url); } include_once(FULL_PATH . EDITOR_PATH . 'fckeditor.php'); $oFCKeditor = new FCKeditor($name); $oFCKeditor->FullUrl = $this->Application->BaseURL(); $oFCKeditor->BaseUrl = BASE_PATH . '/'; $oFCKeditor->BasePath = BASE_PATH . EDITOR_PATH; $oFCKeditor->Width = $params['width'] ; $oFCKeditor->Height = $params['height'] ; $oFCKeditor->ToolbarSet = $page_id && $content_id ? 'Advanced' : 'Default'; $oFCKeditor->Value = $value; $oFCKeditor->PreviewUrl = $preview_url; $oFCKeditor->DefaultLanguage = $this->_getFCKLanguage(); $oFCKeditor->LateLoad = array_key_exists('late_load', $params) && $params['late_load']; $oFCKeditor->Config = Array ( //'UserFilesPath' => $pathtoroot.'kernel/user_files', 'ProjectPath' => BASE_PATH . '/', 'CustomConfigurationsPath' => $this->Application->BaseURL() . 'core/admin_templates/js/inp_fckconfig.js', 'StylesXmlPath' => $styles_xml, 'EditorAreaCSS' => $styles_css, 'DefaultStyleLabel' => $this->Application->Phrase('la_editor_default_style'), // 'Debug' => 1, 'Admin' => 1, 'K4' => 1, 'newBgColor' => $bgcolor, 'PreviewUrl' => $preview_url, 'BaseUrl' => BASE_PATH . '/', 'DefaultLanguage' => $this->_getFCKLanguage(), 'EditorAreaStyles' => 'body { background-color: '.$bgcolor.' }', ); return $oFCKeditor->CreateHtml(); } function IsNewItem($params) { $object =& $this->getObject($params); return $object->IsNewItem(); } /** * Creates link to an item including only it's id * * @param Array $params * @return string */ function ItemLink($params) { $object =& $this->getObject($params); if (!isset($params['pass'])) { $params['pass'] = 'm'; } $params[$object->getPrefixSpecial().'_id'] = $object->GetID(); $m =& $this->Application->recallObject('m_TagProcessor'); return $m->t($params); } /** * Calls OnNew event from template, when no other event submitted * * @param Array $params */ function PresetFormFields($params) { $prefix = $this->getPrefixSpecial(); if (!$this->Application->GetVar($prefix.'_event')) { $this->Application->HandleEvent(new kEvent($prefix.':OnNew')); } } function PrintSerializedFields($params) { $object =& $this->getObject(); $field = $this->SelectParam($params, 'field'); $data = unserialize($object->GetDBField($field)); $o = ''; $std_params['name'] = $params['render_as']; $std_params['field'] = $params['field']; $std_params['pass_params'] = true; foreach ($data as $key => $row) { $block_params = array_merge($std_params, $row, array('key'=>$key)); $o .= $this->Application->ParseBlock($block_params); } return $o; } /** * Checks if current prefix is main item * * @param Array $params * @return bool */ function IsTopmostPrefix($params) { return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix); } function PermSection($params) { $section = $this->SelectParam($params, 'section,name'); $perm_sections = $this->Application->getUnitOption($this->Prefix, 'PermSection'); return isset($perm_sections[$section]) ? $perm_sections[$section] : ''; } function PerPageSelected($params) { $list =& $this->GetList($params); return $list->PerPage == $params['per_page'] ? $params['selected'] : ''; } /** * Returns prefix + generated sepcial + any word * * @param Array $params * @return string */ function VarName($params) { $list =& $this->GetList($params); return $list->getPrefixSpecial().'_'.$params['type']; } /** * Returns edit tabs by specified preset name or false in case of error * * @param string $preset_name * @return mixed */ function getEditTabs($preset_name) { $presets = $this->Application->getUnitOption($this->Prefix, 'EditTabPresets'); if (!$presets || !isset($presets[$preset_name]) || count($presets[$preset_name]) == 0) { return false; } return count($presets[$preset_name]) > 1 ? $presets[$preset_name] : false; } /** * Detects if specified preset has tabs in it * * @param Array $params * @return bool */ function HasEditTabs($params) { return $this->getEditTabs($params['preset_name']) ? true : false; } /** * Sorts edit tabs based on their priority * * @param Array $tab_a * @param Array $tab_b * @return int */ function sortEditTabs($tab_a, $tab_b) { if ($tab_a['priority'] == $tab_b['priority']) { return 0; } return $tab_a['priority'] < $tab_b['priority'] ? -1 : 1; } /** * Prints edit tabs based on preset name specified * * @param Array $params * @return string */ function PrintEditTabs($params) { $edit_tabs = $this->getEditTabs($params['preset_name']); if (!$edit_tabs) { return ; } usort($edit_tabs, Array (&$this, 'sortEditTabs')); $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; foreach ($edit_tabs as $tab_info) { $block_params['title'] = $tab_info['title']; $block_params['template'] = $tab_info['t']; $ret .= $this->Application->ParseBlock($block_params); } return $ret; } /** * Performs image resize to required dimensions and returns resulting url (cached resized image) * * @param Array $params * @return string */ function ImageSrc($params) { $max_width = isset($params['MaxWidth']) ? $params['MaxWidth'] : false; $max_height = isset($params['MaxHeight']) ? $params['MaxHeight'] : false; $logo_filename = isset($params['LogoFilename']) ? $params['LogoFilename'] : false; $logo_h_margin = isset($params['LogoHMargin']) ? $params['LogoHMargin'] : false; $logo_v_margin = isset($params['LogoVMargin']) ? $params['LogoVMargin'] : false; $object =& $this->getObject($params); $field = $this->SelectParam($params, 'name,field'); return $object->GetField($field, 'resize:'.$max_width.'x'.$max_height.';wm:'.$logo_filename.'|'.$logo_h_margin.'|'.$logo_v_margin); } /** * Allows to retrieve given setting from unit config * * @param Array $params * @return mixed */ function UnitOption($params) { return $this->Application->getUnitOption($this->Prefix, $params['name']); } /** * Returns list of allowed toolbar buttons or false, when all is allowed * * @param Array $params * @return string */ function VisibleToolbarButtons($params) { $preset_name = replaceModuleSection($params['title_preset']); $title_presets = $this->Application->getUnitOption($this->Prefix, 'TitlePresets'); if (!array_key_exists($preset_name, $title_presets)) { trigger_error('Title preset not specified or missing (in tag "<strong>' . $this->getPrefixSpecial() . ':' . __METHOD__ . '</strong>")', E_USER_WARNING); return false; } $preset_info = $title_presets[$preset_name]; if (!array_key_exists('toolbar_buttons', $preset_info) || !is_array($preset_info['toolbar_buttons'])) { return false; } // always add search buttons array_push($preset_info['toolbar_buttons'], 'search', 'search_reset_alt'); $toolbar_buttons = array_map('addslashes', $preset_info['toolbar_buttons']); return $toolbar_buttons ? "'" . implode("', '", $toolbar_buttons) . "'" : 'false'; } /** * Checks, that "To" part of at least one of range filters is used * * @param Array $params * @return bool */ function RangeFiltersUsed($params) { $search_helper =& $this->Application->recallObject('SearchHelper'); /* @var $search_helper kSearchHelper */ return $search_helper->rangeFiltersUsed($this->getPrefixSpecial(), $params['grid']); } /** * This is abstract tag, used to modify unit config data based on template, where it's used. * Tag is called from "combined_header" block in admin only. * * @param Array $params */ function ModifyUnitConfig($params) { } /** * Checks, that field is visible on edit form * * @param Array $params * @return bool */ function FieldVisible($params) { $check_field = $params['field']; $fields = $this->Application->getUnitOption($this->Prefix, 'Fields'); if (!array_key_exists($check_field, $fields)) { // field not found in real fields array -> it's 100% virtual then $fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields'); } if (!array_key_exists($check_field, $fields)) { $params['field'] = 'Password'; return $check_field == 'VerifyPassword' ? $this->FieldVisible($params) : true; } $show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true; if ($show_mode === smDEBUG) { return defined('DEBUG_MODE') && DEBUG_MODE; } return $show_mode; } /** * Checks, that there area visible fields in given section on edit form * * @param Array $params * @return bool */ function FieldsVisible($params) { if (!$params['fields']) { return true; } $check_fields = explode(',', $params['fields']); $fields = $this->Application->getUnitOption($this->Prefix, 'Fields'); $virtual_fields = $this->Application->getUnitOption($this->Prefix, 'VirtualFields'); foreach ($check_fields as $check_field) { // when at least one field in subsection is visible, then subsection is visible too if (array_key_exists($check_field, $fields)) { $show_mode = array_key_exists('show_mode', $fields[$check_field]) ? $fields[$check_field]['show_mode'] : true; } else { $show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true; } if (($show_mode === true) || (($show_mode === smDEBUG) && (defined('DEBUG_MODE') && DEBUG_MODE))) { // field is visible return true; } } return false; } } \ No newline at end of file Index: branches/5.0.x/core/units/helpers/csv_helper.php =================================================================== --- branches/5.0.x/core/units/helpers/csv_helper.php (revision 13232) +++ branches/5.0.x/core/units/helpers/csv_helper.php (revision 13233) @@ -1,374 +1,375 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ defined('FULL_PATH') or die('restricted access!'); safeDefine('EXPORT_STEP', 100); // export by 100 items safeDefine('IMPORT_STEP', 10); class kCSVHelper extends kHelper { var $PrefixSpecial; var $grid; var $delimiter_mapping = Array(0 => "\t", 1 => ',', 2 => ';', 3 => ' ', 4 => ':'); var $enclosure_mapping = Array(0 => '"', 1 => "'"); var $separator_mapping = Array(0 => "\n", 1 => "\r\n"); function ExportStep() { $export_data = $this->Application->RecallVar('export_data'); $export_rand = $this->Application->RecallVar('export_rand'); $get_rand = $this->Application->GetVar('export_rand'); if($export_data && $export_rand == $get_rand) { $export_data = unserialize($export_data); $first_step = false; } else { // first step $export_data = Array(); $export_data['prefix'] = $this->PrefixSpecial; $export_data['grid'] = $this->grid; $export_data['file_name'] = EXPORT_PATH.'/'.$this->ValidateFileName(EXPORT_PATH, 'export_'.$export_data['prefix'].'.csv'); $export_data['step'] = EXPORT_STEP; $export_data['delimiter'] = $this->delimiter_mapping[(int)$this->Application->ConfigValue('CSVExportDelimiter')]; $export_data['enclosure'] = $this->enclosure_mapping[(int)$this->Application->ConfigValue('CSVExportEnclosure')]; $export_data['record_separator'] = $this->separator_mapping[(int)$this->Application->ConfigValue('CSVExportSeparator')]; $export_data['page'] = 1; $lang_object =& $this->Application->recallObject('lang.current'); /* @var $lang_object LanguagesItem */ $export_data['source_encoding'] = strtoupper( $lang_object->GetDBField('Charset') ); $export_data['encoding'] = $this->Application->ConfigValue('CSVExportEncoding') ? false : 'UTF-16LE'; $this->Application->StoreVar('export_rand', $get_rand); $first_step = true; } $file = fopen($export_data['file_name'], $first_step ? 'w' : 'a'); $prefix_elems = split('\.|_', $export_data['prefix']); $grids = $this->Application->getUnitOption($prefix_elems[0], 'Grids'); $grid_config = $grids[ $export_data['grid'] ]['Fields']; $list_params = Array('per_page' => $export_data['step'], 'grid' => $export_data['grid']); $list =& $this->Application->recallObject(rtrim(implode('.', $prefix_elems), '.'), $prefix_elems[0].'_List', $list_params); /* @var $list kDBList */ $list->SetPage($export_data['page']); $list->Query(); $list->GoFirst(); $picker_helper =& $this->Application->RecallObject('ColumnPickerHelper'); /* @var $picker_helper kColumnPickerHelper */ $picker_helper->ApplyPicker(rtrim(implode('.', $prefix_elems), '.'), $grid_config, $export_data['grid']); if($first_step) { // if UTF-16, write Unicode marker if($export_data['encoding'] == 'UTF-16LE') { fwrite($file, chr(0xFF).chr(0xFE)); } // inserting header line $headers = Array(); foreach($grid_config as $field_name => $field_data) { $header = $this->Application->Phrase( $field_data['title'] ); array_push($headers, $header); } $csv_line = getcsvline($headers, $export_data['delimiter'], $export_data['enclosure'], $export_data['record_separator']); if($export_data['encoding']) { $csv_line = mb_convert_encoding($csv_line, $export_data['encoding'], $export_data['source_encoding']); } fwrite($file, $csv_line); } while(!$list->EOL()) { $data = Array(); foreach($grid_config as $field_name => $field_data) { if(isset($field_data['export_field'])) { $field_name = $field_data['export_field']; } $value = $list->GetField($field_name, isset($field_data['format']) ? $field_data['format'] : null); $value = str_replace("\r\n", "\n", $value); $value = str_replace("\r", "\n", $value); array_push($data, $value); } if($export_data['encoding'] == 'UTF-16LE') { fwrite($file, chr(0xFF).chr(0xFE)); } $csv_line = getcsvline($data, $export_data['delimiter'], $export_data['enclosure'], $export_data['record_separator']); if($export_data['encoding']) { $csv_line = mb_convert_encoding($csv_line, $export_data['encoding'], $export_data['source_encoding']); } fwrite($file, $csv_line); $list->GoNext(); } $records_processed = $export_data['page'] * $export_data['step']; $percent_complete = min($records_processed / $list->RecordsCount * 100, 100); fclose($file); if ($records_processed >= $list->RecordsCount) { $this->Application->StoreVar('export_data', serialize($export_data)); $this->Application->Redirect($this->Application->GetVar('finish_template')); } echo $percent_complete; $export_data['page']++; $this->Application->StoreVar('export_data', serialize($export_data)); } function ValidateFileName($path, $name) { $parts = pathinfo($name); $ext = '.'.$parts['extension']; $filename = mb_substr($parts['basename'], 0, -mb_strlen($ext)); $new_name = $filename.$ext; while ( file_exists($path.'/'.$new_name) ) { if ( preg_match('/('.preg_quote($filename, '/').'_)([0-9]*)('.preg_quote($ext, '/').')/', $new_name, $regs) ) { $new_name = $regs[1].($regs[2]+1).$regs[3]; } else { $new_name = $filename.'_1'.$ext; } } return $new_name; } function ExportData($name) { $export_data = unserialize($this->Application->RecallVar('export_data')); return isset($export_data[$name]) ? $export_data[$name] : false; } function GetCSV() { safeDefine('DBG_SKIP_REPORTING', 1); - $export_data = unserialize($this->Application->RecallVar('export_data')); + $export_data = unserialize($this->Application->RecallVar('export_data')); + $filename = preg_replace('/(.*)\.csv$/', '\1', basename($export_data['file_name'])) . '.csv'; + header('Content-type: text/csv'); - $filename = rtrim(basename($export_data['file_name']), '.csv').'.csv'; - header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Content-Disposition: attachment; filename="' . $filename . '"'); readfile($export_data['file_name']); die(); } function ImportStart($filename) { if(!file_exists($filename) || !is_file($filename)) return 'cant_open_file'; $import_data = Array(); $lang_object =& $this->Application->recallObject('lang.current'); /* @var $lang_object LanguagesItem */ $import_data['source_encoding'] = strtoupper( $lang_object->GetDBField('Charset') ); $import_data['encoding'] = $this->Application->ConfigValue('CSVExportEncoding') ? false : 'UTF-16LE'; $import_data['errors'] = ''; // convert file in case of UTF-16LE if($import_data['source_encoding'] != $import_data['encoding']) { copy($filename, $filename.'.orginal'); $file_content = file_get_contents($filename); $file = fopen($filename, 'w'); fwrite($file, mb_convert_encoding(str_replace(chr(0xFF).chr(0xFE), '', $file_content), $import_data['source_encoding'], $import_data['encoding'])); fclose($file); } $import_data['prefix'] = $this->PrefixSpecial; $import_data['grid'] = $this->grid; $import_data['file'] = $filename; $import_data['total_lines'] = count(file($filename)); if(!$import_data['total_lines']) $import_data['total_lines'] = 1; unset($file_content); $import_data['lines_processed'] = 0; $import_data['delimiter'] = $this->delimiter_mapping[(int)$this->Application->ConfigValue('CSVExportDelimiter')]; $import_data['enclosure'] = $this->enclosure_mapping[(int)$this->Application->ConfigValue('CSVExportEnclosure')]; $import_data['step'] = IMPORT_STEP; $import_data['not_imported_lines'] = ''; $import_data['added'] = 0; $import_data['updated'] = 0; $file = fopen($filename, 'r'); // getting first line for headers $headers = fgetcsv($file, 8192, $import_data['delimiter'], $import_data['enclosure']); fclose($file); $prefix_elems = split('\.|_', $import_data['prefix']); $grids = $this->Application->getUnitOption($prefix_elems[0], 'Grids'); $grid_config = $grids[ $import_data['grid'] ]['Fields']; $field_list = Array(); foreach($grid_config as $field_name => $field_data) { if(isset($field_data['export_field'])) { $field_name = $field_data['export_field']; } $field_label = $this->Application->Phrase( $field_data['title'] ); $field_pos = array_search($field_label, $headers); if($field_pos !== false) { $field_list[$field_pos] = $field_name; } } if(!count($field_list)) return 'no_matching_columns'; $import_data['field_list'] = $field_list; // getting key list $field_positions = Array(); $config_key_list = $this->Application->getUnitOption($prefix_elems[0], 'ImportKeys'); if(!$config_key_list) $config_key_list = Array(); array_unshift($config_key_list, Array($this->Application->getUnitOption($prefix_elems[0], 'IDField'))); $key_list = Array(); foreach($config_key_list as $arr_key => $import_key) { $key_list[$arr_key] = is_array($import_key) ? $import_key : Array($import_key); foreach($key_list[$arr_key] as $key_field) { $field_positions[$key_field] = array_search($key_field, $import_data['field_list']); if($field_positions[$key_field] === false) { // no such key field combination in imported file unset($key_list[$arr_key]); break; } } } $import_data['key_list'] = $key_list; $import_data['field_positions'] = $field_positions; $this->Application->StoreVar('import_data', serialize($import_data)); return true; } function ImportStep() { $import_data = unserialize($this->Application->RecallVar('import_data')); $prefix_elems = split('\.|_', $import_data['prefix']); $object =& $this->Application->recallObject($prefix_elems[0].'.-csvimport', $prefix_elems[0], Array('skip_autoload' => true, 'populate_ml_fields' => true)); /* @var $object kDBItem */ $file = fopen($import_data['file'], 'r'); $eof = false; // skipping lines that has been already imported for($i = 0; $i < $import_data['lines_processed'] + 1; $i++) { if(feof($file)) break; fgets($file, 8192); } $import_event = new kEvent($prefix_elems[0].'.-csvimport:OnBeforeCSVLineImport'); for($i = 0; $i < $import_data['step']; $i++) { if(feof($file)) break; $data = fgetcsv($file, 8192, $import_data['delimiter'], $import_data['enclosure']); if(!$data) continue; $object->Clear(); $action = 'Create'; // 1. trying to load object by keys foreach($import_data['key_list'] as $key) { $fail = false; $key_array = Array(); foreach($key as $key_field) { if(!isset($data[ $import_data['field_positions'][$key_field] ])) { $fail = true; break; } $key_array[$key_field] = $data[ $import_data['field_positions'][$key_field] ]; } if($fail) continue; if($object->Load($key_array)) { $action = 'Update'; break; } } // 2. set object fields foreach($import_data['field_list'] as $position => $field_name) { if(isset($data[$position])) { $object->SetField($field_name, $data[$position]); } } // 3. validate item and run event $status = $object->Validate(); $import_event->status = $status ? erSUCCESS : erFAIL; $this->Application->HandleEvent($import_event); if($import_event->status == erSUCCESS && $object->$action()) { $import_data[ ($action == 'Create') ? 'added' : 'updated' ]++; } else { $msg = ''; foreach ($object->FieldErrors as $field => $info) { if (!$info['pseudo']) continue; $msg .= "$field: {$info['pseudo']} "; } $import_data['errors'] .= ($i + $import_data['lines_processed'] + 1).": $msg\n"; $import_data['not_imported_lines'] .= ','.($i + $import_data['lines_processed'] + 1); } } $import_data['lines_processed'] += $import_data['step']; $import_data['not_imported_lines'] = ltrim($import_data['not_imported_lines'], ','); $this->Application->StoreVar('import_data', serialize($import_data)); $feof = feof($file); fclose($file); if($feof) { $this->Application->Redirect($this->Application->GetVar('finish_template')); } else { $percent_complete = floor($import_data['lines_processed'] / $import_data['total_lines'] * 100); if($percent_complete > 99) $percent_complete = 99; echo $percent_complete; } } function ImportData($name) { $import_data = unserialize($this->Application->RecallVar('import_data')); return isset($import_data[$name]) ? $import_data[$name] : false; } function GetNotImportedLines() { $import_data = unserialize($this->Application->RecallVar('import_data')); if(!$import_data['not_imported_lines']) return false; $line_numbers = explode(',', $import_data['not_imported_lines']); $line_numbers[] = 0; // include header row in output $file = fopen($import_data['file'], 'r'); $eof = false; $result = ''; for($i = 0; $i <= max($line_numbers); $i++) { if(feof($file)) break; $line = fgets($file, 8192); if(in_array($i, $line_numbers)) { $result .= $i.':'.$line; } } return $result."\n\n".$import_data['errors']; } } \ No newline at end of file Index: branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php =================================================================== --- branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php (revision 13232) +++ branches/5.0.x/core/units/helpers/cat_dbitem_export_helper.php (revision 13233) @@ -1,1452 +1,1455 @@ <?php /** * @version $Id$ * @package In-Portal * @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved. * @license GNU/GPL * In-Portal is Open Source software. * This means that this software may have been modified pursuant * the GNU General Public License, and as distributed it includes * or is derivative of works licensed under the GNU General Public License * or other free or open source software licenses. * See http://www.in-portal.org/license for copyright notices and details. */ defined('FULL_PATH') or die('restricted access!'); define('EXPORT_STEP', 100); // export by 200 items (e.g. links) define('IMPORT_STEP', 20); // export by 200 items (e.g. links) define('IMPORT_CHUNK', 10240); // 10240); //30720); //50120); // 5 KB define('IMPORT_TEMP', 1); define('IMPORT_LIVE', 2); class kCatDBItemExportHelper extends kHelper { var $false = false; var $cache = Array(); /** * Allows to find out what items are new in cache * * @var Array */ var $cacheStatus = Array(); var $cacheTable = ''; var $exportFields = Array(); /** * Export options * * @var Array */ var $exportOptions = Array(); /** * Item beeing currenly exported * * @var kCatDBItem */ var $curItem = null; /** * Dummy category object * * @var CategoriesItem */ var $dummyCategory = null; /** * Pointer to opened file * * @var resource */ var $filePointer = null; /** * Custom fields definition of current item * * @var Array */ var $customFields = Array(); function kCatDBItemExportHelper() { parent::kHelper(); $this->cacheTable = TABLE_PREFIX.'ImportCache'; } /** * Returns value from cache if found or false otherwise * * @param string $type * @param int $key * @return mixed */ function getFromCache($type, $key) { return getArrayValue($this->cache, $type, $key); } /** * Adds value to be cached * * @param string $type * @param int $key * @param mixed $value */ function addToCache($type, $key, $value, $is_new = true) { // if (!isset($this->cache[$type])) $this->cache[$type] = Array(); $this->cache[$type][$key] = $value; if ($is_new) { $this->cacheStatus[$type][$key] = true; } } function storeCache($cache_types) { $cache_types = explode(',', $cache_types); $values_sql = ''; foreach ($cache_types as $cache_type) { $sql_mask = '('.$this->Conn->qstr($cache_type).',%s,%s),'; $cache = getArrayValue($this->cacheStatus, $cache_type); if (!$cache) $cache = Array(); foreach ($cache as $var_name => $cache_status) { $var_value = $this->cache[$cache_type][$var_name]; $values_sql .= sprintf($sql_mask, $this->Conn->qstr($var_name), $this->Conn->qstr($var_value) ); } } $values_sql = substr($values_sql, 0, -1); if ($values_sql) { $sql = 'INSERT INTO '.$this->cacheTable.'(`CacheName`,`VarName`,`VarValue`) VALUES '.$values_sql; $this->Conn->Query($sql); } } function loadCache() { $sql = 'SELECT * FROM '.$this->cacheTable; $records = $this->Conn->Query($sql); $this->cache = Array(); foreach ($records as $record) { $this->addToCache($record['CacheName'], $record['VarName'], $record['VarValue'], false); } } /** * Fill required fields with dummy values * * @param kEvent $event */ function fillRequiredFields(&$event, &$object, $set_status = false) { if ($object == $this->false) { $object =& $event->getObject(); } $has_empty = false; $fields = array_keys($object->Fields); foreach ($fields as $field_name) { $field_options =& $object->Fields[$field_name]; if (isset($object->VirtualFields[$field_name]) || !getArrayValue($field_options, 'required') ) continue; if ( $object->GetDBField($field_name) ) continue; $formatter_class = getArrayValue($field_options, 'formatter'); if ($formatter_class) // not tested { $formatter =& $this->Application->recallObject($formatter_class); $sample_value = $formatter->GetSample($field_name, $field_options, $object); } $has_empty = true; $object->SetField($field_name, isset($sample_value) && $sample_value ? $sample_value : 'no value'); } $object->UpdateFormattersSubFields(); if ($set_status && $has_empty) { $object->SetDBField('Status', 0); } } /** * Verifies that all user entered export params are correct * * @param kEvent $event */ function verifyOptions(&$event) { if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid')) { $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 0); return false; } $this->fillRequiredFields($event, $this->false); $object =& $event->getObject(); $cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy'); if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field { $object->setRequired('CategorySeparator', true); $cross_unique_fields[] = 'CategorySeparator'; } $ret = $object->Validate(); // check if cross unique fields has no same values foreach ($cross_unique_fields as $field_index => $field_name) { if (getArrayValue($object->FieldErrors, $field_name, 'pseudo') == 'required') continue; $check_fields = $cross_unique_fields; unset($check_fields[$field_index]); foreach ($check_fields as $check_field) { if ($object->GetDBField($field_name) == $object->GetDBField($check_field)) { $object->SetError($check_field, 'unique'); } } } if ($event->Special == 'import') { $this->exportOptions = $this->loadOptions($event); $automatic_fields = ($object->GetDBField('FieldTitles') == 1); $object->setRequired('ExportColumns', !$automatic_fields); $category_prefix = '__CATEGORY__'; if ( $automatic_fields && ($this->exportOptions['SkipFirstRow']) ) { $this->openFile($event); $this->exportOptions['ExportColumns'] = $this->readRecord(); if (!$this->exportOptions['ExportColumns']) { $this->exportOptions['ExportColumns'] = Array (); } $this->closeFile(); // remove additional (non-parseble columns) foreach ($this->exportOptions['ExportColumns'] as $field_index => $field_name) { if (!$this->validateField($field_name, $object)) { unset($this->exportOptions['ExportColumns'][$field_index]); } } $category_prefix = ''; } // 1. check, that we have column definitions if (!$this->exportOptions['ExportColumns']) { $object->setError('ExportColumns', 'required'); $ret = false; } else { // 1.1. check that all required fields are present in imported file $missing_columns = Array(); foreach ($object->Fields as $field_name => $field_options) { if ($object->skipField($field_name)) continue; if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) { $missing_columns[] = $field_name; $object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing'); $ret = false; } } if (!$ret && $this->Application->isDebugMode()) { $this->Application->Debugger->appendHTML('Missing required for import/export:'); $this->Application->Debugger->dumpVars($missing_columns); } } // 2. check, that we have only mixed category field or only separated category fields $category_found['mixed'] = false; $category_found['separated'] = false; foreach ($this->exportOptions['ExportColumns'] as $import_field) { if (preg_match('/^'.$category_prefix.'Category(Path|[0-9]+)/', $import_field, $rets)) { $category_found[$rets[1] == 'Path' ? 'mixed' : 'separated'] = true; } } if ($category_found['mixed'] && $category_found['separated']) { $object->SetError('ExportColumns', 'unique_category', 'la_error_unique_category_field'); $ret = false; } // 3. check, that duplicates check fields are selected & present in imported fields if ($this->exportOptions['ReplaceDuplicates']) { if ($this->exportOptions['CheckDuplicatesMethod'] == 1) { $check_fields = Array($object->IDField); } else { $check_fields = $this->exportOptions['DuplicateCheckFields'] ? explode('|', substr($this->exportOptions['DuplicateCheckFields'], 1, -1)) : Array(); $object =& $event->getObject(); $language_id = $this->Application->GetDefaultLanguageId(); foreach ($check_fields as $index => $check_field) { foreach ($object->Fields as $field_name => $field_options) { if ($field_name == 'l'.$language_id.'_'.$check_field) { $check_fields[$index] = 'l'.$language_id.'_'.$check_field; break; } } } } $this->exportOptions['DuplicateCheckFields'] = $check_fields; if (!$check_fields) { $object->setError('CheckDuplicatesMethod', 'required'); $ret = false; } else { foreach ($check_fields as $check_field) { $check_field = preg_replace('/^cust_(.*)/', 'Custom_\\1', $check_field); if (!in_array($check_field, $this->exportOptions['ExportColumns'])) { $object->setError('ExportColumns', 'required'); $ret = false; break; } } } } $this->saveOptions($event); } return $ret; } /** * Returns filename to read import data from * * @return string */ function getImportFilename() { if ($this->exportOptions['ImportSource'] == 1) { $ret = $this->exportOptions['ImportFilename']; // ['name']; commented by Kostja } else { $ret = $this->exportOptions['ImportLocalFilename']; } return EXPORT_PATH.'/'.$ret; } /** * Returns filename to write export data to * * @return string */ function getExportFilename() { - return EXPORT_PATH.'/'.$this->exportOptions['ExportFilename'].'.'.$this->getFileExtension(); + $extension = $this->getFileExtension(); + $filename = preg_replace('/(.*)\.' . $extension . '$/', '\1', $this->exportOptions['ExportFilename']) . '.' . $extension; + + return EXPORT_PATH . DIRECTORY_SEPARATOR . $filename; } /** * Opens file required for export/import operations * * @param kEvent $event */ function openFile(&$event) { if ($event->Special == 'export') { $write_mode = ($this->exportOptions['start_from'] == 0) ? 'w' : 'a'; $this->filePointer = fopen($this->getExportFilename(), $write_mode); } else { $this->filePointer = fopen($this->getImportFilename(), 'r'); } // skip UTF-8 BOM Modifier $first_chars = fread($this->filePointer, 3); if (bin2hex($first_chars) != 'efbbbf') { fseek($this->filePointer, 0); } } /** * Closes opened file * */ function closeFile() { fclose($this->filePointer); } function getCustomSQL() { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); $custom_sql = ''; foreach ($this->customFields as $custom_id => $custom_name) { $custom_sql .= 'custom_data.'.$ml_formatter->LangFieldName('cust_'.$custom_id).' AS cust_'.$custom_name.', '; } return substr($custom_sql, 0, -2); } function getPlainExportSQL($count_only = false) { if ($count_only && isset($this->exportOptions['ForceCountSQL'])) { $sql = $this->exportOptions['ForceCountSQL']; } elseif (!$count_only && isset($this->exportOptions['ForceSelectSQL'])) { $sql = $this->exportOptions['ForceSelectSQL']; } else { $items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List'); $items_list->SetPerPage(-1); if ($options['export_ids'] != '') { $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')'); } if ($count_only) { $sql = $items_list->getCountSQL( $items_list->GetSelectSQL(true,false) ); } else { $sql = $items_list->GetSelectSQL(); } } if (!$count_only) { $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP; } // else { // $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql); // } return $sql; } function getExportSQL($count_only = false) { if (!$this->Application->getUnitOption($this->curItem->Prefix, 'CatalogItem')) { return $this->GetPlainExportSQL($count_only); // in case this is not a CategoryItem } if ($this->exportOptions['export_ids'] === false) { // get links from current category & all it's subcategories $join_clauses = Array(); $custom_sql = $this->getCustomSQL(); if ($custom_sql) { $custom_table = $this->Application->getUnitOption($this->curItem->Prefix.'-cdata', 'TableName'); $join_clauses[$custom_table.' custom_data'] = 'custom_data.ResourceId = item_table.ResourceId'; } $join_clauses[TABLE_PREFIX.'CategoryItems ci'] = 'ci.ItemResourceId = item_table.ResourceId'; $join_clauses[TABLE_PREFIX.'Category c'] = 'c.CategoryId = ci.CategoryId'; $sql = 'SELECT item_table.*, ci.CategoryId'.($custom_sql ? ', '.$custom_sql : '').' FROM '.$this->curItem->TableName.' item_table'; foreach ($join_clauses as $table_name => $join_expression) { $sql .= ' LEFT JOIN '.$table_name.' ON '.$join_expression; } $sql .= ' WHERE '; if ($this->exportOptions['export_cats_ids'][0] == 0) { $sql .= '1'; } else { foreach ($this->exportOptions['export_cats_ids'] as $category_id) { $sql .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR '; } $sql = substr($sql, 0, -4); } $sql .= ' ORDER BY ci.PrimaryCat DESC'; // NEW } else { // get only selected links $sql = 'SELECT item_table.*, '.$this->exportOptions['export_cats_ids'][0].' AS CategoryId FROM '.$this->curItem->TableName.' item_table WHERE '.$this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')'; } if (!$count_only) { $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP; } else { $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql); } return $sql; } /** * Enter description here... * * @param kEvent $event */ function performExport(&$event) { $this->exportOptions = $this->loadOptions($event); $this->exportFields = $this->exportOptions['ExportColumns']; $this->curItem =& $event->getObject( Array('skip_autoload' => true) ); $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); $this->openFile($event); if ($this->exportOptions['start_from'] == 0) // first export step { if (!getArrayValue($this->exportOptions, 'IsBaseCategory')) { $this->exportOptions['IsBaseCategory'] = 0; } if ($this->exportOptions['IsBaseCategory'] ) { $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = ' . (int)$this->Application->GetVar('m_cat_id'); $parent_path = $this->Conn->GetOne($sql); $parent_path = explode('|', substr($parent_path, 1, -1)); if ($parent_path && $parent_path[0] == $this->Application->findModule('Name', 'Core', 'RootCat')) { array_shift($parent_path); } $this->exportOptions['BaseLevel'] = count($parent_path); // level to cut from other categories } // 1. export field titles if required if ($this->exportOptions['IncludeFieldTitles']) { $data_array = Array(); foreach ($this->exportFields as $export_field) { $data_array = array_merge($data_array, $this->getFieldCaption($export_field)); } $this->writeRecord($data_array); } $this->exportOptions['total_records'] = $this->Conn->GetOne( $this->getExportSQL(true) ); } // 2. export data $records = $this->Conn->Query( $this->getExportSQL() ); $records_exported = 0; foreach ($records as $record_info) { $this->curItem->Clear(); $this->curItem->SetDBFieldsFromHash($record_info); $this->setCurrentID(); $this->curItem->raiseEvent('OnAfterItemLoad', $this->curItem->GetID() ); $data_array = Array(); foreach ($this->exportFields as $export_field) { $data_array = array_merge($data_array, $this->getFieldValue($export_field) ); } $this->writeRecord($data_array); $records_exported++; } $this->closeFile(); $this->exportOptions['start_from'] += $records_exported; $this->saveOptions($event); return $this->exportOptions; } function getItemFields() { // just in case dummy user selected automtic mode & moved columns too :( return array_merge($this->curItem->Fields['AvailableColumns']['options'], $this->curItem->Fields['ExportColumns']['options']); } /** * Checks if field really belongs to importable field list * * @param string $field_name * @param kCatDBItem $object * @return bool */ function validateField($field_name, &$object) { // 1. convert custom field $field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name); // 2. convert category field (mixed version & serparated version) $field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name); $valid_fields = $object->getPossibleExportColumns(); return isset($valid_fields[$field_name]) || isset($valid_fields['__VIRTUAL__'.$field_name]); } /** * Enter description here... * * @param kEvent $event */ function performImport(&$event) { if (!$this->exportOptions) { // load import options in case if not previously loaded in verification function $this->exportOptions = $this->loadOptions($event); } $backup_category_id = $this->Application->GetVar('m_cat_id'); $this->Application->SetVar('m_cat_id', (int)$this->Application->RecallVar('ImportCategory') ); $this->openFile($event); $bytes_imported = 0; if ($this->exportOptions['start_from'] == 0) // first export step { // 1st time run if ($this->exportOptions['SkipFirstRow']) { $this->readRecord(); $this->exportOptions['start_from'] = ftell($this->filePointer); $bytes_imported = ftell($this->filePointer); } $current_category_id = $this->Application->GetVar('m_cat_id'); if ($current_category_id > 0) { $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$current_category_id; $this->exportOptions['ImportCategoryPath'] = $this->Conn->GetOne($sql); } else { $this->exportOptions['ImportCategoryPath'] = ''; } $this->exportOptions['total_records'] = filesize($this->getImportFilename()); } else { $this->loadCache(); } $this->exportFields = $this->exportOptions['ExportColumns']; $this->addToCache('category_parent_path', $this->Application->GetVar('m_cat_id'), $this->exportOptions['ImportCategoryPath']); // 2. import data $this->dummyCategory =& $this->Application->recallObject('c.-tmpitem', 'c', Array('skip_autoload' => true)); fseek($this->filePointer, $this->exportOptions['start_from']); $items_processed = 0; while (($bytes_imported < IMPORT_CHUNK && $items_processed < IMPORT_STEP) && !feof($this->filePointer)) { $data = $this->readRecord(); if ($data) { if ($this->exportOptions['ReplaceDuplicates']) { // set fields used as keys for replace duplicates code $this->resetImportObject($event, IMPORT_TEMP, $data); } $this->processCurrentItem($event, $data); } $bytes_imported = ftell($this->filePointer) - $this->exportOptions['start_from']; $items_processed++; } $this->closeFile(); $this->Application->SetVar('m_cat_id', $backup_category_id); $this->exportOptions['start_from'] += $bytes_imported; $this->storeCache('new_ids'); $this->saveOptions($event); if ($this->exportOptions['start_from'] == $this->exportOptions['total_records']) { $this->Conn->Query('TRUNCATE TABLE '.$this->cacheTable); } return $this->exportOptions; } function setCurrentID() { $this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) ); } function setFieldValue($field_index, $value) { if (empty($value)) { $value = null; } $field_name = getArrayValue($this->exportFields, $field_index); if ($field_name == 'ResourceId') { return false; } if (substr($field_name, 0, 7) == 'Custom_') { $field_name = 'cust_'.substr($field_name, 7); $this->curItem->SetField($field_name, $value); } elseif ($field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath') { $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array(); } elseif (substr($field_name, 0, 8) == 'Category') { $this->curItem->CategoryPath[ (int)substr($field_name, 8) - 1 ] = $value; } elseif (substr($field_name, 0, 20) == '__CATEGORY__Category') { $this->curItem->CategoryPath[ (int)substr($field_name, 20) ] = $value; } elseif (substr($field_name, 0, 11) == '__VIRTUAL__') { $field_name = substr($field_name, 11); $this->curItem->SetField($field_name, $value); } else { $this->curItem->SetField($field_name, $value); } $pseudo_error = getArrayValue($this->curItem->FieldErrors, $field_name, 'pseudo'); if ($pseudo_error) { $this->curItem->SetDBField($field_name, null); unset($this->curItem->FieldErrors[$field_name]); } } function resetImportObject(&$event, $object_type, $record_data = null) { switch ($object_type) { case IMPORT_TEMP: $this->curItem =& $event->getObject( Array('skip_autoload' => true) ); break; case IMPORT_LIVE: $this->curItem =& $this->Application->recallObject($event->Prefix.'.-tmpitem'.$event->Special, $event->Prefix, Array('skip_autoload' => true)); break; } $this->curItem->Clear(); $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); if (isset($record_data)) { $this->setImportData($record_data); } } function setImportData($record_data) { foreach ($record_data as $field_index => $field_value) { $this->setFieldValue($field_index, $field_value); } $this->setCurrentID(); } function getItemCategory() { static $lang_prefix = null; $backup_category_id = $this->Application->GetVar('m_cat_id'); $category_id = $this->getFromCache('category_names', implode(':', $this->curItem->CategoryPath)); if ($category_id) { $this->Application->SetVar('m_cat_id', $category_id); return $category_id; } if (is_null($lang_prefix)) { $lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_'; } foreach ($this->curItem->CategoryPath as $category_index => $category_name) { if (!$category_name) continue; $category_key = crc32( implode(':', array_slice($this->curItem->CategoryPath, 0, $category_index + 1) ) ); $category_id = $this->getFromCache('category_names', $category_key); if ($category_id === false) { // get parent category path to search only in it $current_category_id = $this->Application->GetVar('m_cat_id'); // $parent_path = $this->getParentPath($current_category_id); // get category id from database by name $sql = 'SELECT CategoryId FROM '.TABLE_PREFIX.'Category WHERE ('.$lang_prefix.'Name = '.$this->Conn->qstr($category_name).') AND (ParentId = '.(int)$current_category_id.')'; $category_id = $this->Conn->GetOne($sql); if ($category_id === false) { // category not in db -> create $category_fields = Array( $lang_prefix.'Name' => $category_name, $lang_prefix.'Description' => $category_name, 'Status' => STATUS_ACTIVE, 'ParentId' => $current_category_id, 'AutomaticFilename' => 1 ); $this->dummyCategory->SetDBFieldsFromHash($category_fields); if ($this->dummyCategory->Create()) { $category_id = $this->dummyCategory->GetID(); $this->addToCache('category_parent_path', $category_id, $this->dummyCategory->GetDBField('ParentPath')); $this->addToCache('category_names', $category_key, $category_id); } } else { $this->addToCache('category_names', $category_key, $category_id); } } if ($category_id) { $this->Application->SetVar('m_cat_id', $category_id); } } if (!$this->curItem->CategoryPath) { $category_id = $backup_category_id; } return $category_id; } /** * Enter description here... * * @param kEvent $event */ function processCurrentItem(&$event, $record_data) { $save_method = 'Create'; $load_keys = Array(); // create/update categories $backup_category_id = $this->Application->GetVar('m_cat_id'); // perform replace duplicates code if ($this->exportOptions['ReplaceDuplicates']) { // get replace keys first, then reset current item to empty one $category_id = $this->getItemCategory(); if ($this->exportOptions['CheckDuplicatesMethod'] == 1) { if ($this->curItem->GetID()) { $load_keys = Array($this->curItem->IDField => $this->curItem->GetID()); } } else { $key_fields = $this->exportOptions['DuplicateCheckFields']; foreach ($key_fields as $key_field) { $load_keys[$key_field] = $this->curItem->GetDBField($key_field); } } $this->resetImportObject($event, IMPORT_LIVE); if (count($load_keys)) { $where_clause = ''; $language_id = (int)$this->Application->GetVar('m_lang'); if (!$language_id) { $language_id = 1; } foreach ($load_keys as $field_name => $field_value) { if (preg_match('/^cust_(.*)/', $field_name, $regs)) { $custom_id = array_search($regs[1], $this->customFields); $field_name = 'l'.$language_id.'_cust_'.$custom_id; $where_clause .= '(custom_data.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND '; } else { $where_clause .= '(item_table.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND '; } } $where_clause = substr($where_clause, 0, -5); $item_id = $this->getFromCache('new_ids', crc32($where_clause)); if (!$item_id) { if ($this->exportOptions['CheckDuplicatesMethod'] == 2) { // by other fields $parent_path = $this->getParentPath($category_id); $where_clause = '(c.ParentPath LIKE "'.$parent_path.'%") AND '.$where_clause; } $cdata_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName'); $sql = 'SELECT '.$this->curItem->IDField.' FROM '.$this->curItem->TableName.' item_table LEFT JOIN '.$cdata_table.' custom_data ON custom_data.ResourceId = item_table.ResourceId LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId WHERE '.$where_clause; $item_id = $this->Conn->GetOne($sql); } $save_method = $item_id && $this->curItem->Load($item_id) ? 'Update' : 'Create'; if ($save_method == 'Update') { // replace id from csv file with found id (only when ID is found in cvs file) if (in_array($this->curItem->IDField, $this->exportFields)) { $record_data[ array_search($this->curItem->IDField, $this->exportFields) ] = $item_id; } } } $this->setImportData($record_data); } else { $this->resetImportObject($event, IMPORT_LIVE, $record_data); $category_id = $this->getItemCategory(); } // create main record if ($save_method == 'Create') { $this->fillRequiredFields($this->false, $this->curItem, true); } // $sql_start = getmicrotime(); if (!$this->curItem->$save_method()) { $this->Application->SetVar('m_cat_id', $backup_category_id); return false; } // $sql_end = getmicrotime(); // $this->saveLog('SQL ['.$save_method.'] Time: '.($sql_end - $sql_start).'s'); if ($load_keys && ($save_method == 'Create') && $this->exportOptions['ReplaceDuplicates']) { // map new id to old id $this->addToCache('new_ids', crc32($where_clause), $this->curItem->GetID() ); } // assign item to categories $this->curItem->assignToCategory($category_id, false); $this->Application->SetVar('m_cat_id', $backup_category_id); return true; } /*function saveLog($msg) { static $first_time = true; $fp = fopen(FULL_PATH.'/sqls.log', $first_time ? 'w' : 'a'); fwrite($fp, $msg."\n"); fclose($fp); $first_time = false; }*/ /** * Returns category parent path, if possible, then from cache * * @param int $category_id * @return string */ function getParentPath($category_id) { $parent_path = $this->getFromCache('category_parent_path', $category_id); if ($parent_path === false) { $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$category_id; $parent_path = $this->Conn->GetOne($sql); $this->addToCache('category_parent_path', $category_id, $parent_path); } return $parent_path; } function getFileExtension() { return $this->exportOptions['ExportFormat'] == 1 ? 'csv' : 'xml'; } function getLineSeparator($option = 'LineEndings') { return $this->exportOptions[$option] == 1 ? "\r\n" : "\n"; } /** * Returns field caption for any exported field * * @param string $field * @return string */ function getFieldCaption($field) { if (substr($field, 0, 10) == '__CUSTOM__') { $ret = 'Custom_'.substr($field, 10, strlen($field) ); } elseif (substr($field, 0, 12) == '__CATEGORY__') { return $this->getCategoryTitle(); } elseif (substr($field, 0, 11) == '__VIRTUAL__') { $ret = substr($field, 11); } else { $ret = $field; } return Array($ret); } /** * Returns requested field value (including custom fields and category fields) * * @param string $field * @return string */ function getFieldValue($field) { if (substr($field, 0, 10) == '__CUSTOM__') { $field = 'cust_'.substr($field, 10, strlen($field)); $ret = $this->curItem->GetField($field); } elseif (substr($field, 0, 12) == '__CATEGORY__') { return $this->getCategoryPath(); } elseif (substr($field, 0, 11) == '__VIRTUAL__') { $field = substr($field, 11); $ret = $this->curItem->GetField($field); } else { $ret = $this->curItem->GetField($field); } $ret = str_replace("\r\n", $this->getLineSeparator('LineEndingsInside'), $ret); return Array($ret); } /** * Returns category field(-s) caption based on export mode * * @return string */ function getCategoryTitle() { // category path in separated fields $category_count = $this->getMaxCategoryLevel(); if ($this->exportOptions['CategoryFormat'] == 1) { // category path in one field return $category_count ? Array('CategoryPath') : Array(); } else { $i = 0; $ret = Array(); while ($i < $category_count) { $ret[] = 'Category'.($i + 1); $i++; } return $ret; } } /** * Returns category path in required format for current link * * @return string */ function getCategoryPath() { $category_id = $this->curItem->GetDBField('CategoryId'); $category_path = $this->getFromCache('category_path', $category_id); if (!$category_path) { $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); $sql = 'SELECT '.$ml_formatter->LangFieldName('CachedNavbar').' FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$category_id; $category_path = $this->Conn->GetOne($sql); $category_path = $category_path ? explode('&|&', $category_path) : Array(); if ($category_path && strtolower($category_path[0]) == 'content') { array_shift($category_path); } if ($this->exportOptions['IsBaseCategory']) { $i = $this->exportOptions['BaseLevel']; while ($i > 0) { array_shift($category_path); $i--; } } $category_count = $this->getMaxCategoryLevel(); if ($this->exportOptions['CategoryFormat'] == 1) { // category path in single field $category_path = $category_count ? Array( implode($this->exportOptions['CategorySeparator'], $category_path) ) : Array(); } else { // category path in separated fields $levels_used = count($category_path); if ($levels_used < $category_count) { $i = 0; while ($i < $category_count - $levels_used) { $category_path[] = ''; $i++; } } } $this->addToCache('category_path', $category_id, $category_path); } return $category_path; } /** * Get maximal category deep level from links beeing exported * * @return int */ function getMaxCategoryLevel() { static $max_level = -1; if ($max_level != -1) { return $max_level; } $sql = 'SELECT IF(c.CategoryId IS NULL, 0, MAX( LENGTH(c.ParentPath) - LENGTH( REPLACE(c.ParentPath, "|", "") ) - 1 )) FROM '.$this->curItem->TableName.' item_table LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON item_table.ResourceId = ci.ItemResourceId LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId WHERE (ci.PrimaryCat = 1) AND '; $where_clause = ''; if ($this->exportOptions['export_ids'] === false) { // get links from current category & all it's subcategories if ($this->exportOptions['export_cats_ids'][0] == 0) { $where_clause = 1; } else { foreach ($this->exportOptions['export_cats_ids'] as $category_id) { $where_clause .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR '; } $where_clause = substr($where_clause, 0, -4); } } else { // get only selected links $where_clause = $this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')'; } $max_level = $this->Conn->GetOne($sql.'('.$where_clause.')'); if ($this->exportOptions['IsBaseCategory'] ) { $max_level -= $this->exportOptions['BaseLevel']; } return $max_level; } /** * Saves one record to export file * * @param Array $fields_hash */ function writeRecord($fields_hash) { fputcsv2($this->filePointer, $fields_hash, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy'], $this->getLineSeparator() ); } function readRecord() { return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']); } function saveOptions(&$event, $options = null) { if (!isset($options)) { $options = $this->exportOptions; } $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) ); } function loadOptions(&$event) { return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options')); } /** * Sets correct available & export fields * * @param kEvent $event */ function prepareExportColumns(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); if (!array_key_exists('ExportColumns', $object->Fields)) { // import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported return ; } $available_columns = Array(); if ($this->Application->getUnitOption($event->Prefix, 'CatalogItem')) { // category field (mixed) $available_columns['__CATEGORY__CategoryPath'] = 'CategoryPath'; if ($event->Special == 'import') { // category field (separated fields) $max_level = $this->Application->ConfigValue('MaxImportCategoryLevels'); $i = 0; while ($i < $max_level) { $available_columns['__CATEGORY__Category'.($i + 1)] = 'Category'.($i + 1); $i++; } } } // db fields foreach ($object->Fields as $field_name => $field_options) { if (!$object->skipField($field_name)) { $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : ''); } } $handler =& $this->Application->recallObject($event->Prefix.'_EventHandler'); $available_columns = array_merge_recursive2($available_columns, $handler->getCustomExportColumns($event)); // custom fields foreach ($object->customFields as $custom_id => $custom_name) { $available_columns['__CUSTOM__'.$custom_name] = $custom_name; } // columns already in use $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if ($items_info) { list($item_id, $field_values) = each($items_info); $export_keys = $field_values['ExportColumns']; $export_keys = $export_keys ? explode('|', substr($export_keys, 1, -1) ) : Array(); } else { $export_keys = Array(); } $export_columns = Array(); foreach ($export_keys as $field_key) { $field_name = $this->getExportField($field_key); $export_columns[$field_key] = $field_name; unset($available_columns[$field_key]); } $options = $object->GetFieldOptions('ExportColumns'); $options['options'] = $export_columns; $object->SetFieldOptions('ExportColumns', $options); $options = $object->GetFieldOptions('AvailableColumns'); $options['options'] = $available_columns; $object->SetFieldOptions('AvailableColumns', $options); $this->updateImportFiles($event); $this->PrepareExportPresets($event); } function PrepareExportPresets(&$event) { $object =& $event->getObject( Array('skip_autoload' => true) ); $options = $object->GetFieldOptions('ExportPresets'); $export_settings = $this->Application->RecallPersistentVar('export_settings'); if (!$export_settings) return ; $export_settings = unserialize($export_settings); if (!isset($export_settings[$event->Prefix])) return ; $export_presets = array(''=>''); foreach ($export_settings[$event->Prefix] as $key => $val) { $export_presets[implode('|', $val['ExportColumns'])] = $key; } $options['options'] = $export_presets; $object->SetFieldOptions('ExportPresets', $options); } function getExportField($field_key) { $prepends = Array('__CUSTOM__', '__CATEGORY__'); foreach ($prepends as $prepend) { if (substr($field_key, 0, strlen($prepend) ) == $prepend) { $field_key = substr($field_key, strlen($prepend), strlen($field_key) ); break; } } return $field_key; } /** * Updates uploaded files list * * @param kEvent $event */ function updateImportFiles(&$event) { if ($event->Special != 'import') { return false; } $object =& $event->getObject(); $import_filenames = Array(); if ($folder_handle = opendir(EXPORT_PATH)) { while (false !== ($file = readdir($folder_handle))) { if (is_dir(EXPORT_PATH.'/'.$file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH.'/'.$file) == 0) continue; $file_size = formatSize( filesize(EXPORT_PATH.'/'.$file) ); $import_filenames[$file] = $file.' ('.$file_size.')'; } closedir($folder_handle); } $options = $object->GetFieldOptions('ImportLocalFilename'); $options['options'] = $import_filenames; $object->SetFieldOptions('ImportLocalFilename', $options); } /** * Returns module folder * * @param kEvent $event * @return string */ function getModuleFolder(&$event) { return $this->Application->getUnitOption($event->Prefix, 'ModuleFolder'); } /** * Export form validation & processing * * @param kEvent $event */ function OnExportBegin(&$event) { $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if (!$items_info) { $items_info = unserialize( $this->Application->RecallVar($event->getPrefixSpecial().'_ItemsInfo') ); $this->Application->SetVar($event->getPrefixSpecial(true), $items_info); } list($item_id, $field_values) = each($items_info); $object =& $event->getObject( Array('skip_autoload' => true) ); $object->SetFieldsFromHash($field_values); $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!! $object->setID($item_id); $this->setRequiredFields($event); $export_object =& $this->Application->recallObject('CatItemExportHelper'); // save export/import options if ($event->Special == 'export') { $export_ids = $this->Application->RecallVar($event->Prefix.'_export_ids'); $export_cats_ids = $this->Application->RecallVar($event->Prefix.'_export_cats_ids'); // used for multistep export $field_values['export_ids'] = $export_ids ? explode(',', $export_ids) : false; $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array( $this->Application->GetVar('m_cat_id') ); } $field_values['ExportColumns'] = $field_values['ExportColumns'] ? explode('|', substr($field_values['ExportColumns'], 1, -1) ) : Array(); $field_values['start_from'] = 0; $this->Application->HandleEvent($nevent, $event->Prefix.':OnBeforeExportBegin', array('options'=>$field_values)); $field_values = $nevent->getEventParam('options'); $export_object->saveOptions($event, $field_values); if( $export_object->verifyOptions($event) ) { if ($this->_getExportSavePreset($object)) { $name = $object->GetDBField('ExportPresetName'); $export_settings = $this->Application->RecallPersistentVar('export_settings'); $export_settings = $export_settings ? unserialize($export_settings) : array(); $export_settings[$event->Prefix][$name] = $field_values; $this->Application->StorePersistentVar('export_settings', serialize($export_settings)); } $progress_t = $this->Application->RecallVar('export_progress_t'); if ($progress_t) { $this->Application->RemoveVar('export_progress_t'); } else { $progress_t = $export_object->getModuleFolder($event).'/'.$event->Special.'_progress'; } $event->redirect = $progress_t; if ($event->Special == 'import') { $import_category = (int)$this->Application->RecallVar('ImportCategory'); // in future could use module root category if import category will be unavailable :) $event->SetRedirectParam('m_cat_id', $import_category); // for template permission checking $this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking } } else { // make uploaded file local & change source selection $filename = getArrayValue($field_values, 'ImportFilename'); if ($filename) { $export_object->updateImportFiles($event); $object->SetDBField('ImportSource', 2); $field_values['ImportSource'] = 2; $object->SetDBField('ImportLocalFilename', $filename); $field_values['ImportLocalFilename'] = $filename; $export_object->saveOptions($event, $field_values); } $event->status = erFAIL; $event->redirect = false; } } /** * Returns export save preset name, when used at all * * @param kDBItem $object * @return string */ function _getExportSavePreset(&$object) { if (!array_key_exists('ExportSavePreset', $object->Fields)) { return ''; } return $object->GetDBField('ExportSavePreset'); } /** * set required fields based on import or export params * * @param kEvent $event */ function setRequiredFields(&$event) { $required_fields['common'] = Array('FieldsSeparatedBy', 'LineEndings', 'CategoryFormat'); $required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns'); $object =& $event->getObject(); if ($this->_getExportSavePreset($object)) { $required_fields['export'][] = 'ExportPresetName'; } $required_fields['import'] = Array('FieldTitles', 'ImportSource', 'CheckDuplicatesMethod'); // ImportFilename, ImportLocalFilename if ($event->Special == 'import') { $import_source = Array(1 => 'ImportFilename', 2 => 'ImportLocalFilename'); $used_field = $import_source[ $object->GetDBField('ImportSource') ]; $required_fields[$event->Special][] = $used_field; $object->Fields[$used_field]['error_field'] = 'ImportSource'; if ($object->GetDBField('FieldTitles') == 2) $required_fields[$event->Special][] = 'ExportColumns'; // manual field titles } $required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]); foreach ($required_fields as $required_field) { $object->setRequired($required_field, true); } } } \ No newline at end of file