Index: branches/5.0.x/core/kernel/db/db_tag_processor.php =================================================================== diff -u -N -r12323 -r12343 --- branches/5.0.x/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 12323) +++ branches/5.0.x/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 12343) @@ -1,6 +1,6 @@ Special) - { - case 'showall': - $this->clearFilters(false,true,false,false); - break; - } - return parent::GetWhereClause($for_counting,$system_filters_only); - }*/ - - } \ No newline at end of file Index: branches/5.0.x/core/kernel/processors/tag_processor.php =================================================================== diff -u -N -r12323 -r12343 --- branches/5.0.x/core/kernel/processors/tag_processor.php (.../tag_processor.php) (revision 12323) +++ branches/5.0.x/core/kernel/processors/tag_processor.php (.../tag_processor.php) (revision 12343) @@ -1,6 +1,6 @@ cacheTable = TABLE_PREFIX.'ImportCache'; - } - - /** - * Returns value from cache if found or false otherwise - * - * @param string $type - * @param int $key - * @return mixed - */ - function getFromCache($type, $key) - { - return getArrayValue($this->cache, $type, $key); - } - - /** - * Adds value to be cached - * - * @param string $type - * @param int $key - * @param mixed $value - */ - function addToCache($type, $key, $value, $is_new = true) - { -// if (!isset($this->cache[$type])) $this->cache[$type] = Array(); - $this->cache[$type][$key] = $value; - if ($is_new) { - $this->cacheStatus[$type][$key] = true; - } - } - - function storeCache($cache_types) - { - $cache_types = explode(',', $cache_types); - - $values_sql = ''; - foreach ($cache_types as $cache_type) { - $sql_mask = '('.$this->Conn->qstr($cache_type).',%s,%s),'; - $cache = getArrayValue($this->cacheStatus, $cache_type); - if (!$cache) $cache = Array(); - foreach ($cache as $var_name => $cache_status) { - $var_value = $this->cache[$cache_type][$var_name]; - $values_sql .= sprintf($sql_mask, $this->Conn->qstr($var_name), $this->Conn->qstr($var_value) ); - } - } - $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql); - if ($values_sql) { - $sql = 'INSERT INTO '.$this->cacheTable.'(`CacheName`,`VarName`,`VarValue`) VALUES '.$values_sql; - $this->Conn->Query($sql); - } - - } - - function loadCache() - { - $sql = 'SELECT * FROM '.$this->cacheTable; - $records = $this->Conn->Query($sql); - - $this->cache = Array(); - foreach ($records as $record) { - $this->addToCache($record['CacheName'], $record['VarName'], $record['VarValue'], false); - } - } - - /** - * Fill required fields with dummy values - * - * @param kEvent $event - */ - function fillRequiredFields(&$event, &$object, $set_status = false) - { - if ($object == $this->false) { - $object =& $event->getObject(); - } - - $has_empty = false; - $fields = array_keys($object->Fields); - foreach ($fields as $field_name) - { - $field_options =& $object->Fields[$field_name]; - if (isset($object->VirtualFields[$field_name]) || !getArrayValue($field_options, 'required') ) continue; - if ( $object->GetDBField($field_name) ) continue; - - $formatter_class = getArrayValue($field_options, 'formatter'); - if ($formatter_class) // not tested - { - $formatter =& $this->Application->recallObject($formatter_class); - $sample_value = $formatter->GetSample($field_name, $field_options, $object); - } - - $has_empty = true; - $object->SetField($field_name, isset($sample_value) && $sample_value ? $sample_value : 'no value'); - } - $object->UpdateFormattersSubFields(); - - if ($set_status && $has_empty) { - $object->SetDBField('Status', 0); - } - } - - /** - * Verifies that all user entered export params are correct - * - * @param kEvent $event - */ - function verifyOptions(&$event) - { - if ($this->Application->RecallVar($event->getPrefixSpecial().'_ForceNotValid')) - { - $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 0); - return false; - } - - $this->fillRequiredFields($event, $this->false); - - $object =& $event->getObject(); - $cross_unique_fields = Array('FieldsSeparatedBy', 'FieldsEnclosedBy'); - if (($object->GetDBField('CategoryFormat') == 1) || ($event->Special == 'import')) // in one field - { - $object->setRequired('CategorySeparator', true); - $cross_unique_fields[] = 'CategorySeparator'; - } - - $ret = $object->Validate(); - - // check if cross unique fields has no same values - foreach ($cross_unique_fields as $field_index => $field_name) - { - if (getArrayValue($object->FieldErrors, $field_name, 'pseudo') == 'required') continue; - - $check_fields = $cross_unique_fields; - unset($check_fields[$field_index]); - - foreach ($check_fields as $check_field) - { - if ($object->GetDBField($field_name) == $object->GetDBField($check_field)) - { - $object->SetError($check_field, 'unique'); - } - } - } - - if ($event->Special == 'import') - { - $this->exportOptions = $this->loadOptions($event); - - $automatic_fields = ($object->GetDBField('FieldTitles') == 1); - $object->setRequired('ExportColumns', !$automatic_fields); - $category_prefix = '__CATEGORY__'; - if ( $automatic_fields && ($this->exportOptions['SkipFirstRow']) ) { - $this->openFile($event); - $this->exportOptions['ExportColumns'] = $this->readRecord(); - - if (!$this->exportOptions['ExportColumns']) { - $this->exportOptions['ExportColumns'] = Array (); - } - - $this->closeFile(); - - // remove additional (non-parseble columns) - foreach ($this->exportOptions['ExportColumns'] as $field_index => $field_name) { - if (!$this->validateField($field_name, $object)) { - unset($this->exportOptions['ExportColumns'][$field_index]); - } - } - $category_prefix = ''; - } - - // 1. check, that we have column definitions - if (!$this->exportOptions['ExportColumns']) { - $object->setError('ExportColumns', 'required'); - $ret = false; - } - else { - // 1.1. check that all required fields are present in imported file - $missing_columns = Array(); - foreach ($object->Fields as $field_name => $field_options) { - if ($object->skipField($field_name)) continue; - if (getArrayValue($field_options, 'required') && !in_array($field_name, $this->exportOptions['ExportColumns']) ) { - $missing_columns[] = $field_name; - $object->setError('ExportColumns', 'required_fields_missing', 'la_error_RequiredColumnsMissing'); - $ret = false; - } - } - - if (!$ret && $this->Application->isDebugMode()) { - $this->Application->Debugger->appendHTML('Missing required for import/export:'); - $this->Application->Debugger->dumpVars($missing_columns); - } - } - - - // 2. check, that we have only mixed category field or only separated category fields - $category_found['mixed'] = false; - $category_found['separated'] = false; - - foreach ($this->exportOptions['ExportColumns'] as $import_field) { - if (preg_match('/^'.$category_prefix.'Category(Path|[0-9]+)/', $import_field, $rets)) { - $category_found[$rets[1] == 'Path' ? 'mixed' : 'separated'] = true; - } - } - if ($category_found['mixed'] && $category_found['separated']) { - $object->SetError('ExportColumns', 'unique_category', 'la_error_unique_category_field'); - $ret = false; - } - - // 3. check, that duplicates check fields are selected & present in imported fields - if ($this->exportOptions['ReplaceDuplicates']) { - if ($this->exportOptions['CheckDuplicatesMethod'] == 1) { - $check_fields = Array($object->IDField); - } - else { - $check_fields = $this->exportOptions['DuplicateCheckFields'] ? explode('|', substr($this->exportOptions['DuplicateCheckFields'], 1, -1)) : Array(); - $object =& $event->getObject(); - - $language_id = $this->Application->GetDefaultLanguageId(); - foreach ($check_fields as $index => $check_field) { - foreach ($object->Fields as $field_name => $field_options) { - if ($field_name == 'l'.$language_id.'_'.$check_field) { - $check_fields[$index] = 'l'.$language_id.'_'.$check_field; - break; - } - } - } - } - $this->exportOptions['DuplicateCheckFields'] = $check_fields; - - if (!$check_fields) { - $object->setError('CheckDuplicatesMethod', 'required'); - $ret = false; - } - else { - foreach ($check_fields as $check_field) { - $check_field = preg_replace('/^cust_(.*)/', 'Custom_\\1', $check_field); - if (!in_array($check_field, $this->exportOptions['ExportColumns'])) { - $object->setError('ExportColumns', 'required'); - $ret = false; - break; - } - } - } - } - $this->saveOptions($event); - } - - return $ret; - } - - /** - * Returns filename to read import data from - * - * @return string - */ - function getImportFilename() - { - if ($this->exportOptions['ImportSource'] == 1) - { - $ret = $this->exportOptions['ImportFilename']; // ['name']; commented by Kostja - } - else { - $ret = $this->exportOptions['ImportLocalFilename']; - } - return EXPORT_PATH.'/'.$ret; - } - - /** - * Returns filename to write export data to - * - * @return string - */ - function getExportFilename() - { - return EXPORT_PATH.'/'.$this->exportOptions['ExportFilename'].'.'.$this->getFileExtension(); - } - - /** - * Opens file required for export/import operations - * - * @param kEvent $event - */ - function openFile(&$event) - { - if ($event->Special == 'export') { - $write_mode = ($this->exportOptions['start_from'] == 0) ? 'w' : 'a'; - $this->filePointer = fopen($this->getExportFilename(), $write_mode); - } - else { - $this->filePointer = fopen($this->getImportFilename(), 'r'); - } - - // skip UTF-8 BOM Modifier - $first_chars = fread($this->filePointer, 3); - if (bin2hex($first_chars) != 'efbbbf') { - fseek($this->filePointer, 0); - } - } - - /** - * Closes opened file - * - */ - function closeFile() - { - fclose($this->filePointer); - } - - function getCustomSQL() - { - $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); - - $custom_sql = ''; - foreach ($this->customFields as $custom_id => $custom_name) { - $custom_sql .= 'custom_data.'.$ml_formatter->LangFieldName('cust_'.$custom_id).' AS cust_'.$custom_name.', '; - } - - return preg_replace('/(.*), /', '\\1', $custom_sql); - } - - function getPlainExportSQL($count_only = false) { - if ($count_only && isset($this->exportOptions['ForceCountSQL'])) { - $sql = $this->exportOptions['ForceCountSQL']; - } - elseif (!$count_only && isset($this->exportOptions['ForceSelectSQL'])) { - $sql = $this->exportOptions['ForceSelectSQL']; - } - else { - $items_list =& $this->Application->recallObject($this->curItem->Prefix.'.export-items-list', $this->curItem->Prefix.'_List'); - $items_list->SetPerPage(-1); - - if ($options['export_ids'] != '') { - $items_list->AddFilter('export_ids', $items_list->TableName.'.'.$items_list->IDField.' IN ('.implode(',',$options['export_ids']).')'); - } - - if ($count_only) { - $sql = $items_list->getCountSQL( $items_list->GetSelectSQL(true,false) ); - } - else { - $sql = $items_list->GetSelectSQL(); - } - } - - if (!$count_only) - { - $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP; - } -// else { -// $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql); -// } - - return $sql; - } - - function getExportSQL($count_only = false) - { - if (!$this->Application->getUnitOption($this->curItem->Prefix, 'CatalogItem')) { - return $this->GetPlainExportSQL($count_only); // in case this is not a CategoryItem - } - - if ($this->exportOptions['export_ids'] === false) - { - // get links from current category & all it's subcategories - $join_clauses = Array(); - - $custom_sql = $this->getCustomSQL(); - if ($custom_sql) { - $custom_table = $this->Application->getUnitOption($this->curItem->Prefix.'-cdata', 'TableName'); - $join_clauses[$custom_table.' custom_data'] = 'custom_data.ResourceId = item_table.ResourceId'; - } - - $join_clauses[TABLE_PREFIX.'CategoryItems ci'] = 'ci.ItemResourceId = item_table.ResourceId'; - $join_clauses[TABLE_PREFIX.'Category c'] = 'c.CategoryId = ci.CategoryId'; - - $sql = 'SELECT item_table.*, ci.CategoryId'.($custom_sql ? ', '.$custom_sql : '').' - FROM '.$this->curItem->TableName.' item_table'; - - foreach ($join_clauses as $table_name => $join_expression) { - $sql .= ' LEFT JOIN '.$table_name.' ON '.$join_expression; - } - $sql .= ' WHERE '; - - if ($this->exportOptions['export_cats_ids'][0] == 0) - { - $sql .= '1'; - } - else { - foreach ($this->exportOptions['export_cats_ids'] as $category_id) { - $sql .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR '; - } - $sql = preg_replace('/(.*) OR $/', '\\1', $sql); - } - - $sql .= ' ORDER BY ci.PrimaryCat DESC'; // NEW - } - else { - // get only selected links - $sql = 'SELECT item_table.*, '.$this->exportOptions['export_cats_ids'][0].' AS CategoryId - FROM '.$this->curItem->TableName.' item_table - WHERE '.$this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')'; - } - - if (!$count_only) - { - $sql .= ' LIMIT '.$this->exportOptions['start_from'].','.EXPORT_STEP; - } - else { - $sql = preg_replace("/^.*SELECT(.*?)FROM(?!_)/is", "SELECT COUNT(*) AS count FROM ", $sql); - } - - return $sql; - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function performExport(&$event) - { - $this->exportOptions = $this->loadOptions($event); - $this->exportFields = $this->exportOptions['ExportColumns']; - $this->curItem =& $event->getObject( Array('skip_autoload' => true) ); - $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); - $this->openFile($event); - - if ($this->exportOptions['start_from'] == 0) // first export step - { - if (!getArrayValue($this->exportOptions, 'IsBaseCategory')) { - $this->exportOptions['IsBaseCategory'] = 0; - } - - if ($this->exportOptions['IsBaseCategory'] ) { - $sql = 'SELECT ParentPath - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$this->Application->GetVar('m_cat_id'); - $parent_path = $this->Conn->GetOne($sql); - $parent_path = explode('|', substr($parent_path, 1, -1)); - if ($parent_path && $parent_path[0] == $this->Application->findModule('Name', 'Core', 'RootCat')) { - array_shift($parent_path); - } - - $this->exportOptions['BaseLevel'] = count($parent_path); // level to cut from other categories - } - - // 1. export field titles if required - if ($this->exportOptions['IncludeFieldTitles']) - { - $data_array = Array(); - foreach ($this->exportFields as $export_field) - { - $data_array = array_merge($data_array, $this->getFieldCaption($export_field)); - } - $this->writeRecord($data_array); - } - $this->exportOptions['total_records'] = $this->Conn->GetOne( $this->getExportSQL(true) ); - } - - // 2. export data - $records = $this->Conn->Query( $this->getExportSQL() ); - $records_exported = 0; - foreach ($records as $record_info) { - $this->curItem->Clear(); - $this->curItem->SetDBFieldsFromHash($record_info); - $this->setCurrentID(); - $this->curItem->raiseEvent('OnAfterItemLoad', $this->curItem->GetID() ); - - $data_array = Array(); - foreach ($this->exportFields as $export_field) - { - $data_array = array_merge($data_array, $this->getFieldValue($export_field) ); - } - $this->writeRecord($data_array); - $records_exported++; - } - $this->closeFile(); - - $this->exportOptions['start_from'] += $records_exported; - $this->saveOptions($event); - - return $this->exportOptions; - } - - function getItemFields() - { - // just in case dummy user selected automtic mode & moved columns too :( - return array_merge($this->curItem->Fields['AvailableColumns']['options'], $this->curItem->Fields['ExportColumns']['options']); - } - - /** - * Checks if field really belongs to importable field list - * - * @param string $field_name - * @param kCatDBItem $object - * @return bool - */ - function validateField($field_name, &$object) - { - // 1. convert custom field - $field_name = preg_replace('/^Custom_(.*)/', '__CUSTOM__\\1', $field_name); - - // 2. convert category field (mixed version & serparated version) - $field_name = preg_replace('/^Category(Path|[0-9]+)/', '__CATEGORY__Category\\1', $field_name); - - $valid_fields = $object->getPossibleExportColumns(); - return isset($valid_fields[$field_name]) || isset($valid_fields['__VIRTUAL__'.$field_name]); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function performImport(&$event) - { - if (!$this->exportOptions) { - // load import options in case if not previously loaded in verification function - $this->exportOptions = $this->loadOptions($event); - } - - $backup_category_id = $this->Application->GetVar('m_cat_id'); - $this->Application->SetVar('m_cat_id', (int)$this->Application->RecallVar('ImportCategory') ); - - $this->openFile($event); - - $bytes_imported = 0; - if ($this->exportOptions['start_from'] == 0) // first export step - { - // 1st time run - if ($this->exportOptions['SkipFirstRow']) { - $this->readRecord(); - $this->exportOptions['start_from'] = ftell($this->filePointer); - $bytes_imported = ftell($this->filePointer); - } - - $current_category_id = $this->Application->GetVar('m_cat_id'); - if ($current_category_id > 0) { - $sql = 'SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId = '.$current_category_id; - $this->exportOptions['ImportCategoryPath'] = $this->Conn->GetOne($sql); - } - else { - $this->exportOptions['ImportCategoryPath'] = ''; - } - $this->exportOptions['total_records'] = filesize($this->getImportFilename()); - } - else { - $this->loadCache(); - } - - $this->exportFields = $this->exportOptions['ExportColumns']; - $this->addToCache('category_parent_path', $this->Application->GetVar('m_cat_id'), $this->exportOptions['ImportCategoryPath']); - - // 2. import data - $this->dummyCategory =& $this->Application->recallObject('c.-tmpitem', 'c', Array('skip_autoload' => true)); - fseek($this->filePointer, $this->exportOptions['start_from']); - - $items_processed = 0; - while (($bytes_imported < IMPORT_CHUNK && $items_processed < IMPORT_STEP) && !feof($this->filePointer)) { - $data = $this->readRecord(); - if ($data) { - if ($this->exportOptions['ReplaceDuplicates']) { - // set fields used as keys for replace duplicates code - $this->resetImportObject($event, IMPORT_TEMP, $data); - } - - $this->processCurrentItem($event, $data); - } - $bytes_imported = ftell($this->filePointer) - $this->exportOptions['start_from']; - $items_processed++; - } - - $this->closeFile(); - $this->Application->SetVar('m_cat_id', $backup_category_id); - - $this->exportOptions['start_from'] += $bytes_imported; - $this->storeCache('new_ids'); - - $this->saveOptions($event); - - if ($this->exportOptions['start_from'] == $this->exportOptions['total_records']) { - $this->Conn->Query('TRUNCATE TABLE '.$this->cacheTable); - } - - return $this->exportOptions; - } - - function setCurrentID() - { - $this->curItem->setID( $this->curItem->GetDBField($this->curItem->IDField) ); - } - - function setFieldValue($field_index, $value) - { - if (empty($value)) { - $value = null; - } - - $field_name = getArrayValue($this->exportFields, $field_index); - if ($field_name == 'ResourceId') { - return false; - } - - if (substr($field_name, 0, 7) == 'Custom_') { - $field_name = 'cust_'.substr($field_name, 7); - $this->curItem->SetField($field_name, $value); - } - elseif ($field_name == 'CategoryPath' || $field_name == '__CATEGORY__CategoryPath') { - $this->curItem->CategoryPath = $value ? explode($this->exportOptions['CategorySeparator'], $value) : Array(); - } - elseif (substr($field_name, 0, 8) == 'Category') { - $this->curItem->CategoryPath[ (int)substr($field_name, 8) - 1 ] = $value; - } - elseif (substr($field_name, 0, 20) == '__CATEGORY__Category') { - $this->curItem->CategoryPath[ (int)substr($field_name, 20) ] = $value; - } - elseif (substr($field_name, 0, 11) == '__VIRTUAL__') { - $field_name = substr($field_name, 11); - $this->curItem->SetField($field_name, $value); - } - else { - $this->curItem->SetField($field_name, $value); - } - - $pseudo_error = getArrayValue($this->curItem->FieldErrors, $field_name, 'pseudo'); - if ($pseudo_error) { - $this->curItem->SetDBField($field_name, null); - unset($this->curItem->FieldErrors[$field_name]); - } - } - - function resetImportObject(&$event, $object_type, $record_data = null) - { - switch ($object_type) { - case IMPORT_TEMP: - $this->curItem =& $event->getObject( Array('skip_autoload' => true) ); - break; - - case IMPORT_LIVE: - $this->curItem =& $this->Application->recallObject($event->Prefix.'.-tmpitem'.$event->Special, $event->Prefix, Array('skip_autoload' => true)); - break; - } - $this->curItem->Clear(); - $this->customFields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); - - if (isset($record_data)) { - $this->setImportData($record_data); - } - } - - function setImportData($record_data) - { - foreach ($record_data as $field_index => $field_value) { - $this->setFieldValue($field_index, $field_value); - } - $this->setCurrentID(); - } - - - function getItemCategory() - { - static $lang_prefix = null; - $backup_category_id = $this->Application->GetVar('m_cat_id'); - - $category_id = $this->getFromCache('category_names', implode(':', $this->curItem->CategoryPath)); - if ($category_id) { - $this->Application->SetVar('m_cat_id', $category_id); - return $category_id; - } - - if (is_null($lang_prefix)) { - $lang_prefix = 'l'.$this->Application->GetVar('m_lang').'_'; - } - - foreach ($this->curItem->CategoryPath as $category_index => $category_name) { - if (!$category_name) continue; - $category_key = crc32( implode(':', array_slice($this->curItem->CategoryPath, 0, $category_index + 1) ) ); - - $category_id = $this->getFromCache('category_names', $category_key); - if ($category_id === false) { - // get parent category path to search only in it - $current_category_id = $this->Application->GetVar('m_cat_id'); -// $parent_path = $this->getParentPath($current_category_id); - - // get category id from database by name - $sql = 'SELECT CategoryId - FROM '.TABLE_PREFIX.'Category - WHERE ('.$lang_prefix.'Name = '.$this->Conn->qstr($category_name).') AND (ParentId = '.$current_category_id.')'; - $category_id = $this->Conn->GetOne($sql); - - if ($category_id === false) { - // category not in db -> create - $category_fields = Array( $lang_prefix.'Name' => $category_name, $lang_prefix.'Description' => $category_name, - 'Status' => STATUS_ACTIVE, 'ParentId' => $current_category_id, 'AutomaticFilename' => 1 - ); - $this->dummyCategory->SetDBFieldsFromHash($category_fields); - if ($this->dummyCategory->Create()) { - $category_id = $this->dummyCategory->GetID(); - $this->addToCache('category_parent_path', $category_id, $this->dummyCategory->GetDBField('ParentPath')); - $this->addToCache('category_names', $category_key, $category_id); - } - } - else { - $this->addToCache('category_names', $category_key, $category_id); - } - } - - if ($category_id) { - $this->Application->SetVar('m_cat_id', $category_id); - } - } - if (!$this->curItem->CategoryPath) { - $category_id = $backup_category_id; - } - - return $category_id; - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function processCurrentItem(&$event, $record_data) - { - $save_method = 'Create'; - $load_keys = Array(); - - // create/update categories - $backup_category_id = $this->Application->GetVar('m_cat_id'); - - // perform replace duplicates code - if ($this->exportOptions['ReplaceDuplicates']) { - // get replace keys first, then reset current item to empty one - $category_id = $this->getItemCategory(); - if ($this->exportOptions['CheckDuplicatesMethod'] == 1) { - if ($this->curItem->GetID()) { - $load_keys = Array($this->curItem->IDField => $this->curItem->GetID()); - } - } - else { - $key_fields = $this->exportOptions['DuplicateCheckFields']; - foreach ($key_fields as $key_field) { - $load_keys[$key_field] = $this->curItem->GetDBField($key_field); - } - } - - $this->resetImportObject($event, IMPORT_LIVE); - - if (count($load_keys)) { - $where_clause = ''; - foreach ($load_keys as $field_name => $field_value) { - if (preg_match('/^cust_(.*)/', $field_name, $regs)) { - $custom_id = array_search($regs[1], $this->customFields); - $field_name = 'l'.$this->Application->GetVar('m_lang').'_cust_'.$custom_id; - $where_clause .= '(custom_data.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND '; - } - else { - $where_clause .= '(item_table.`'.$field_name.'` = '.$this->Conn->qstr($field_value).') AND '; - } - - } - $where_clause = preg_replace('/(.*) AND $/', '\\1', $where_clause); - - $item_id = $this->getFromCache('new_ids', crc32($where_clause)); - if (!$item_id) { - if ($this->exportOptions['CheckDuplicatesMethod'] == 2) { - // by other fields - $parent_path = $this->getParentPath($category_id); - $where_clause = '(c.ParentPath LIKE "'.$parent_path.'%") AND '.$where_clause; - } - - $cdata_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName'); - $sql = 'SELECT '.$this->curItem->IDField.' - FROM '.$this->curItem->TableName.' item_table - LEFT JOIN '.$cdata_table.' custom_data ON custom_data.ResourceId = item_table.ResourceId - LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON ci.ItemResourceId = item_table.ResourceId - LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId - WHERE '.$where_clause; - $item_id = $this->Conn->GetOne($sql); - } - $save_method = $item_id && $this->curItem->Load($item_id) ? 'Update' : 'Create'; - if ($save_method == 'Update') { - // replace id from csv file with found id (only when ID is found in cvs file) - if (in_array($this->curItem->IDField, $this->exportFields)) { - $record_data[ array_search($this->curItem->IDField, $this->exportFields) ] = $item_id; - } - } - } - - $this->setImportData($record_data); - } - else { - $this->resetImportObject($event, IMPORT_LIVE, $record_data); - $category_id = $this->getItemCategory(); - } - - // create main record - if ($save_method == 'Create') { - $this->fillRequiredFields($this->false, $this->curItem, true); - } - -// $sql_start = getmicrotime(); - if (!$this->curItem->$save_method()) { - $this->Application->SetVar('m_cat_id', $backup_category_id); - return false; - } -// $sql_end = getmicrotime(); -// $this->saveLog('SQL ['.$save_method.'] Time: '.($sql_end - $sql_start).'s'); - - if ($load_keys && ($save_method == 'Create') && $this->exportOptions['ReplaceDuplicates']) { - // map new id to old id - $this->addToCache('new_ids', crc32($where_clause), $this->curItem->GetID() ); - } - - // assign item to categories - $this->curItem->assignToCategory($category_id, false); - - $this->Application->SetVar('m_cat_id', $backup_category_id); - return true; - } - - /*function saveLog($msg) - { - static $first_time = true; - - $fp = fopen(FULL_PATH.'/sqls.log', $first_time ? 'w' : 'a'); - fwrite($fp, $msg."\n"); - fclose($fp); - - $first_time = false; - }*/ - - /** - * Returns category parent path, if possible, then from cache - * - * @param int $category_id - * @return string - */ - function getParentPath($category_id) - { - $parent_path = $this->getFromCache('category_parent_path', $category_id); - if ($parent_path === false) { - $sql = 'SELECT ParentPath - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$category_id; - $parent_path = $this->Conn->GetOne($sql); - $this->addToCache('category_parent_path', $category_id, $parent_path); - } - return $parent_path; - } - - function getFileExtension() - { - return $this->exportOptions['ExportFormat'] == 1 ? 'csv' : 'xml'; - } - - function getLineSeparator($option = 'LineEndings') - { - return $this->exportOptions[$option] == 1 ? "\r\n" : "\n"; - } - - /** - * Returns field caption for any exported field - * - * @param string $field - * @return string - */ - function getFieldCaption($field) - { - if (substr($field, 0, 10) == '__CUSTOM__') - { - $ret = 'Custom_'.substr($field, 10, strlen($field) ); - } - elseif (substr($field, 0, 12) == '__CATEGORY__') - { - return $this->getCategoryTitle(); - } - elseif (substr($field, 0, 11) == '__VIRTUAL__') { - $ret = substr($field, 11); - } - else - { - $ret = $field; - } - - return Array($ret); - } - - /** - * Returns requested field value (including custom fields and category fields) - * - * @param string $field - * @return string - */ - function getFieldValue($field) - { - if (substr($field, 0, 10) == '__CUSTOM__') { - $field = 'cust_'.substr($field, 10, strlen($field)); - $ret = $this->curItem->GetField($field); - } - elseif (substr($field, 0, 12) == '__CATEGORY__') { - return $this->getCategoryPath(); - } - elseif (substr($field, 0, 11) == '__VIRTUAL__') { - $field = substr($field, 11); - $ret = $this->curItem->GetField($field); - } - else - { - $ret = $this->curItem->GetField($field); - } - - $ret = str_replace("\r\n", $this->getLineSeparator('LineEndingsInside'), $ret); - return Array($ret); - } - - /** - * Returns category field(-s) caption based on export mode - * - * @return string - */ - function getCategoryTitle() - { - // category path in separated fields - $category_count = $this->getMaxCategoryLevel(); - if ($this->exportOptions['CategoryFormat'] == 1) - { - // category path in one field - return $category_count ? Array('CategoryPath') : Array(); - } - else - { - $i = 0; - $ret = Array(); - while ($i < $category_count) { - $ret[] = 'Category'.($i + 1); - $i++; - } - return $ret; - } - } - - /** - * Returns category path in required format for current link - * - * @return string - */ - function getCategoryPath() - { - $category_id = $this->curItem->GetDBField('CategoryId'); - $category_path = $this->getFromCache('category_path', $category_id); - if (!$category_path) - { - $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); - $sql = 'SELECT '.$ml_formatter->LangFieldName('CachedNavbar').' - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$category_id; - $category_path = $this->Conn->GetOne($sql); - - $category_path = $category_path ? explode('&|&', $category_path) : Array(); - if ($category_path && strtolower($category_path[0]) == 'content') { - array_shift($category_path); - } - - if ($this->exportOptions['IsBaseCategory']) { - $i = $this->exportOptions['BaseLevel']; - while ($i > 0) { - array_shift($category_path); - $i--; - } - } - - $category_count = $this->getMaxCategoryLevel(); - if ($this->exportOptions['CategoryFormat'] == 1) { - // category path in single field - $category_path = $category_count ? Array( implode($this->exportOptions['CategorySeparator'], $category_path) ) : Array(); - } - else { - // category path in separated fields - $levels_used = count($category_path); - if ($levels_used < $category_count) - { - $i = 0; - while ($i < $category_count - $levels_used) { - $category_path[] = ''; - $i++; - } - } - } - $this->addToCache('category_path', $category_id, $category_path); - } - - return $category_path; - } - - /** - * Get maximal category deep level from links beeing exported - * - * @return int - */ - function getMaxCategoryLevel() - { - static $max_level = -1; - - if ($max_level != -1) - { - return $max_level; - } - - $sql = 'SELECT IF(c.CategoryId IS NULL, 0, MAX( LENGTH(c.ParentPath) - LENGTH( REPLACE(c.ParentPath, "|", "") ) - 1 )) - FROM '.$this->curItem->TableName.' item_table - LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON item_table.ResourceId = ci.ItemResourceId - LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId - WHERE (ci.PrimaryCat = 1) AND '; - - $where_clause = ''; - if ($this->exportOptions['export_ids'] === false) { - // get links from current category & all it's subcategories - if ($this->exportOptions['export_cats_ids'][0] == 0) { - $where_clause = 1; - } - else { - foreach ($this->exportOptions['export_cats_ids'] as $category_id) { - $where_clause .= '(c.ParentPath LIKE "%|'.$category_id.'|%") OR '; - } - $where_clause = preg_replace('/(.*) OR $/', '\\1', $where_clause); - } - } - else { - // get only selected links - $where_clause = $this->curItem->IDField.' IN ('.implode(',', $this->exportOptions['export_ids']).')'; - } - - $max_level = $this->Conn->GetOne($sql.'('.$where_clause.')'); - - if ($this->exportOptions['IsBaseCategory'] ) { - $max_level -= $this->exportOptions['BaseLevel']; - } - - return $max_level; - } - - /** - * Saves one record to export file - * - * @param Array $fields_hash - */ - function writeRecord($fields_hash) - { - fputcsv2($this->filePointer, $fields_hash, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy'], $this->getLineSeparator() ); - } - - function readRecord() - { - return fgetcsv($this->filePointer, 10000, $this->exportOptions['FieldsSeparatedBy'], $this->exportOptions['FieldsEnclosedBy']); - } - - function saveOptions(&$event, $options = null) - { - if (!isset($options)) { - $options = $this->exportOptions; - } - $this->Application->StoreVar($event->getPrefixSpecial().'_options', serialize($options) ); - } - - function loadOptions(&$event) - { - return unserialize($this->Application->RecallVar($event->getPrefixSpecial().'_options')); - } - - /** - * Sets correct available & export fields - * - * @param kEvent $event - */ - function prepareExportColumns(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - - if (!array_key_exists('ExportColumns', $object->Fields)) { - // import/export prefix was used (see kDBEventHandler::prepareObject) but object don't plan to be imported/exported - return ; - } - - $available_columns = Array(); - - if ($this->Application->getUnitOption($event->Prefix, 'CatalogItem')) { - // category field (mixed) - $available_columns['__CATEGORY__CategoryPath'] = 'CategoryPath'; - - if ($event->Special == 'import') { - // category field (separated fields) - $max_level = $this->Application->ConfigValue('MaxImportCategoryLevels'); - $i = 0; - while ($i < $max_level) { - $available_columns['__CATEGORY__Category'.($i + 1)] = 'Category'.($i + 1); - $i++; - } - } - } - - // db fields - foreach ($object->Fields as $field_name => $field_options) - { - if (!$object->skipField($field_name)) - { - $available_columns[$field_name] = $field_name.(getArrayValue($field_options, 'required') ? '*' : ''); - } - } - - $handler =& $this->Application->recallObject($event->Prefix.'_EventHandler'); - $available_columns = array_merge_recursive2($available_columns, $handler->getCustomExportColumns($event)); - - // custom fields - foreach ($object->customFields as $custom_id => $custom_name) - { - $available_columns['__CUSTOM__'.$custom_name] = $custom_name; - } - - // columns already in use - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if ($items_info) - { - list($item_id, $field_values) = each($items_info); - $export_keys = $field_values['ExportColumns']; - $export_keys = $export_keys ? explode('|', substr($export_keys, 1, -1) ) : Array(); - } - else { - $export_keys = Array(); - } - - $export_columns = Array(); - foreach ($export_keys as $field_key) - { - $field_name = $this->getExportField($field_key); - $export_columns[$field_key] = $field_name; - unset($available_columns[$field_key]); - } - - $options = $object->GetFieldOptions('ExportColumns'); - $options['options'] = $export_columns; - $object->SetFieldOptions('ExportColumns', $options); - - $options = $object->GetFieldOptions('AvailableColumns'); - $options['options'] = $available_columns; - $object->SetFieldOptions('AvailableColumns', $options); - - $this->updateImportFiles($event); - $this->PrepareExportPresets($event); - } - - function PrepareExportPresets(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - $options = $object->GetFieldOptions('ExportPresets'); - - $export_settings = $this->Application->RecallPersistentVar('export_settings'); - if (!$export_settings) return ; - $export_settings = unserialize($export_settings); - - if (!isset($export_settings[$event->Prefix])) return ; - - - $export_presets = array(''=>''); - foreach ($export_settings[$event->Prefix] as $key => $val) { - $export_presets[implode('|', $val['ExportColumns'])] = $key; - } - - $options['options'] = $export_presets; - $object->SetFieldOptions('ExportPresets', $options); - } - - function getExportField($field_key) - { - $prepends = Array('__CUSTOM__', '__CATEGORY__'); - foreach ($prepends as $prepend) - { - if (substr($field_key, 0, strlen($prepend) ) == $prepend) - { - $field_key = substr($field_key, strlen($prepend), strlen($field_key) ); - break; - } - } - return $field_key; - } - - /** - * Updates uploaded files list - * - * @param kEvent $event - */ - function updateImportFiles(&$event) - { - if ($event->Special != 'import') { - return false; - } - - $object =& $event->getObject(); - - $import_filenames = Array(); - - if ($folder_handle = opendir(EXPORT_PATH)) { - while (false !== ($file = readdir($folder_handle))) { - if (is_dir(EXPORT_PATH.'/'.$file) || substr($file, 0, 1) == '.' || strtolower($file) == 'cvs' || strtolower($file) == 'dummy' || filesize(EXPORT_PATH.'/'.$file) == 0) continue; - - $file_size = formatSize( filesize(EXPORT_PATH.'/'.$file) ); - $import_filenames[$file] = $file.' ('.$file_size.')'; - } - closedir($folder_handle); - } - - $options = $object->GetFieldOptions('ImportLocalFilename'); - $options['options'] = $import_filenames; - $object->SetFieldOptions('ImportLocalFilename', $options); - } - - /** - * Returns module folder - * - * @param kEvent $event - * @return string - */ - function getModuleFolder(&$event) - { - return $this->Application->getUnitOption($event->Prefix, 'ModuleFolder'); - } - - /** - * Export form validation & processing - * - * @param kEvent $event - */ - function OnExportBegin(&$event) - { - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if (!$items_info) - { - $items_info = unserialize( $this->Application->RecallVar($event->getPrefixSpecial().'_ItemsInfo') ); - $this->Application->SetVar($event->getPrefixSpecial(true), $items_info); - } - - list($item_id, $field_values) = each($items_info); - - $object =& $event->getObject( Array('skip_autoload' => true) ); - $object->SetFieldsFromHash($field_values); - $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!! - - $object->setID($item_id); - $this->setRequiredFields($event); - - $export_object =& $this->Application->recallObject('CatItemExportHelper'); - - // save export/import options - if ($event->Special == 'export') - { - $export_ids = $this->Application->RecallVar($event->Prefix.'_export_ids'); - $export_cats_ids = $this->Application->RecallVar($event->Prefix.'_export_cats_ids'); - - // used for multistep export - $field_values['export_ids'] = $export_ids ? explode(',', $export_ids) : false; - $field_values['export_cats_ids'] = $export_cats_ids ? explode(',', $export_cats_ids) : Array( $this->Application->GetVar('m_cat_id') ); - } - - $field_values['ExportColumns'] = $field_values['ExportColumns'] ? explode('|', substr($field_values['ExportColumns'], 1, -1) ) : Array(); - $field_values['start_from'] = 0; - - $this->Application->HandleEvent($nevent, $event->Prefix.':OnBeforeExportBegin', array('options'=>$field_values)); - $field_values = $nevent->getEventParam('options'); - - $export_object->saveOptions($event, $field_values); - - if( $export_object->verifyOptions($event) ) - { - if ($this->_getExportSavePreset($object)) { - $name = $object->GetDBField('ExportPresetName'); - - $export_settings = $this->Application->RecallPersistentVar('export_settings'); - $export_settings = $export_settings ? unserialize($export_settings) : array(); - $export_settings[$event->Prefix][$name] = $field_values; - $this->Application->StorePersistentVar('export_settings', serialize($export_settings)); - } - - $progress_t = $this->Application->RecallVar('export_progress_t'); - if ($progress_t) { - $this->Application->RemoveVar('export_progress_t'); - } - else { - $progress_t = $export_object->getModuleFolder($event).'/'.$event->Special.'_progress'; - } - $event->redirect = $progress_t; - - if ($event->Special == 'import') { - $import_category = (int)$this->Application->RecallVar('ImportCategory'); - - // in future could use module root category if import category will be unavailable :) - $event->SetRedirectParam('m_cat_id', $import_category); // for template permission checking - $this->Application->StoreVar('m_cat_id', $import_category); // for event permission checking - } - } - else - { - // make uploaded file local & change source selection - $filename = getArrayValue($field_values, 'ImportFilename'); - if ($filename) { - $export_object->updateImportFiles($event); - $object->SetDBField('ImportSource', 2); - $field_values['ImportSource'] = 2; - $object->SetDBField('ImportLocalFilename', $filename); - $field_values['ImportLocalFilename'] = $filename; - $export_object->saveOptions($event, $field_values); - } - - $event->status = erFAIL; - $event->redirect = false; - } - } - - /** - * Returns export save preset name, when used at all - * - * @param kDBItem $object - * @return string - */ - function _getExportSavePreset(&$object) - { - if (!array_key_exists('ExportSavePreset', $object->Fields)) { - return ''; - } - - return $object->GetDBField('ExportSavePreset'); - } - - /** - * set required fields based on import or export params - * - * @param kEvent $event - */ - function setRequiredFields(&$event) - { - $required_fields['common'] = Array('FieldsSeparatedBy', 'LineEndings', 'CategoryFormat'); - - $required_fields['export'] = Array('ExportFormat', 'ExportFilename','ExportColumns'); - - $object =& $event->getObject(); - if ($this->_getExportSavePreset($object)) { - $required_fields['export'][] = 'ExportPresetName'; - } - - $required_fields['import'] = Array('FieldTitles', 'ImportSource', 'CheckDuplicatesMethod'); // ImportFilename, ImportLocalFilename - - if ($event->Special == 'import') - { - $import_source = Array(1 => 'ImportFilename', 2 => 'ImportLocalFilename'); - $used_field = $import_source[ $object->GetDBField('ImportSource') ]; - - $required_fields[$event->Special][] = $used_field; - $object->Fields[$used_field]['error_field'] = 'ImportSource'; - - if ($object->GetDBField('FieldTitles') == 2) $required_fields[$event->Special][] = 'ExportColumns'; // manual field titles - } - - $required_fields = array_merge($required_fields['common'], $required_fields[$event->Special]); - foreach ($required_fields as $required_field) { - $object->setRequired($required_field, true); - } - } - - } \ No newline at end of file Index: branches/5.0.x/core/kernel/db/cat_dbitem.php =================================================================== diff -u -N -r12299 -r12343 --- branches/5.0.x/core/kernel/db/cat_dbitem.php (.../units/general/cat_dbitem.php) (revision 12299) +++ branches/5.0.x/core/kernel/db/cat_dbitem.php (.../kernel/db/cat_dbitem.php) (revision 12343) @@ -1,6 +1,6 @@ Array ('self' => 'add|edit|advanced:import'), - 'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'), - 'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'), - - 'OnCopy' => Array ('self' => true), - 'OnDownloadFile' => Array ('self' => 'view'), - 'OnCancelAction' => Array ('self' => true), - 'OnItemBuild' => Array ('self' => true), - 'OnMakeVote' => Array ('self' => true), - ); - - $this->permMapping = array_merge($this->permMapping, $permissions); - } - - /** - * Load item if id is available - * - * @param kEvent $event - */ - function LoadItem(&$event) - { - $object =& $event->getObject(); - $id = $this->getPassedID($event); - if ($object->Load($id)) { - $actions =& $this->Application->recallObject('kActions'); - $actions->Set($event->Prefix_Special.'_id', $object->GetID() ); - - $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing'); - if ($use_pending_editing && $event->Special != 'original') { - $this->Application->SetVar($event->Prefix.'.original_id', $object->GetDBField('OrgId')); - } - } - else { - $object->setID($id); - } - } - - /** - * Checks permissions of user - * - * @param kEvent $event - */ - function CheckPermission(&$event) - { - if (!$this->Application->IsAdmin()) { - if ($event->Name == 'OnSetSortingDirect') { - // allow sorting on front event without view permission - return true; - } - } - - if ($event->Name == 'OnExport') { - // save category_id before doing export - $this->Application->LinkVar('m_cat_id'); - } - - if (in_array($event->Name, $this->_getMassPermissionEvents())) { - $items = $this->_getPermissionCheckInfo($event); - - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - if (($event->Name == 'OnSave') && array_key_exists(0, $items)) { - // adding new item (ID = 0) - $perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0; - } - else { - // leave only items, that can be edited - $ids = Array (); - $check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission'; - foreach ($items as $item_id => $item_data) { - if ($perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0) { - $ids[] = $item_id; - } - } - - if (!$ids) { - // no items left for editing -> no permission - return $perm_helper->finalizePermissionCheck($event, false); - } - - $perm_value = true; - $event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method - } - - return $perm_helper->finalizePermissionCheck($event, $perm_value); - } - - $export_events = Array ('OnSaveSettings', 'OnResetSettings', 'OnExportBegin'); - if (in_array($event->Name, $export_events)) { - // when import settings before selecting target import category - return $this->Application->CheckPermission('in-portal:main_import.view'); - } - - if ($event->Name == 'OnProcessSelected') { - if ($this->Application->RecallVar('dst_field') == 'ImportCategory') { - // when selecting target import category - return $this->Application->CheckPermission('in-portal:main_import.view'); - } - } - - return parent::CheckPermission($event); - } - - /** - * Returns events, that require item-based (not just event-name based) permission check - * - * @return Array - */ - function _getMassPermissionEvents() - { - return Array ( - 'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove', - 'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown', - 'OnCut', - ); - } - - /** - * Returns category item IDs, that require permission checking - * - * @param kEvent $event - * @return string - */ - function _getPermissionCheckIDs(&$event) - { - if ($event->Name == 'OnSave') { - $selected_ids = implode(',', $this->getSelectedIDs($event, true)); - if (!$selected_ids) { - $selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave) - } - } - else { - // OnEdit, OnMassDelete events, when items are checked in grid - $selected_ids = implode(',', $this->StoreSelectedIDs($event)); - } - - return $selected_ids; - } - - /** - * Returns information used in permission checking - * - * @param kEvent $event - * @return Array - */ - function _getPermissionCheckInfo(&$event) - { - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - // when saving data from temp table to live table check by data from temp table - $item_ids = $this->_getPermissionCheckIDs($event); - $items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave'); - - if (!$items) { - // when item not present in temp table, then permission is not checked, because there are no data in db to check - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - list ($id, $fields_hash) = each($items_info); - - if (array_key_exists('CategoryId', $fields_hash)) { - $item_category = $fields_hash['CategoryId']; - } - else { - $item_category = $this->Application->GetVar('m_cat_id'); - } - - $items[$id] = Array ( - 'CreatedById' => $this->Application->RecallVar('use_id'), - 'CategoryId' => $item_category, - ); - } - - return $items; - } - - /** - * Add selected items to clipboard with mode = COPY (CLONE) - * - * @param kEvent $event - */ - function OnCopy(&$event) - { - $this->Application->RemoveVar('clipboard'); - $clipboard_helper =& $this->Application->recallObject('ClipboardHelper'); - $clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event)); - $this->clearSelectedIDs($event); - } - - /** - * Add selected items to clipboard with mode = CUT - * - * @param kEvent $event - */ - function OnCut(&$event) - { - $this->Application->RemoveVar('clipboard'); - $clipboard_helper =& $this->Application->recallObject('ClipboardHelper'); - $clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event)); - $this->clearSelectedIDs($event); - } - - /** - * Checks permission for OnPaste event - * - * @param kEvent $event - * @return bool - */ - function _checkPastePermission(&$event) - { - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - $category_id = $this->Application->GetVar('m_cat_id'); - if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) { - // no items left for editing -> no permission - return $perm_helper->finalizePermissionCheck($event, false); - } - - return true; - } - - /** - * Performs category item paste - * - * @param kEvent $event - */ - function OnPaste(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) { - return; - } - - $clipboard_data = $event->getEventParam('clipboard_data'); - - if (!$clipboard_data['cut'] && !$clipboard_data['copy']) { - return false; - } - - if ($clipboard_data['copy']) { - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - /* @var $temp kTempTablesHandler */ - - $this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone" - $temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']); - } - - if ($clipboard_data['cut']) { - $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix, Array('skip_autoload' => true)); - - foreach ($clipboard_data['cut'] as $id) { - $object->Load($id); - $object->MoveToCat(); - } - } - } - - /** - * Deletes all selected items. - * Automatically recurse into sub-items using temp handler, and deletes sub-items - * by calling its Delete method if sub-item has AutoDelete set to true in its config file - * - * @param kEvent $event - */ - function OnMassDelete(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $event->status=erSUCCESS; - - $ids = $this->StoreSelectedIDs($event); - - $to_delete = array(); - if ($recycle_bin = $this->Application->ConfigValue('RecycleBinFolder')) { - $rb =& $this->Application->recallObject('c.recycle', null, array('skip_autoload' => true)); - $rb->Load($recycle_bin); - $object =& $this->Application->recallObject($event->Prefix.'.recycleitem', null, Array ('skip_autoload' => true)); - foreach ($ids as $id) { - $object->Load($id); - if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $object->GetDBField('ParentPath'))) { - $to_delete[] = $id; - continue; - } - $object->MoveToCat($recycle_bin); - } - $ids = $to_delete; - } - - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - - $event->setEventParam('ids', $ids); - $this->customProcessing($event, 'before'); - $ids = $event->getEventParam('ids'); - - if($ids) - { - $temp->DeleteItems($event->Prefix, $event->Special, $ids); - } - $this->clearSelectedIDs($event); - } - - - /** - * Return type clauses for list bulding on front - * - * @param kEvent $event - * @return Array - */ - function getTypeClauses(&$event) - { - $types = $event->getEventParam('types'); - $types = $types ? explode(',', $types) : Array (); - - $except_types = $event->getEventParam('except'); - $except_types = $except_types ? explode(',', $except_types) : Array (); - - $type_clauses = Array(); - - $user_id = $this->Application->RecallVar('user_id'); - $owner_field = $this->getOwnerField($event->Prefix); - - $type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id; - $type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id; - $type_clauses['my_items']['having_filter'] = false; - - $type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'; - $type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'; - $type_clauses['pick']['having_filter'] = false; - - $type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1'; - $type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1'; - $type_clauses['hot']['having_filter'] = true; - - $type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1'; - $type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1'; - $type_clauses['pop']['having_filter'] = true; - - $type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1'; - $type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1'; - $type_clauses['new']['having_filter'] = true; - - $type_clauses['displayed']['include'] = ''; - $displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids'); - if ($displayed) { - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')'; - } - else { - $type_clauses['displayed']['except'] = ''; - } - $type_clauses['displayed']['having_filter'] = false; - - if (in_array('search', $types) || in_array('search', $except_types)) { - $event_mapping = Array( - 'simple' => 'OnSimpleSearch', - 'subsearch' => 'OnSubSearch', - 'advanced' => 'OnAdvancedSearch'); - if($this->Application->GetVar('INPORTAL_ON') && $this->Application->GetVar('Action') == 'm_simple_subsearch') - { - $type = 'subsearch'; - } - else - { - $type = $this->Application->GetVar('search_type') ? $this->Application->GetVar('search_type') : 'simple'; - } - - if($keywords = $event->getEventParam('keyword_string')) // processing keyword_string param of ListProducts tag - { - $this->Application->SetVar('keywords', $keywords); - $type = 'simple'; - } - $search_event = $event_mapping[$type]; - $this->$search_event($event); - - $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; - if ($this->Conn->Query($sql)) { - $search_res_ids = $this->Conn->GetCol('SELECT ResourceId FROM '.$search_table); - } - - if (isset($search_res_ids) && $search_res_ids) { - $type_clauses['search']['include'] = '%1$s.ResourceId IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')'; - $type_clauses['search']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')'; - } - else { - $type_clauses['search']['include'] = '0'; - $type_clauses['search']['except'] = '1'; - } - $type_clauses['search']['having_filter'] = false; - } - - if (in_array('related', $types) || in_array('related', $except_types)) { - - $related_to = $event->getEventParam('related_to'); - if (!$related_to) { - $related_prefix = $event->Prefix; - } - else { - $sql = 'SELECT Prefix - FROM '.TABLE_PREFIX.'ItemTypes - WHERE ItemName = '.$this->Conn->qstr($related_to); - $related_prefix = $this->Conn->GetOne($sql); - } - - $rel_table = $this->Application->getUnitOption('rel', 'TableName'); - $item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType'); - - if ($item_type == 0) { - trigger_error('ItemType not defined for prefix ' . $event->Prefix . '', E_USER_WARNING); - } - - // process case, then this list is called inside another list - $prefix_special = $event->getEventParam('PrefixSpecial'); - if (!$prefix_special) { - $prefix_special = $this->Application->Parser->GetParam('PrefixSpecial'); - } - - $id = false; - if ($prefix_special !== false) { - $processed_prefix = $this->Application->processPrefix($prefix_special); - if ($processed_prefix['prefix'] == $related_prefix) { - // printing related categories within list of items (not on details page) - $list =& $this->Application->recallObject($prefix_special); - /* @var $list kDBList */ - - $id = $list->GetID(); - } - } - - if ($id === false) { - // printing related categories for single item (possibly on details page) - if ($related_prefix == 'c') { - $id = $this->Application->GetVar('m_cat_id'); - } - else { - $id = $this->Application->GetVar($related_prefix . '_id'); - } - } - - $p_item =& $this->Application->recallObject($related_prefix.'.current', null, Array('skip_autoload' => true)); - $p_item->Load( (int)$id ); - - $p_resource_id = $p_item->GetDBField('ResourceId'); - - $sql = 'SELECT SourceId, TargetId FROM '.$rel_table.' - WHERE - (Enabled = 1) - AND ( - (Type = 0 AND SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.') - OR - (Type = 1 - AND ( - (SourceId = '.$p_resource_id.' AND TargetType = '.$item_type.') - OR - (TargetId = '.$p_resource_id.' AND SourceType = '.$item_type.') - ) - ) - )'; - - $related_ids_array = $this->Conn->Query($sql); - $related_ids = Array(); - - foreach ($related_ids_array as $key => $record) { - $related_ids[] = $record[ $record['SourceId'] == $p_resource_id ? 'TargetId' : 'SourceId' ]; - } - - if (count($related_ids) > 0) { - $type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).') AND PrimaryCat = 1'; - $type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).') AND PrimaryCat = 1'; - } - else { - $type_clauses['related']['include'] = '0'; - $type_clauses['related']['except'] = '1'; - } - $type_clauses['related']['having_filter'] = false; - } - - if (in_array('favorites', $types) || in_array('favorites', $except_types)) { - $sql = 'SELECT ResourceId - FROM '.$this->Application->getUnitOption('fav', 'TableName').' - WHERE PortalUserId = '.$this->Application->RecallVar('user_id'); - $favorite_ids = $this->Conn->GetCol($sql); - if ($favorite_ids) { - $type_clauses['favorites']['include'] = '%1$s.ResourceId IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1'; - $type_clauses['favorites']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $favorite_ids).') AND PrimaryCat = 1'; - } - else { - $type_clauses['favorites']['include'] = 0; - $type_clauses['favorites']['except'] = 1; - } - $type_clauses['favorites']['having_filter'] = false; - } - - return $type_clauses; - } - - /** - * Returns SQL clause, that will help to select only data from specified category & it's children - * - * @param int $category_id - * @return string - */ - function getCategoryLimitClause($category_id) - { - if (!$category_id) { - return false; - } - - $tree_indexes = $this->Application->getTreeIndex($category_id); - if (!$tree_indexes) { - // id of non-existing category was given - return 'FALSE'; - } - - return TABLE_PREFIX.'Category.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight']; - } - - /** - * Apply filters to list - * - * @param kEvent $event - */ - function SetCustomQuery(&$event) - { - parent::SetCustomQuery($event); - - $object =& $event->getObject(); - /* @var $object kDBList */ - - // add category filter if needed - if ($event->Special != 'showall' && $event->Special != 'user') { - if ($event->getEventParam('parent_cat_id') !== false) { - $parent_cat_id = $event->getEventParam('parent_cat_id'); - } - else { - $parent_cat_id = $this->Application->GetVar('c_id'); - if (!$parent_cat_id) { - $parent_cat_id = $this->Application->GetVar('m_cat_id'); - } - if (!$parent_cat_id) { - $parent_cat_id = 0; - } - } - - if ("$parent_cat_id" == '0') { - // replace "0" category with "Content" category id (this way template - $parent_cat_id = $this->Application->findModule('Name', 'Core', 'RootCat'); - } - - if ((string)$parent_cat_id != 'any') { - if ($event->getEventParam('recursive')) { - $filter_clause = $this->getCategoryLimitClause($parent_cat_id); - if ($filter_clause !== false) { - $object->addFilter('category_filter', $filter_clause); - } - - $object->addFilter('primary_filter', 'PrimaryCat = 1'); - } - else { - $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id ); - } - } - else { - $object->addFilter('primary_filter', 'PrimaryCat = 1'); - } - } - else { - $object->addFilter('primary_filter', 'PrimaryCat = 1'); - - // if using recycle bin don't show items from there - $recycle_bin = $this->Application->ConfigValue('RecycleBinFolder'); - if ($recycle_bin) { - $object->addFilter('recyclebin_filter', TABLE_PREFIX.'CategoryItems.CategoryId <> '.$recycle_bin); - } - } - - if ($event->Special == 'user') { - $editable_user = $this->Application->GetVar('u_id'); - $object->addFilter('owner_filter', '%1$s.'.$this->getOwnerField($event->Prefix).' = '.$editable_user); - } - - // add permission filter - if ($this->Application->RecallVar('user_id') == -1) { - // for "root" CATEGORY.VIEW permission is checked for items lists too - $view_perm = 1; - } - else { - // for any real user itemlist view permission is checked instead of CATEGORY.VIEW - $count_helper =& $this->Application->recallObject('CountHelper'); - /* @var $count_helper kCountHelper */ - - list ($view_perm, $view_filter) = $count_helper->GetPermissionClause($event->Prefix, 'perm'); - $object->addFilter('perm_filter2', $view_filter); - } - - $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm); - - - $types = $event->getEventParam('types'); - $this->applyItemStatusFilter($object, $types); - - $except_types = $event->getEventParam('except'); - $type_clauses = $this->getTypeClauses($event); - - // convert prepared type clauses into list filters - $includes_or_filter =& $this->Application->makeClass('kMultipleFilter'); - $includes_or_filter->setType(FLT_TYPE_OR); - - $excepts_and_filter =& $this->Application->makeClass('kMultipleFilter'); - $excepts_and_filter->setType(FLT_TYPE_AND); - - $includes_or_filter_h =& $this->Application->makeClass('kMultipleFilter'); - $includes_or_filter_h->setType(FLT_TYPE_OR); - - $excepts_and_filter_h =& $this->Application->makeClass('kMultipleFilter'); - $excepts_and_filter_h->setType(FLT_TYPE_AND); - - if ($types) { - $types_array = explode(',', $types); - for ($i = 0; $i < sizeof($types_array); $i++) { - $type = trim($types_array[$i]); - if (isset($type_clauses[$type])) { - if ($type_clauses[$type]['having_filter']) { - $includes_or_filter_h->removeFilter('filter_'.$type); - $includes_or_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['include']); - }else { - $includes_or_filter->removeFilter('filter_'.$type); - $includes_or_filter->addFilter('filter_'.$type, $type_clauses[$type]['include']); - } - } - } - } - - if ($except_types) { - $except_types_array = explode(',', $except_types); - for ($i = 0; $i < sizeof($except_types_array); $i++) { - $type = trim($except_types_array[$i]); - if (isset($type_clauses[$type])) { - if ($type_clauses[$type]['having_filter']) { - $excepts_and_filter_h->removeFilter('filter_'.$type); - $excepts_and_filter_h->addFilter('filter_'.$type, $type_clauses[$type]['except']); - }else { - $excepts_and_filter->removeFilter('filter_'.$type); - $excepts_and_filter->addFilter('filter_'.$type, $type_clauses[$type]['except']); - } - } - } - } - - /*if ( !$this->Application->IsAdmin() ) { - $object->addFilter('expire_filter', '%1$s.Expire IS NULL OR %1$s.Expire > UNIX_TIMESTAMP()'); - }*/ - - /*$list_type = $event->getEventParam('ListType'); - switch($list_type) - { - case 'favorites': - $fav_table = $this->Application->getUnitOption('fav','TableName'); - $user_id =& $this->Application->RecallVar('user_id'); - - $sql = 'SELECT DISTINCT f.ResourceId - FROM '.$fav_table.' f - LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId - WHERE f.PortalUserId = '.$user_id; - $ids = $this->Conn->GetCol($sql); - if(!$ids) $ids = Array(-1); - $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'); - $object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); - break; - case 'search': - $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - $sql = ' SELECT DISTINCT ResourceId - FROM '.$search_results_table.' - WHERE ItemType=11'; - $ids = $this->Conn->GetCol($sql); - if(!$ids) $ids = Array(-1); - $object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); - break; - } */ - - $object->addFilter('includes_filter', $includes_or_filter); - $object->addFilter('excepts_filter', $excepts_and_filter); - - $object->addFilter('includes_filter_h', $includes_or_filter_h, HAVING_FILTER); - $object->addFilter('excepts_filter_h', $excepts_and_filter_h, HAVING_FILTER); - } - - /** - * Adds filter that filters out items with non-required statuses - * - * @param kDBList $object - * @param string $types - */ - function applyItemStatusFilter(&$object, $types) - { - // Link1 (before modifications) [Status = 1, OrgId = NULL], Link2 (after modifications) [Status = -2, OrgId = Link1_ID] - $pending_editing = $this->Application->getUnitOption($object->Prefix, 'UsePendingEditing'); - - if ( !$this->Application->IsAdmin() ) { - $types = explode(',', $types); - if (in_array('my_items', $types)) { - $allow_statuses = Array (STATUS_ACTIVE, STATUS_PENDING, STATUS_PENDING_EDITING); - $object->addFilter('status_filter', '%1$s.Status IN ('.implode(',', $allow_statuses).')'); - - if ($pending_editing) { - $user_id = $this->Application->RecallVar('user_id'); - $this->applyPendingEditingFilter($object, $user_id); - } - } - else { - $object->addFilter('status_filter', '(%1$s.Status = ' . STATUS_ACTIVE . ') AND (' . TABLE_PREFIX . 'Category.Status = ' . STATUS_ACTIVE . ')'); - if ($pending_editing) { - // if category item uses pending editing abilities, then in no cases show pending copies on front - $object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL'); - } - } - } - else { - if ($pending_editing) { - $this->applyPendingEditingFilter($object); - } - } - } - - /** - * Adds filter, that removes live items if they have pending editing copies - * - * @param kDBList $object - * @param int $user_id - */ - function applyPendingEditingFilter(&$object, $user_id = null) - { - $sql = 'SELECT OrgId - FROM '.$object->TableName.' - WHERE Status = '.STATUS_PENDING_EDITING.' AND OrgId IS NOT NULL'; - - if (isset($user_id)) { - $owner_field = $this->getOwnerField($object->Prefix); - $sql .= ' AND '.$owner_field.' = '.$user_id; - } - - $pending_ids = $this->Conn->GetCol($sql); - if ($pending_ids) { - $object->addFilter('no_original_filter', '%1$s.'.$object->IDField.' NOT IN ('.implode(',', $pending_ids).')'); - } - } - - /** - * Adds calculates fields for item statuses - * - * @param kCatDBItem $object - * @param kEvent $event - */ - function prepareObject(&$object, &$event) - { - $this->prepareItemStatuses($event); - - $object->addCalculatedField('CachedNavbar', 'l'.$this->Application->GetVar('m_lang').'_CachedNavbar'); - - if ($event->Special == 'export' || $event->Special == 'import') { - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - $export_helper->prepareExportColumns($event); - } - } - - /** - * Creates calculated fields for all item statuses based on config settings - * - * @param kEvent $event - */ - function prepareItemStatuses(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - - $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); - if (!$property_map) { - return ; - } - - // new items - $object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2, - IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '. - $this->Application->ConfigValue($property_map['NewDays']). - '*3600*24), 1, 0), - %1$s.NewItem - )'); - - // hot items (cache updated every hour) - $sql = 'SELECT Data - FROM '.TABLE_PREFIX.'Cache - WHERE (VarName = "'.$property_map['HotLimit'].'") AND (Cached >'.(adodb_mktime() - 3600).')'; - $hot_limit = $this->Conn->GetOne($sql); - if ($hot_limit === false) { - $hot_limit = $this->CalculateHotLimit($event); - } - $object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2, - IF(%1$s.'.$property_map['ClickField'].' >= '.$hot_limit.', 1, 0), - %1$s.HotItem - )'); - - // popular items - $object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2, - IF(%1$s.CachedVotesQty >= '. - $this->Application->ConfigValue($property_map['MinPopVotes']). - ' AND %1$s.CachedRating >= '. - $this->Application->ConfigValue($property_map['MinPopRating']). - ', 1, 0), - %1$s.PopItem)'); - - } - - function CalculateHotLimit(&$event) - { - $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); - if (!$property_map) { - return; - } - $click_field = $property_map['ClickField']; - - $last_hot = $this->Application->ConfigValue($property_map['MaxHotNumber']) - 1; - $sql = 'SELECT '.$click_field.' FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' - ORDER BY '.$click_field.' DESC - LIMIT '.$last_hot.', 1'; - $res = $this->Conn->GetCol($sql); - $hot_limit = (double)array_shift($res); - $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("'.$property_map['HotLimit'].'", "'.$hot_limit.'", '.adodb_mktime().')'); - return $hot_limit; - - return 0; - } - - /** - * Moves item to preferred category, updates item hits - * - * @param kEvent $event - */ - function OnBeforeItemUpdate(&$event) - { - parent::OnBeforeItemUpdate($event); - - // update hits field - $property_map = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); - if ($property_map) { - $click_field = $property_map['ClickField']; - - $object =& $event->getObject(); - /* @var $object kCatDBItem */ - - if( $this->Application->IsAdmin() && ($this->Application->GetVar($click_field.'_original') !== false) && - floor($this->Application->GetVar($click_field.'_original')) != $object->GetDBField($click_field) ) - { - $sql = 'SELECT MAX('.$click_field.') FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' - WHERE FLOOR('.$click_field.') = '.$object->GetDBField($click_field); - $hits = ( $res = $this->Conn->GetOne($sql) ) ? $res + 0.000001 : $object->GetDBField($click_field); - $object->SetDBField($click_field, $hits); - } - } - - // change category - $target_category = $object->GetDBField('CategoryId'); - if ($object->GetOriginalField('CategoryId') != $target_category) { - $object->MoveToCat($target_category); - } - } - - /** - * Load price from temp table if product mode is temp table - * - * @param kEvent $event - */ - function OnAfterItemLoad(&$event) - { - $special = substr($event->Special, -6); - - $object =& $event->getObject(); - /* @var $object kCatDBItem */ - - if ($special == 'import' || $special == 'export') { - $image_data = $object->getPrimaryImageData(); - - if ($image_data) { - $thumbnail_image = $image_data[$image_data['LocalThumb'] ? 'ThumbPath' : 'ThumbUrl']; - if ($image_data['SameImages']) { - $full_image = ''; - } - else { - $full_image = $image_data[$image_data['LocalImage'] ? 'LocalPath' : 'Url']; - } - $object->SetDBField('ThumbnailImage', $thumbnail_image); - $object->SetDBField('FullImage', $full_image); - $object->SetDBField('ImageAlt', $image_data['AltName']); - } - } - - // substituiting pending status value for pending editing - if ($object->HasField('OrgId') && $object->GetDBField('OrgId') > 0 && $object->GetDBField('Status') == -2) { - $options = $object->Fields['Status']['options']; - foreach ($options as $key => $val) { - if ($key == 2) $key = -2; - $new_options[$key] = $val; - } - $object->Fields['Status']['options'] = $new_options; - } - - // linking existing images for item with virtual fields - $image_helper =& $this->Application->recallObject('ImageHelper'); - /* @var $image_helper ImageHelper */ - - $image_helper->LoadItemImages($object); - - // linking existing files for item with virtual fields - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - $file_helper->LoadItemFiles($object); - - // set item's additional categories to virtual field (used in editing) - $item_categories = $this->getItemCategories($object->GetDBField('ResourceId')); - $object->SetDBField('MoreCategories', $item_categories ? '|'.implode('|', $item_categories).'|' : ''); - } - - function OnAfterItemUpdate(&$event) - { - $this->CalculateHotLimit($event); - - if ( substr($event->Special, -6) == 'import') { - $this->setCustomExportColumns($event); - } - - if (!$this->Application->IsAdmin()) { - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $image_helper =& $this->Application->recallObject('ImageHelper'); - /* @var $image_helper ImageHelper */ - - // process image upload in virtual fields - $image_helper->SaveItemImages($object); - - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - // process file upload in virtual fields - $file_helper->SaveItemFiles($object); - - if ($event->Special != '-item') { - // don't touch categories during cloning - $this->processAdditionalCategories($object, 'update'); - } - } - } - - /** - * sets values for import process - * - * @param kEvent $event - */ - function OnAfterItemCreate(&$event) - { - if ( substr($event->Special, -6) == 'import') { - $this->setCustomExportColumns($event); - } - - if (!$this->Application->IsAdmin()) { - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $image_helper =& $this->Application->recallObject('ImageHelper'); - /* @var $image_helper ImageHelper */ - - // process image upload in virtual fields - $image_helper->SaveItemImages($object); - - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - // process file upload in virtual fields - $file_helper->SaveItemFiles($object); - - if ($event->Special != '-item') { - // don't touch categories during cloning - $this->processAdditionalCategories($object, 'create'); - } - } - } - - /** - * Make record to search log - * - * @param string $keywords - * @param int $search_type 0 - simple search, 1 - advanced search - */ - function saveToSearchLog($keywords, $search_type = 0) - { - // don't save keywords for each module separately, just one time - // static variable can't help here, because each module uses it's own class instance ! - if (!$this->Application->GetVar('search_logged')) { - $sql = 'UPDATE '.TABLE_PREFIX.'SearchLog - SET Indices = Indices + 1 - WHERE Keyword = '.$this->Conn->qstr($keywords).' AND SearchType = '.$search_type; // 0 - simple search, 1 - advanced search - $this->Conn->Query($sql); - if ($this->Conn->getAffectedRows() == 0) { - $fields_hash = Array('Keyword' => $keywords, 'Indices' => 1, 'SearchType' => $search_type); - $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SearchLog'); - } - - $this->Application->SetVar('search_logged', 1); - } - } - - /** - * Makes simple search for products - * based on keywords string - * - * @param kEvent $event - * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! - */ - function OnSimpleSearch(&$event) - { - if($this->Application->GetVar('INPORTAL_ON') && !($this->Application->GetVar('Action') == 'm_simple_search')) - { - return; - } - - $event->redirect = false; - $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - - $keywords = unhtmlentities( trim($this->Application->GetVar('keywords')) ); - - $query_object =& $this->Application->recallObject('HTTPQuery'); - $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; - - if(!isset($query_object->Get['keywords']) && - !isset($query_object->Post['keywords']) && - $this->Conn->Query($sql)) - { - return; // used when navigating by pages or changing sorting in search results - } - if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length')) - { - $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); - $this->Application->SetVar('keywords_too_short', 1); - return; // if no or too short keyword entered, doing nothing - } - - $this->Application->StoreVar('keywords', $keywords); - if (!$this->Application->GetVar('INPORTAL_ON')) { - // don't save search log, because in-portal already saved it - $this->saveToSearchLog($keywords, 0); // 0 - simple search, 1 - advanced search - } - - $keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_')); - - $event->setPseudoClass('_List'); - - $object =& $event->getObject(); - /* @var $object kDBList */ - - $this->Application->SetVar($event->getPrefixSpecial().'_Page', 1); - $lang = $this->Application->GetVar('m_lang'); - $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); - $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name'); - - $sql = 'SELECT * - FROM ' . $this->Application->getUnitOption('confs', 'TableName') . ' - WHERE ModuleName = ' . $this->Conn->qstr($module_name) . ' AND SimpleSearch = 1'; - $search_config = $this->Conn->Query($sql, 'FieldName'); - - $field_list = array_keys($search_config); - - $join_clauses = Array(); - - // field processing - $weight_sum = 0; - - $alias_counter = 0; - - $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); - if ($custom_fields) { - $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName'); - $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId'; - } - - // what field in search config becomes what field in sql (key - new field, value - old field (from searchconfig table)) - $search_config_map = Array(); - - foreach ($field_list as $key => $field) { - $options = $object->getFieldOptions($field); - $local_table = TABLE_PREFIX.$search_config[$field]['TableName']; - $weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause - - // processing multilingual fields - if (getArrayValue($options, 'formatter') == 'kMultiLanguage') { - $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field; - $field_list[$key] = 'l'.$lang.'_'.$field; - - if (!isset($search_config[$field]['ForeignField'])) { - $field_list[$key.'_primary'] = $local_table.'.'.$field_list[$key.'_primary']; - $search_config_map[ $field_list[$key.'_primary'] ] = $field; - } - } - - // processing fields from other tables - if ($foreign_field = $search_config[$field]['ForeignField']) { - $exploded = explode(':', $foreign_field, 2); - if ($exploded[0] == 'CALC') { - // ignoring having type clauses in simple search - unset($field_list[$key]); - continue; - } - else { - $multi_lingual = false; - if ($exploded[0] == 'MULTI') { - $multi_lingual = true; - $foreign_field = $exploded[1]; - } - - $exploded = explode('.', $foreign_field); // format: table.field_name - $foreign_table = TABLE_PREFIX.$exploded[0]; - - $alias_counter++; - $alias = 't'.$alias_counter; - - if ($multi_lingual) { - $field_list[$key] = $alias.'.'.'l'.$lang.'_'.$exploded[1]; - $field_list[$key.'_primary'] = 'l'.$this->Application->GetDefaultLanguageId().'_'.$field; - $search_config_map[ $field_list[$key] ] = $field; - $search_config_map[ $field_list[$key.'_primary'] ] = $field; - } - else { - $field_list[$key] = $alias.'.'.$exploded[1]; - $search_config_map[ $field_list[$key] ] = $field; - } - - $join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']); - $join_clause = str_replace('{LocalTable}', $items_table, $join_clause); - - $join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.' - ON '.$join_clause; - } - } - else { - // processing fields from local table - if ($search_config[$field]['CustomFieldId']) { - $local_table = 'custom_data'; - - // search by custom field value on current language - $custom_field_id = array_search($field_list[$key], $custom_fields); - $field_list[$key] = 'l'.$lang.'_cust_'.$custom_field_id; - - // search by custom field value on primary language - $field_list[$key.'_primary'] = $local_table.'.l'.$this->Application->GetDefaultLanguageId().'_cust_'.$custom_field_id; - $search_config_map[ $field_list[$key.'_primary'] ] = $field; - } - - $field_list[$key] = $local_table.'.'.$field_list[$key]; - $search_config_map[ $field_list[$key] ] = $field; - } - } - - // keyword string processing - $search_helper =& $this->Application->recallObject('SearchHelper'); - /* @var $search_helper kSearchHelper */ - - $where_clause = Array (); - foreach ($field_list as $field) { - if (preg_match('/^' . preg_quote($items_table, '/') . '\.(.*)/', $field, $regs)) { - // local real field - $filter_data = $search_helper->getSearchClause($object, $regs[1], $keywords, false); - if ($filter_data) { - $where_clause[] = $filter_data['value']; - } - } - elseif (preg_match('/^custom_data\.(.*)/', $field, $regs)) { - $custom_field_name = 'cust_' . $search_config_map[$field]; - $filter_data = $search_helper->getSearchClause($object, $custom_field_name, $keywords, false); - if ($filter_data) { - $where_clause[] = str_replace('`' . $custom_field_name . '`', $field, $filter_data['value']); - } - } - else { - $where_clause[] = $search_helper->buildWhereClause($keywords, Array ($field)); - } - } - - $where_clause = '(' . implode(') OR (', $where_clause) . ')'; - - $search_scope = $this->Application->GetVar('search_scope'); - if ($search_scope == 'category') { - $category_id = $this->Application->GetVar('m_cat_id'); - $category_filter = $this->getCategoryLimitClause($category_id); - if ($category_filter !== false) { - $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON '.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$items_table.'.ResourceId'; - $join_clauses[] = ' LEFT JOIN '.TABLE_PREFIX.'Category ON '.TABLE_PREFIX.'Category.CategoryId = '.TABLE_PREFIX.'CategoryItems.CategoryId'; - - $where_clause = '('.$this->getCategoryLimitClause($category_id).') AND '.$where_clause; - } - } - - $where_clause = $where_clause.' AND '.$items_table.'.Status=1'; - - if($this->Application->GetVar('Action') == 'm_simple_subsearch') // subsearch, In-portal - { - if( $event->getEventParam('ResultIds') ) - { - $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->specificParams['ResultIds']).')'; - } - } - if( $event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild' ) // subsearch, k4 - { - if( $event->MasterEvent->getEventParam('ResultIds') ) - { - $where_clause .= ' AND '.$items_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')'; - } - } - - // making relevance clause - $positive_words = $search_helper->getPositiveKeywords($keywords); - $this->Application->StoreVar('highlight_keywords', serialize($positive_words)); - $revelance_parts = Array(); - reset($search_config); - - foreach ($positive_words as $keyword_index => $positive_word) { - $positive_words[$keyword_index] = mysql_real_escape_string($positive_word); - } - - foreach ($field_list as $field) { - - if (!array_key_exists($field, $search_config_map)) { - $map_key = $search_config_map[$items_table . '.' . $field]; - } - else { - $map_key = $search_config_map[$field]; - } - - $config_elem = $search_config[ $map_key ]; - $weight = $config_elem['Priority']; - $revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)'; - foreach ($positive_words as $keyword) { - $revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$weight.', 0)'; - } - } - $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix'); - $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100; - $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100; - $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100; - $relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords; - if ($rel_pop && isset($object->Fields['Hits'])) { - $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop; - } - if ($rel_rating && isset($object->Fields['CachedRating'])) { - $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating; - } - - // building final search query - if (!$this->Application->GetVar('do_not_drop_search_table') && !$this->Application->GetVar('INPORTAL_ON')) { - $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event - $this->Application->SetVar('do_not_drop_search_table', true); - } - - - $search_table_exists = $this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"'); - if ($search_table_exists) { - $select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) '; - } - else { - $select_intro = 'CREATE TABLE '.$search_table.' AS '; - } - - $edpick_clause = $this->Application->getUnitOption($event->Prefix.'.EditorsPick', 'Fields') ? $items_table.'.EditorsPick' : '0'; - - - $sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance, - '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField').' AS ItemId, - '.$items_table.'.ResourceId, - '.$this->Application->getUnitOption($event->Prefix, 'ItemType').' AS ItemType, - '.$edpick_clause.' AS EdPick - FROM '.$object->TableName.' - '.implode(' ', $join_clauses).' - WHERE '.$where_clause.' - GROUP BY '.$items_table.'.'.$this->Application->getUnitOption($event->Prefix, 'IDField'); - - $res = $this->Conn->Query($sql); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnSubSearch(&$event) - { - $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; - if($this->Conn->Query($sql)) - { - $sql = 'SELECT DISTINCT ResourceId FROM '.$search_table; - $ids = $this->Conn->GetCol($sql); - } - $event->setEventParam('ResultIds', $ids); - $event->CallSubEvent('OnSimpleSearch'); - } - - /** - * Enter description here... - * - * @param kEvent $event - * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! - */ - function OnAdvancedSearch(&$event) - { - $query_object =& $this->Application->recallObject('HTTPQuery'); - if(!isset($query_object->Post['andor'])) - { - return; // used when navigating by pages or changing sorting in search results - } - - $this->Application->RemoveVar('keywords'); - $this->Application->RemoveVar('Search_Keywords'); - - $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name'); - - $sql = 'SELECT * - FROM '.$this->Application->getUnitOption('confs', 'TableName').' - WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)'; - $search_config = $this->Conn->Query($sql); - - $lang = $this->Application->GetVar('m_lang'); - $object =& $event->getObject(); - $object->SetPage(1); - - $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); - - $search_keywords = $this->Application->GetVar('value'); // will not be changed - - $keywords = $this->Application->GetVar('value'); // will be changed down there - $verbs = $this->Application->GetVar('verb'); - $glues = $this->Application->GetVar('andor'); - - $and_conditions = Array(); - $or_conditions = Array(); - $and_having_conditions = Array(); - $or_having_conditions = Array(); - $join_clauses = Array(); - $highlight_keywords = Array(); - $relevance_parts = Array(); - - $alias_counter = 0; - - $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); - if ($custom_fields) { - $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName'); - $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId'; - } - - $search_log = ''; - $weight_sum = 0; - - // processing fields and preparing conditions - foreach ($search_config as $record) { - $field = $record['FieldName']; - $join_clause = ''; - $condition_mode = 'WHERE'; - - // field processing - - $options = $object->getFieldOptions($field); - $local_table = TABLE_PREFIX.$record['TableName']; - $weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause - - // processing multilingual fields - if (getArrayValue($options, 'formatter') == 'kMultiLanguage') { - $field_name = 'l'.$lang.'_'.$field; - } - else { - $field_name = $field; - } - - // processing fields from other tables - if ($foreign_field = $record['ForeignField']) { - $exploded = explode(':', $foreign_field, 2); - if($exploded[0] == 'CALC') - { - $user_groups = $this->Application->RecallVar('UserGroups'); - $field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]); - $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']); - $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause); - $join_clause = ' LEFT JOIN '.$join_clause; - - $condition_mode = 'HAVING'; - } - else { - $exploded = explode('.', $foreign_field); - $foreign_table = TABLE_PREFIX.$exploded[0]; - - if($record['CustomFieldId']) { - $exploded[1] = 'l'.$lang.'_'.$exploded[1]; - } - - $alias_counter++; - $alias = 't'.$alias_counter; - - $field_name = $alias.'.'.$exploded[1]; - $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']); - $join_clause = str_replace('{LocalTable}', $items_table, $join_clause); - - if($record['CustomFieldId']) - { - $join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId']; - } - $join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.' - ON '.$join_clause; - } - } - else - { - // processing fields from local table - if ($record['CustomFieldId']) { - $local_table = 'custom_data'; - $field_name = 'l'.$lang.'_cust_'.array_search($field_name, $custom_fields); - } - - $field_name = $local_table.'.'.$field_name; - } - - $condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords); - if ($record['CustomFieldId'] && strlen($condition)) { - // search in primary value of custom field + value in current language - $field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields); - $primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords); - $condition = '('.$condition.' OR '.$primary_condition.')'; - } - - if ($condition) { - if ($join_clause) { - $join_clauses[] = $join_clause; - } - - $relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)'; - if ($glues[$field] == 1) { // and - if ($condition_mode == 'WHERE') { - $and_conditions[] = $condition; - } - else { - $and_having_conditions[] = $condition; - } - } - else { // or - if ($condition_mode == 'WHERE') { - $or_conditions[] = $condition; - } - else { - $or_having_conditions[] = $condition; - } - } - - // create search log record - $search_log_data = Array('search_config' => $record, 'verb' => getArrayValue($verbs, $field), 'value' => ($record['FieldType'] == 'range') ? $search_keywords[$field.'_from'].'|'.$search_keywords[$field.'_to'] : $search_keywords[$field]); - $search_log[] = $this->Application->Phrase('la_Field').' "'.$this->getHuman('Field', $search_log_data).'" '.$this->getHuman('Verb', $search_log_data).' '.$this->Application->Phrase('la_Value').' '.$this->getHuman('Value', $search_log_data).' '.$this->Application->Phrase($glues[$field] == 1 ? 'lu_And' : 'lu_Or'); - } - } - - if ($search_log) { - $search_log = implode('
', $search_log); - $search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log); - $this->saveToSearchLog($search_log, 1); // advanced search - } - - $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords)); - - // making relevance clause - if($relevance_parts) - { - $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix'); - $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100; - $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100; - $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100; - $relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords; - $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop; - $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating; - } - else - { - $relevance_clause = '0'; - } - - // building having clause - if($or_having_conditions) - { - $and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')'; - } - $having_clause = implode(' AND ', $and_having_conditions); - $having_clause = $having_clause ? ' HAVING '.$having_clause : ''; - - // building where clause - if($or_conditions) - { - $and_conditions[] = '('.implode(' OR ', $or_conditions).')'; - } -// $and_conditions[] = $items_table.'.Status = 1'; - $where_clause = implode(' AND ', $and_conditions); - if(!$where_clause) - { - if($having_clause) - { - $where_clause = '1'; - } - else - { - $where_clause = '0'; - $this->Application->SetVar('adv_search_error', 1); - } - } - $where_clause .= ' AND '.$items_table.'.Status = 1'; - - // building final search query - $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - - $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); - - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); - $pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0'; - - $sql = ' CREATE TABLE '.$search_table.' - SELECT '.$relevance_clause.' AS Relevance, - '.$items_table.'.'.$id_field.' AS ItemId, - '.$items_table.'.ResourceId AS ResourceId, - 11 AS ItemType, - '.$pick_field.' AS EdPick - FROM '.$items_table.' - '.implode(' ', $join_clauses).' - WHERE '.$where_clause.' - GROUP BY '.$items_table.'.'.$id_field. - $having_clause; - - $res = $this->Conn->Query($sql); - } - - function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords) - { - $field = $record['FieldName']; - - $condition_patterns = Array ( - 'any' => '%s LIKE %s', - 'contains' => '%s LIKE %s', - 'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)', - 'is' => '%s = %s', - 'isnot' => '(%1$s != %2$s OR %1$s IS NULL)' - ); - - $condition = ''; - switch ($record['FieldType']) { - case 'select': - $keywords[$field] = unhtmlentities( $keywords[$field] ); - if ($keywords[$field]) { - $condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] )); - } - break; - - case 'multiselect': - $keywords[$field] = unhtmlentities( $keywords[$field] ); - if ($keywords[$field]) { - $condition = Array (); - $values = explode('|', substr($keywords[$field], 1, -1)); - foreach ($values as $selected_value) { - $condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%')); - } - $condition = '('.implode(' OR ', $condition).')'; - } - break; - - case 'text': - $keywords[$field] = unhtmlentities( $keywords[$field] ); - - if (mb_strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) { - $highlight_keywords[] = $keywords[$field]; - if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) { - $keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%'; - } - $condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] )); - } - break; - - case 'boolean': - if ($keywords[$field] != -1) { - $property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings'); - $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); - - switch ($field) { - case 'HotItem': - $hot_limit_var = getArrayValue($property_mappings, 'HotLimit'); - if ($hot_limit_var) { - $sql = 'SELECT Data - FROM '.TABLE_PREFIX.'Cache - WHERE VarName = "'.$hot_limit_var.'"'; - $hot_limit = (int)$this->Conn->GetOne($sql); - - $condition = 'IF('.$items_table.'.HotItem = 2, - IF('.$items_table.'.Hits >= '. - $hot_limit. - ', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field]; - } - break; - - case 'PopItem': - $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop'); - $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop'); - if ($votes2pop_var && $rating2pop_var) { - $condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '. - $this->Application->ConfigValue($votes2pop_var). - ' AND '.$items_table.'.CachedRating >= '. - $this->Application->ConfigValue($rating2pop_var). - ', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field]; - } - break; - - case 'NewItem': - $new_days_var = getArrayValue($property_mappings, 'NewDays'); - if ($new_days_var) { - $condition = 'IF('.$items_table.'.NewItem = 2, - IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '. - $this->Application->ConfigValue($new_days_var). - '*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field]; - } - break; - - case 'EditorsPick': - $condition = $items_table.'.EditorsPick = '.$keywords[$field]; - break; - } - } - break; - - case 'range': - $range_conditions = Array(); - if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) { - $range_conditions[] = $field_name.' >= '.$keywords[$field.'_from']; - } - if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) { - $range_conditions[] = $field_name.' <= '.$keywords[$field.'_to']; - } - if ($range_conditions) { - $condition = implode(' AND ', $range_conditions); - } - break; - - case 'date': - if ($keywords[$field]) { - if (in_array($keywords[$field], Array('today', 'yesterday'))) { - $current_time = getdate(); - $day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']); - $time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400)); - $min_time = $time_mapping[$keywords[$field]]; - } - else { - $time_mapping = Array ( - 'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000, - 'last_6_months' => 15768000, 'last_year' => 31536000, - ); - $min_time = adodb_mktime() - $time_mapping[$keywords[$field]]; - } - $condition = $field_name.' > '.$min_time; - } - break; - } - - return $condition; - } - - function getHuman($type, $search_data) - { - $type = ucfirst(strtolower($type)); - extract($search_data); - - switch ($type) { - case 'Field': - return $this->Application->Phrase($search_config['DisplayName']); - break; - - case 'Verb': - return $verb ? $this->Application->Phrase('lu_advsearch_'.$verb) : ''; - break; - - case 'Value': - switch ($search_config['FieldType']) { - case 'date': - $values = Array(0 => 'lu_comm_Any', 'today' => 'lu_comm_Today', - 'yesterday' => 'lu_comm_Yesterday', 'last_week' => 'lu_comm_LastWeek', - 'last_month' => 'lu_comm_LastMonth', 'last_3_months' => 'lu_comm_Last3Months', - 'last_6_months' => 'lu_comm_Last6Months', 'last_year' => 'lu_comm_LastYear'); - $ret = $this->Application->Phrase($values[$value]); - break; - - case 'range': - $value = explode('|', $value); - return $this->Application->Phrase('lu_comm_From').' "'.$value[0].'" '.$this->Application->Phrase('lu_comm_To').' "'.$value[1].'"'; - break; - - case 'boolean': - $values = Array(1 => 'lu_comm_Yes', 0 => 'lu_comm_No', -1 => 'lu_comm_Both'); - $ret = $this->Application->Phrase($values[$value]); - break; - - default: - $ret = $value; - break; - - } - return '"'.$ret.'"'; - break; - } - } - - - - /** - * Set's correct page for list - * based on data provided with event - * - * @param kEvent $event - * @access private - * @see OnListBuild - */ - function SetPagination(&$event) - { - // get PerPage (forced -> session -> config -> 10) - $per_page = $this->getPerPage($event); - - - $object =& $event->getObject(); - $object->SetPerPage($per_page); - $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1); - - $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page'); - if (!$page) - { - $page = $this->Application->GetVar($event->getPrefixSpecial(true).'_Page'); - } - - if (!$page) - { - if( $this->Application->RewriteURLs() ) - { - $page = $this->Application->GetVar($event->Prefix.'_Page'); - if (!$page) - { - $page = $this->Application->RecallVar($event->Prefix.'_Page'); - } - if($page) $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page); - } - else - { - $page = $this->Application->RecallVar($event->getPrefixSpecial().'_Page'); - } - } - else { - $this->Application->StoreVar($event->getPrefixSpecial().'_Page', $page); - } - - if( !$event->getEventParam('skip_counting') ) - { - $pages = $object->GetTotalPages(); - if($page > $pages) - { - $this->Application->StoreVar($event->getPrefixSpecial().'_Page', 1); - $page = 1; - } - } - - /*$cur_per_page = $per_page; - $per_page = $event->getEventParam('per_page'); - if ($per_page == 'list_next') { - - $cur_page = $page; - - $object =& $this->Application->recallObject($event->Prefix); - $object->SetPerPage(1); - $cur_item_index = $object->CurrentIndex; - - $page = ($cur_page-1) * $cur_per_page + $cur_item_index + 1; - $object->SetPerPage(1); - }*/ - - $object->SetPage($page); - } - -/* === RELATED TO IMPORT/EXPORT: BEGIN === */ - - /** - * Shows export dialog - * - * @param kEvent $event - */ - function OnExport(&$event) - { - $selected_ids = $this->StoreSelectedIDs($event); - if (implode(',', $selected_ids) == '') { - // K4 fix when no ids found bad selected ids array is formed - $selected_ids = false; - } - - $selected_cats_ids = $this->Application->GetVar('export_categories'); - - $this->Application->StoreVar($event->Prefix.'_export_ids', $selected_ids ? implode(',', $selected_ids) : '' ); - $this->Application->StoreVar($event->Prefix.'_export_cats_ids', $selected_cats_ids); - - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - /* @var $export_helper kCatDBItemExportHelper */ - - $redirect_params = Array ( - $this->Prefix.'.export_event' => 'OnNew', - 'pass' => 'all,'.$this->Prefix.'.export' - ); - - $event->setRedirectParams($redirect_params); - } - - /** - * Performs each export step & displays progress percent - * - * @param kEvent $event - */ - function OnExportProgress(&$event) - { - $export_object =& $this->Application->recallObject('CatItemExportHelper'); - /* @var $export_object kCatDBItemExportHelper */ - - $event = new kEvent($event->getPrefixSpecial().':OnDummy'); - - $action_method = 'perform'.ucfirst($event->Special); - $field_values = $export_object->$action_method($event); - - // finish code is done from JS now - if ($field_values['start_from'] == $field_values['total_records']) { - if ($event->Special == 'import') { - $this->Application->StoreVar('PermCache_UpdateRequired', 1); - $url_params = Array( - 't' => 'catalog/catalog', - 'm_cat_id' => $this->Application->RecallVar('ImportCategory'), - 'anchor' => 'tab-' . $event->Prefix, - ); - $this->Application->EventManager->openerStackChange($url_params); - - $event->SetRedirectParam('opener', 'u'); - } - elseif ($event->Special == 'export') { - $event->redirect = $this->Application->getUnitOption($event->Prefix, 'ModuleFolder') . '/' . $event->Special . '_finish'; - $event->SetRedirectParam('pass', 'all'); - } - - return ; - } - - $export_options = $export_object->loadOptions($event); - echo $export_options['start_from'] * 100 / $export_options['total_records']; - - $event->status = erSTOP; - } - - /** - * Returns specific to each item type columns only - * - * @param kEvent $event - * @return Array - */ - function getCustomExportColumns(&$event) - { - return Array( '__VIRTUAL__ThumbnailImage' => 'ThumbnailImage', - '__VIRTUAL__FullImage' => 'FullImage', - '__VIRTUAL__ImageAlt' => 'ImageAlt'); - } - - /** - * Sets non standart virtual fields (e.g. to other tables) - * - * @param kEvent $event - */ - function setCustomExportColumns(&$event) - { - $this->restorePrimaryImage($event); - } - - /** - * Create/Update primary image record in info found in imported data - * - * @param kEvent $event - */ - function restorePrimaryImage(&$event) - { - $object =& $event->getObject(); - - $has_image_info = $object->GetDBField('ImageAlt') && ($object->GetDBField('ThumbnailImage') || $object->GetDBField('FullImage')); - if (!$has_image_info) { - return false; - } - - $image_data = $object->getPrimaryImageData(); - - $image =& $this->Application->recallObject('img', null, Array('skip_autoload' => true)); - if ($image_data) { - $image->Load($image_data['ImageId']); - } - else { - $image->Clear(); - $image->SetDBField('Name', 'main'); - $image->SetDBField('DefaultImg', 1); - $image->SetDBField('ResourceId', $object->GetDBField('ResourceId')); - } - - $image->SetDBField('AltName', $object->GetDBField('ImageAlt')); - - if ($object->GetDBField('ThumbnailImage')) { - $thumbnail_field = $this->isURL( $object->GetDBField('ThumbnailImage') ) ? 'ThumbUrl' : 'ThumbPath'; - $image->SetDBField($thumbnail_field, $object->GetDBField('ThumbnailImage') ); - $image->SetDBField('LocalThumb', $thumbnail_field == 'ThumbPath' ? 1 : 0); - } - - if (!$object->GetDBField('FullImage')) { - $image->SetDBField('SameImages', 1); - } - else { - $image->SetDBField('SameImages', 0); - $full_field = $this->isURL( $object->GetDBField('FullImage') ) ? 'Url' : 'LocalPath'; - $image->SetDBField($full_field, $object->GetDBField('FullImage') ); - $image->SetDBField('LocalImage', $full_field == 'LocalPath' ? 1 : 0); - } - - if ($image->isLoaded()) { - $image->Update(); - } - else { - $image->Create(); - } - } - - function isURL($path) - { - return preg_match('#(http|https)://(.*)#', $path); - } - - /** - * Prepares item for import/export operations - * - * @param kEvent $event - */ - function OnNew(&$event) - { - parent::OnNew($event); - - if ($event->Special == 'import' || $event->Special == 'export') { - $export_helper =& $this->Application->recallObject('CatItemExportHelper'); - $export_helper->setRequiredFields($event); - } - } - - /** - * Process items selected in item_selector - * - * @param kEvent $event - */ - function OnProcessSelected(&$event) - { - $selected_ids = $this->Application->GetVar('selected_ids'); - - $dst_field = $this->Application->RecallVar('dst_field'); - - if ($dst_field == 'ItemCategory') { - // Item Edit -> Categories Tab -> New Categories - $object =& $event->getObject(); - $category_ids = explode(',', $selected_ids['c']); - foreach ($category_ids as $category_id) { - $object->assignToCategory($category_id); - } - } - - if ($dst_field == 'ImportCategory') { - // Tools -> Import -> Item Import -> Select Import Category - $this->Application->StoreVar('ImportCategory', $selected_ids['c']); -// $this->Application->StoreVar($event->getPrefixSpecial().'_ForceNotValid', 1); // not to loose import/export values on form refresh - - $url_params = Array ( - $event->getPrefixSpecial() . '_id' => 0, - $event->getPrefixSpecial() . '_event' => 'OnExportBegin', -// 'm_opener' => 's', - ); - - $this->Application->EventManager->openerStackChange($url_params); - } - - $event->SetRedirectParam('opener', 'u'); - } - - /** - * Saves Import/Export settings to session - * - * @param kEvent $event - */ - function OnSaveSettings(&$event) - { - $event->redirect = false; - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if ($items_info) { - list($id, $field_values) = each($items_info); - - $object =& $event->getObject( Array('skip_autoload' => true) ); - $object->SetFieldsFromHash($field_values); - $field_values['ImportFilename'] = $object->GetDBField('ImportFilename'); //if upload formatter has renamed the file during moving !!! - $field_values['ImportSource'] = 2; - $field_values['ImportLocalFilename'] = $object->GetDBField('ImportFilename'); - $items_info[$id] = $field_values; - - $this->Application->StoreVar($event->getPrefixSpecial().'_ItemsInfo', serialize($items_info)); - } - } - - /** - * Saves Import/Export settings to session - * - * @param kEvent $event - */ - function OnResetSettings(&$event) - { - $this->Application->StoreVar('ImportCategory', $this->Application->findModule('Name', 'Core', 'RootCat')); - } - - function OnCancelAction(&$event) - { - $event->redirect_params = Array('pass' => 'all,'.$event->GetPrefixSpecial()); - $event->redirect = $this->Application->GetVar('cancel_template'); - } - -/* === RELATED TO IMPORT/EXPORT: END === */ - - /** - * Stores item's owner login into separate field together with id - * - * @param kEvent $event - * @param string $id_field - * @param string $cached_field - */ - function cacheItemOwner(&$event, $id_field, $cached_field) - { - $object =& $event->getObject(); - - $user_id = $object->GetDBField($id_field); - $options = $object->GetFieldOptions($id_field); - if (isset($options['options'][$user_id])) { - $object->SetDBField($cached_field, $options['options'][$user_id]); - } - else { - $id_field = $this->Application->getUnitOption('u', 'IDField'); - $table_name = $this->Application->getUnitOption('u', 'TableName'); - - $sql = 'SELECT Login - FROM '.$table_name.' - WHERE '.$id_field.' = '.$user_id; - $object->SetDBField($cached_field, $this->Conn->GetOne($sql)); - } - } - - /** - * Saves item beeing edited into temp table - * - * @param kEvent $event - */ - function OnPreSave(&$event) - { - parent::OnPreSave($event); - $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing'); - if ($event->status == erSUCCESS && $use_pending_editing) { - // decision: clone or not clone - - $object =& $event->getObject(); - if ($object->GetID() == 0 || $object->GetDBField('OrgId') > 0) { - // new items or cloned items shouldn't be cloned again - return true; - } - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - $owner_field = $this->getOwnerField($event->Prefix); - - if ($perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix) == 2) { - - // 1. clone original item - $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($object->GetID()), null, null, null, true); - $ci_table = $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems'); - - // 2. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem - $sql = 'SELECT ResourceId - FROM '.$object->TableName.' - WHERE '.$object->IDField.' = '.$cloned_ids[0]; - $clone_resource_id = $this->Conn->GetOne($sql); - - $sql = 'DELETE FROM '.$ci_table.' - WHERE ItemResourceId = '.$clone_resource_id.' AND PrimaryCat = 1'; - $this->Conn->Query($sql); - - // 3. copy main item categoryitems to cloned item - $sql = ' INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename) - SELECT CategoryId, '.$clone_resource_id.' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename - FROM '.$ci_table.' - WHERE ItemResourceId = '.$object->GetDBField('ResourceId'); - $this->Conn->Query($sql); - - // 4. put cloned id to OrgId field of item being cloned - $sql = 'UPDATE '.$object->TableName.' - SET OrgId = '.$object->GetID().' - WHERE '.$object->IDField.' = '.$cloned_ids[0]; - $this->Conn->Query($sql); - - // 5. substitute id of item being cloned with clone id - $this->Application->SetVar($event->getPrefixSpecial().'_id', $cloned_ids[0]); - - $selected_ids = $this->getSelectedIDs($event, true); - $selected_ids[ array_search($object->GetID(), $selected_ids) ] = $cloned_ids[0]; - $this->StoreSelectedIDs($event, $selected_ids); - - // 6. delete original item from temp table - $temp_handler->DeleteItems($event->Prefix, $event->Special, Array($object->GetID())); - } - } - } - - /** - * Sets default expiration based on module setting - * - * @param kEvent $event - */ - function OnPreCreate(&$event) - { - parent::OnPreCreate($event); - - if ($event->status == erSUCCESS) { - $object =& $event->getObject(); - $owner_field = $this->getOwnerField($event->Prefix); - - $object->SetDBField($owner_field, $this->Application->RecallVar('user_id')); - } - } - - /** - * Occures before original item of item in pending editing got deleted (for hooking only) - * - * @param kEvent $event - */ - function OnBeforeDeleteOriginal(&$event) - { - - } - - /** - * Occures before an item is cloneded - * Id of ORIGINAL item is passed as event' 'id' param - * Do not call object' Update method in this event, just set needed fields! - * - * @param kEvent $event - */ - function OnBeforeClone(&$event) - { - if ($this->Application->GetVar('ResetCatBeforeClone')) { - $object =& $event->getObject(); - $object->SetDBField('CategoryId', null); - } - } - - /** - * Set status for new category item based on user permission in category - * - * @param kEvent $event - */ - function OnBeforeItemCreate(&$event) - { - if ($this->Application->IsAdmin()) { - return true; - } - - $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing'); - if ($use_pending_editing) { - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - $primary_category = $object->GetDBField('CategoryId') > 0 ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id'); - $item_status = $perm_helper->AddCheckPermission($primary_category, $event->Prefix); - if ($item_status == STATUS_DISABLED) { - $event->status = erFAIL; - return false; - } - else { - $object->SetDBField('Status', $item_status); - } - } - } - - /** - * Creates category item & redirects to confirmation template (front-end only) - * - * @param kEvent $event - */ - function OnCreate(&$event) - { - parent::OnCreate($event); - $this->SetFrontRedirectTemplate($event, 'suggest'); - } - - /** - * Returns item's categories (allows to exclude primary category) - * - * @param int $resource_id - * @param bool $with_primary - * @return Array - */ - function getItemCategories($resource_id, $with_primary = false) - { - $sql = 'SELECT CategoryId - FROM '.TABLE_PREFIX.'CategoryItems - WHERE (ItemResourceId = '.$resource_id.')'; - - if (!$with_primary) { - $sql .= ' AND (PrimaryCat = 0)'; - } - - return $this->Conn->GetCol($sql); - } - - /** - * Adds new and removes old additional categories from category item - * - * @param kCatDBItem $object - */ - function processAdditionalCategories(&$object, $mode) - { - $process_categories = $object->GetDBField('MoreCategories'); - if ($process_categories === '') { - // field was not in submit & have default value (when no categories submitted, then value is null) - return ; - } - - if ($mode == 'create') { - // prevents first additional category to become primary - $object->assignPrimaryCategory(); - } - - $process_categories = $process_categories ? explode('|', substr($process_categories, 1, -1)) : Array (); - $existing_categories = $this->getItemCategories($object->GetDBField('ResourceId')); - - $add_categories = array_diff($process_categories, $existing_categories); - foreach ($add_categories as $category_id) { - $object->assignToCategory($category_id); - } - - $remove_categories = array_diff($existing_categories, $process_categories); - foreach ($remove_categories as $category_id) { - $object->removeFromCategory($category_id); - } - } - - /** - * Creates category item & redirects to confirmation template (front-end only) - * - * @param kEvent $event - */ - function OnUpdate(&$event) - { - $use_pending = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing'); - if ($this->Application->IsAdmin() || !$use_pending) { - parent::OnUpdate($event); - $this->SetFrontRedirectTemplate($event, 'modify'); - return ; - } - - $object =& $event->getObject(Array('skip_autoload' => true)); - /* @var $object kCatDBItem */ - - $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); - if ($items_info) { - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - $temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - /* @var $temp_handler kTempTablesHandler */ - - $owner_field = $this->getOwnerField($event->Prefix); - - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - foreach ($items_info as $id => $field_values) { - $object->Load($id); - $edit_perm = $perm_helper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $event->Prefix); - - if ($use_pending && !$object->GetDBField('OrgId') && ($edit_perm == STATUS_PENDING)) { - // pending editing enabled + not pending copy -> get/create pending copy & save changes to it - $original_id = $object->GetID(); - $original_resource_id = $object->GetDBField('ResourceId'); - $file_helper->PreserveItemFiles($field_values); - - $object->Load($original_id, 'OrgId'); - if (!$object->isLoaded()) { - // 1. user has no pending copy of live item -> clone live item - $cloned_ids = $temp_handler->CloneItems($event->Prefix, $event->Special, Array($original_id), null, null, null, true); - - $object->Load($cloned_ids[0]); - $object->SetFieldsFromHash($field_values); - - // 1a. delete record from CategoryItems (about cloned item) that was automatically created during call of Create method of kCatDBItem - $ci_table = $this->Application->getUnitOption('ci', 'TableName'); - $sql = 'DELETE FROM '.$ci_table.' - WHERE ItemResourceId = '.$object->GetDBField('ResourceId').' AND PrimaryCat = 1'; - $this->Conn->Query($sql); - - // 1b. copy main item categoryitems to cloned item - $sql = 'INSERT INTO '.$ci_table.' (CategoryId, ItemResourceId, PrimaryCat, ItemPrefix, Filename) - SELECT CategoryId, '.$object->GetDBField('ResourceId').' AS ItemResourceId, PrimaryCat, ItemPrefix, Filename - FROM '.$ci_table.' - WHERE ItemResourceId = '.$original_resource_id; - $this->Conn->Query($sql); - - // 1c. put cloned id to OrgId field of item being cloned - $object->SetDBField('Status', STATUS_PENDING_EDITING); - $object->SetDBField('OrgId', $original_id); - } - else { - // 2. user has pending copy of live item -> just update field values - $object->SetFieldsFromHash($field_values); - } - - // update id in request (used for redirect in mod-rewrite mode) - $this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetID()); - } - else { - // 3. already editing pending copy -> just update field values - $object->SetFieldsFromHash($field_values); - } - - if ($object->Update()) { - $event->status = erSUCCESS; - } - else { - $event->status = erFAIL; - $event->redirect = false; - break; - } - } - } - - $this->SetFrontRedirectTemplate($event, 'modify'); - } - - /** - * Sets next template to one required for front-end after adding/modifying item - * - * @param kEvent $event - * @param string $template_key - {suggest,modify} - */ - function SetFrontRedirectTemplate(&$event, $template_key) - { - if ($this->Application->IsAdmin() || $event->status != erSUCCESS) { - return ; - } - - // prepare redirect template - $object =& $event->getObject(); - $is_active = ($object->GetDBField('Status') == STATUS_ACTIVE); - - $next_template = $is_active ? 'confirm_template' : 'pending_confirm_template'; - $event->redirect = $this->Application->GetVar($template_key.'_'.$next_template); - $event->SetRedirectParam('opener', 's'); - - // send email events - $perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix'); - switch ($event->Name) { - case 'OnCreate': - $event_suffix = $is_active ? 'ADD' : 'ADD.PENDING'; - $owner_field = $this->getOwnerField($event->Prefix); - - $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :( - $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField($owner_field)); - break; - - case 'OnUpdate': - $event_suffix = $is_active ? 'MODIFY' : 'MODIFY.PENDING'; - $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); // there are no ADD.PENDING event for admin :( - $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('ModifiedById')); - break; - } - } - - /** - * Apply same processing to each item beeing selected in grid - * - * @param kEvent $event - * @access private - */ - function iterateItems(&$event) - { - if ($event->Name != 'OnMassApprove' && $event->Name != 'OnMassDecline') { - return parent::iterateItems($event); - } - - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } - - $object =& $event->getObject( Array('skip_autoload' => true) ); - $ids = $this->StoreSelectedIDs($event); - - if ($ids) { - foreach ($ids as $id) { - $object->Load($id); - - switch ($event->Name) { - case 'OnMassApprove': - $ret = $object->ApproveChanges(); - break; - - case 'OnMassDecline': - $ret = $object->DeclineChanges(); - break; - } - - if (!$ret) { - $event->status = erFAIL; - $event->redirect = false; - break; - } - } - } - - $this->clearSelectedIDs($event); - } - - /** - * Deletes items & preserves clean env - * - * @param kEvent $event - */ - function OnDelete(&$event) - { - parent::OnDelete($event); - - if ($event->status == erSUCCESS && !$this->Application->IsAdmin()) { - $event->SetRedirectParam('pass', 'm'); - $event->SetRedirectParam('m_cat_id', 0); - } - } - - /** - * Checks, that currently loaded item is allowed for viewing (non permission-based) - * - * @param kEvent $event - * @return bool - */ - function checkItemStatus(&$event) - { - $object =& $event->getObject(); - if (!$object->isLoaded()) { - $this->_errorNotFound($event); - - return true; - } - - $status = $object->GetDBField('Status'); - $user_id = $this->Application->RecallVar('user_id'); - $owner_field = $this->getOwnerField($event->Prefix); - - if (($status == -2 || $status == STATUS_PENDING) && ($object->GetDBField($owner_field) == $user_id)) { - return true; - } - - return $status == STATUS_ACTIVE; - } - - /** - * Set's correct sorting for list - * based on data provided with event - * - * @param kEvent $event - * @access private - * @see OnListBuild - */ - function SetSorting(&$event) - { - if (!$this->Application->IsAdmin()) { - $event->setEventParam('same_special', true); - } - - parent::SetSorting($event); - } - - /** - * Returns current per-page setting for list - * - * @param kEvent $event - * @return int - */ - function getPerPage(&$event) - { - if (!$this->Application->IsAdmin()) { - $event->setEventParam('same_special', true); - } - - return parent::getPerPage($event); - } - - function getOwnerField($prefix) - { - $owner_field = $this->Application->getUnitOption($prefix, 'OwnerField'); - if (!$owner_field) { - $owner_field = 'CreatedById'; - } - - return $owner_field; - } - - /** - * Creates virtual image fields for item - * - * @param kEvent $event - */ - function OnAfterConfigRead(&$event) - { - parent::OnAfterConfigRead($event); - - if (defined('IS_INSTALL') && IS_INSTALL) { - return ; - } - - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - $file_helper->createItemFiles($event->Prefix, true); // create image fields - $file_helper->createItemFiles($event->Prefix, false); // create file fields - - // add EditorsPick to ForcedSorting if needed - $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping'); - if (array_key_exists('ForceEditorPick', $config_mapping) && $this->Application->ConfigValue($config_mapping['ForceEditorPick'])) { - $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings'); - - $new_forced_sorting = Array ('EditorsPick' => 'DESC'); - - if (array_key_exists('ForcedSorting', $list_sortings[''])) { - foreach ($list_sortings['']['ForcedSorting'] as $sort_field => $sort_order) { - $new_forced_sorting[$sort_field] = $sort_order; - } - } - $list_sortings['']['ForcedSorting'] = $new_forced_sorting; - - $this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings); - } - - // add grids for advanced view (with primary category column) - $grids = $this->Application->getUnitOption($this->Prefix, 'Grids'); - $process_grids = Array ('Default', 'Radio'); - foreach ($process_grids as $process_grid) { - $grid_data = $grids[$process_grid]; - $grid_data['Fields']['CachedNavbar'] = Array ('title' => 'la_col_Path', 'data_block' => 'grid_primary_category_td', 'filter_block' => 'grid_like_filter'); - $grids[$process_grid . 'ShowAll'] = $grid_data; - } - $this->Application->setUnitOption($this->Prefix, 'Grids', $grids); - - // add options for CategoryId field (quick way to select item's primary category) - $category_helper =& $this->Application->recallObject('CategoryHelper'); - /* @var $category_helper CategoryHelper */ - - $virtual_fields = $this->Application->getUnitOption($event->Prefix, 'VirtualFields'); - - $virtual_fields['CategoryId']['default'] = (int)$this->Application->GetVar('m_cat_id'); - $virtual_fields['CategoryId']['options'] = $category_helper->getStructureTreeAsOptions(); - - $this->Application->setUnitOption($event->Prefix, 'VirtualFields', $virtual_fields); - } - - /** - * Returns file contents associated with item - * - * @param kEvent $event - */ - function OnDownloadFile(&$event) - { - $object =& $event->getObject(); - /* @var $object kDBItem */ - - $event->status = erSTOP; - - $field = $this->Application->GetVar('field'); - if (!preg_match('/^File([\d]+)/', $field)) { - return ; - } - - $file_helper =& $this->Application->recallObject('FileHelper'); - /* @var $file_helper FileHelper */ - - $filename = $object->GetField($field, 'full_path'); - $file_helper->DownloadFile($filename); - } - - /** - * Saves user's vote - * - * @param kEvent $event - */ - function OnMakeVote(&$event) - { - $event->status = erSTOP; - - if ($this->Application->GetVar('ajax') != 'yes') { - // this is supposed to call from AJAX only - return ; - } - - $rating_helper =& $this->Application->recallObject('RatingHelper'); - /* @var $rating_helper RatingHelper */ - - $object =& $event->getObject( Array ('skip_autoload' => true) ); - /* @var $object kDBItem */ - - $object->Load( $this->Application->GetVar('id') ); - - echo $rating_helper->makeVote($object); - } -} \ No newline at end of file Index: branches/5.0.x/core/kernel/application.php =================================================================== diff -u -N -r12323 -r12343 --- branches/5.0.x/core/kernel/application.php (.../application.php) (revision 12323) +++ branches/5.0.x/core/kernel/application.php (.../application.php) (revision 12343) @@ -1,6 +1,6 @@ registerClass('kTempTablesHandler', KERNEL_PATH.'/utility/temp_handler.php'); - $this->registerClass('kEventManager', KERNEL_PATH.'/event_manager.php', 'EventManager'); - $this->registerClass('kUnitConfigReader', KERNEL_PATH.'/utility/unit_config_reader.php'); + $this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php'); + $this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager'); + $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); - $this->registerClass('kArray', KERNEL_PATH.'/utility/params.php'); - $this->registerClass('Params', KERNEL_PATH.'/utility/params.php'); - $this->registerClass('kHelper', KERNEL_PATH.'/kbase.php'); + $this->registerClass('kArray', KERNEL_PATH . '/utility/params.php'); + $this->registerClass('Params', KERNEL_PATH . '/utility/params.php'); + $this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions'); + $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'Cache', 'Params'); + $this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery', 'Params'); - $this->registerClass('kCache', KERNEL_PATH.'/utility/cache.php', 'Cache', 'Params'); - $this->registerClass('kHTTPQuery', KERNEL_PATH.'/utility/http_query.php', 'HTTPQuery', 'Params'); + $this->registerClass('kHelper', KERNEL_PATH . '/kbase.php'); + $this->registerClass('kMultipleFilter', KERNEL_PATH . '/utility/filters.php'); - $this->registerClass('Session', KERNEL_PATH.'/session/session.php'); - $this->registerClass('SessionStorage', KERNEL_PATH.'/session/session.php'); + $this->registerClass('Session', KERNEL_PATH . '/session/session.php'); + $this->registerClass('SessionStorage', KERNEL_PATH . '/session/session.php'); + $this->registerClass('InpSession', KERNEL_PATH . '/session/inp_session.php', 'Session'); + $this->registerClass('InpSessionStorage', KERNEL_PATH . '/session/inp_session.php', 'SessionStorage'); - $this->registerClass('Params', KERNEL_PATH.'/utility/params.php', 'kActions'); + $this->registerClass('kTagProcessor', KERNEL_PATH . '/processors/tag_processor.php'); + $this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php','m_TagProcessor', 'kTagProcessor'); - $this->registerClass('kMultipleFilter', KERNEL_PATH.'/utility/filters.php'); - $this->registerClass('kDBList', KERNEL_PATH.'/db/dblist.php'); - $this->registerClass('kDBItem', KERNEL_PATH.'/db/dbitem.php'); - $this->registerClass('kDBEventHandler', KERNEL_PATH.'/db/db_event_handler.php'); + $this->registerClass('kDBList', KERNEL_PATH . '/db/dblist.php'); + $this->registerClass('kDBItem', KERNEL_PATH . '/db/dbitem.php'); + $this->registerClass('kDBEventHandler', KERNEL_PATH . '/db/db_event_handler.php'); + $this->registerClass('kDBTagProcessor', KERNEL_PATH . '/db/db_tag_processor.php', null, 'kTagProcessor'); + $this->registerClass('kCatDBItem', KERNEL_PATH . '/db/cat_dbitem.php'); + $this->registerClass('kCatDBList', KERNEL_PATH . '/db/cat_dblist.php'); + $this->registerClass('kCatDBEventHandler', KERNEL_PATH . '/db/cat_event_handler.php'); + $this->registerClass('kCatDBTagProcessor', KERNEL_PATH . '/db/cat_tag_processor.php'); - $this->registerClass('kTagProcessor', KERNEL_PATH.'/processors/tag_processor.php'); - $this->registerClass('kMainTagProcessor', KERNEL_PATH.'/processors/main_processor.php','m_TagProcessor', 'kTagProcessor'); - $this->registerClass('kDBTagProcessor', KERNEL_PATH.'/db/db_tag_processor.php', null, 'kTagProcessor'); + $this->registerClass('NParser', KERNEL_PATH . '/nparser/nparser.php'); + $this->registerClass('TemplatesCache', KERNEL_PATH . '/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor')); - $this->registerClass('TemplatesCache', KERNEL_PATH.'/nparser/template_cache.php', null, Array ('kHelper', 'kDBTagProcessor')); - $this->registerClass('NParser', KERNEL_PATH.'/nparser/nparser.php'); + $this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender', 'kHelper'); + $this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket'); - $this->registerClass('kEmailSendingHelper', KERNEL_PATH.'/utility/email_send.php', 'EmailSender', 'kHelper'); - $this->registerClass('kSocket', KERNEL_PATH.'/utility/socket.php', 'Socket'); - - if (file_exists(MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php')) { - $this->registerClass('kCurrencyRates', MODULES_PATH.'/in-commerce/units/currencies/currency_rates.php'); + if (file_exists(MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php')) { + $this->registerClass('kCurrencyRates', MODULES_PATH . '/in-commerce/units/currencies/currency_rates.php'); } - /* Moved from MyApplication */ - - $this->registerClass('InpSession',KERNEL_PATH.'/../units/general/inp_ses_storage.php', 'Session'); - $this->registerClass('InpSessionStorage',KERNEL_PATH.'/../units/general/inp_ses_storage.php', 'SessionStorage'); - - $this->registerClass('kCatDBItem',KERNEL_PATH.'/../units/general/cat_dbitem.php'); - $this->registerClass('kCatDBItemExportHelper',KERNEL_PATH.'/../units/general/cat_dbitem_export.php', 'CatItemExportHelper'); - $this->registerClass('kCatDBList',KERNEL_PATH.'/../units/general/cat_dblist.php'); - $this->registerClass('kCatDBEventHandler',KERNEL_PATH.'/../units/general/cat_event_handler.php'); - $this->registerClass('kCatDBTagProcessor',KERNEL_PATH.'/../units/general/cat_tag_processor.php'); - - // Do not move to config - this helper is used before configs are read - $this->registerClass('kModulesHelper', KERNEL_PATH.'/../units/helpers/modules_helper.php', 'ModulesHelper'); - - /* End moved */ - + // do not move to config - this helper is used before configs are read + $this->registerClass('kModulesHelper', KERNEL_PATH . '/../units/helpers/modules_helper.php', 'ModulesHelper'); } function RegisterDefaultBuildEvents() Index: branches/5.0.x/core/units/helpers/cat_dbitem_export.php =================================================================== diff -u -N -r12299 -r12343 --- branches/5.0.x/core/units/helpers/cat_dbitem_export.php (.../general/cat_dbitem_export.php) (revision 12299) +++ branches/5.0.x/core/units/helpers/cat_dbitem_export.php (.../helpers/cat_dbitem_export_helper.php) (revision 12343) @@ -1,6 +1,6 @@ 'In-Portal', 'PermSection' => Array ('search' => 'in-portal:configuration_search', 'custom' => 'in-portal:configuration_custom'), - ); \ No newline at end of file Index: branches/5.0.x/core/units/general/cat_dbitem.php =================================================================== diff -u -N --- branches/5.0.x/core/units/general/cat_dbitem.php (revision 12299) +++ branches/5.0.x/core/units/general/cat_dbitem.php (revision 0) @@ -1,598 +0,0 @@ -CategoryPath = Array(); - } - - /** - * Set's prefix and special - * - * @param string $prefix - * @param string $special - * @access public - */ - function Init($prefix, $special, $event_params = null) - { - parent::Init($prefix, $special, $event_params); - $this->usePendingEditing = $this->Application->getUnitOption($this->Prefix, 'UsePendingEditing'); - } - - function Create($force_id = false, $system_create = false) - { - // TODO: move to OnBeforeItemCreate method - if ($this->Validate()) { - // TODO: such approach will not respect changes from OnBeforeItemCreate event - $this->SetDBField('ResourceId', $this->Application->NextResourceId()); - } - - $this->SetDBField('Modified_date', adodb_mktime() ); - $this->SetDBField('Modified_time', adodb_mktime() ); - - if ($this->mode != 't' && !$this->Application->IsAdmin()) { - $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); - if (!$owner_field) { - $owner_field = 'CreatedById'; - } - $this->SetDBField($owner_field, $this->Application->RecallVar('user_id')); - } - - if ($this->useFilenames) { - $this->checkFilename(); - $this->generateFilename(); - } - - $ret = parent::Create($force_id, $system_create); - - if ($ret) { - // TODO: move to OnAfterItemCreate method - $this->assignPrimaryCategory(); - } - return $ret; - } - - function assignPrimaryCategory() - { - $primary_category = $this->GetDBField('CategoryId') > 0 ? $this->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id'); - $this->assignToCategory($primary_category, true); - } - - function Update($id=null, $system_update=false) - { - $this->VirtualFields['ResourceId'] = Array(); - $this->SetDBField('Modified', adodb_mktime() ); - $this->UpdateFormattersSubFields(array('Modified')); - $this->SetDBField('ModifiedById', $this->Application->RecallVar('user_id')); - - if ($this->useFilenames) { - $this->checkFilename(); - $this->generateFilename(); - } - - $ret = parent::Update($id, $system_update); - - if ($ret) { - $filename = $this->useFilenames ? $this->GetDBField('Filename') : ''; - $sql = 'UPDATE '.$this->CategoryItemsTable().' - SET Filename = '.$this->Conn->qstr($filename).' - WHERE ItemResourceId = '.$this->GetDBField('ResourceId'); - $this->Conn->Query($sql); - } - - unset($this->VirtualFields['ResourceId']); - return $ret; - } - - /** - * Returns CategoryItems table based on current item mode (temp/live) - * - * @return string - */ - function CategoryItemsTable() - { - $table = TABLE_PREFIX.'CategoryItems'; - if ($this->Application->IsTempTable($this->TableName)) { - $table = $this->Application->GetTempName($table, 'prefix:'.$this->Prefix); - } - - return $table; - } - - - function checkFilename() - { - if( !$this->GetDBField('AutomaticFilename') ) - { - $filename = $this->GetDBField('Filename'); - $this->SetDBField('Filename', $this->stripDisallowed($filename) ); - } - } - - function Copy($cat_id=null) - { - if (!isset($cat_id)) $cat_id = $this->Application->GetVar('m_cat_id'); - $this->NameCopy($cat_id); - return $this->Create($cat_id); - } - - function NameCopy($master=null, $foreign_key=null) - { - $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField'); - if (!$title_field) return; - - $new_name = $this->GetDBField($title_field); - $cat_id = $this->Application->GetVar('m_cat_id'); - $original_checked = false; - do { - if ( preg_match('/Copy ([0-9]*) *of (.*)/', $new_name, $regs) ) { - $new_name = 'Copy '.( (int)$regs[1] + 1 ).' of '.$regs[2]; - } - elseif ($original_checked) { - $new_name = 'Copy of '.$new_name; - } - $query = 'SELECT '.$title_field.' FROM '.$this->TableName.' - LEFT JOIN '.TABLE_PREFIX.'CategoryItems ON - ('.TABLE_PREFIX.'CategoryItems.ItemResourceId = '.$this->TableName.'.ResourceId) - WHERE ('.TABLE_PREFIX.'CategoryItems.CategoryId = '.$cat_id.') AND '. - $title_field.' = '.$this->Conn->qstr($new_name); - $res = $this->Conn->GetOne($query); - $original_checked = true; - } while ($res !== false); - $this->SetDBField($title_field, $new_name); - - // this is needed, because Create will create items in its own CategoryId (if it's set), - // but we need to create it in target Paste category @see{kCatDBItem::Create} and its primary_category detection - $this->SetDBField('CategoryId', $cat_id); - } - - /** - * Changes item primary category to given/current category - * - * @param int $category_id - */ - function MoveToCat($category_id = null) - { -// $this->NameCopy(); - if (!isset($category_id)) { - $category_id = $this->Application->GetVar('m_cat_id'); - } - - $table_name = TABLE_PREFIX . 'CategoryItems'; - if ($this->IsTempTable()) { - $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix); - } - - // check if the item already exists in destination category - $sql = 'SELECT PrimaryCat - FROM ' . $table_name . ' - WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')'; - $is_primary = $this->Conn->GetOne($sql); - - // if it's not found is_primary will be FALSE, if it's found but not primary it will be int 0 - $exists = $is_primary !== false; - - if ($exists) { - // if the item already exists in destination category - if ($is_primary) { - // do nothing when we paste to primary - return ; - } - - // if it's not primary - delete it from destination category, as we will move it from current primary below - $sql = 'DELETE FROM ' . $table_name . ' - WHERE (CategoryId = ' . $category_id . ') AND (ItemResourceId = ' . $this->GetDBField('ResourceId') . ')'; - $this->Conn->Query($sql); - } - - // change category id in existing primary category record - $sql = 'UPDATE ' . $table_name . ' - SET CategoryId = ' . $category_id . ' - WHERE (ItemResourceId = ' . $this->GetDBField('ResourceId') . ') AND (PrimaryCat = 1)'; - $this->Conn->Query($sql); - - $this->Update(); - } - - /** - * When item is deleted, then also delete it from all categories - * - * @param int $id - * @return bool - */ - function Delete($id = null) - { - if( isset($id) ) { - $this->setID($id); - } - - $this->Load($this->GetID()); - - $ret = parent::Delete(); - - if ($ret) { - // TODO: move to OnAfterItemDelete method - $query = ' DELETE FROM ' . $this->CategoryItemsTable() . ' - WHERE ItemResourceId = ' . $this->GetDBField('ResourceId'); - $this->Conn->Query($query); - } - - return $ret; - } - - /** - * Deletes item from categories - * - * @param Array $delete_category_ids - * @author Alex - */ - function DeleteFromCategories($delete_category_ids) - { - $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); // because item was loaded before by ResourceId - - $ci_table = $this->Application->getUnitOption($this->Prefix.'-ci', 'TableName'); - $resource_id = $this->GetDBField('ResourceId'); - - $item_cats_sql = 'SELECT CategoryId FROM %s WHERE ItemResourceId = %s'; - $delete_category_items_sql = 'DELETE FROM %s WHERE ItemResourceId = %s AND CategoryId IN (%s)'; - - $category_ids = $this->Conn->GetCol( sprintf($item_cats_sql, $ci_table, $resource_id) ); - $cats_left = array_diff($category_ids, $delete_category_ids); - if(!$cats_left) - { - $sql = 'SELECT %s FROM %s WHERE ResourceId = %s'; - $ids = $this->Conn->GetCol( sprintf($sql, $id_field, $this->TableName, $resource_id) ); - - $temp =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - $temp->DeleteItems($this->Prefix, $this->Special, $ids); - } - else - { - $this->Conn->Query( sprintf($delete_category_items_sql, $ci_table, $resource_id, implode(',', $delete_category_ids) ) ); - - $sql = 'SELECT CategoryId FROM %s WHERE PrimaryCat = 1 AND ItemResourceId = %s'; - $primary_cat_id = $this->Conn->GetCol( sprintf($sql, $ci_table, $resource_id) ); - if( count($primary_cat_id) == 0 ) - { - $sql = 'UPDATE %s SET PrimaryCat = 1 WHERE (CategoryId = %s) AND (ItemResourceId = %s)'; - $this->Conn->Query( sprintf($sql, $ci_table, reset($cats_left), $resource_id ) ); - } - } - } - - /** - * replace not allowed symbols with "_" chars + remove duplicate "_" chars in result - * - * @param string $string - * @return string - */ - function stripDisallowed($filename) - { - $filenames_helper =& $this->Application->recallObject('FilenamesHelper'); - $table = $this->mode == 't' ? $this->Application->GetTempName(TABLE_PREFIX.'CategoryItems', 'prefix:'.$this->Prefix) : TABLE_PREFIX.'CategoryItems'; - - return $filenames_helper->stripDisallowed($table, 'ItemResourceId', $this->GetDBField('ResourceId'), $filename); - } - - /* commented out because it's called only from stripDisallowed body, which is moved to helper - - function checkAutoFilename($filename) - { - $filenames_helper =& $this->Application->recallObject('FilenamesHelper'); - return $filenames_helper->checkAutoFilename($this->TableName, $this->IDField, $this->GetID(), $filename); - }*/ - - /** - * Generate item's filename based on it's title field value - * - * @return string - */ - function generateFilename() - { - if ( !$this->GetDBField('AutomaticFilename') && $this->GetDBField('Filename') ) return false; - - $title_field = $this->Application->getUnitOption($this->Prefix, 'TitleField'); - if (preg_match('/l([\d]+)_(.*)/', $title_field, $regs)) { - // if title field is multilingual, then use it's name from primary language - $title_field = 'l'.$this->Application->GetDefaultLanguageId().'_'.$regs[2]; - } - $name = $this->stripDisallowed( $this->GetDBField($title_field) ); - - if ( $name != $this->GetDBField('Filename') ) $this->SetDBField('Filename', $name); - } - - /** - * Check if value is set for required field - * - * @param string $field field name - * @param Array $params field options from config - * @return bool - * @access private - */ - function ValidateRequired($field, $params) - { - $res = true; - if (getArrayValue($params, 'required')) { - $res = ( (string) $this->FieldValues[$field] != ''); - } - if (!$res) { - $this->SetError($field, 'required'); - } - return $res; - } - - /** - * Adds item to other category - * - * @param int $category_id - * @param bool $is_primary - */ - function assignToCategory($category_id, $is_primary = false) - { - $table = $this->CategoryItemsTable(); - $key_clause = '(ItemResourceId = '.$this->GetDBField('ResourceId').')'; - - // get all cateories, where item is in - $sql = 'SELECT PrimaryCat, CategoryId FROM '.$table.' WHERE '.$key_clause; - $item_categories = $this->Conn->GetCol($sql, 'CategoryId'); - if (!$item_categories) { - $item_categories = Array(); - $primary_found = false; - } - - // find primary category - foreach ($item_categories as $item_category_id => $primary_found) { - if ($primary_found) { - break; - } - } - - if ($primary_found && ($item_category_id == $category_id) && !$is_primary) { - // want to make primary category as non-primary :( - return true; - } - else if (!$primary_found) { - $is_primary = true; - } - - if ($is_primary && $item_categories) { - // reset primary mark from all other categories - $sql = 'UPDATE '.$table.' SET PrimaryCat = 0 WHERE '.$key_clause; - $this->Conn->Query($sql); - } - - // UPDATE & INSERT instead of REPLACE because CategoryItems table has no primary key defined in database - if (isset($item_categories[$category_id])) { - $sql = 'UPDATE '.$table.' SET PrimaryCat = '.($is_primary ? 1 : 0).' WHERE '.$key_clause.' AND (CategoryId = '.$category_id.')'; - $this->Conn->Query($sql); - } - else { - $fields_hash = Array( - 'CategoryId' => $category_id, - 'ItemResourceId' => $this->GetField('ResourceId'), - 'PrimaryCat' => $is_primary ? 1 : 0, - 'ItemPrefix' => $this->Prefix, - 'Filename' => $this->useFilenames ? $this->GetDBField('Filename') : '', // because some prefixes does not use filenames, - ); - $this->Conn->doInsert($fields_hash, $table); - } - // to ensure filename update after adding to another category - // this is critical since there may be an item with same filename in newly added category! - $this->Update(); - } - - /** - * Removes item from category specified - * - * @param int $category_id - */ - function removeFromCategory($category_id) - { - $sql = 'DELETE FROM '.TABLE_PREFIX.'CategoryItems WHERE (CategoryId = %s) AND (ItemResourceId = %s)'; - $this->Conn->Query( sprintf($sql, $category_id, $this->GetDBField('ResourceId')) ); - } - - /** - * Returns list of columns, that could exist in imported file - * - * @return Array - */ - function getPossibleExportColumns() - { - static $columns = null; - if (!is_array($columns)) { - $columns = array_merge($this->Fields['AvailableColumns']['options'], $this->Fields['ExportColumns']['options']); - } - return $columns; - } - - /** - * Returns item's primary image data - * - * @return Array - */ - function getPrimaryImageData() - { - $sql = 'SELECT * - FROM '.TABLE_PREFIX.'Images - WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (DefaultImg = 1)'; - $image_data = $this->Conn->GetRow($sql); - if (!$image_data) { - // 2. no primary image, then get image with name "main" - $sql = 'SELECT * - FROM '.TABLE_PREFIX.'Images - WHERE (ResourceId = '.$this->GetDBField('ResourceId').') AND (Name = "main")'; - $image_data = $this->Conn->GetRow($sql); - } - return $image_data; - } - - function ChangeStatus($new_status) - { - $status_field = array_shift( $this->Application->getUnitOption($this->Prefix,'StatusField') ); - if ($new_status != $this->GetDBField($status_field)) { - // status was changed - $this->sendEmailEvents($new_status); - } - $this->SetDBField($status_field, $new_status); - - return $this->Update(); - } - - function sendEmailEvents($new_status) - { - $perm_prefix = $this->Application->getUnitOption($this->Prefix, 'PermItemPrefix'); - $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); - if (!$owner_field) { - $owner_field = 'CreatedById'; - } - - $event_name = $perm_prefix.'.'.($new_status == STATUS_ACTIVE ? 'APPROVE' : 'DENY'); - $this->Application->EmailEventUser($event_name, $this->GetDBField($owner_field)); - } - - /** - * Approves changes made to category item - * - * @return bool - */ - function ApproveChanges() - { - $original_id = $this->GetDBField('OrgId'); - - if (!($this->usePendingEditing && $original_id)) { - // non-pending copy of original link - return $this->ChangeStatus(STATUS_ACTIVE); - } - - if ($this->raiseEvent('OnBeforeDeleteOriginal', null, Array('original_id' => $original_id))) { - // delete original item, because changes made in pending copy (this item) got to be approved in this method - $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($original_id)); - - $this->SetDBField('OrgId', 0); - return $this->ChangeStatus(STATUS_ACTIVE); - } - - return false; - } - - /** - * Decline changes made to category item - * - * @return bool - */ - function DeclineChanges() - { - $original_id = $this->GetDBField('OrgId'); - - if (!($this->usePendingEditing && $original_id)) { - // non-pending copy of original link - return $this->ChangeStatus(STATUS_DISABLED); - } - - // delete this item, because changes made in pending copy (this item) will be declined in this method - $temp_handler =& $this->Application->recallObject($this->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - $temp_handler->DeleteItems($this->Prefix, $this->Special, Array($this->GetID())); - - // original item is not changed here, because it is already enabled (thrus pending copy is visible to item's owner or admin with permission) - return true; - } - - function RegisterHit() - { - $already_viewed = $this->Application->RecallVar($this->getPrefixSpecial().'_already_viewed'); - $already_viewed = $already_viewed ? unserialize($already_viewed) : Array (); - - $id = $this->GetID(); - if (!in_array($id, $already_viewed)) { - $property_map = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings'); - if (!$property_map) { - return ; - } - $hits_field = $property_map['ClickField']; - $new_hits = $this->GetDBField($hits_field) + 1; - - $sql = 'SELECT MAX('.$hits_field.') - FROM '.$this->TableName.' - WHERE FLOOR('.$hits_field.') = '.$new_hits; - $max_hits = $this->Conn->GetOne($sql); - if ($max_hits) { - $new_hits = $max_hits + 0.000001; - } - - $fields_hash = Array ( - $hits_field => $new_hits, - ); - $this->Conn->doUpdate($fields_hash, $this->TableName, $this->IDField.' = '.$id); - - array_push($already_viewed, $id); - $this->Application->StoreVar($this->getPrefixSpecial().'_already_viewed', serialize($already_viewed)); - } - } - - /** - * Returns part of SQL WHERE clause identifing the record, ex. id = 25 - * - * @access public - * @param string $method Child class may want to know who called GetKeyClause, Load(), Update(), Delete() send its names as method - * @param Array $keys_hash alternative, then item id, keys hash to load item by - * @return void - * @see kDBItem::Load() - * @see kDBItem::Update() - * @see kDBItem::Delete() - */ - function GetKeyClause($method = null, $keys_hash = null) - { - if ($method == 'load') { - // for item with many categories makes primary to load - $ci_table = TABLE_PREFIX.'CategoryItems'; - if ($this->IsTempTable()) { - $ci_table = $this->Application->GetTempName($ci_table, 'prefix:'.$this->Prefix); - } - $keys_hash = Array( - $this->IDField => $this->ID, - '`'.$ci_table.'`.`PrimaryCat`' => 1, - ); - } - return parent::GetKeyClause($method, $keys_hash); - } - -} \ No newline at end of file Index: branches/5.0.x/core/units/general/cat_tag_processor.php =================================================================== diff -u -N --- branches/5.0.x/core/units/general/cat_tag_processor.php (revision 12299) +++ branches/5.0.x/core/units/general/cat_tag_processor.php (revision 0) @@ -1,789 +0,0 @@ -PermHelper = $this->Application->recallObject('PermissionsHelper'); - } - - function ItemIcon($params) - { - $object =& $this->Application->recallObject($this->getPrefixSpecial(),$this->Prefix, $params); - - $grids = $this->Application->getUnitOption($this->Prefix,'Grids'); - $icons =& $grids[ $params['grid'] ]['Icons']; - - $status_fields = $this->Application->getUnitOption($this->Prefix,'StatusField'); - if (!$status_fields) return $icons['default']; - - $value = $object->GetDBField($status_fields[0]); // sets base status icon - /* @var $object kDBItem */ - if ($value == STATUS_ACTIVE) { - if( $object->HasField('IsPop') && $object->GetDBField('IsPop') ) $value = 'POP'; - if( $object->HasField('IsHot') && $object->GetDBField('IsHot') ) $value = 'HOT'; - if( $object->HasField('IsNew') && $object->GetDBField('IsNew') ) $value = 'NEW'; - if( $object->HasField('EditorsPick') && $object->GetDBField('EditorsPick') ) $value = 'PICK'; - } - - return isset($icons[$value]) ? $icons[$value] : $icons['default']; - } - - /** - * Allows to create valid mod-rewrite compatible link to module item - * - * @param Array $params - * @param string $id_prefix - * @return string - */ - function ItemLink($params, $id_prefix = null) - { - if (!isset($params['pass'])) { - $params['pass'] = 'm,'.$this->Prefix; - } - - $item_id = isset($params[$id_prefix.'_id']) && $params[$id_prefix.'_id']; - if (!$item_id) { - $item_id = $this->Application->GetVar($this->getPrefixSpecial().'_id'); - if (!$item_id) { - $item_id = $this->Application->GetVar($this->Prefix.'_id'); - } - } - $params[$this->Prefix.'_id'] = $item_id; - - $object =& $this->getObject($params); - $params['m_cat_id'] = $object->GetDBField('CategoryId'); - $params['m_cat_page'] = 1; - $params['pass_category'] = 1; - - return $this->Application->ProcessParsedTag('m', 't', $params); - } - - function CategoryPath($params) - { - if ($this->Application->IsAdmin()) { - // path for module root category in admin - if (!isset($params['cat_id'])) { - $params['cat_id'] = $this->Application->RecallVar($params['session_var'], 0); - } - } - else { - // path for category item category in front-end - $object =& $this->getObject($params); - $params['cat_id'] = $object->GetDBField('CategoryId'); - } - - return $this->Application->ProcessParsedTag('c', 'CategoryPath', $params); - } - - function BuildListSpecial($params) - { - if ($this->Special != '') return $this->Special; - if ( isset($params['parent_cat_id']) ) { - $parent_cat_id = $params['parent_cat_id']; - } - else { - $parent_cat_id = $this->Application->GetVar('c_id'); - if (!$parent_cat_id) { - $parent_cat_id = $this->Application->GetVar('m_cat_id'); - } - } - - $recursive = isset($params['recursive']); - - $list_unique_key = $this->getUniqueListKey($params).$recursive; - if ($list_unique_key == '') { - return parent::BuildListSpecial($params); - } - - return crc32($parent_cat_id.$list_unique_key); - } - - function CatalogItemCount($params) - { - $params['skip_quering'] = true; - $object =& $this->GetList($params); - - if (!$object->Counted) { - $object->CountRecs(); - } - - return $object->NoFilterCount != $object->RecordsCount ? $object->RecordsCount.' / '.$object->NoFilterCount : $object->RecordsCount; - } - - function ListReviews($params) - { - $prefix = $this->Prefix.'-rev'; - $review_tag_processor =& $this->Application->recallObject($prefix.'.item_TagProcessor'); - return $review_tag_processor->PrintList($params); - } - - function ReviewCount($params) - { - $review_tag_processor =& $this->Application->recallObject('rev.item_TagProcessor'); - return $review_tag_processor->TotalRecords($params); - } - - function InitCatalogTab($params) - { - $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible - $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab - $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid - - // set default params (same as in catalog) - if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi'; - if ($tab_params['special'] === false) $tab_params['special'] = ''; - if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes'; - - // pass params to block with tab content - $params['name'] = $params['render_as']; - $special = $tab_params['special'] ? $tab_params['special'] : $this->Special; - - $params['prefix'] = trim($this->Prefix.'.'.$special, '.'); - - $prefix_append = $this->Application->GetVar('prefix_append'); - if ($prefix_append) { - $params['prefix'] .= $prefix_append; - } - - $default_grid = array_key_exists('default_grid', $params) ? $params['default_grid'] : 'Default'; - $radio_grid = array_key_exists('radio_grid', $params) ? $params['radio_grid'] : 'Radio'; - - - $params['cat_prefix'] = trim('c.'.$special, '.'); - $params['tab_mode'] = $tab_params['mode']; - $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $default_grid : $radio_grid; - $params['tab_dependant'] = $tab_params['dependant']; - $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name - - if ($special == 'showall' || $special == 'user') { - $params['grid_name'] .= 'ShowAll'; - } - - return $this->Application->ParseBlock($params, 1); - } - - /** - * Show CachedNavbar of current item primary category - * - * @param Array $params - * @return string - */ - function CategoryName($params) - { - // show category cachednavbar of - $object =& $this->getObject($params); - $category_id = isset($params['cat_id']) ? $params['cat_id'] : $object->GetDBField('CategoryId'); - - $category_path = $this->Application->getCache('category_paths', $category_id); - if ($category_path === false) { - // not chached - if ($category_id > 0) { - $cached_navbar = preg_replace('/^(Content&\|&|Content)/i', '', $object->GetField('CachedNavbar')); - $category_path = trim($this->CategoryName( Array('cat_id' => 0) ).' > '.str_replace('&|&', ' > ', $cached_navbar), ' > '); - } - else { - $category_path = $this->Application->Phrase( $this->Application->ConfigValue('Root_Name') ); - } - $this->Application->setCache('category_paths', $category_id, $category_path); - } - return $category_path; - } - - /** - * Allows to determine if original value should be shown - * - * @param Array $params - * @return bool - */ - function DisplayOriginal($params) - { - // original id found & greather then zero + show original - $display_original = isset($params['display_original']) && $params['display_original']; - - $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); - if (!$owner_field) { - $owner_field = 'CreatedById'; - } - - $object =& $this->getObject($params); - $perm_value = $this->PermHelper->ModifyCheckPermission($object->GetDBField($owner_field), $object->GetDBField('CategoryId'), $this->Prefix); - - return $display_original && ($perm_value == 1) && $this->Application->GetVar($this->Prefix.'.original_id'); - } - - /** - * Checks if user have one of required permissions - * - * @param Array $params - * @return bool - */ - function HasPermission($params) - { - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ - - $params['raise_warnings'] = 0; - $object =& $this->getObject($params); - /* @var $object kCatDBItem */ - - // 1. category restriction - $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id'); - - // 2. owner restriction - $owner_field = $this->Application->getUnitOption($this->Prefix, 'OwnerField'); - if (!$owner_field) { - $owner_field = 'CreatedById'; - } - $is_owner = $object->GetDBField($owner_field) == $this->Application->RecallVar('user_id'); - - return $perm_helper->TagPermissionCheck($params, $is_owner); - } - - /** - * Creates link to current category or to module root category, when current category is home - * - * @param Array $params - * @return string - */ - function SuggestItemLink($params) - { - if (!isset($params['cat_id'])) { - $params['cat_id'] = $this->Application->GetVar('m_cat_id'); - } - - if ($params['cat_id'] == 0) { - $params['cat_id'] = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); - } - - $params['m_cat_page'] = 1; - - return $this->Application->ProcessParsedTag('c', 'CategoryLink', $params); - } - - /** - * Allows to detect if item has any additional images available - * - * @param Array $params - * @return string - */ - function HasAdditionalImages($params) - { - $object =& $this->getObject($params); - $sql = 'SELECT ImageId - FROM '.$this->Application->getUnitOption('img', 'TableName').' - WHERE ResourceId = '.$object->GetDBField('ResourceId').' AND DefaultImg != 1 AND Enabled = 1'; - return $this->Conn->GetOne($sql) ? 1 : 0; - } - - /** - * Checks that item is pending - * - * @param Array $params - * @return bool - */ - function IsPending($params) - { - $object =& $this->getObject($params); - - $pending_status = Array (STATUS_PENDING, STATUS_PENDING_EDITING); - return in_array($object->GetDBField('Status'), $pending_status); - } - - function IsFavorite($params) - { - static $favorite_status = Array (); - - $object =& $this->getObject($params); - /* @var $object kDBList */ - - if (!isset($favorite_status[$this->Special])) { - $resource_ids = $object->GetCol('ResourceId'); - - $user_id = $this->Application->RecallVar('user_id'); - $sql = 'SELECT FavoriteId, ResourceId - FROM '.$this->Application->getUnitOption('fav', 'TableName').' - WHERE (PortalUserId = '.$user_id.') AND (ResourceId IN ('.implode(',', $resource_ids).'))'; - $favorite_status[$this->Special] = $this->Conn->GetCol($sql, 'ResourceId'); - } - - return isset($favorite_status[$this->Special][$object->GetDBField('ResourceId')]); - } - - /** - * Returns item's editors pick status (using not formatted value) - * - * @param Array $params - * @return bool - */ - function IsEditorsPick($params) - { - $object =& $this->getObject($params); - - return $object->GetDBField('EditorsPick') == 1; - } - - function FavoriteToggleLink($params) - { - $fav_prefix = $this->Prefix.'-fav'; - - $params['pass'] = implode(',', Array('m', $this->Prefix, $fav_prefix)); - $params[$fav_prefix.'_event'] = 'OnFavoriteToggle'; - - return $this->ItemLink($params); - } - - /** - * Checks if item is passed in url - * - * @param Array $params - * @return bool - */ - function ItemAvailable($params) - { - return $this->Application->GetVar($this->getPrefixSpecial().'_id') > 0; - } - - function SortingSelected($params) - { - $list =& $this->GetList($params); - $user_sorting_start = $this->getUserSortIndex(); - - $sorting_field = $list->GetOrderField($user_sorting_start); - $sorting = strtolower($sorting_field . '|' . $list->GetOrderDirection($user_sorting_start)); - - $field_options = $list->GetFieldOptions($sorting_field); - if (array_key_exists('formatter', $field_options) && $field_options['formatter'] == 'kMultiLanguage') { - // remove language prefix - $sorting = preg_replace('/^l[\d]+_(.*)/', '\\1', $sorting); - $params['sorting'] = preg_replace('/^l[\d]+_(.*)/', '\\1', $params['sorting']); - } - - return $sorting == strtolower($params['sorting']) ? $params['selected'] : ''; - } - - function CombinedSortingDropDownName($params) - { - return $this->Prefix.'_CombinedSorting'; - } - - /** - * Prepares name for field with event in it (used only on front-end) - * - * @param Array $params - * @return string - */ - function SubmitName($params) - { - return 'events['.$this->Prefix.']['.$params['event'].']'; - } - - /** - * Returns prefix + any word (used for shared between categories per page settings) - * - * @param Array $params - * @return string - */ - function VarName($params) - { - return $this->Prefix.'_'.$params['type']; - } - - /** - * Checks if we are viewing module root category - * - * @param Array $params - * @return bool - */ - function IsModuleHome($params) - { - $root_category = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); - - return $root_category == $this->Application->GetVar('m_cat_id'); - } - - /** - * Dynamic votes indicator - * - * @param Array $params - * - * @return string - */ - function VotesIndicator($params) - { - $object =& $this->getObject($params); - /* @var $object kDBItem */ - - $rating_helper =& $this->Application->recallObject('RatingHelper'); - /* @var $rating_helper RatingHelper */ - - $small_style = array_key_exists('small_style', $params) ? $params['small_style'] : false; - - return $rating_helper->ratingBar($object, true, '', $small_style); - } - - function RelevanceIndicator($params) - { - $object =& $this->getObject($params); - - $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; - $sql = 'SELECT Relevance - FROM '.$search_results_table.' - WHERE ResourceId = '.$object->GetDBField('ResourceId'); - - $percents_off = (int)(100 - (100 * $this->Conn->GetOne($sql))); - $percents_off = ($percents_off < 0) ? 0 : $percents_off; - if ($percents_off) { - $params['percent_off'] = $percents_off; - $params['percent_on'] = 100 - $percents_off; - $params['name'] = $this->SelectParam($params, 'relevance_normal_render_as,block_relevance_normal'); - } - else { - $params['name'] = $this->SelectParam($params, 'relevance_full_render_as,block_relevance_full'); - } - return $this->Application->ParseBlock($params); - } - - function SearchResultField($params) - { - $ret = $this->Field($params); - - $keywords = unserialize( $this->Application->RecallVar('highlight_keywords') ); - $opening = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_opening_render_as,block_highlight_opening')) ); - $closing = $this->Application->ParseBlock( Array('name' => $this->SelectParam($params, 'highlight_closing_render_as,block_highlight_closing')) ); - - foreach ($keywords as $index => $keyword) { - $keywords[$index] = preg_quote($keyword, '/'); - } - - return preg_replace('/('.implode('|', $keywords).')/i', $opening.'\\1'.$closing, $ret); - } - - /** - * Shows keywords, that user searched - * - * @param Array $params - * @return bool - */ - function SearchKeywords($params) - { - $keywords = $this->Application->GetVar('keywords'); - $sub_search = $this->Application->GetVar('search_type') == 'subsearch'; - - return ($keywords !== false) && !$sub_search ? $keywords : $this->Application->RecallVar('keywords'); - } - - function AdvancedSearchForm($params) - { - $search_table = $this->Application->getUnitOption('confs', 'TableName'); - $module_name = $this->Application->findModule('Var', $this->Prefix, 'Name'); - - $sql = 'SELECT * - FROM '.$search_table.' - WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1) - ORDER BY DisplayOrder'; - $search_config = $this->Conn->Query($sql); - - $ret = ''; - foreach ($search_config as $record) { - $params['name'] = $this->SelectParam($params, 'and_or_render_as,and_or_block'); - $params['field'] = $record['FieldName']; - $params['andor'] = $this->Application->ParseBlock($params); - - $params['name'] = $this->SelectParam($params, $record['FieldType'].'_render_as,'.$record['FieldType'].'_block'); - $params['caption'] = $this->Application->Phrase($record['DisplayName']); - $ret .= $this->Application->ParseBlock($params); - } - return $ret; - } - - /** - * Returns last modification date of items in category / system - * - * @param Array $params - * @return string - */ - function LastUpdated($params) - { - $category_id = $this->Application->GetVar('m_cat_id'); - $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); - - if (isset($params['local']) && $params['local'] && $category_id > 0) { - // scan only current category & it's children - $sql = 'SELECT TreeLeft, TreeRight - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$category_id; - $tree_info = $this->Conn->GetRow($sql); - - $sql = 'SELECT MAX(item_table.Modified) AS ModDate, MAX(item_table.CreatedOn) AS NewDate - FROM '.$table_name.' item_table - LEFT JOIN '.TABLE_PREFIX.'CategoryItems ci ON (item_table.ResourceId = ci.ItemResourceId) - LEFT JOIN '.TABLE_PREFIX.'Category c ON c.CategoryId = ci.CategoryId - WHERE c.TreeLeft BETWEEN '.$tree_info['TreeLeft'].' AND '.$tree_info['TreeRight']; - } - else { - // scan all categories in system - $sql = 'SELECT MAX(Modified) AS ModDate, MAX(CreatedOn) AS NewDate - FROM '.$table_name; - } - - $row_data = $this->Conn->GetRow($sql); - if (!$row_data) { - return ''; - } - - $date = $row_data[ $row_data['NewDate'] > $row_data['ModDate'] ? 'NewDate' : 'ModDate' ]; - - // format date - $format = isset($params['format']) ? $params['format'] : '_regional_DateTimeFormat'; - if (preg_match("/_regional_(.*)/", $format, $regs)) { - $lang =& $this->Application->recallObject('lang.current'); - if ($regs[1] == 'DateTimeFormat') { - // combined format - $format = $lang->GetDBField('DateFormat').' '.$lang->GetDBField('TimeFormat'); - } - else { - // simple format - $format = $lang->GetDBField($regs[1]); - } - } - - return adodb_date($format, $date); - } - - /** - * Counts category item count in system (not category-dependent) - * - * @param Array $params - * @return int - */ - function ItemCount($params) - { - $count_helper =& $this->Application->recallObject('CountHelper'); - /* @var $count_helper kCountHelper */ - - $today_only = isset($params['today']) && $params['today']; - return $count_helper->ItemCount($this->Prefix, $today_only); - } - - function CategorySelector($params) - { - $category_id = isset($params['category_id']) && is_numeric($params['category_id']) ? $params['category_id'] : false; - if ($category_id === false) { - // if category id not given use module root category - $category_id = $this->Application->findModule('Var', $this->Prefix, 'RootCat'); - } - - $id_field = $this->Application->getUnitOption('c', 'IDField'); - $title_field = $this->Application->getUnitOption('c', 'TitleField'); - $table_name = $this->Application->getUnitOption('c', 'TableName'); - - $count_helper =& $this->Application->recallObject('CountHelper'); - /* @var $count_helper kCountHelper */ - - list ($view_perm, $view_filter) = $count_helper->GetPermissionClause('c', 'perm_cache'); - - // get category list (permission based) - $sql = 'SELECT c.'.$title_field.', c.'.$id_field.' - FROM '.$table_name.' c - INNER JOIN '.TABLE_PREFIX.'PermCache perm_cache ON c.CategoryId = perm_cache.CategoryId - WHERE (ParentId = '.$category_id.') AND ('.$view_filter.') AND (perm_cache.PermId = '.$view_perm.') AND (c.Status = '.STATUS_ACTIVE.') - ORDER BY c.'.$title_field.' ASC'; - $categories = $this->Conn->GetCol($sql, $id_field); - - $block_params = $this->prepareTagParams($params); - $block_params['name'] = $params['render_as']; - $block_params['strip_nl'] = 2; - - $ret = ''; - foreach ($categories as $category_id => $category_name) { - // print category - $block_params['separator'] = isset($params['category_id']) ? $params['separator'] : ''; // return original separator, remove separator for top level categories - $block_params['category_id'] = $category_id; - $block_params['category_name'] = $category_name; - $ret .= $this->Application->ParseBlock($block_params); - - // print it's children - $block_params['separator'] = '   '.$params['separator']; - $ret .= $this->CategorySelector($block_params); - } - - return $ret; - } - - function PrintMoreCategories($params) - { - $object =& $this->getObject(); - /* @var $object kDBItem */ - - $category_ids = $this->Field($params); - if (!$category_ids) { - return ''; - } - - $category_ids = explode('|', substr($category_ids, 1, -1)); - - $id_field = $this->Application->getUnitOption('c', 'IDField'); - $title_field = $this->Application->getUnitOption('c', 'TitleField'); - $table_name = $this->Application->getUnitOption('c', 'TableName'); - - $sql = 'SELECT '.$title_field.', '.$id_field.' - FROM '.$table_name.' - WHERE '.$id_field.' IN ('.implode(',', $category_ids).')'; - $categories = $this->Conn->GetCol($sql, $id_field); - - $block_params = $this->prepareTagParams($params); - $block_params['name'] = $params['render_as']; - - $ret = ''; - foreach ($categories as $category_id => $category_name) { - $block_params['category_id'] = $category_id; - $block_params['category_name'] = $category_name; - $ret .= $this->Application->ParseBlock($block_params); - } - - return $ret; - } - - function DownloadFileLink($params) - { - $params[$this->getPrefixSpecial().'_event'] = 'OnDownloadFile'; - - return $this->ItemLink($params); - } - - function ImageSrc($params) - { - list ($ret, $tag_processed) = $this->processAggregatedTag('ImageSrc', $params, $this->getPrefixSpecial()); - return $tag_processed ? $ret : false; - } - - /** - * Registers hit for item (one time per session) - * - * @param Array $params - */ - function RegisterHit($params) - { - $object =& $this->getObject(); - /* @var $object kCatDBItem */ - - if ($object->isLoaded()) { - $object->RegisterHit(); - } - } - - /** - * Returns link to item's author public profile - * - * @param Array $params - * @return string - */ - function ProfileLink($params) - { - $object =& $this->getObject($params); - $owner_field = array_key_exists('owner_field', $params) ? $params['owner_field'] : 'CreatedById'; - $params['user_id'] = $object->GetDBField($owner_field); - unset($params['owner_field']); - - return $this->Application->ProcessParsedTag('m', 'Link', $params); - } - - /** - * Checks, that "view in browse mode" functionality available - * - * @param Array $params - * @return bool - */ - function BrowseModeAvailable($params) - { - $valid_special = $valid_special = $params['Special'] != 'user'; - $not_selector = $this->Application->GetVar('type') != 'item_selector'; - - return $valid_special && $not_selector; - } - - /** - * Returns a link for editing product - * - * @param Array $params - * @return string - */ - function ItemEditLink($params) - { - $object =& $this->getObject(); - /* @var $object kDBList */ - - $edit_template = $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePath') . '/' . $this->Application->getUnitOption($this->Prefix, 'AdminTemplatePrefix') . 'edit'; - - $url_params = Array ( - 'm_opener' => 'd', - $this->Prefix.'_mode' => 't', - $this->Prefix.'_event' => 'OnEdit', - $this->Prefix.'_id' => $object->GetID(), - 'm_cat_id' => $object->GetDBField('CategoryId'), - 'pass' => 'all,'.$this->Prefix, - 'no_pass_through' => 1, - ); - - return $this->Application->HREF($edit_template,'', $url_params); - } - - function LanguageVisible($params) - { - $field = $this->SelectParam($params, 'name,field'); - - preg_match('/l([\d]+)_(.*)/', $field, $regs); - $params['name'] = $regs[2]; - - return $this->HasLanguageError($params) || $this->Application->GetVar('m_lang') == $regs[1]; - } - - function HasLanguageError($params) - { - static $languages = null; - - if (!isset($languages)) { - $sql = 'SELECT ' . $this->Application->getUnitOption('lang', 'IDField') . ' - FROM ' . $this->Application->getUnitOption('lang', 'TableName') . ' - WHERE Enabled = 1'; - $languages = $this->Conn->GetCol($sql); - } - - $field = $this->SelectParam($params, 'name,field'); - - $object =& $this->getObject($params); - /* @var $object kDBItem */ - - foreach ($languages as $language_id) { - $check_field = 'l' . $language_id . '_' . $field; - if ($object->GetErrorMsg($check_field, false)) { - return true; - } - } - - return false; - } - } \ No newline at end of file Index: branches/5.0.x/core/kernel/db/cat_event_handler.php =================================================================== diff -u -N -r12299 -r12343 --- branches/5.0.x/core/kernel/db/cat_event_handler.php (.../units/general/cat_event_handler.php) (revision 12299) +++ branches/5.0.x/core/kernel/db/cat_event_handler.php (.../kernel/db/cat_event_handler.php) (revision 12343) @@ -1,6 +1,6 @@ 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'), Array ('class' => 'kBracketsHelper', 'pseudo' => 'BracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'), Array ('class' => 'kXMLHelper', 'pseudo' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'), + Array ('class' => 'kCatDBItemExportHelper', 'pseudo' => 'CatItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'), ), ); \ No newline at end of file Index: branches/5.0.x/core/units/sections/site_config_tp.php =================================================================== diff -u -N -r12299 -r12343 --- branches/5.0.x/core/units/sections/site_config_tp.php (.../site_config_tp.php) (revision 12299) +++ branches/5.0.x/core/units/sections/site_config_tp.php (.../site_config_tp.php) (revision 12343) @@ -1,6 +1,6 @@ SessionTimeout = $this->Application->ConfigValue('SessionTimeout'); - - $path = (BASE_PATH == '') ? '/' : BASE_PATH; -// if ( $this->Application->IsAdmin() ) $path = rtrim($path, '/').'/admin'; - $this->SetCookiePath($path); - - $cookie_name = $this->Application->ConfigValue('SessionCookieName'); - if (!$cookie_name) $cookie_name = 'sid'; - if (($this->Application->IsAdmin() && $special !== 'front') || $special == 'admin' ) { // || $this->Application->GetVar('admin') == 1 - $cookie_name = 'adm_'.$cookie_name; - } - $this->SetCookieName($cookie_name); - - $this->SetCookieDomain(SERVER_NAME); - - if( $this->Application->IsAdmin()) { // && $this->Application->GetVar('admin') != 1 - $mode = smAUTO; - } - elseif (constOn('IS_INSTALL')) { - $mode = smCOOKIES_ONLY; - } - else { - $ses_mode = $this->Application->ConfigValue('CookieSessions'); - if ($ses_mode == 2) $mode = smAUTO; - if ($ses_mode == 1) $mode = smCOOKIES_ONLY; - if ($ses_mode == 0) $mode = smGET_ONLY; - } - $this->SetMode($mode); - - parent::Init($prefix,$special); - - if( !$this->Application->IsAdmin() && $this->GetField('PortalUserId') <= 0 ) - { - $group_list = $this->Application->ConfigValue('User_GuestGroup').','.$this->Application->ConfigValue('User_LoggedInGroup'); - $this->SetField('GroupId', $this->Application->ConfigValue('User_GuestGroup')); - $this->SetField('GroupList', $group_list); - } - } - - function Destroy() - { - $this->Storage->DeleteSession($this); - $this->Storage->DeleteEditTables(); - $this->Data = new Params(); - $this->SID = $this->CachedSID = ''; - if ($this->CookiesEnabled) $this->SetSessionCookie(); //will remove the cookie due to value (sid) is empty - - $this->SetSession(); //will create a new session - } - - } - -class InpSessionStorage extends SessionStorage { - - function Init($prefix,$special) - { - parent::Init($prefix,$special); - $this->setTableName(TABLE_PREFIX.'UserSession'); - $this->SessionDataTable = TABLE_PREFIX.'SessionData'; - $this->setIDField('SessionKey'); - $this->TimestampField = 'LastAccessed'; - $this->DataValueField = 'VariableValue'; - $this->DataVarField = 'VariableName'; - } - - function LocateSession($sid) - { - $res = parent::LocateSession($sid); - if ($res) { - $this->Expiration += $this->SessionTimeout; - } - return $res; - } - - function UpdateSession(&$session) - { - $time = adodb_mktime(); - // Update LastAccessed only if it's newer than 1/10 of session timeout - perfomance optimization to eliminate needless updates on every click -// if ($time - $this->DirectVars['LastAccessed'] > $this->SessionTimeout/10) { - $this->SetField($session, $this->TimestampField, $time + $this->SessionTimeout); -// } - } - - - function StoreSession(&$session, $additional_fields = Array()) - { - $fields_hash = Array ( - 'PortalUserId' => $this->Application->IsAdmin() ? 0 : -2, // Guest - 'Language' => $this->Application->GetDefaultLanguageId(), - 'Theme' => $this->Application->GetDefaultThemeId(), - 'IpAddress' => $_SERVER['REMOTE_ADDR'], - 'GroupId' => $this->Application->ConfigValue('User_GuestGroup'), - 'GroupList' => $this->Application->ConfigValue('User_GuestGroup'), - 'CurrentTempKey'=> $session->SID, - ); - - parent::StoreSession($session, $fields_hash); - } - - function GetExpiredSIDs() - { - $query = ' SELECT '.$this->IDField.' FROM '.$this->TableName.' WHERE '.$this->TimestampField.' < '.(adodb_mktime()); - $ret = $this->Conn->GetCol($query); - if($ret) { - $this->DeleteEditTables(); - } - return $ret; - - } - - function DeleteEditTables() - { - $tables = $this->Conn->GetCol('SHOW TABLES'); - $mask_edit_table = '/'.TABLE_PREFIX.'ses_(.*)_edit_(.*)/'; - $mask_search_table = '/'.TABLE_PREFIX.'ses_(.*?)_(.*)/'; - - $sql='SELECT COUNT(*) FROM '.$this->TableName.' WHERE '.$this->IDField.' = \'%s\''; - foreach($tables as $table) - { - if( preg_match($mask_edit_table,$table,$rets) || preg_match($mask_search_table,$table,$rets) ) - { - $sid = preg_replace('/(.*)_(.*)/', '\\1', $rets[1]); // remove popup's wid from sid - $is_alive = $this->Conn->GetOne( sprintf($sql,$sid) ); - if(!$is_alive) $this->Conn->Query('DROP TABLE IF EXISTS '.$table); - } - } - } -} \ No newline at end of file Index: branches/5.0.x/core/kernel/processors/main_processor.php =================================================================== diff -u -N -r12325 -r12343 --- branches/5.0.x/core/kernel/processors/main_processor.php (.../main_processor.php) (revision 12325) +++ branches/5.0.x/core/kernel/processors/main_processor.php (.../main_processor.php) (revision 12343) @@ -1,6 +1,6 @@