Index: branches/5.0.x/core/units/categories/categories_event_handler.php =================================================================== diff -u -r12277 -r12299 --- branches/5.0.x/core/units/categories/categories_event_handler.php (.../categories_event_handler.php) (revision 12277) +++ branches/5.0.x/core/units/categories/categories_event_handler.php (.../categories_event_handler.php) (revision 12299) @@ -1,6 +1,6 @@ Array ('self' => 'add|edit'), - 'OnCopy' => Array ('self' => true), - 'OnCut' => Array ('self' => 'edit'), - 'OnPasteClipboard' => Array ('self' => true), - 'OnPaste' => Array ('self' => 'add|edit', 'subitem' => 'edit'), + /** + * Allows to override standart permission mapping + * + */ + function mapPermissions() + { + parent::mapPermissions(); - 'OnRecalculatePriorities' => Array ('self' => 'add|edit'), // category ordering - 'OnItemBuild' => Array ('self' => true), // always allow to view individual categories (regardless of CATEGORY.VIEW right) - 'OnUpdatePreviewBlock' => Array ('self' => true), // for FCKEditor integration - ); + $permissions = Array ( + 'OnRebuildCache' => Array ('self' => 'add|edit'), + 'OnCopy' => Array ('self' => true), + 'OnCut' => Array ('self' => 'edit'), + 'OnPasteClipboard' => Array ('self' => true), + 'OnPaste' => Array ('self' => 'add|edit', 'subitem' => 'edit'), - $this->permMapping = array_merge($this->permMapping, $permissions); - } + 'OnRecalculatePriorities' => Array ('self' => 'add|edit'), // category ordering + 'OnItemBuild' => Array ('self' => true), // always allow to view individual categories (regardless of CATEGORY.VIEW right) + 'OnUpdatePreviewBlock' => Array ('self' => true), // for FCKEditor integration + ); - /** - * Categories are sorted using special sorting event - * - */ - function mapEvents() - { - parent::mapEvents(); + $this->permMapping = array_merge($this->permMapping, $permissions); + } - $events_map = Array ( - 'OnMassMoveUp' => 'OnChangePriority', - 'OnMassMoveDown' => 'OnChangePriority', - ); + /** + * Categories are sorted using special sorting event + * + */ + function mapEvents() + { + parent::mapEvents(); - $this->eventMethods = array_merge($this->eventMethods, $events_map); - } + $events_map = Array ( + 'OnMassMoveUp' => 'OnChangePriority', + 'OnMassMoveDown' => 'OnChangePriority', + ); - /** - * 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; - } + $this->eventMethods = array_merge($this->eventMethods, $events_map); + } - if ($event->Name == 'OnItemBuild') { - $category_id = $this->getPassedID($event); - if ($category_id == 0) { + /** + * 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 == 'OnItemBuild') { + $category_id = $this->getPassedID($event); + if ($category_id == 0) { + return true; + } + } } - } - if (in_array($event->Name, $this->_getMassPermissionEvents())) { - $items = $this->_getPermissionCheckInfo($event); + if (in_array($event->Name, $this->_getMassPermissionEvents())) { + $items = $this->_getPermissionCheckInfo($event); - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ + $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]['ParentId'], $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['ParentId'], $event->Prefix) > 0) { - $ids[] = $item_id; - } + if (($event->Name == 'OnSave') && array_key_exists(0, $items)) { + // adding new item (ID = 0) + $perm_value = $perm_helper->AddCheckPermission($items[0]['ParentId'], $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['ParentId'], $event->Prefix) > 0) { + $ids[] = $item_id; + } + } - if (!$ids) { - // no items left for editing -> no permission - return $perm_helper->finalizePermissionCheck($event, false); + 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 } - $perm_value = true; - $event->setEventParam('ids', $ids); // will be used later by "kDBEventHandler::StoreSelectedIDs" method + return $perm_helper->finalizePermissionCheck($event, $perm_value); } - return $perm_helper->finalizePermissionCheck($event, $perm_value); + if ($event->Name == 'OnPasteClipboard') { + // forces permission check to work by current category for "Paste In Category" operation + $category_id = $this->Application->GetVar('m_cat_id'); + $this->Application->SetVar('c_id', $category_id); + } + + return parent::CheckPermission($event); } - if ($event->Name == 'OnPasteClipboard') { - // forces permission check to work by current category for "Paste In Category" operation - $category_id = $this->Application->GetVar('m_cat_id'); - $this->Application->SetVar('c_id', $category_id); + /** + * 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', + ); } - 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) + /** + * 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; } - 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) + { + // when saving data from temp table to live table check by data from temp table + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); - /** - * Returns information used in permission checking - * - * @param kEvent $event - * @return Array - */ - function _getPermissionCheckInfo(&$event) - { - // when saving data from temp table to live table check by data from temp table - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); + if ($event->Name == 'OnSave') { + $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $event->Prefix); + } - if ($event->Name == 'OnSave') { - $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $event->Prefix); - } + $sql = 'SELECT ' . $id_field . ', CreatedById, ParentId + FROM ' . $table_name . ' + WHERE ' . $id_field . ' IN (' . $this->_getPermissionCheckIDs($event) . ')'; + $items = $this->Conn->Query($sql, $id_field); - $sql = 'SELECT ' . $id_field . ', CreatedById, ParentId - FROM ' . $table_name . ' - WHERE ' . $id_field . ' IN (' . $this->_getPermissionCheckIDs($event) . ')'; - $items = $this->Conn->Query($sql, $id_field); + if (!$items) { + // when creating new category, then no IDs are stored in session + $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); + list ($id, $fields_hash) = each($items_info); - if (!$items) { - // when creating new category, then no IDs are stored in session - $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - list ($id, $fields_hash) = each($items_info); + if (array_key_exists('ParentId', $fields_hash)) { + $item_category = $fields_hash['ParentId']; + } + else { + $item_category = $this->Application->RecallVar('m_cat_id'); // saved in c:OnPreCreate event permission checking + } - if (array_key_exists('ParentId', $fields_hash)) { - $item_category = $fields_hash['ParentId']; + $items[$id] = Array ( + 'CreatedById' => $this->Application->RecallVar('user_id'), + 'ParentId' => $item_category, + ); } - else { - $item_category = $this->Application->RecallVar('m_cat_id'); // saved in c:OnPreCreate event permission checking - } - $items[$id] = Array ( - 'CreatedById' => $this->Application->RecallVar('user_id'), - 'ParentId' => $item_category, - ); + return $items; } - return $items; - } + /** + * Set's mark, that root category is edited + * + * @param kEvent $event + */ + function OnEdit(&$event) + { + $category_id = $this->Application->GetVar($event->getPrefixSpecial().'_id'); + $this->Application->StoreVar('IsRootCategory_'.$this->Application->GetVar('m_wid'), $category_id === '0'); - /** - * Set's mark, that root category is edited - * - * @param kEvent $event - */ - function OnEdit(&$event) - { - $category_id = $this->Application->GetVar($event->getPrefixSpecial().'_id'); - $this->Application->StoreVar('IsRootCategory_'.$this->Application->GetVar('m_wid'), $category_id === '0'); + parent::OnEdit($event); + } - parent::OnEdit($event); - } + /** + * Adds selected link to listing + * + * @param kEvent $event + */ + function OnProcessSelected(&$event) + { + $object =& $event->getObject(); + /* @var $object kDBItem */ - /** - * Adds selected link to listing - * - * @param kEvent $event - */ - function OnProcessSelected(&$event) - { - $object =& $event->getObject(); - /* @var $object kDBItem */ + $selected_ids = $this->Application->GetVar('selected_ids'); - $selected_ids = $this->Application->GetVar('selected_ids'); + $this->RemoveRequiredFields($object); + $object->SetDBField($this->Application->RecallVar('dst_field'), $selected_ids['c']); + $object->Update(); - $this->RemoveRequiredFields($object); - $object->SetDBField($this->Application->RecallVar('dst_field'), $selected_ids['c']); - $object->Update(); + $this->finalizePopup($event); + } - $this->finalizePopup($event); - } + /** + * Apply system filter to categories list + * + * @param kEvent $event + */ + function SetCustomQuery(&$event) + { + parent::SetCustomQuery($event); - /** - * Apply system filter to categories list - * - * @param kEvent $event - */ - function SetCustomQuery(&$event) - { - parent::SetCustomQuery($event); + $object =& $event->getObject(); + /* @var $object kDBList */ - $object =& $event->getObject(); - /* @var $object kDBList */ + // don't show "Content" category in advanced view + $object->addFilter('system_categories', '%1$s.Status <> 4'); - // don't show "Content" category in advanced view - $object->addFilter('system_categories', '%1$s.Status <> 4'); + // show system templates from current theme only + all virtual templates + $object->addFilter('theme_filter', '%1$s.ThemeId = ' . $this->_getCurrentThemeId() . ' OR %1$s.ThemeId = 0'); - // show system templates from current theme only + all virtual templates - $object->addFilter('theme_filter', '%1$s.ThemeId = ' . $this->_getCurrentThemeId() . ' OR %1$s.ThemeId = 0'); + if ($event->Special == 'showall') { + // if using recycle bin don't show categories from there + $recycle_bin = $this->Application->ConfigValue('RecycleBinFolder'); + if ($recycle_bin) { + $sql = 'SELECT TreeLeft, TreeRight + FROM '.TABLE_PREFIX.'Category + WHERE CategoryId = '.$recycle_bin; + $tree_indexes = $this->Conn->GetRow($sql); - if ($event->Special == 'showall') { - // if using recycle bin don't show categories from there - $recycle_bin = $this->Application->ConfigValue('RecycleBinFolder'); - if ($recycle_bin) { - $sql = 'SELECT TreeLeft, TreeRight - FROM '.TABLE_PREFIX.'Category - WHERE CategoryId = '.$recycle_bin; - $tree_indexes = $this->Conn->GetRow($sql); - - $object->addFilter('recyclebin_filter', '%1$s.TreeLeft < '.$tree_indexes['TreeLeft'].' OR %1$s.TreeLeft > '.$tree_indexes['TreeRight']); + $object->addFilter('recyclebin_filter', '%1$s.TreeLeft < '.$tree_indexes['TreeLeft'].' OR %1$s.TreeLeft > '.$tree_indexes['TreeRight']); + } } - } - if ($event->getEventParam('parent_cat_id') !== false) { - $parent_cat_id = $event->getEventParam('parent_cat_id'); + if ($event->getEventParam('parent_cat_id') !== false) { + $parent_cat_id = $event->getEventParam('parent_cat_id'); - if ("$parent_cat_id" == 'Root') { - $module_name = $event->getEventParam('module') ? $event->getEventParam('module') : 'In-Commerce'; - $parent_cat_id = $this->Application->findModule('Name', $module_name, 'RootCat'); + if ("$parent_cat_id" == 'Root') { + $module_name = $event->getEventParam('module') ? $event->getEventParam('module') : 'In-Commerce'; + $parent_cat_id = $this->Application->findModule('Name', $module_name, 'RootCat'); + } } - } - else { - $parent_cat_id = $this->Application->GetVar('c_id'); - if (!$parent_cat_id) { - $parent_cat_id = $this->Application->GetVar('m_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) { - $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 ("$parent_cat_id" == '0') { - // replace "0" category with "Content" category id (this way template - $parent_cat_id = $this->Application->findModule('Name', 'Core', 'RootCat'); - } + if ("$parent_cat_id" != 'any') { + if ($event->getEventParam('recursive')) { + if ($parent_cat_id > 0) { + // not "Home" category + $tree_indexes = $this->Application->getTreeIndex($parent_cat_id); - if ("$parent_cat_id" != 'any') { - if ($event->getEventParam('recursive')) { - if ($parent_cat_id > 0) { - // not "Home" category - $tree_indexes = $this->Application->getTreeIndex($parent_cat_id); + $object->addFilter('parent_filter', TABLE_PREFIX.'Category.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight']); + } + } + else { + $object->addFilter('parent_filter', 'ParentId = '.$parent_cat_id); + } + } - $object->addFilter('parent_filter', TABLE_PREFIX.'Category.TreeLeft BETWEEN '.$tree_indexes['TreeLeft'].' AND '.$tree_indexes['TreeRight']); + $object->addFilter('perm_filter', 'PermId = 1'); // check for CATEGORY.VIEW permission + if ($this->Application->RecallVar('user_id') != -1) { + // apply permission filters to all users except "root" + $groups = explode(',',$this->Application->RecallVar('UserGroups')); + foreach ($groups as $group) { + $view_filters[] = 'FIND_IN_SET('.$group.', acl)'; } + $view_filter = implode(' OR ', $view_filters); + $object->addFilter('perm_filter2', $view_filter); } - else { - $object->addFilter('parent_filter', 'ParentId = '.$parent_cat_id); - } - } - $object->addFilter('perm_filter', 'PermId = 1'); // check for CATEGORY.VIEW permission - if ($this->Application->RecallVar('user_id') != -1) { - // apply permission filters to all users except "root" - $groups = explode(',',$this->Application->RecallVar('UserGroups')); - foreach ($groups as $group) { - $view_filters[] = 'FIND_IN_SET('.$group.', acl)'; + if (!$this->Application->IsAdmin()) { + // apply status filter only on front + $object->addFilter('status_filter', $object->TableName.'.Status = 1'); } - $view_filter = implode(' OR ', $view_filters); - $object->addFilter('perm_filter2', $view_filter); - } - if (!$this->Application->IsAdmin()) { - // apply status filter only on front - $object->addFilter('status_filter', $object->TableName.'.Status = 1'); - } + // process "types" and "except" parameters + $type_clauses = Array(); - // process "types" and "except" parameters - $type_clauses = Array(); + $types = $event->getEventParam('types'); + $types = $types ? explode(',', $types) : Array (); - $types = $event->getEventParam('types'); - $types = $types ? explode(',', $types) : Array (); + $except_types = $event->getEventParam('except'); + $except_types = $except_types ? explode(',', $except_types) : Array (); - $except_types = $event->getEventParam('except'); - $except_types = $except_types ? explode(',', $except_types) : Array (); + 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); + } - 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'); - $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); + } - 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'); + } - // 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 = 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(); + } + } - $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'); + } } - } - if ($id === false) { - // printing related categories for single item (possibly on details page) - if ($related_prefix == 'c') { - $id = $this->Application->GetVar('m_cat_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).')'; + $type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).')'; + } else { - $id = $this->Application->GetVar($related_prefix . '_id'); + $type_clauses['related']['include'] = '0'; + $type_clauses['related']['except'] = '1'; } + + $type_clauses['related']['having_filter'] = false; } - $p_item =& $this->Application->recallObject($related_prefix . '.current', null, Array('skip_autoload' => true)); - $p_item->Load( (int)$id ); + if (in_array('category_related', $type_clauses)) { + $object->removeFilter('parent_filter'); + $resource_id = $this->Conn->GetOne(' + SELECT ResourceId FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + WHERE CategoryId = '.$parent_cat_id + ); - $p_resource_id = $p_item->GetDBField('ResourceId'); + $sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'Relationship + WHERE SourceId = '.$resource_id.' AND SourceType = 1'; + $related_cats = $this->Conn->GetCol($sql); + $related_cats = is_array($related_cats) ? $related_cats : Array(); - $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.') - ) - ) - )'; + $sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'Relationship + WHERE TargetId = '.$resource_id.' AND TargetType = 1 AND Type = 1'; + $related_cats2 = $this->Conn->GetCol($sql); + $related_cats2 = is_array($related_cats2) ? $related_cats2 : Array(); + $related_cats = array_unique( array_merge( $related_cats2, $related_cats ) ); - $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 ($related_cats) { + $type_clauses['category_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')'; + $type_clauses['category_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')'; + } + else + { + $type_clauses['category_related']['include'] = '0'; + $type_clauses['category_related']['except'] = '1'; + } + $type_clauses['category_related']['having_filter'] = false; } - if (count($related_ids) > 0) { - $type_clauses['related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_ids).')'; - $type_clauses['related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_ids).')'; - } - else { - $type_clauses['related']['include'] = '0'; - $type_clauses['related']['except'] = '1'; - } + if (in_array('product_related', $types)) { + $object->removeFilter('parent_filter'); - $type_clauses['related']['having_filter'] = false; - } + $product_id = $event->getEventParam('product_id') ? $event->getEventParam('product_id') : $this->Application->GetVar('p_id'); + $resource_id = $this->Conn->GetOne(' + SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').' + WHERE ProductId = '.$product_id + ); - if (in_array('category_related', $type_clauses)) { - $object->removeFilter('parent_filter'); - $resource_id = $this->Conn->GetOne(' - SELECT ResourceId FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' - WHERE CategoryId = '.$parent_cat_id - ); + $sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'Relationship + WHERE SourceId = '.$resource_id.' AND TargetType = 1'; + $related_cats = $this->Conn->GetCol($sql); + $related_cats = is_array($related_cats) ? $related_cats : Array(); + $sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'Relationship + WHERE TargetId = '.$resource_id.' AND SourceType = 1 AND Type = 1'; + $related_cats2 = $this->Conn->GetCol($sql); + $related_cats2 = is_array($related_cats2) ? $related_cats2 : Array(); + $related_cats = array_unique( array_merge( $related_cats2, $related_cats ) ); - $sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'Relationship - WHERE SourceId = '.$resource_id.' AND SourceType = 1'; - $related_cats = $this->Conn->GetCol($sql); - $related_cats = is_array($related_cats) ? $related_cats : Array(); + if ($related_cats) { + $type_clauses['product_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')'; + $type_clauses['product_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')'; + } + else { + $type_clauses['product_related']['include'] = '0'; + $type_clauses['product_related']['except'] = '1'; + } - $sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'Relationship - WHERE TargetId = '.$resource_id.' AND TargetType = 1 AND Type = 1'; - $related_cats2 = $this->Conn->GetCol($sql); - $related_cats2 = is_array($related_cats2) ? $related_cats2 : Array(); - $related_cats = array_unique( array_merge( $related_cats2, $related_cats ) ); - - if ($related_cats) { - $type_clauses['category_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')'; - $type_clauses['category_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')'; + $type_clauses['product_related']['having_filter'] = false; } - else - { - $type_clauses['category_related']['include'] = '0'; - $type_clauses['category_related']['except'] = '1'; - } - $type_clauses['category_related']['having_filter'] = false; + + $type_clauses['menu']['include'] = '%1$s.IsMenu = 1'; + $type_clauses['menu']['except'] = '%1$s.IsMenu = 0'; + + $search_helper =& $this->Application->recallObject('SearchHelper'); + /* @var $search_helper kSearchHelper */ + + $search_helper->SetComplexFilter($event, $type_clauses, implode(',', $types), implode(',', $except_types)); } - if (in_array('product_related', $types)) { - $object->removeFilter('parent_filter'); + /** + * Returns current theme id + * + * @return int + */ + function _getCurrentThemeId() + { + $themes_helper =& $this->Application->recallObject('ThemesHelper'); + /* @var $themes_helper kThemesHelper */ - $product_id = $event->getEventParam('product_id') ? $event->getEventParam('product_id') : $this->Application->GetVar('p_id'); - $resource_id = $this->Conn->GetOne(' - SELECT ResourceId FROM '.$this->Application->getUnitOption('p', 'TableName').' - WHERE ProductId = '.$product_id - ); + return (int)$themes_helper->getCurrentThemeId(); + } - $sql = 'SELECT DISTINCT(TargetId) FROM '.TABLE_PREFIX.'Relationship - WHERE SourceId = '.$resource_id.' AND TargetType = 1'; - $related_cats = $this->Conn->GetCol($sql); - $related_cats = is_array($related_cats) ? $related_cats : Array(); - $sql = 'SELECT DISTINCT(SourceId) FROM '.TABLE_PREFIX.'Relationship - WHERE TargetId = '.$resource_id.' AND SourceType = 1 AND Type = 1'; - $related_cats2 = $this->Conn->GetCol($sql); - $related_cats2 = is_array($related_cats2) ? $related_cats2 : Array(); - $related_cats = array_unique( array_merge( $related_cats2, $related_cats ) ); + /** + * Enter description here... + * + * @param kEvent $event + * @return int + */ + function getPassedID(&$event) + { + if (($event->Special == 'page') || ($event->Special == '-virtual') || ($event->Prefix == 'st')) { + return $this->_getPassedStructureID($event); + } - if ($related_cats) { - $type_clauses['product_related']['include'] = '%1$s.ResourceId IN ('.implode(',', $related_cats).')'; - $type_clauses['product_related']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $related_cats).')'; + if ($this->Application->IsAdmin()) { + return parent::getPassedID($event); } - else { - $type_clauses['product_related']['include'] = '0'; - $type_clauses['product_related']['except'] = '1'; - } - $type_clauses['product_related']['having_filter'] = false; + return $this->Application->GetVar('m_cat_id'); } - $type_clauses['menu']['include'] = '%1$s.IsMenu = 1'; - $type_clauses['menu']['except'] = '%1$s.IsMenu = 0'; + /** + * Enter description here... + * + * @param kEvent $event + * @return int + */ + function _getPassedStructureID(&$event) + { + static $page_by_template = Array (); - $search_helper =& $this->Application->recallObject('SearchHelper'); - /* @var $search_helper kSearchHelper */ + if ($event->Special == 'current') { + return $this->Application->GetVar('m_cat_id'); + } - $search_helper->SetComplexFilter($event, $type_clauses, implode(',', $types), implode(',', $except_types)); - } + $event->setEventParam('raise_warnings', 0); - /** - * Returns current theme id - * - * @return int - */ - function _getCurrentThemeId() - { - $themes_helper =& $this->Application->recallObject('ThemesHelper'); - /* @var $themes_helper kThemesHelper */ + $page_id = parent::getPassedID($event); - return (int)$themes_helper->getCurrentThemeId(); - } + if ($page_id === false) { + $template = $event->getEventParam('page'); + if (!$template) { + $template = $this->Application->GetVar('t'); + } - /** - * Enter description here... - * - * @param kEvent $event - * @return int - */ - function getPassedID(&$event) - { - if (($event->Special == 'page') || ($event->Special == '-virtual') || ($event->Prefix == 'st')) { - return $this->_getPassedStructureID($event); - } + // bug: when template contains "-" symbols (or others, that stripDisallowed will replace) it's not found + if (!array_key_exists($template, $page_by_template)) { + $sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . ' + FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' + WHERE + ( + (NamedParentPath = ' . $this->Conn->qstr($template) . ') OR + (NamedParentPath = ' . $this->Conn->qstr('Content/' . $template) . ') OR + (IsSystem = 1 AND CachedTemplate = ' . $this->Conn->qstr($template) . ') + ) AND (ThemeId = ' . $this->_getCurrentThemeId() . ' OR ThemeId = 0)'; - if ($this->Application->IsAdmin()) { - return parent::getPassedID($event); - } + $page_id = $this->Conn->GetOne($sql); + } + else { + $page_id = $page_by_template[$template]; + } - return $this->Application->GetVar('m_cat_id'); - } + if ($page_id === false && EDITING_MODE) { + // create missing pages, when in editing mode + $object =& $this->Application->recallObject($this->Prefix . '.-new', null, Array('skip_autoload' => true)); + /* @var $object kDBItem */ - /** - * Enter description here... - * - * @param kEvent $event - * @return int - */ - function _getPassedStructureID(&$event) - { - static $page_by_template = Array (); + $created = $this->_prepareAutoPage($object, $template, null, SMS_MODE_AUTO, false); // create virtual (not system!) page + if ($created) { + if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild') || !$this->Application->IsAdmin()) { + $updater =& $this->Application->recallObject('kPermCacheUpdater'); + /* @var $updater kPermCacheUpdater */ - if ($event->Special == 'current') { - return $this->Application->GetVar('m_cat_id'); - } + $updater->OneStepRun(); + } - $event->setEventParam('raise_warnings', 0); + $event->CallSubEvent('OnResetMenuCache'); - $page_id = parent::getPassedID($event); + $this->Application->RemoveVar('PermCache_UpdateRequired'); - if ($page_id === false) { - $template = $event->getEventParam('page'); - if (!$template) { - $template = $this->Application->GetVar('t'); + $page_id = $object->GetID(); + $this->Application->SetVar('m_cat_id', $page_id); + } + } + + if ($page_id) { + $page_by_template[$template] = $page_id; + } } - // bug: when template contains "-" symbols (or others, that stripDisallowed will replace) it's not found - if (!array_key_exists($template, $page_by_template)) { - $sql = 'SELECT ' . $this->Application->getUnitOption($event->Prefix, 'IDField') . ' - FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' - WHERE - ( - (NamedParentPath = ' . $this->Conn->qstr($template) . ') OR - (NamedParentPath = ' . $this->Conn->qstr('Content/' . $template) . ') OR - (IsSystem = 1 AND CachedTemplate = ' . $this->Conn->qstr($template) . ') - ) AND (ThemeId = ' . $this->_getCurrentThemeId() . ' OR ThemeId = 0)'; - - $page_id = $this->Conn->GetOne($sql); + if (!$page_id && !$this->Application->IsAdmin()) { + $page_id = $this->Application->GetVar('m_cat_id'); } - else { - $page_id = $page_by_template[$template]; - } - if ($page_id === false && EDITING_MODE) { - // create missing pages, when in editing mode - $object =& $this->Application->recallObject($this->Prefix . '.-new', null, Array('skip_autoload' => true)); - /* @var $object kDBItem */ + return $page_id; + } - $created = $this->_prepareAutoPage($object, $template, null, SMS_MODE_AUTO, false); // create virtual (not system!) page - if ($created) { - if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild') || !$this->Application->IsAdmin()) { - $updater =& $this->Application->recallObject('kPermCacheUpdater'); - /* @var $updater kPermCacheUpdater */ + function ParentGetPassedId(&$event) + { + return parent::GetPassedId($event); + } - $updater->OneStepRun(); - } + /** + * Adds calculates fields for item statuses + * + * @param kCatDBItem $object + * @param kEvent $event + */ + function prepareObject(&$object, &$event) + { + $object =& $event->getObject( Array('skip_autoload' => true) ); - $event->CallSubEvent('OnResetMenuCache'); + $object->addCalculatedField( + 'IsNew', + ' IF(%1$s.NewItem = 2, + IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '. + $this->Application->ConfigValue('Category_DaysNew'). + '*3600*24), 1, 0), + %1$s.NewItem + )'); + } - $this->Application->RemoveVar('PermCache_UpdateRequired'); - - $page_id = $object->GetID(); - $this->Application->SetVar('m_cat_id', $page_id); + /** + * Set correct parent path for newly created categories + * + * @param kEvent $event + */ + function OnAfterCopyToLive(&$event) + { + $parent_path = false; + $object =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true, 'live_table' => true)); + $object->Load($event->getEventParam('id')); + if ($event->getEventParam('temp_id') == 0) { + if ($object->isLoaded()) { + // update path only for real categories (not including "Home" root category) + $fields_hash = Array('ParentPath' => $object->buildParentPath()); + $this->Conn->doUpdate($fields_hash, $object->TableName, 'CategoryId = '.$object->GetID()); + $parent_path = $fields_hash['ParentPath']; } } + else { + $parent_path = $object->GetDBField('ParentPath'); + } - if ($page_id) { - $page_by_template[$template] = $page_id; + if ($parent_path) { + $cache_updater =& $this->Application->recallObject('kPermCacheUpdater', null, array('strict_path' => $parent_path)); + $cache_updater->OneStepRun(); + $cache_updater->StrictPath = false; } } - if (!$page_id && !$this->Application->IsAdmin()) { - $page_id = $this->Application->GetVar('m_cat_id'); - } + /** + * Set cache modification mark if needed + * + * @param kEvent $event + */ + function OnBeforeDeleteFromLive(&$event) + { + $id = $event->getEventParam('id'); - return $page_id; - } + // loding anyway, because this object is needed by "c-perm:OnBeforeDeleteFromLive" event + $temp_object =& $event->getObject( Array('skip_autoload' => true) ); + $temp_object->Load($id); - function ParentGetPassedId(&$event) - { - return parent::GetPassedId($event); - } + if ($id == 0) { + if ($temp_object->isLoaded()) { + // new category -> update cache (not loaded when "Home" category) + $this->Application->StoreVar('PermCache_UpdateRequired', 1); + } + return ; + } - /** - * Adds calculates fields for item statuses - * - * @param kCatDBItem $object - * @param kEvent $event - */ - function prepareObject(&$object, &$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); + // existing category was edited, check if in-cache fields are modified + $live_object =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('live_table' => true, 'skip_autoload' => true)); + $live_object->Load($id); - $object->addCalculatedField( - 'IsNew', - ' IF(%1$s.NewItem = 2, - IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '. - $this->Application->ConfigValue('Category_DaysNew'). - '*3600*24), 1, 0), - %1$s.NewItem - )'); - } + $cached_fields = Array('Name', 'Filename', 'Template', 'ParentId', 'Priority'); - /** - * Set correct parent path for newly created categories - * - * @param kEvent $event - */ - function OnAfterCopyToLive(&$event) - { - $parent_path = false; - $object =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('skip_autoload' => true, 'live_table' => true)); - $object->Load($event->getEventParam('id')); - if ($event->getEventParam('temp_id') == 0) { - if ($object->isLoaded()) { - // update path only for real categories (not including "Home" root category) - $fields_hash = Array('ParentPath' => $object->buildParentPath()); - $this->Conn->doUpdate($fields_hash, $object->TableName, 'CategoryId = '.$object->GetID()); - $parent_path = $fields_hash['ParentPath']; + foreach ($cached_fields as $cached_field) { + if ($live_object->GetDBField($cached_field) != $temp_object->GetDBField($cached_field)) { + // use session instead of REQUEST because of permission editing in category can contain + // multiple submits, that changes data before OnSave event occurs + $this->Application->StoreVar('PermCache_UpdateRequired', 1); + break; + } } } - else { - $parent_path = $object->GetDBField('ParentPath'); - } - if ($parent_path) { - $cache_updater =& $this->Application->recallObject('kPermCacheUpdater', null, array('strict_path' => $parent_path)); - $cache_updater->OneStepRun(); - $cache_updater->StrictPath = false; + /** + * Calls kDBEventHandler::OnSave original event + * Used in proj-cms:StructureEventHandler->OnSave + * + * @param kEvent $event + */ + function parentOnSave(&$event) + { + parent::OnSave($event); } - } - /** - * Set cache modification mark if needed - * - * @param kEvent $event - */ - function OnBeforeDeleteFromLive(&$event) - { - $id = $event->getEventParam('id'); + /** + * Reset root-category flag when new category is created + * + * @param kEvent $event + */ + function OnPreCreate(&$event) + { + // 1. for permission editing of Home category + $this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); - // loding anyway, because this object is needed by "c-perm:OnBeforeDeleteFromLive" event - $temp_object =& $event->getObject( Array('skip_autoload' => true) ); - $temp_object->Load($id); + parent::OnPreCreate($event); - if ($id == 0) { - if ($temp_object->isLoaded()) { - // new category -> update cache (not loaded when "Home" category) - $this->Application->StoreVar('PermCache_UpdateRequired', 1); + $object =& $event->getObject(); + + // 2. preset template + $category_id = $this->Application->GetVar('m_cat_id'); + $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); + if ($category_id == $root_category) { + $object->SetDBField('Template', $this->_getDefaultDesign()); } - return ; + + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ + + // 3. prepare priorities dropdown + $priority_helper->preparePriorities($event, true, 'ParentId = ' . $category_id); } - // existing category was edited, check if in-cache fields are modified - $live_object =& $this->Application->recallObject($event->Prefix.'.-item', null, Array('live_table' => true, 'skip_autoload' => true)); - $live_object->Load($id); + /** + * Checks cache update mark and redirect to cache if needed + * + * @param kEvent $event + */ + function OnSave(&$event) + { + $object =& $event->getObject(); + if ($object->IsRoot()) { + $event->setEventParam('master_ids', Array(0)); + $this->RemoveRequiredFields($object); + } - $cached_fields = Array('Name', 'Filename', 'Template', 'ParentId', 'Priority'); + parent::OnSave($event); - foreach ($cached_fields as $cached_field) { - if ($live_object->GetDBField($cached_field) != $temp_object->GetDBField($cached_field)) { - // use session instead of REQUEST because of permission editing in category can contain - // multiple submits, that changes data before OnSave event occurs - $this->Application->StoreVar('PermCache_UpdateRequired', 1); - break; + if ($event->status != erSUCCESS) { + return ; } - } - } - /** - * Calls kDBEventHandler::OnSave original event - * Used in proj-cms:StructureEventHandler->OnSave - * - * @param kEvent $event - */ - function parentOnSave(&$event) - { - parent::OnSave($event); - } + // 1. update priorities + $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); + $changes = $tmp ? unserialize($tmp) : Array (); + $changed_ids = array_keys($changes); - /** - * Reset root-category flag when new category is created - * - * @param kEvent $event - */ - function OnPreCreate(&$event) - { - // 1. for permission editing of Home category - $this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - parent::OnPreCreate($event); + $priority_helper->updatePriorities($event, $changes, Array (0 => $event->getEventParam('ids'))); - $object =& $event->getObject(); + if ($this->Application->RecallVar('PermCache_UpdateRequired')) { + $this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); + } - // 2. preset template - $category_id = $this->Application->GetVar('m_cat_id'); - $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); - if ($category_id == $root_category) { - $object->SetDBField('Template', $this->_getDefaultDesign()); + $this->Application->StoreVar('RefreshStructureTree', 1); + $event->CallSubEvent('OnResetMenuCache'); } - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + /** + * Creates a new item in temp table and + * stores item id in App vars and Session on succsess + * + * @param kEvent $event + */ + function OnPreSaveCreated(&$event) + { + $object =& $event->getObject( Array('skip_autoload' => true) ); + /* @var $object CategoriesItem */ - // 3. prepare priorities dropdown - $priority_helper->preparePriorities($event, true, 'ParentId = ' . $category_id); - } + if ($object->IsRoot()) { + // don't create root category while saving permissions + return ; + } - /** - * Checks cache update mark and redirect to cache if needed - * - * @param kEvent $event - */ - function OnSave(&$event) - { - $object =& $event->getObject(); - if ($object->IsRoot()) { - $event->setEventParam('master_ids', Array(0)); - $this->RemoveRequiredFields($object); - } + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - parent::OnSave($event); + $category_id = $this->Application->GetVar('m_cat_id'); + $priority_helper->preparePriorities($event, true, 'ParentId = ' . $category_id); - if ($event->status != erSUCCESS) { - return ; + parent::OnPreSaveCreated($event); } - // 1. update priorities - $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); - $changes = $tmp ? unserialize($tmp) : Array (); - $changed_ids = array_keys($changes); + /** + * Deletes sym link to other category + * + * @param kEvent $event + */ + function OnAfterItemDelete(&$event) + { + parent::OnAfterItemDelete($event); - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + $object =& $event->getObject(); + /* @var $object kDBItem */ - $priority_helper->updatePriorities($event, $changes, Array (0 => $event->getEventParam('ids'))); + $sql = 'UPDATE '.$object->TableName.' + SET SymLinkCategoryId = NULL + WHERE SymLinkCategoryId = '.$object->GetID(); - if ($this->Application->RecallVar('PermCache_UpdateRequired')) { - $this->Application->RemoveVar('IsRootCategory_' . $this->Application->GetVar('m_wid')); + $this->Conn->Query($sql); } - $this->Application->StoreVar('RefreshStructureTree', 1); - $event->CallSubEvent('OnResetMenuCache'); - } - /** - * Creates a new item in temp table and - * stores item id in App vars and Session on succsess - * - * @param kEvent $event - */ - function OnPreSaveCreated(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - /* @var $object CategoriesItem */ + /** + * Exclude root categories from deleting + * + * @param kEvent $event + */ + function customProcessing(&$event, $type) + { + if ($event->Name == 'OnMassDelete' && $type == 'before') { + $ids = $event->getEventParam('ids'); + if (!$ids || $this->Application->ConfigValue('AllowDeleteRootCats')) { + return ; + } - if ($object->IsRoot()) { - // don't create root category while saving permissions - return ; - } + // get module root categories and exclude them + foreach ($this->Application->ModuleInfo as $module_info) { + $root_categories[] = $module_info['RootCat']; + } + $root_categories = array_unique($root_categories); - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + if ($root_categories && array_intersect($ids, $root_categories)) { + $event->setEventParam('ids', array_diff($ids, $root_categories)); + $this->Application->StoreVar('root_delete_error', 1); + } + } - $category_id = $this->Application->GetVar('m_cat_id'); - $priority_helper->preparePriorities($event, true, 'ParentId = ' . $category_id); + $change_events = Array ('OnPreSave', 'OnPreSaveCreated', 'OnUpdate', 'OnSave'); + if ($type == 'after' && in_array($event->Name, $change_events)) { + $object =& $event->getObject(); - parent::OnPreSaveCreated($event); - } + $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); + $changes = $tmp ? unserialize($tmp) : array(); - /** - * Deletes sym link to other category - * - * @param kEvent $event - */ - function OnAfterItemDelete(&$event) - { - parent::OnAfterItemDelete($event); + if (!isset($changes[$object->GetID()])) { + $changes[$object->GetId()]['old'] = $object->GetID() == 0 ? 'new' : $object->GetDBField('OldPriority'); + } - $object =& $event->getObject(); - /* @var $object kDBItem */ + if ($changes[$object->GetId()]['old'] == $object->GetDBField('Priority')) return ; - $sql = 'UPDATE '.$object->TableName.' - SET SymLinkCategoryId = NULL - WHERE SymLinkCategoryId = '.$object->GetID(); + $changes[$object->GetId()]['new'] = $object->GetDBField('Priority'); + $changes[$object->GetId()]['parent'] = $object->GetDBField('ParentId'); - $this->Conn->Query($sql); - } + $this->Application->StoreVar('priority_changes'.$this->Application->GetVar('m_wid'), serialize($changes)); + } + } + /** + * Checks, that given template exists (physically) in given theme + * + * @param string $template + * @param int $theme_id + * @return bool + */ + function _templateFound($template, $theme_id = null) + { + static $init_made = false; - /** - * Exclude root categories from deleting - * - * @param kEvent $event - */ - function customProcessing(&$event, $type) - { - if ($event->Name == 'OnMassDelete' && $type == 'before') { - $ids = $event->getEventParam('ids'); - if (!$ids || $this->Application->ConfigValue('AllowDeleteRootCats')) { - return ; + if (!$init_made) { + $this->Application->InitParser(true); + $init_made = true; } - // get module root categories and exclude them - foreach ($this->Application->ModuleInfo as $module_info) { - $root_categories[] = $module_info['RootCat']; + if (!isset($theme_id)) { + $theme_id = $this->_getCurrentThemeId(); } - $root_categories = array_unique($root_categories); - if ($root_categories && array_intersect($ids, $root_categories)) { - $event->setEventParam('ids', array_diff($ids, $root_categories)); - $this->Application->StoreVar('root_delete_error', 1); - } + $theme_name = $this->_getThemeName($theme_id); + + return $this->Application->TemplatesCache->TemplateExists('theme:' . $theme_name . '/' . $template); } - $change_events = Array ('OnPreSave', 'OnPreSaveCreated', 'OnUpdate', 'OnSave'); - if ($type == 'after' && in_array($event->Name, $change_events)) { - $object =& $event->getObject(); + /** + * Removes ".tpl" in template path + * + * @param string $template + * @return string + */ + function _stripTemplateExtension($template) + { + // return preg_replace('/\.[^.\\\\\\/]*$/', '', $template); - $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); - $changes = $tmp ? unserialize($tmp) : array(); + return preg_replace('/^[\\/]{0,1}(.*)\.tpl$/', "$1", $template); + } - if (!isset($changes[$object->GetID()])) { - $changes[$object->GetId()]['old'] = $object->GetID() == 0 ? 'new' : $object->GetDBField('OldPriority'); + /** + * 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; } - if ($changes[$object->GetId()]['old'] == $object->GetDBField('Priority')) return ; + $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); + $cat =& $event->getObject(Array('skip_autoload' => true)); + foreach ($ids as $id) { + $cat->Load($id); + if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $cat->GetDBField('ParentPath'))) { + $to_delete[] = $id; + continue; + } + $cat->SetDBField('ParentId', $recycle_bin); + $cat->Update(); + } + $ids = $to_delete; + $event->redirect = 'categories/cache_updater'; + } - $changes[$object->GetId()]['new'] = $object->GetDBField('Priority'); - $changes[$object->GetId()]['parent'] = $object->GetDBField('ParentId'); + $event->setEventParam('ids', $ids); + $this->customProcessing($event, 'before'); + $ids = $event->getEventParam('ids'); - $this->Application->StoreVar('priority_changes'.$this->Application->GetVar('m_wid'), serialize($changes)); - } - } + if ($ids) { + $recursive_helper =& $this->Application->recallObject('RecursiveHelper'); + /* @var $recursive_helper kRecursiveHelper */ - /** - * Checks, that given template exists (physically) in given theme - * - * @param string $template - * @param int $theme_id - * @return bool - */ - function _templateFound($template, $theme_id = null) - { - static $init_made = false; + foreach ($ids as $id) { + $recursive_helper->DeleteCategory($id, $event->Prefix); + } + } + $this->clearSelectedIDs($event); - if (!$init_made) { - $this->Application->InitParser(true); - $init_made = true; + // update priorities + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ + + // after deleting categories, all priorities should be recalculated + $parent_id = $this->Application->GetVar('m_cat_id'); + $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); + + $this->Application->StoreVar('RefreshStructureTree', 1); + $event->CallSubEvent('OnResetMenuCache'); } - if (!isset($theme_id)) { - $theme_id = $this->_getCurrentThemeId(); + /** + * 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); } - $theme_name = $this->_getThemeName($theme_id); + /** + * 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); + } - return $this->Application->TemplatesCache->TemplateExists('theme:' . $theme_name . '/' . $template); - } + /** + * Controls all item paste operations. Can occur only with filled clipbord. + * + * @param kEvent $event + */ + function OnPasteClipboard(&$event) + { + $clipboard = unserialize( $this->Application->RecallVar('clipboard') ); + foreach ($clipboard as $prefix => $clipboard_data) { + $paste_event = new kEvent($prefix.':OnPaste', Array('clipboard_data' => $clipboard_data)); + $this->Application->HandleEvent($paste_event); - /** - * Removes ".tpl" in template path - * - * @param string $template - * @return string - */ - function _stripTemplateExtension($template) - { -// return preg_replace('/\.[^.\\\\\\/]*$/', '', $template); + $event->redirect = $paste_event->redirect; + $event->redirect_params = $paste_event->redirect_params; + $event->status = $paste_event->status; + } + } - return preg_replace('/^[\\/]{0,1}(.*)\.tpl$/', "$1", $template); - } + /** + * Checks permission for OnPaste event + * + * @param kEvent $event + * @return bool + */ + function _checkPastePermission(&$event) + { + $perm_helper =& $this->Application->recallObject('PermissionsHelper'); + /* @var $perm_helper kPermissionsHelper */ - /** - * 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; + $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; } - $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); - $cat =& $event->getObject(Array('skip_autoload' => true)); - foreach ($ids as $id) { - $cat->Load($id); - if (preg_match('/^'.preg_quote($rb->GetDBField('ParentPath'),'/').'/', $cat->GetDBField('ParentPath'))) { - $to_delete[] = $id; - continue; - } - $cat->SetDBField('ParentId', $recycle_bin); - $cat->Update(); + /** + * Paste categories with subitems from clipboard + * + * @param kEvent $event + */ + function OnPaste(&$event) + { + if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) { + return ; } - $ids = $to_delete; - $event->redirect = 'categories/cache_updater'; - } - $event->setEventParam('ids', $ids); - $this->customProcessing($event, 'before'); - $ids = $event->getEventParam('ids'); + $clipboard_data = $event->getEventParam('clipboard_data'); - if ($ids) { + if (!$clipboard_data['cut'] && !$clipboard_data['copy']) { + return false; + } + + // 1. get ParentId of moved category(-es) before it gets updated!!!) + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + + if ($clipboard_data['cut']) { + $sql = 'SELECT ParentId + FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' + WHERE ' . $id_field . ' = ' . $clipboard_data['cut'][0]; + $source_category_id = $this->Conn->GetOne($sql); + } + $recursive_helper =& $this->Application->recallObject('RecursiveHelper'); /* @var $recursive_helper kRecursiveHelper */ - foreach ($ids as $id) { - $recursive_helper->DeleteCategory($id, $event->Prefix); + if ($clipboard_data['cut']) { + $recursive_helper->MoveCategories($clipboard_data['cut'], $this->Application->GetVar('m_cat_id')); } - } - $this->clearSelectedIDs($event); - // update priorities - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + if ($clipboard_data['copy']) { + foreach ($clipboard_data['copy'] as $id) { + $recursive_helper->PasteCategory($id, $event->Prefix); + } + } - // after deleting categories, all priorities should be recalculated - $parent_id = $this->Application->GetVar('m_cat_id'); - $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - $this->Application->StoreVar('RefreshStructureTree', 1); - $event->CallSubEvent('OnResetMenuCache'); - } - /** - * 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); - } + if ($clipboard_data['cut']) { + $priority_helper->recalculatePriorities($event, 'ParentId = '.$source_category_id); + } - /** - * 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); - } + // recalculate priorities of newly pasted categories in destination category + $parent_id = $this->Application->GetVar('m_cat_id'); + $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); - /** - * Controls all item paste operations. Can occur only with filled clipbord. - * - * @param kEvent $event - */ - function OnPasteClipboard(&$event) - { - $clipboard = unserialize( $this->Application->RecallVar('clipboard') ); - foreach ($clipboard as $prefix => $clipboard_data) { - $paste_event = new kEvent($prefix.':OnPaste', Array('clipboard_data' => $clipboard_data)); - $this->Application->HandleEvent($paste_event); + if ($clipboard_data['cut'] || $clipboard_data['copy']) { + // rebuild with progress bar + if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) { + $updater =& $this->Application->recallObject('kPermCacheUpdater'); + /* @var $updater kPermCacheUpdater */ - $event->redirect = $paste_event->redirect; - $event->redirect_params = $paste_event->redirect_params; - $event->status = $paste_event->status; - } - } + $updater->OneStepRun(); + } + else { + $event->redirect = 'categories/cache_updater'; + } - /** - * 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); + $event->CallSubEvent('OnResetMenuCache'); + $this->Application->StoreVar('RefreshStructureTree', 1); + } } - return true; - } + /** + * Occurs when pasting category + * + * @param kEvent $event + */ + /*function OnCatPaste(&$event) + { + $inp_clipboard = $this->Application->RecallVar('ClipBoard'); + $inp_clipboard = explode('-', $inp_clipboard, 2); - /** - * Paste categories with subitems from clipboard - * - * @param kEvent $event - */ - function OnPaste(&$event) - { - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) || !$this->_checkPastePermission($event)) { - return ; - } + if($inp_clipboard[0] == 'COPY') + { + $saved_cat_id = $this->Application->GetVar('m_cat_id'); + $cat_ids = $event->getEventParam('cat_ids'); - $clipboard_data = $event->getEventParam('clipboard_data'); + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $table = $this->Application->getUnitOption($event->Prefix, 'TableName'); + $ids_sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE ResourceId IN (%s)'; + $resource_ids_sql = 'SELECT ItemResourceId FROM '.TABLE_PREFIX.'CategoryItems WHERE CategoryId = %s AND PrimaryCat = 1'; - if (!$clipboard_data['cut'] && !$clipboard_data['copy']) { - return false; - } + $object =& $this->Application->recallObject($event->Prefix.'.item', $event->Prefix, Array('skip_autoload' => true)); - // 1. get ParentId of moved category(-es) before it gets updated!!!) - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + foreach($cat_ids as $source_cat => $dest_cat) + { + $item_resource_ids = $this->Conn->GetCol( sprintf($resource_ids_sql, $source_cat) ); + if(!$item_resource_ids) continue; - if ($clipboard_data['cut']) { - $sql = 'SELECT ParentId - FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' - WHERE ' . $id_field . ' = ' . $clipboard_data['cut'][0]; - $source_category_id = $this->Conn->GetOne($sql); - } + $this->Application->SetVar('m_cat_id', $dest_cat); + $item_ids = $this->Conn->GetCol( sprintf($ids_sql, implode(',', $item_resource_ids) ) ); - $recursive_helper =& $this->Application->recallObject('RecursiveHelper'); - /* @var $recursive_helper kRecursiveHelper */ + $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); + if($item_ids) $temp->CloneItems($event->Prefix, $event->Special, $item_ids); + } - if ($clipboard_data['cut']) { - $recursive_helper->MoveCategories($clipboard_data['cut'], $this->Application->GetVar('m_cat_id')); - } - - if ($clipboard_data['copy']) { - foreach ($clipboard_data['copy'] as $id) { - $recursive_helper->PasteCategory($id, $event->Prefix); + $this->Application->SetVar('m_cat_id', $saved_cat_id); } + }*/ + + /** + * Cleares clipboard content + * + * @param kEvent $event + */ + function OnClearClipboard(&$event) + { + $this->Application->RemoveVar('clipboard'); } - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + /** + * Sets correct status for new categories created on front-end + * + * @param kEvent $event + */ + function OnBeforeItemCreate(&$event) + { + $this->_beforeItemChange($event); + if ($this->Application->IsAdmin() || $event->Prefix == 'st') { + // don't check category permissions when auto-creating structure pages + return ; + } - if ($clipboard_data['cut']) { - $priority_helper->recalculatePriorities($event, 'ParentId = '.$source_category_id); - } + $perm_helper =& $this->Application->recallObject('PermissionsHelper'); + /* @var $perm_helper kPermissionsHelper */ - // recalculate priorities of newly pasted categories in destination category - $parent_id = $this->Application->GetVar('m_cat_id'); - $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); + $new_status = false; + $category_id = $this->Application->GetVar('m_cat_id'); + if ($perm_helper->CheckPermission('CATEGORY.ADD', 0, $category_id)) { + $new_status = STATUS_ACTIVE; + } + else if ($perm_helper->CheckPermission('CATEGORY.ADD.PENDING', 0, $category_id)) { + $new_status = STATUS_PENDING; + } - if ($clipboard_data['cut'] || $clipboard_data['copy']) { - // rebuild with progress bar - if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) { - $updater =& $this->Application->recallObject('kPermCacheUpdater'); - /* @var $updater kPermCacheUpdater */ + if ($new_status) { + $object =& $event->getObject(); + /* @var $object kDBItem */ - $updater->OneStepRun(); + $object->SetDBField('Status', $new_status); + + /* + if (!$this->Application->IsAdmin()) { + $object->SetDBField('IsMenu', 0); // add all suggested categories as non-menu + } + */ } else { - $event->redirect = 'categories/cache_updater'; + $event->status = erPERM_FAIL; + return ; } - - $event->CallSubEvent('OnResetMenuCache'); - $this->Application->StoreVar('RefreshStructureTree', 1); } - } - /** - * Occurs when pasting category - * - * @param kEvent $event - */ - /*function OnCatPaste(&$event) - { - $inp_clipboard = $this->Application->RecallVar('ClipBoard'); - $inp_clipboard = explode('-', $inp_clipboard, 2); - - if($inp_clipboard[0] == 'COPY') + /** + * Sets correct status for new categories created on front-end + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) { - $saved_cat_id = $this->Application->GetVar('m_cat_id'); - $cat_ids = $event->getEventParam('cat_ids'); + parent::OnBeforeItemUpdate($event); - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $table = $this->Application->getUnitOption($event->Prefix, 'TableName'); - $ids_sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE ResourceId IN (%s)'; - $resource_ids_sql = 'SELECT ItemResourceId FROM '.TABLE_PREFIX.'CategoryItems WHERE CategoryId = %s AND PrimaryCat = 1'; + $this->_beforeItemChange($event); + } - $object =& $this->Application->recallObject($event->Prefix.'.item', $event->Prefix, Array('skip_autoload' => true)); + /** + * Performs redirect to correct suggest confirmation template + * + * @param kEvent $event + */ + function OnCreate(&$event) + { + parent::OnCreate($event); - foreach($cat_ids as $source_cat => $dest_cat) - { - $item_resource_ids = $this->Conn->GetCol( sprintf($resource_ids_sql, $source_cat) ); - if(!$item_resource_ids) continue; + if ($this->Application->IsAdmin() || $event->status != erSUCCESS) { + return ; + } - $this->Application->SetVar('m_cat_id', $dest_cat); - $item_ids = $this->Conn->GetCol( sprintf($ids_sql, implode(',', $item_resource_ids) ) ); + $object =& $event->getObject(); - $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); - if($item_ids) $temp->CloneItems($event->Prefix, $event->Special, $item_ids); - } + $cache_updater =& $this->Application->recallObject('kPermCacheUpdater', null, array('strict_path' => $object->GetDBField('ParentPath'))); + $cache_updater->OneStepRun(); + $cache_updater->StrictPath = false; - $this->Application->SetVar('m_cat_id', $saved_cat_id); - } - }*/ + $is_active = ($object->GetDBField('Status') == STATUS_ACTIVE); - /** - * Cleares clipboard content - * - * @param kEvent $event - */ - function OnClearClipboard(&$event) - { - $this->Application->RemoveVar('clipboard'); - } + $next_template = $is_active ? 'suggest_confirm_template' : 'suggest_pending_confirm_template'; + $event->redirect = $this->Application->GetVar($next_template); + $event->SetRedirectParam('opener', 's'); - /** - * Sets correct status for new categories created on front-end - * - * @param kEvent $event - */ - function OnBeforeItemCreate(&$event) - { - $this->_beforeItemChange($event); + // send email events + $perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix'); - if ($this->Application->IsAdmin() || $event->Prefix == 'st') { - // don't check category permissions when auto-creating structure pages - return ; + $event_suffix = $is_active ? 'ADD' : 'ADD.PENDING'; + $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); + $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('CreatedById')); } - $perm_helper =& $this->Application->recallObject('PermissionsHelper'); - /* @var $perm_helper kPermissionsHelper */ + /** + * Returns current per-page setting for list + * + * @param kEvent $event + * @return int + */ + function getPerPage(&$event) + { + if (!$this->Application->IsAdmin()) { + $event->setEventParam('same_special', true); + } - $new_status = false; - $category_id = $this->Application->GetVar('m_cat_id'); - if ($perm_helper->CheckPermission('CATEGORY.ADD', 0, $category_id)) { - $new_status = STATUS_ACTIVE; + return parent::getPerPage($event); } - else if ($perm_helper->CheckPermission('CATEGORY.ADD.PENDING', 0, $category_id)) { - $new_status = STATUS_PENDING; - } - if ($new_status) { - $object =& $event->getObject(); - /* @var $object kDBItem */ + /** + * Set's correct page for list + * based on data provided with event + * + * @param kEvent $event + * @access private + * @see OnListBuild + */ + function SetPagination(&$event) + { + parent::SetPagination($event); - $object->SetDBField('Status', $new_status); - - /* if (!$this->Application->IsAdmin()) { - $object->SetDBField('IsMenu', 0); // add all suggested categories as non-menu + $page_var = $event->getEventParam('page_var'); + if ($page_var !== false) { + $page = $this->Application->GetVar($page_var); + if (is_numeric($page)) { + $object =& $event->getObject(); + $object->SetPage($page); + } + } } - */ } - else { - $event->status = erPERM_FAIL; - return ; - } - } - /** - * Sets correct status for new categories created on front-end - * - * @param kEvent $event - */ - function OnBeforeItemUpdate(&$event) - { - parent::OnBeforeItemUpdate($event); + /** + * 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); + } - $this->_beforeItemChange($event); - } + if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { + return; + } - /** - * Performs redirect to correct suggest confirmation template - * - * @param kEvent $event - */ - function OnCreate(&$event) - { - parent::OnCreate($event); + $object =& $event->getObject( Array('skip_autoload' => true) ); + $ids = $this->StoreSelectedIDs($event); - if ($this->Application->IsAdmin() || $event->status != erSUCCESS) { - return ; - } + if ($ids) { + $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') ); - $object =& $event->getObject(); + foreach ($ids as $id) { + $object->Load($id); - $cache_updater =& $this->Application->recallObject('kPermCacheUpdater', null, array('strict_path' => $object->GetDBField('ParentPath'))); - $cache_updater->OneStepRun(); - $cache_updater->StrictPath = false; + switch ($event->Name) { + case 'OnMassApprove': + $object->SetDBField($status_field, 1); + break; - $is_active = ($object->GetDBField('Status') == STATUS_ACTIVE); + case 'OnMassDecline': + $object->SetDBField($status_field, 0); + break; + } - $next_template = $is_active ? 'suggest_confirm_template' : 'suggest_pending_confirm_template'; - $event->redirect = $this->Application->GetVar($next_template); - $event->SetRedirectParam('opener', 's'); + if ($this->Application->GetVar('propagate_category_status')) { + $sql = 'UPDATE '.$object->TableName.' + SET '.$status_field.' = '.$object->GetDBField($status_field).' + WHERE TreeLeft BETWEEN '.$object->GetDBField('TreeLeft').' AND '.$object->GetDBField('TreeRight'); + $this->Conn->Query($sql); + } - // send email events - $perm_prefix = $this->Application->getUnitOption($event->Prefix, 'PermItemPrefix'); - - $event_suffix = $is_active ? 'ADD' : 'ADD.PENDING'; - $this->Application->EmailEventAdmin($perm_prefix.'.'.$event_suffix); - $this->Application->EmailEventUser($perm_prefix.'.'.$event_suffix, $object->GetDBField('CreatedById')); - } - - /** - * 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); - } - - /** - * Set's correct page for list - * based on data provided with event - * - * @param kEvent $event - * @access private - * @see OnListBuild - */ - function SetPagination(&$event) - { - parent::SetPagination($event); - - if (!$this->Application->IsAdmin()) { - $page_var = $event->getEventParam('page_var'); - if ($page_var !== false) { - $page = $this->Application->GetVar($page_var); - if (is_numeric($page)) { - $object =& $event->getObject(); - $object->SetPage($page); + if ($object->Update()) { + $event->status = erSUCCESS; + } + else { + $event->status = erFAIL; + $event->redirect = false; + 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); + $this->clearSelectedIDs($event); + $this->Application->StoreVar('RefreshStructureTree', 1); } - if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - return; - } + /** + * Checks, that currently loaded item is allowed for viewing (non permission-based) + * + * @param kEvent $event + * @return bool + */ + function checkItemStatus(&$event) + { + $status_fields = $this->Application->getUnitOption($event->Prefix,'StatusField'); + if (!$status_fields) { + return true; + } - $object =& $event->getObject( Array('skip_autoload' => true) ); - $ids = $this->StoreSelectedIDs($event); - - if ($ids) { - $status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') ); - - foreach ($ids as $id) { - $object->Load($id); - - switch ($event->Name) { - case 'OnMassApprove': - $object->SetDBField($status_field, 1); - break; - - case 'OnMassDecline': - $object->SetDBField($status_field, 0); - break; + $status_field = array_shift($status_fields); + if ($status_field == 'Status' || $status_field == 'Enabled') { + $object =& $event->getObject(); + if (!$object->isLoaded()) { + return true; } - if ($this->Application->GetVar('propagate_category_status')) { - $sql = 'UPDATE '.$object->TableName.' - SET '.$status_field.' = '.$object->GetDBField($status_field).' - WHERE TreeLeft BETWEEN '.$object->GetDBField('TreeLeft').' AND '.$object->GetDBField('TreeRight'); - $this->Conn->Query($sql); - } - - if ($object->Update()) { - $event->status = erSUCCESS; - } - else { - $event->status = erFAIL; - $event->redirect = false; - break; - } + return $object->GetDBField($status_field) == STATUS_ACTIVE || $object->GetDBField($status_field) == 4; } + return true; } - $this->clearSelectedIDs($event); - $this->Application->StoreVar('RefreshStructureTree', 1); - } + // ============= for cms page processing ======================= - /** - * Checks, that currently loaded item is allowed for viewing (non permission-based) - * - * @param kEvent $event - * @return bool - */ - function checkItemStatus(&$event) - { - $status_fields = $this->Application->getUnitOption($event->Prefix,'StatusField'); - if (!$status_fields) { - return true; + /** + * Returns default design template + * + * @return string + */ + function _getDefaultDesign() + { + $default_design = $this->Application->ConfigValue('cms_DefaultDesign'); + return '/' . trim($default_design ? $default_design : 'designs/default_design', '/'); } - $status_field = array_shift($status_fields); - if ($status_field == 'Status' || $status_field == 'Enabled') { - $object =& $event->getObject(); - if (!$object->isLoaded()) { - return true; + /** + * Returns default design based on given virtual template (used from kApplication::Run) + * + * @return string + */ + function GetDesignTemplate($t = null) + { + if (!isset($t)) { + $t = $this->Application->GetVar('t'); } - return $object->GetDBField($status_field) == STATUS_ACTIVE || $object->GetDBField($status_field) == 4; - } - return true; - } + $page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, Array ('page' => $t)); + if ($page->isLoaded()) { + $real_t = $page->GetDBField('CachedTemplate'); + $this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId') ); + if ($page->GetDBField('FormId')) { + $this->Application->SetVar('form_id', $page->GetDBField('FormId')); + } + } + else { + $real_t = $this->_getDefaultDesign(); + } - // ============= for cms page processing ======================= + // $this->Application->SetVar('t', $t); - /** - * Returns default design template - * - * @return string - */ - function _getDefaultDesign() - { - $default_design = $this->Application->ConfigValue('cms_DefaultDesign'); - return '/' . trim($default_design ? $default_design : 'designs/default_design', '/'); - } + return $real_t; + } - /** - * Returns default design based on given virtual template (used from kApplication::Run) - * - * @return string - */ - function GetDesignTemplate($t = null) - { - if (!isset($t)) { + /** + * Sets category id based on found template (used from kApplication::Run) + * + * @deprecated + */ + /*function SetCatByTemplate() + { $t = $this->Application->GetVar('t'); - } + $page =& $this->Application->recallObject($this->Prefix . '.-virtual'); - $page =& $this->Application->recallObject($this->Prefix . '.-virtual', null, Array ('page' => $t)); - if ($page->isLoaded()) { - $real_t = $page->GetDBField('CachedTemplate'); - $this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId') ); - if ($page->GetDBField('FormId')) { - $this->Application->SetVar('form_id', $page->GetDBField('FormId')); + if ($page->isLoaded()) { + $this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId') ); } - } - else { - $real_t = $this->_getDefaultDesign(); - } + }*/ -// $this->Application->SetVar('t', $t); + /** + * Prepares template paths + * + * @param kEvent $event + */ + function _beforeItemChange(&$event) + { + $object =& $event->getObject(); + /* @var $object kDBItem */ - return $real_t; - } + $object->SetDBField('Template', $this->_stripTemplateExtension( $object->GetDBField('Template') )); - /** - * Sets category id based on found template (used from kApplication::Run) - * - * @deprecated - */ - /*function SetCatByTemplate() - { - $t = $this->Application->GetVar('t'); - $page =& $this->Application->recallObject($this->Prefix . '.-virtual'); + if ($object->GetDBField('IsSystem') == 1) { + if (!$this->_templateFound($object->GetDBField('Template'), $object->GetDBField('ThemeId'))) { + $object->SetError('Template', 'template_file_missing', 'la_error_TemplateFileMissing'); + } + } - if ($page->isLoaded()) { - $this->Application->SetVar('m_cat_id', $page->GetDBField('CategoryId') ); - } - }*/ + $this->_saveTitleField($object, 'Title'); + $this->_saveTitleField($object, 'MenuTitle'); - /** - * Prepares template paths - * - * @param kEvent $event - */ - function _beforeItemChange(&$event) - { - $object =& $event->getObject(); - /* @var $object kDBItem */ + $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); - $object->SetDBField('Template', $this->_stripTemplateExtension( $object->GetDBField('Template') )); - - if ($object->GetDBField('IsSystem') == 1) { - if (!$this->_templateFound($object->GetDBField('Template'), $object->GetDBField('ThemeId'))) { - $object->SetError('Template', 'template_file_missing', 'la_error_TemplateFileMissing'); + if (($object->GetDBField('ParentId') == $root_category) && ($object->GetDBField('Template') == CATEGORY_TEMPLATE_INHERIT)) { + $object->SetError('Template', 'no_inherit'); } - } - $this->_saveTitleField($object, 'Title'); - $this->_saveTitleField($object, 'MenuTitle'); + if (!$this->Application->IsAdmin() || !$this->Application->LoggedIn()) { + // only administrator can set/change "cust_RssSource" field - $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); - - if (($object->GetDBField('ParentId') == $root_category) && ($object->GetDBField('Template') == CATEGORY_TEMPLATE_INHERIT)) { - $object->SetError('Template', 'no_inherit'); + if ($object->GetDBField('cust_RssSource') != $object->GetOriginalField('cust_RssSource')) { + $object->SetError('cust_RssSource', 'not_allowed', 'la_error_NotAllowed'); + } + } } - if (!$this->Application->IsAdmin() || !$this->Application->LoggedIn()) { - // only administrator can set/change "cust_RssSource" field + /** + * Sets page name to requested field in case when: + * 1. page was auto created (through theme file rebuld) + * 2. requested field is emtpy + * + * @param kDBItem $object + * @param string $field + * @author Alex + */ + function _saveTitleField(&$object, $field) + { + $value = $object->GetField($field, 'no_default'); + if ($value == '' || preg_match('/^_Auto: (.*)/', $value)) { + $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); + /* @var $ml_formatter kMultiLanguage */ - if ($object->GetDBField('cust_RssSource') != $object->GetOriginalField('cust_RssSource')) { - $object->SetError('cust_RssSource', 'not_allowed', 'la_error_NotAllowed'); + $object->SetField( + $ml_formatter->LangFieldName($field), + $object->GetField( $ml_formatter->LangFieldName('Name') ) + ); } } - } - /** - * Sets page name to requested field in case when: - * 1. page was auto created (through theme file rebuld) - * 2. requested field is emtpy - * - * @param kDBItem $object - * @param string $field - * @author Alex - */ - function _saveTitleField(&$object, $field) - { - $value = $object->GetField($field, 'no_default'); - if ($value == '' || preg_match('/^_Auto: (.*)/', $value)) { - $ml_formatter =& $this->Application->recallObject('kMultiLanguage'); - /* @var $ml_formatter kMultiLanguage */ - - $object->SetField( - $ml_formatter->LangFieldName($field), - $object->GetField( $ml_formatter->LangFieldName('Name') ) - ); + /** + * Don't allow to delete system pages, when not in debug mode + * + * @param kEvent $event + */ + function OnBeforeItemDelete(&$event) + { + $object =& $event->getObject(); + if ($object->GetDBField('IsSystem') && !$this->Application->isDebugMode()) { + $event->status = erFAIL; + } } - } - /** - * Don't allow to delete system pages, when not in debug mode - * - * @param kEvent $event - */ - function OnBeforeItemDelete(&$event) - { - $object =& $event->getObject(); - if ($object->GetDBField('IsSystem') && !$this->Application->isDebugMode()) { - $event->status = erFAIL; - } - } + /** + * Enter description here... + * + * @param StructureItem $object + * @param string $template + */ + function _prepareAutoPage(&$object, $template, $theme_id = null, $system_mode = SMS_MODE_AUTO, $template_info = Array ()) + { + $template = $this->_stripTemplateExtension($template); - /** - * Enter description here... - * - * @param StructureItem $object - * @param string $template - */ - function _prepareAutoPage(&$object, $template, $theme_id = null, $system_mode = SMS_MODE_AUTO, $template_info = Array ()) - { - $template = $this->_stripTemplateExtension($template); + if ($system_mode == SMS_MODE_AUTO) { + $system = $this->_templateFound($template, $theme_id) ? 1 : 0; + } + else { + $system = $system_mode == SMS_MODE_FORCE ? 1 : 0; + } - if ($system_mode == SMS_MODE_AUTO) { - $system = $this->_templateFound($template, $theme_id) ? 1 : 0; - } - else { - $system = $system_mode == SMS_MODE_FORCE ? 1 : 0; - } + if ($system && $template_info === false) { + // do not autocreate system pages, when browsing through site + return false; + } - if ($system && $template_info === false) { - // do not autocreate system pages, when browsing through site - return false; - } + if (!isset($theme_id)) { + $theme_id = $this->_getCurrentThemeId(); + } - if (!isset($theme_id)) { - $theme_id = $this->_getCurrentThemeId(); - } + $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); + $page_category = $this->Application->GetVar('m_cat_id'); + if (!$page_category) { + $page_category = $root_category; + $this->Application->SetVar('m_cat_id', $page_category); + } - $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); - $page_category = $this->Application->GetVar('m_cat_id'); - if (!$page_category) { - $page_category = $root_category; - $this->Application->SetVar('m_cat_id', $page_category); - } + if (!$system && strpos($template, '/') !== false) { + // virtual page, but have "/" in template path -> create it's path + $category_path = explode('/', $template); + $template = array_pop($category_path); - if (!$system && strpos($template, '/') !== false) { - // virtual page, but have "/" in template path -> create it's path - $category_path = explode('/', $template); - $template = array_pop($category_path); + $page_category = $this->_getParentCategoryFromPath($category_path, $root_category, $theme_id); + } - $page_category = $this->_getParentCategoryFromPath($category_path, $root_category, $theme_id); - } + $page_name = $system ? '_Auto: ' . $template : $template; + $page_description = ''; - $page_name = $system ? '_Auto: ' . $template : $template; - $page_description = ''; + if ($system) { + $design_template = strtolower($template); // leading "/" not added ! + if ($template_info) { + if (array_key_exists('name', $template_info) && $template_info['name']) { + $page_name = $template_info['name']; + } - if ($system) { - $design_template = strtolower($template); // leading "/" not added ! - if ($template_info) { - if (array_key_exists('name', $template_info) && $template_info['name']) { - $page_name = $template_info['name']; - } + if (array_key_exists('desc', $template_info) && $template_info['desc']) { + $page_description = $template_info['desc']; + } - if (array_key_exists('desc', $template_info) && $template_info['desc']) { - $page_description = $template_info['desc']; + if (array_key_exists('section', $template_info) && $template_info['section']) { + // this will override any global "m_cat_id" + $page_category = $this->_getParentCategoryFromPath(explode('||', $template_info['section']), $root_category, $theme_id); + } } - - if (array_key_exists('section', $template_info) && $template_info['section']) { - // this will override any global "m_cat_id" - $page_category = $this->_getParentCategoryFromPath(explode('||', $template_info['section']), $root_category, $theme_id); - } } - } - else { - $design_template = $this->_getDefaultDesign(); // leading "/" added ! - } + else { + $design_template = $this->_getDefaultDesign(); // leading "/" added ! + } - // put all templates to then end of list (in their category) - $sql = 'SELECT MIN(Priority) - FROM ' . $object->TableName . ' - WHERE ParentId = ' . $page_category; - $min_priority = (int)$this->Conn->GetOne($sql); + // put all templates to then end of list (in their category) + $sql = 'SELECT MIN(Priority) + FROM ' . $object->TableName . ' + WHERE ParentId = ' . $page_category; + $min_priority = (int)$this->Conn->GetOne($sql); - $object->Clear(); - $object->SetDBField('ParentId', $page_category); - $object->SetDBField('IsSystem', $system); + $object->Clear(); + $object->SetDBField('ParentId', $page_category); + $object->SetDBField('IsSystem', $system); - // system templates don't build their NamedParentPath based on their location because they are all added under - // "Content" when theme file structure is rebuilded and for ex. file "in-edit/designs/general" will have filename - // (after stripDisallowed) like "in_edit_designs_general" witch is less readable like "in-edit/designs/general" - // as for now. + // system templates don't build their NamedParentPath based on their location because they are all added under + // "Content" when theme file structure is rebuilded and for ex. file "in-edit/designs/general" will have filename + // (after stripDisallowed) like "in_edit_designs_general" witch is less readable like "in-edit/designs/general" + // as for now. - // TODO: 1. make system template NamedParentPath dependent on their location in structure. - // 2. load cms-page not only by NamedParentPath, but also by 'OR (Template = "$template" AND IsSystem = 1)' - // This way we can store CMS-blocks based on system template name on HDD no matter where it's location is - // and we can address him from template using his system path OR structure path (CMS-blocks should work too). + // TODO: 1. make system template NamedParentPath dependent on their location in structure. + // 2. load cms-page not only by NamedParentPath, but also by 'OR (Template = "$template" AND IsSystem = 1)' + // This way we can store CMS-blocks based on system template name on HDD no matter where it's location is + // and we can address him from template using his system path OR structure path (CMS-blocks should work too). - $object->SetDBField('IsMenu', 0); - $object->SetDBField('ThemeId', $system ? $theme_id : 0); - $object->SetDBField('Priority', $min_priority - 1); - $object->SetDBField('Template', $design_template); - $object->SetDBField('CachedTemplate', $design_template); + $object->SetDBField('IsMenu', 0); + $object->SetDBField('ThemeId', $system ? $theme_id : 0); + $object->SetDBField('Priority', $min_priority - 1); + $object->SetDBField('Template', $design_template); + $object->SetDBField('CachedTemplate', $design_template); - $primary_language = $this->Application->GetDefaultLanguageId(); - $current_language = $this->Application->GetVar('m_lang'); - $object->SetDBField('l' . $primary_language . '_Name', $page_name); - $object->SetDBField('l' . $current_language . '_Name', $page_name); - $object->SetDBField('l' . $primary_language . '_Description', $page_description); - $object->SetDBField('l' . $current_language . '_Description', $page_description); + $primary_language = $this->Application->GetDefaultLanguageId(); + $current_language = $this->Application->GetVar('m_lang'); + $object->SetDBField('l' . $primary_language . '_Name', $page_name); + $object->SetDBField('l' . $current_language . '_Name', $page_name); + $object->SetDBField('l' . $primary_language . '_Description', $page_description); + $object->SetDBField('l' . $current_language . '_Description', $page_description); - return $object->Create(); - } + return $object->Create(); + } - function _getParentCategoryFromPath($category_path, $base_category, $theme_id = null) - { - static $category_ids = Array (); + function _getParentCategoryFromPath($category_path, $base_category, $theme_id = null) + { + static $category_ids = Array (); - if (!$category_path) { - return $base_category; - } + if (!$category_path) { + return $base_category; + } - if (array_key_exists(implode('||', $category_path), $category_ids)) { - return $category_ids[ implode('||', $category_path) ]; - } + if (array_key_exists(implode('||', $category_path), $category_ids)) { + return $category_ids[ implode('||', $category_path) ]; + } - $backup_category_id = $this->Application->GetVar('m_cat_id'); + $backup_category_id = $this->Application->GetVar('m_cat_id'); - $object =& $this->Application->recallObject($this->Prefix . '.-item', null, Array ('skip_autoload' => true)); - /* @var $object kDBItem */ + $object =& $this->Application->recallObject($this->Prefix . '.-item', null, Array ('skip_autoload' => true)); + /* @var $object kDBItem */ - $parent_id = $base_category; + $parent_id = $base_category; - $filenames_helper =& $this->Application->recallObject('FilenamesHelper'); - /* @var $filenames_helper kFilenamesHelper */ + $filenames_helper =& $this->Application->recallObject('FilenamesHelper'); + /* @var $filenames_helper kFilenamesHelper */ - $safe_category_path = array_map(Array (&$filenames_helper, 'replaceSequences'), $category_path); + $safe_category_path = array_map(Array (&$filenames_helper, 'replaceSequences'), $category_path); - foreach ($category_path as $category_order => $category_name) { - $this->Application->SetVar('m_cat_id', $parent_id); + foreach ($category_path as $category_order => $category_name) { + $this->Application->SetVar('m_cat_id', $parent_id); - // get virtual category first, when possible - $sql = 'SELECT ' . $object->IDField . ' - FROM ' . $object->TableName . ' - WHERE - ( - Filename = ' . $this->Conn->qstr($safe_category_path[$category_order]) . ' OR - Filename = ' . $this->Conn->qstr( $filenames_helper->replaceSequences('_Auto: ' . $category_name) ) . ' - ) AND - (ParentId = ' . $parent_id . ') AND - (ThemeId = 0 OR ThemeId = ' . $theme_id . ') - ORDER BY ThemeId ASC'; - $parent_id = $this->Conn->GetOne($sql); + // get virtual category first, when possible + $sql = 'SELECT ' . $object->IDField . ' + FROM ' . $object->TableName . ' + WHERE + ( + Filename = ' . $this->Conn->qstr($safe_category_path[$category_order]) . ' OR + Filename = ' . $this->Conn->qstr( $filenames_helper->replaceSequences('_Auto: ' . $category_name) ) . ' + ) AND + (ParentId = ' . $parent_id . ') AND + (ThemeId = 0 OR ThemeId = ' . $theme_id . ') + ORDER BY ThemeId ASC'; + $parent_id = $this->Conn->GetOne($sql); - if ($parent_id === false) { - // page not found - $template = implode('/', array_slice($safe_category_path, 0, $category_order + 1)); + if ($parent_id === false) { + // page not found + $template = implode('/', array_slice($safe_category_path, 0, $category_order + 1)); - // don't process system templates in sub-categories - $system = $this->_templateFound($template, $theme_id) && (strpos($template, '/') === false); + // don't process system templates in sub-categories + $system = $this->_templateFound($template, $theme_id) && (strpos($template, '/') === false); - if (!$this->_prepareAutoPage($object, $category_name, $theme_id, $system ? SMS_MODE_FORCE : false)) { - // page was not created - break; - } + if (!$this->_prepareAutoPage($object, $category_name, $theme_id, $system ? SMS_MODE_FORCE : false)) { + // page was not created + break; + } - $parent_id = $object->GetID(); + $parent_id = $object->GetID(); + } } + + $this->Application->SetVar('m_cat_id', $backup_category_id); + $category_ids[ implode('||', $category_path) ] = $parent_id; + + return $parent_id; } - $this->Application->SetVar('m_cat_id', $backup_category_id); - $category_ids[ implode('||', $category_path) ] = $parent_id; + /** + * Returns theme name by it's id. Used in structure page creation. + * + * @param int $theme_id + * @return string + */ + function _getThemeName($theme_id) + { + static $themes = null; - return $parent_id; - } + if (!isset($themes)) { + $id_field = $this->Application->getUnitOption('theme', 'IDField'); + $table_name = $this->Application->getUnitOption('theme', 'TableName'); - /** - * Returns theme name by it's id. Used in structure page creation. - * - * @param int $theme_id - * @return string - */ - function _getThemeName($theme_id) - { - static $themes = null; + $sql = 'SELECT Name, ' . $id_field . ' + FROM ' . $table_name . ' + WHERE Enabled = 1'; + $themes = $this->Conn->GetCol($sql, $id_field); + } - if (!isset($themes)) { - $id_field = $this->Application->getUnitOption('theme', 'IDField'); - $table_name = $this->Application->getUnitOption('theme', 'TableName'); + return array_key_exists($theme_id, $themes) ? $themes[$theme_id] : false; + } - $sql = 'SELECT Name, ' . $id_field . ' - FROM ' . $table_name . ' - WHERE Enabled = 1'; - $themes = $this->Conn->GetCol($sql, $id_field); + /** + * Resets SMS-menu cache + * + * @param kEvent $event + */ + function OnResetMenuCache(&$event) + { + $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")'); } - return array_key_exists($theme_id, $themes) ? $themes[$theme_id] : false; - } + /** + * Updates structure config + * + * @param kEvent $event + */ + function OnAfterConfigRead(&$event) + { + parent::OnAfterConfigRead($event); - /** - * Resets SMS-menu cache - * - * @param kEvent $event - */ - function OnResetMenuCache(&$event) - { - $this->Conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName IN ("cms_menu", "StructureTree")'); - } + if (defined('IS_INSTALL') && IS_INSTALL) { + // skip any processing, because Category table doesn't exists until install is finished + return ; + } - /** - * Updates structure config - * - * @param kEvent $event - */ - function OnAfterConfigRead(&$event) - { - parent::OnAfterConfigRead($event); + $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); - if (defined('IS_INSTALL') && IS_INSTALL) { - // skip any processing, because Category table doesn't exists until install is finished - return ; - } + // set root category + $section_ajustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments'); - $root_category = $this->Application->findModule('Name', 'Core', 'RootCat'); + $section_ajustments['in-portal:browse'] = Array ( + 'url' => Array ('m_cat_id' => $root_category), + 'late_load' => Array ('m_cat_id' => $root_category), + 'onclick' => 'checkCatalog(' . $root_category . ')', + ); - // set root category - $section_ajustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments'); + $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_ajustments); - $section_ajustments['in-portal:browse'] = Array ( - 'url' => Array ('m_cat_id' => $root_category), - 'late_load' => Array ('m_cat_id' => $root_category), - 'onclick' => 'checkCatalog(' . $root_category . ')', - ); + // prepare structure dropdown + $category_helper =& $this->Application->recallObject('CategoryHelper'); + /* @var $category_helper CategoryHelper */ - $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_ajustments); + $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); - // prepare structure dropdown - $category_helper =& $this->Application->recallObject('CategoryHelper'); - /* @var $category_helper CategoryHelper */ + $fields['ParentId']['default'] = (int)$this->Application->GetVar('m_cat_id'); + $fields['ParentId']['options'] = $category_helper->getStructureTreeAsOptions(); - $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); + // limit design list by theme + $design_folders = Array ('tf.FilePath = "/designs"', 'tf.FilePath = "/platform/designs"'); + foreach ($this->Application->ModuleInfo as $module_name => $module_info) { + $design_folders[] = 'tf.FilePath = "/' . $module_info['TemplatePath'] . 'designs"'; + } + $design_folders = array_unique($design_folders); - $fields['ParentId']['default'] = (int)$this->Application->GetVar('m_cat_id'); - $fields['ParentId']['options'] = $category_helper->getStructureTreeAsOptions(); + $theme_id = $this->_getCurrentThemeId(); + $design_sql = $fields['Template']['options_sql']; + $design_sql = str_replace('(tf.FilePath = "/designs")', '(' . implode(' OR ', $design_folders) . ')' . ' AND (t.ThemeId = ' . $theme_id . ')', $design_sql); + $fields['Template']['options_sql'] = $design_sql; - // limit design list by theme - $design_folders = Array ('tf.FilePath = "/designs"', 'tf.FilePath = "/platform/designs"'); - foreach ($this->Application->ModuleInfo as $module_name => $module_info) { - $design_folders[] = 'tf.FilePath = "/' . $module_info['TemplatePath'] . 'designs"'; - } - $design_folders = array_unique($design_folders); + // adds "Inherit From Parent" option to "Template" field + $fields['Template']['options'] = Array (CATEGORY_TEMPLATE_INHERIT => $this->Application->Phrase('la_opt_InheritFromParent')); - $theme_id = $this->_getCurrentThemeId(); - $design_sql = $fields['Template']['options_sql']; - $design_sql = str_replace('(tf.FilePath = "/designs")', '(' . implode(' OR ', $design_folders) . ')' . ' AND (t.ThemeId = ' . $theme_id . ')', $design_sql); - $fields['Template']['options_sql'] = $design_sql; + $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); - // adds "Inherit From Parent" option to "Template" field - $fields['Template']['options'] = Array (CATEGORY_TEMPLATE_INHERIT => $this->Application->Phrase('la_opt_InheritFromParent')); + if ($this->Application->IsAdmin()) { + // don't sort by Front-End sorting fields + $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping'); + $remove_keys = Array ('DefaultSorting1Field', 'DefaultSorting2Field', 'DefaultSorting1Dir', 'DefaultSorting2Dir'); + foreach ($remove_keys as $remove_key) { + unset($config_mapping[$remove_key]); + } + $this->Application->setUnitOption($event->Prefix, 'ConfigMapping', $config_mapping); + } + else { + // sort by parent path on Front-End only + $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings'); + $list_sortings['']['ForcedSorting'] = Array ("CurrentSort" => 'asc'); + $this->Application->setUnitOption($event->Prefix, 'ListSortings', $list_sortings); + } - $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); - - if ($this->Application->IsAdmin()) { - // don't sort by Front-End sorting fields - $config_mapping = $this->Application->getUnitOption($event->Prefix, 'ConfigMapping'); - $remove_keys = Array ('DefaultSorting1Field', 'DefaultSorting2Field', 'DefaultSorting1Dir', 'DefaultSorting2Dir'); - foreach ($remove_keys as $remove_key) { - unset($config_mapping[$remove_key]); + // 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_parent_category_td', 'filter_block' => 'grid_like_filter'); + $grids[$process_grid . 'ShowAll'] = $grid_data; } - $this->Application->setUnitOption($event->Prefix, 'ConfigMapping', $config_mapping); + $this->Application->setUnitOption($this->Prefix, 'Grids', $grids); } - else { - // sort by parent path on Front-End only - $list_sortings = $this->Application->getUnitOption($event->Prefix, 'ListSortings'); - $list_sortings['']['ForcedSorting'] = Array ("CurrentSort" => 'asc'); - $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_parent_category_td', 'filter_block' => 'grid_like_filter'); - $grids[$process_grid . 'ShowAll'] = $grid_data; - } - $this->Application->setUnitOption($this->Prefix, 'Grids', $grids); - } + /** + * Removes this item and it's children (recursive) from structure dropdown + * + * @param kEvent $event + */ + function OnAfterItemLoad(&$event) + { + parent::OnAfterItemLoad($event); - /** - * Removes this item and it's children (recursive) from structure dropdown - * - * @param kEvent $event - */ - function OnAfterItemLoad(&$event) - { - parent::OnAfterItemLoad($event); + if (!$this->Application->IsAdmin()) { + return ; + } - if (!$this->Application->IsAdmin()) { - return ; - } + $object =& $event->getObject(); - $object =& $event->getObject(); + // remove this category & it's children from dropdown + $sql = 'SELECT '.$object->IDField.' + FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + WHERE ParentPath LIKE "'.$object->GetDBField('ParentPath').'%"'; + $remove_categories = $this->Conn->GetCol($sql); - // remove this category & it's children from dropdown - $sql = 'SELECT '.$object->IDField.' - FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' - WHERE ParentPath LIKE "'.$object->GetDBField('ParentPath').'%"'; - $remove_categories = $this->Conn->GetCol($sql); + $field_options = $object->GetFieldOptions('ParentId'); + foreach ($remove_categories as $remove_category) { + unset($field_options['options'][$remove_category]); + } + $object->SetFieldOptions('ParentId', $field_options); - $field_options = $object->GetFieldOptions('ParentId'); - foreach ($remove_categories as $remove_category) { - unset($field_options['options'][$remove_category]); - } - $object->SetFieldOptions('ParentId', $field_options); + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + $priority_helper->preparePriorities($event, false, 'ParentId = '.$object->GetDBField('ParentId')); - $priority_helper->preparePriorities($event, false, 'ParentId = '.$object->GetDBField('ParentId')); + // storing prioriry right after load for comparing when updating + $object->SetDBField('OldPriority', $object->GetDBField('Priority')); + } - // storing prioriry right after load for comparing when updating - $object->SetDBField('OldPriority', $object->GetDBField('Priority')); - } + /** + * Builds list + * + * @param kEvent $event + * @access protected + */ + function OnListBuild(&$event) + { + parent::OnListBuild($event); - /** - * Builds list - * - * @param kEvent $event - * @access protected - */ - function OnListBuild(&$event) - { - parent::OnListBuild($event); + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ - - $priority_helper->preparePriorities($event, false, 'ParentId = '.$this->Application->GetVar('m_cat_id')); - } - - /** - * Enter description here... - * - * @param kEvent $event - */ - function OnAfterRebuildThemes(&$event) - { - $sql = 'SELECT t.ThemeId, CONCAT( tf.FilePath, \'/\', tf.FileName ) AS Path, tf.FileMetaInfo - FROM '.TABLE_PREFIX.'ThemeFiles AS tf - LEFT JOIN '.TABLE_PREFIX.'Theme AS t ON t.ThemeId = tf.ThemeId - WHERE t.Enabled = 1 AND tf.FileType = 1 - AND ( - SELECT COUNT(CategoryId) - FROM ' . TABLE_PREFIX . 'Category - WHERE CONCAT(\'/\', ' . TABLE_PREFIX . 'Category.Template, \'.tpl\') = CONCAT( tf.FilePath, \'/\', tf.FileName ) - ) = 0 '; - $files = $this->Conn->Query($sql, 'Path'); - if (!$files) { - // all possible pages are already created - return ; + $priority_helper->preparePriorities($event, false, 'ParentId = '.$this->Application->GetVar('m_cat_id')); } - set_time_limit(0); - ini_set('memory_limit', -1); + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnAfterRebuildThemes(&$event) + { + $sql = 'SELECT t.ThemeId, CONCAT( tf.FilePath, \'/\', tf.FileName ) AS Path, tf.FileMetaInfo + FROM '.TABLE_PREFIX.'ThemeFiles AS tf + LEFT JOIN '.TABLE_PREFIX.'Theme AS t ON t.ThemeId = tf.ThemeId + WHERE t.Enabled = 1 AND tf.FileType = 1 + AND ( + SELECT COUNT(CategoryId) + FROM ' . TABLE_PREFIX . 'Category + WHERE CONCAT(\'/\', ' . TABLE_PREFIX . 'Category.Template, \'.tpl\') = CONCAT( tf.FilePath, \'/\', tf.FileName ) + ) = 0 '; + $files = $this->Conn->Query($sql, 'Path'); + if (!$files) { + // all possible pages are already created + return ; + } - $dummy =& $this->Application->recallObject($event->Prefix . '.-dummy', null, Array ('skip_autoload' => true)); - /* @var $dummy kDBItem */ + set_time_limit(0); + ini_set('memory_limit', -1); - $error_count = 0; - foreach ($files as $a_file => $file_info) { - $status = $this->_prepareAutoPage($dummy, $a_file, $file_info['ThemeId'], SMS_MODE_FORCE, unserialize($file_info['FileMetaInfo'])); // create system page - if (!$status) { - $error_count++; + $dummy =& $this->Application->recallObject($event->Prefix . '.-dummy', null, Array ('skip_autoload' => true)); + /* @var $dummy kDBItem */ + + $error_count = 0; + foreach ($files as $a_file => $file_info) { + $status = $this->_prepareAutoPage($dummy, $a_file, $file_info['ThemeId'], SMS_MODE_FORCE, unserialize($file_info['FileMetaInfo'])); // create system page + if (!$status) { + $error_count++; + } } - } - if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) { - $updater =& $this->Application->recallObject('kPermCacheUpdater'); - /* @var $updater kPermCacheUpdater */ + if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) { + $updater =& $this->Application->recallObject('kPermCacheUpdater'); + /* @var $updater kPermCacheUpdater */ - $updater->OneStepRun(); - } + $updater->OneStepRun(); + } - $event->CallSubEvent('OnResetMenuCache'); + $event->CallSubEvent('OnResetMenuCache'); - if ($error_count) { - // allow user to review error after structure page creation - $event->MasterEvent->redirect = false; + if ($error_count) { + // allow user to review error after structure page creation + $event->MasterEvent->redirect = false; + } } - } - /** - * Processes OnMassMoveUp, OnMassMoveDown events - * - * @param kEvent $event - */ - function OnChangePriority(&$event) - { - $object =& $event->getObject( Array('skip_autoload' => true) ); - $ids = $this->StoreSelectedIDs($event); + /** + * Processes OnMassMoveUp, OnMassMoveDown events + * + * @param kEvent $event + */ + function OnChangePriority(&$event) + { + $object =& $event->getObject( Array('skip_autoload' => true) ); + $ids = $this->StoreSelectedIDs($event); - if ($ids) { - $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); - $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); - $parent_id = $this->Application->GetVar('m_cat_id'); + if ($ids) { + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); + $parent_id = $this->Application->GetVar('m_cat_id'); - $sql = 'SELECT Priority, '.$id_field.' - FROM '.$table_name.' - WHERE '.$id_field.' IN ('.implode(',', $ids).')'; - $priorities = $this->Conn->GetCol($sql, $id_field); + $sql = 'SELECT Priority, '.$id_field.' + FROM '.$table_name.' + WHERE '.$id_field.' IN ('.implode(',', $ids).')'; + $priorities = $this->Conn->GetCol($sql, $id_field); - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - foreach ($ids as $id) { - $new_priority = $priorities[$id] + ($event->Name == 'OnMassMoveUp' ? +1 : -1); + foreach ($ids as $id) { + $new_priority = $priorities[$id] + ($event->Name == 'OnMassMoveUp' ? +1 : -1); - $changes = Array ( - $id => Array ('old' => $priorities[$id], 'new' => $new_priority, 'parent' => $parent_id), - ); + $changes = Array ( + $id => Array ('old' => $priorities[$id], 'new' => $new_priority, 'parent' => $parent_id), + ); - $sql = 'UPDATE '.$table_name.' - SET Priority = '.$new_priority.' - WHERE '.$id_field.' = '.$id; - $this->Conn->Query($sql); + $sql = 'UPDATE '.$table_name.' + SET Priority = '.$new_priority.' + WHERE '.$id_field.' = '.$id; + $this->Conn->Query($sql); - $priority_helper->updatePriorities($event, $changes, Array ($id => $id)); + $priority_helper->updatePriorities($event, $changes, Array ($id => $id)); + } } + + $this->clearSelectedIDs($event); + $this->Application->StoreVar('RefreshStructureTree', 1); } - $this->clearSelectedIDs($event); - $this->Application->StoreVar('RefreshStructureTree', 1); - } + /** + * Completely recalculates priorities in current category + * + * @param kEvent $event + */ + function OnRecalculatePriorities(&$event) + { + $priority_helper =& $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ - /** - * Completely recalculates priorities in current category - * - * @param kEvent $event - */ - function OnRecalculatePriorities(&$event) - { - $priority_helper =& $this->Application->recallObject('PriorityHelper'); - /* @var $priority_helper kPriorityHelper */ + $parent_id = $this->Application->GetVar('m_cat_id'); + $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); + } - $parent_id = $this->Application->GetVar('m_cat_id'); - $priority_helper->recalculatePriorities($event, 'ParentId = ' . $parent_id); - } + /** + * Update Preview Block for FCKEditor + * + * @param kEvent $event + */ + function OnUpdatePreviewBlock(&$event) + { + $event->status = erSTOP; + $string = unhtmlentities($this->Application->GetVar('preview_content')); - /** - * Update Preview Block for FCKEditor - * - * @param kEvent $event - */ - function OnUpdatePreviewBlock(&$event) - { - $event->status = erSTOP; - $string = unhtmlentities($this->Application->GetVar('preview_content')); + $category_helper =& $this->Application->recallObject('CategoryHelper'); + /* @var $category_helper CategoryHelper */ - $category_helper =& $this->Application->recallObject('CategoryHelper'); - /* @var $category_helper CategoryHelper */ + $string = $category_helper->replacePageIds($string); - $string = $category_helper->replacePageIds($string); - - $this->Application->StoreVar('_editor_preview_content_', $string); - } -} - -?> \ No newline at end of file + $this->Application->StoreVar('_editor_preview_content_', $string); + } + } \ No newline at end of file