Index: branches/RC/core/units/general/cat_event_handler.php
===================================================================
diff -u -N
--- branches/RC/core/units/general/cat_event_handler.php (revision 11892)
+++ branches/RC/core/units/general/cat_event_handler.php (revision 0)
@@ -1,2653 +0,0 @@
-Factory->includeClassFile('kDBEventHandler');
-
-class kCatDBEventHandler extends kDBEventHandler {
-
- /**
- * Allows to override standart permission mapping
- *
- */
- function mapPermissions()
- {
- parent::mapPermissions();
- $permissions = Array(
- 'OnSaveSettings' => Array ('self' => 'add|edit|advanced:import'),
- 'OnResetSettings' => Array ('self' => 'add|edit|advanced:import'),
- 'OnBeforeDeleteOriginal' => Array ('self' => 'edit|advanced:approve'),
-
- 'OnCopy' => Array ('self' => true),
- 'OnDownloadFile' => Array ('self' => 'view'),
- 'OnCancelAction' => Array ('self' => true),
- 'OnItemBuild' => Array ('self' => true),
- 'OnMakeVote' => Array ('self' => true),
- );
-
- $this->permMapping = array_merge($this->permMapping, $permissions);
- }
-
- /**
- * Load item if id is available
- *
- * @param kEvent $event
- */
- function LoadItem(&$event)
- {
- $object =& $event->getObject();
- $id = $this->getPassedID($event);
- if ($object->Load($id)) {
- $actions =& $this->Application->recallObject('kActions');
- $actions->Set($event->Prefix_Special.'_id', $object->GetID() );
-
- $use_pending_editing = $this->Application->getUnitOption($event->Prefix, 'UsePendingEditing');
- if ($use_pending_editing && $event->Special != 'original') {
- $this->Application->SetVar($event->Prefix.'.original_id', $object->GetDBField('OrgId'));
- }
- }
- else {
- $object->setID($id);
- }
- }
-
- /**
- * Checks permissions of user
- *
- * @param kEvent $event
- */
- function CheckPermission(&$event)
- {
- if (!$this->Application->IsAdmin()) {
- if ($event->Name == 'OnSetSortingDirect') {
- // allow sorting on front event without view permission
- return true;
- }
- }
-
- if ($event->Name == 'OnExport') {
- // save category_id before doing export
- $this->Application->LinkVar('m_cat_id');
- }
-
- if (in_array($event->Name, $this->_getMassPermissionEvents())) {
- $items = $this->_getPermissionCheckInfo($event);
-
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- if (($event->Name == 'OnSave') && array_key_exists(0, $items)) {
- // adding new item (ID = 0)
- $perm_value = $perm_helper->AddCheckPermission($items[0]['CategoryId'], $event->Prefix) > 0;
- }
- else {
- // leave only items, that can be edited
- $ids = Array ();
- $check_method = in_array($event->Name, Array ('OnMassDelete', 'OnCut')) ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
- foreach ($items as $item_id => $item_data) {
- if ($perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) > 0) {
- $ids[] = $item_id;
- }
- }
-
- if (!$ids) {
- // no items left for editing -> no permission
- return $perm_helper->finalizePermissionCheck($event, false);
- }
-
- $perm_value = true;
- $event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method
- }
-
- return $perm_helper->finalizePermissionCheck($event, $perm_value);
- }
-
- $export_events = Array ('OnSaveSettings', 'OnResetSettings', 'OnExportBegin');
- if (in_array($event->Name, $export_events)) {
- // when import settings before selecting target import category
- return $this->Application->CheckPermission('in-portal:main_import.view');
- }
-
- if ($event->Name == 'OnProcessSelected') {
- if ($this->Application->RecallVar('dst_field') == 'ImportCategory') {
- // when selecting target import category
- return $this->Application->CheckPermission('in-portal:main_import.view');
- }
- }
-
- return parent::CheckPermission($event);
- }
-
- /**
- * Returns events, that require item-based (not just event-name based) permission check
- *
- * @return Array
- */
- function _getMassPermissionEvents()
- {
- return Array (
- 'OnEdit', 'OnSave', 'OnMassDelete', 'OnMassApprove',
- 'OnMassDecline', 'OnMassMoveUp', 'OnMassMoveDown',
- 'OnCut',
- );
- }
-
- /**
- * Returns category item IDs, that require permission checking
- *
- * @param kEvent $event
- * @return string
- */
- function _getPermissionCheckIDs(&$event)
- {
- if ($event->Name == 'OnSave') {
- $selected_ids = implode(',', $this->getSelectedIDs($event, true));
- if (!$selected_ids) {
- $selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
- }
- }
- else {
- // OnEdit, OnMassDelete events, when items are checked in grid
- $selected_ids = implode(',', $this->StoreSelectedIDs($event));
- }
-
- return $selected_ids;
- }
-
- /**
- * Returns information used in permission checking
- *
- * @param kEvent $event
- * @return Array
- */
- function _getPermissionCheckInfo(&$event)
- {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- // when saving data from temp table to live table check by data from temp table
- $item_ids = $this->_getPermissionCheckIDs($event);
- $items = $perm_helper->GetCategoryItemData($event->Prefix, $item_ids, $event->Name == 'OnSave');
-
- if (!$items) {
- // when item not present in temp table, then permission is not checked, because there are no data in db to check
- $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
- list ($id, $fields_hash) = each($items_info);
-
- if (array_key_exists('CategoryId', $fields_hash)) {
- $item_category = $fields_hash['CategoryId'];
- }
- else {
- $item_category = $this->Application->GetVar('m_cat_id');
- }
-
- $items[$id] = Array (
- 'CreatedById' => $this->Application->RecallVar('use_id'),
- 'CategoryId' => $item_category,
- );
- }
-
- return $items;
- }
-
- /**
- * Add selected items to clipboard with mode = COPY (CLONE)
- *
- * @param kEvent $event
- */
- function OnCopy(&$event)
- {
- $this->Application->RemoveVar('clipboard');
- $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
- $clipboard_helper->setClipboard($event, 'copy', $this->StoreSelectedIDs($event));
- $this->clearSelectedIDs($event);
- }
-
- /**
- * Add selected items to clipboard with mode = CUT
- *
- * @param kEvent $event
- */
- function OnCut(&$event)
- {
- $this->Application->RemoveVar('clipboard');
- $clipboard_helper =& $this->Application->recallObject('ClipboardHelper');
- $clipboard_helper->setClipboard($event, 'cut', $this->StoreSelectedIDs($event));
- $this->clearSelectedIDs($event);
- }
-
- /**
- * Checks permission for OnPaste event
- *
- * @param kEvent $event
- * @return bool
- */
- function _checkPastePermission(&$event)
- {
- $perm_helper =& $this->Application->recallObject('PermissionsHelper');
- /* @var $perm_helper kPermissionsHelper */
-
- $category_id = $this->Application->GetVar('m_cat_id');
- if ($perm_helper->AddCheckPermission($category_id, $event->Prefix) == 0) {
- // no items left for editing -> no permission
- return $perm_helper->finalizePermissionCheck($event, false);
- }
-
- return true;
- }
-
- /**
- * Performs category item paste
- *
- * @param kEvent $event
- */
- function OnPaste(&$event)
- {
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) {
- return;
- }
-
- $clipboard_data = $event->getEventParam('clipboard_data');
-
- if (!$clipboard_data['cut'] && !$clipboard_data['copy']) {
- return false;
- }
-
- if ($clipboard_data['copy']) {
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
- /* @var $temp kTempTablesHandler */
-
- $this->Application->SetVar('ResetCatBeforeClone', 1); // used in "kCatDBEventHandler::OnBeforeClone"
- $temp->CloneItems($event->Prefix, $event->Special, $clipboard_data['copy']);
- }
-
- if ($clipboard_data['cut']) {
- $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix, Array('skip_autoload' => true));
-
- foreach ($clipboard_data['cut'] as $id) {
- $object->Load($id);
- $object->MoveToCat();
- }
- }
- }
-
- /**
- * Deletes all selected items.
- * Automatically recurse into sub-items using temp handler, and deletes sub-items
- * by calling its Delete method if sub-item has AutoDelete set to true in its config file
- *
- * @param kEvent $event
- */
- function OnMassDelete(&$event)
- {
- if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
- return;
- }
-
- $event->status=erSUCCESS;
-
- $ids = $this->StoreSelectedIDs($event);
-
- $to_delete = array();
- if ($recycle_bin = $this->Application->ConfigValue('RecycleBinFolder')) {
- $rb =& $this->Application->recallObject('c.recycle', null, array('skip_autoload' => true));
- $rb->Load($recycle_bin);
- $object =& $this->Application->recallObject($event->Prefix.'.recycleitem', null, Array ('skip_autoload' => true));
- foreach ($ids as $id) {
- $object->Load($id);
- if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $object->GetDBField('ParentPath'))) {
- $to_delete[] = $id;
- continue;
- }
- $object->MoveToCat($recycle_bin);
- }
- $ids = $to_delete;
- }
-
- $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
-
- $event->setEventParam('ids', $ids);
- $this->customProcessing($event, 'before');
- $ids = $event->getEventParam('ids');
-
- if($ids)
- {
- $temp->DeleteItems($event->Prefix, $event->Special, $ids);
- }
- $this->clearSelectedIDs($event);
- }
-
-
- /**
- * Return type clauses for list bulding on front
- *
- * @param kEvent $event
- * @return Array
- */
- function getTypeClauses(&$event)
- {
- $types = $event->getEventParam('types');
- $types = $types ? explode(',', $types) : Array ();
-
- $except_types = $event->getEventParam('except');
- $except_types = $except_types ? explode(',', $except_types) : Array ();
-
- $type_clauses = Array();
-
- $user_id = $this->Application->RecallVar('user_id');
- $owner_field = $this->getOwnerField($event->Prefix);
-
- $type_clauses['my_items']['include'] = '%1$s.'.$owner_field.' = '.$user_id;
- $type_clauses['my_items']['except'] = '%1$s.'.$owner_field.' <> '.$user_id;
- $type_clauses['my_items']['having_filter'] = false;
-
- $type_clauses['pick']['include'] = '%1$s.EditorsPick = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
- $type_clauses['pick']['except'] = '%1$s.EditorsPick! = 1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
- $type_clauses['pick']['having_filter'] = false;
-
- $type_clauses['hot']['include'] = '`IsHot` = 1 AND PrimaryCat = 1';
- $type_clauses['hot']['except'] = '`IsHot`! = 1 AND PrimaryCat = 1';
- $type_clauses['hot']['having_filter'] = true;
-
- $type_clauses['pop']['include'] = '`IsPop` = 1 AND PrimaryCat = 1';
- $type_clauses['pop']['except'] = '`IsPop`! = 1 AND PrimaryCat = 1';
- $type_clauses['pop']['having_filter'] = true;
-
- $type_clauses['new']['include'] = '`IsNew` = 1 AND PrimaryCat = 1';
- $type_clauses['new']['except'] = '`IsNew`! = 1 AND PrimaryCat = 1';
- $type_clauses['new']['having_filter'] = true;
-
- $type_clauses['displayed']['include'] = '';
- $displayed = $this->Application->GetVar($event->Prefix.'_displayed_ids');
- if ($displayed) {
- $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
- $type_clauses['displayed']['except'] = '%1$s.'.$id_field.' NOT IN ('.$displayed.')';
- }
- else {
- $type_clauses['displayed']['except'] = '';
- }
- $type_clauses['displayed']['having_filter'] = false;
-
- if (in_array('search', $types) || in_array('search', $except_types)) {
- $event_mapping = Array(
- 'simple' => 'OnSimpleSearch',
- 'subsearch' => 'OnSubSearch',
- 'advanced' => 'OnAdvancedSearch');
- if($this->Application->GetVar('INPORTAL_ON') && $this->Application->GetVar('Action') == 'm_simple_subsearch')
- {
- $type = 'subsearch';
- }
- else
- {
- $type = $this->Application->GetVar('search_type') ? $this->Application->GetVar('search_type') : 'simple';
- }
-
- if($keywords = $event->getEventParam('keyword_string')) // processing keyword_string param of ListProducts tag
- {
- $this->Application->SetVar('keywords', $keywords);
- $type = 'simple';
- }
- $search_event = $event_mapping[$type];
- $this->$search_event($event);
-
- $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search';
- $sql = 'SHOW TABLES LIKE "'.$search_table.'"';
- if ($this->Conn->Query($sql)) {
- $search_res_ids = $this->Conn->GetCol('SELECT ResourceId FROM '.$search_table);
- }
-
- if (isset($search_res_ids) && $search_res_ids) {
- $type_clauses['search']['include'] = '%1$s.ResourceId IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
- $type_clauses['search']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $search_res_ids).') AND PrimaryCat = 1 AND ('.TABLE_PREFIX.'Category.Status = '.STATUS_ACTIVE.')';
- }
- else {
- $type_clauses['search']['include'] = '0';
- $type_clauses['search']['except'] = '1';
- }
- $type_clauses['search']['having_filter'] = false;
- }
-
- if (in_array('related', $types) || in_array('related', $except_types)) {
-
- $related_to = $event->getEventParam('related_to');
- if (!$related_to) {
- $related_prefix = $event->Prefix;
- }
- else {
- $sql = 'SELECT Prefix
- FROM '.TABLE_PREFIX.'ItemTypes
- WHERE ItemName = '.$this->Conn->qstr($related_to);
- $related_prefix = $this->Conn->GetOne($sql);
- }
-
- $rel_table = $this->Application->getUnitOption('rel', 'TableName');
- $item_type = (int)$this->Application->getUnitOption($event->Prefix, 'ItemType');
-
- if ($item_type == 0) {
- trigger_error('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');
-
- // 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