Array ('self' => true), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Define alternative event processing method names * * @return void * @see kEventHandler::$eventMethods * @access protected */ protected function mapEvents() { parent::mapEvents(); $events_map = Array ( 'OnMassMoveUp' => 'OnChangePriority', 'OnMassMoveDown' => 'OnChangePriority', ); $this->eventMethods = array_merge($this->eventMethods, $events_map); } /** * Occurs, when config was parsed, allows to change config data dynamically * * @param kEvent $event * @return void * @access protected */ protected function OnAfterConfigRead(kEvent $event) { parent::OnAfterConfigRead($event); $hooks = Array( Array( 'Mode' => hAFTER, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnAfterItemLoad', 'OnPreCreate', 'OnListBuild'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnPreparePriorities', 'Conditional' => false, ), Array( 'Mode' => hBEFORE, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnPreSaveCreated'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnPreparePriorities', 'Conditional' => false, ), Array( 'Mode' => hAFTER, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnPreSave', 'OnPreSaveCreated', 'OnSave', 'OnUpdate'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnSavePriorityChanges', 'Conditional' => false, ), Array( 'Mode' => hAFTER, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnSave'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnSaveItems', 'Conditional' => false, ), Array( 'Mode' => hBEFORE, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnBeforeItemCreate'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnItemCreate', 'Conditional' => false, ), Array( 'Mode' => hBEFORE, 'Conditional' => false, 'HookToPrefix' => '', 'HookToSpecial' => '*', 'HookToEvent' => Array('OnAfterItemDelete'), 'DoPrefix' => 'priority', 'DoSpecial' => '*', 'DoEvent' => 'OnItemDelete', 'Conditional' => false, ) ); $prefixes = $event->getUnitConfig()->getProcessPrefixes(Array ()); foreach ($prefixes as $prefix) { foreach ($hooks as $hook) { if ( !is_array($hook['HookToEvent']) ) { $hook['HookToEvent'] = Array($hook['HookToEvent']); } foreach ($hook['HookToEvent'] as $hook_event) { $this->Application->registerHook( $prefix . '.' . $hook['HookToSpecial'] . ':' . $hook_event, $event->Prefix . '.' . $hook['DoSpecial'] . ':' . $hook['DoEvent'], $hook['Mode'], $hook['Conditional'] ); } } } } /** * Should be hooked to OnAfterItemLoad, OnPreSaveCreated (why latter?) * * @param kEvent $event */ function OnPreparePriorities($event) { if ( !$this->Application->isAdminUser ) { return ; } /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); list ($constrain, $joins) = $this->getConstrainInfo($event); $is_new = $event->MasterEvent->Name == 'OnPreCreate' || $event->MasterEvent->Name == 'OnPreSaveCreated'; $priority_helper->preparePriorities($event->MasterEvent, $is_new, $constrain, $joins); } /** * Enter description here... * * @param kEvent $event */ function OnSavePriorityChanges($event) { if ($event->MasterEvent->status != kEvent::erSUCCESS) { // don't update priorities, when OnSave validation failed return ; } $object = $event->MasterEvent->getObject(); /* @var $object kDBItem */ $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); $changes = $tmp ? unserialize($tmp) : array(); if (!isset($changes[$object->GetID()])) { $changes[$object->GetId()]['old'] = $object->GetID() == 0 ? 'new' : $object->GetDBField('OldPriority'); } if ($changes[$object->GetId()]['old'] == $object->GetDBField('Priority')) return ; $changes[$object->GetId()]['new'] = $object->GetDBField('Priority'); list ($constrain, $joins) = $this->getConstrainInfo($event); if ($constrain) { $changes[$object->GetId()]['constrain'] = $constrain; } $this->Application->StoreVar('priority_changes'.$this->Application->GetVar('m_wid'), serialize($changes)); } /** * Enter description here... * * @param kEvent $event */ function OnItemDelete($event) { // just store the prefix in which the items were deleted $del = $this->Application->RecallVar('priority_deleted' . $this->Application->GetVar('m_wid')); $del = $del ? unserialize($del) : array(); list ($constrain, $joins) = $this->getConstrainInfo($event); $cache_key = crc32($event->MasterEvent->Prefix . ':' . $constrain . ':' . $joins); if ( !isset($del[$cache_key]) ) { $del[$cache_key] = Array ( 'prefix' => $event->MasterEvent->Prefix, 'constrain' => $constrain, 'joins' => $joins, ); $this->Application->StoreVar('priority_deleted' . $this->Application->GetVar('m_wid'), serialize($del)); } } /** * Called before script shut-down and recalculate all deleted prefixes, to avoid recalculation on each deleted item * * @param kEvent $event */ function OnBeforeShutDown($event) { $del = $this->Application->RecallVar('priority_deleted'.$this->Application->GetVar('m_wid')); $del = $del ? unserialize($del) : array(); /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); foreach ($del as $del_info) { $dummy_event = new kEvent($del_info['prefix'] . ':OnDummy'); $ids = $priority_helper->recalculatePriorities($dummy_event, $del_info['constrain'], $del_info['joins']); if ($ids) { $priority_helper->massUpdateChanged($del_info['prefix'], $ids); } } $this->Application->RemoveVar('priority_deleted'.$this->Application->GetVar('m_wid')); } /** * Enter description here... * * @param kEvent $event */ function OnSaveItems($event) { $tmp = $this->Application->RecallVar('priority_changes'.$this->Application->GetVar('m_wid')); $changes = $tmp ? unserialize($tmp) : array(); /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); list ($constrain, $joins) = $this->getConstrainInfo($event); $ids = $priority_helper->updatePriorities($event->MasterEvent, $changes, Array (0 => $event->MasterEvent->getEventParam('ids')), $constrain, $joins); if ($ids) { $priority_helper->massUpdateChanged($event->MasterEvent->Prefix, $ids); } } function OnItemCreate($event) { $object = $event->MasterEvent->getObject(); /* @var $object kDBItem */ if ($object->GetDBField('Priority') == 0) { /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); list ($constrain, $joins) = $this->getConstrainInfo($event); $priority_helper->preparePriorities($event->MasterEvent, true, $constrain, $joins); } } /** * Processes OnMassMoveUp, OnMassMoveDown events * * @param kEvent $event */ function OnChangePriority($event) { $prefix = $this->Application->GetVar('priority_prefix'); $dummy_event = new kEvent($prefix . ':OnDummy'); $ids = $this->StoreSelectedIDs($dummy_event); if ($ids) { $config = $this->Application->getUnitConfig($prefix); $id_field = $config->getIDField(); $table_name = $config->getTableName(); if ( $this->Application->IsTempMode($prefix) ) { $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $prefix); } $sql = 'SELECT Priority, '.$id_field.' FROM '.$table_name.' WHERE '.$id_field.' IN ('.implode(',', $ids).') ORDER BY Priority DESC'; $priorities = $this->Conn->GetCol($sql, $id_field); /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); list ($constrain, $joins) = $this->getConstrainInfo($event); $sql = 'SELECT IFNULL(MIN(item_table.Priority), -1) FROM '.$table_name . ' item_table ' . $joins; if ( $constrain ) { $sql .= ' WHERE ' . $priority_helper->normalizeConstrain($constrain); } $min_priority = $this->Conn->GetOne($sql); foreach ($ids as $id) { $new_priority = $priorities[$id] + ($event->Name == 'OnMassMoveUp' ? +1 : -1); if ($new_priority > -1 || $new_priority < $min_priority) { continue; } $changes = Array ( $id => Array ('old' => $priorities[$id], 'new' => $new_priority), ); if ($constrain) { $changes[$id]['constrain'] = $constrain; } $sql = 'UPDATE '.$table_name.' SET Priority = '.$new_priority.' WHERE '.$id_field.' = '.$id; $this->Conn->Query($sql); $ids = $priority_helper->updatePriorities($dummy_event, $changes, Array ($id => $id), $constrain, $joins); if ($ids) { $priority_helper->massUpdateChanged($prefix, $ids); } } } $this->clearSelectedIDs($dummy_event); } /** * Completely recalculates priorities in current category * * @param kEvent $event */ function OnRecalculatePriorities($event) { /** @var kPriorityHelper $priority_helper */ $priority_helper = $this->Application->recallObject('PriorityHelper'); $prefix = $this->Application->GetVar('priority_prefix'); $dummy_event = new kEvent($prefix . ':Dummy'); list ($constrain, $joins) = $this->getConstrainInfo($event); $ids = $priority_helper->recalculatePriorities($dummy_event, $constrain, $joins); if ($ids) { $priority_helper->massUpdateChanged($prefix, $ids); } } /** * Returns constrain for current priority calculations * * @param kEvent $event * @return Array */ function getConstrainInfo($event) { $constrain_event = new kEvent($event->MasterEvent->getPrefixSpecial() . ':OnGetConstrainInfo'); $constrain_event->setEventParam('actual_event', $event->Name); $constrain_event->setEventParam('original_special', $event->MasterEvent->Special); $constrain_event->setEventParam('original_event', $event->MasterEvent->Name); $this->Application->HandleEvent($constrain_event); return $constrain_event->getEventParam('constrain_info'); } }