Name) { case 'OnCreate': case 'OnUpdate': $object = $event->getObject(); /* @var $object kDBItem */ $options = unserialize($object->GetDBField('Combination')); ksort($options); $object->SetDBField('CombinationCRC', kUtil::crc32(serialize($options))); break; case 'OnMassDelete': // delete only option combinations that has no associated inventory $object = $event->getObject(); /* @var $object kDBItem */ $ids = $event->getEventParam('ids'); $sql = 'SELECT ' . $object->IDField . ' FROM ' . $object->TableName . ' WHERE (' . $object->IDField . ' IN (' . implode(',', $ids) . ')) AND (QtyInStock = 0) AND (QtyReserved = 0) AND (QtyBackOrdered = 0) AND (QtyOnOrder = 0)'; $event->setEventParam('ids', $this->Conn->GetCol($sql)); break; } } /** * GetOptionValues * * @param kEvent $event */ function GetOptionValues($event, $option_id) { $object = $event->getObject(); if ($object->IsTempTable()) { $table = $this->Application->GetTempName(TABLE_PREFIX.'ProductOptions', 'prefix:'.$event->Prefix); } else { $table = TABLE_PREFIX.'ProductOptions'; } $query = 'SELECT `Values` FROM '.$table.' WHERE ProductOptionId = '.$option_id; return explode(',', $this->Conn->GetOne($query)); } function CreateCombinations(kEvent $event, $fields, $current_option=null) { $recursed = false; $combination = $fields['Combination']; foreach ($combination as $option_id => $option) { if ($option_id == $current_option || $recursed) continue; if ($option == '_ANY_') { $recursed = true; $values = $this->GetOptionValues($event, $option_id); foreach ($values as $a_value) { $fields['Combination'][$option_id] = $a_value; $this->CreateCombinations($event, $fields, $option_id); } } } if (!$recursed) { $object = $event->getObject(); /* @var $object kDBItem */ $salt = $fields['Combination']; ksort($salt); $object->Load(kUtil::crc32(serialize($salt)), 'CombinationCRC'); $object->SetFieldsFromHash($fields); $event->setEventParam('form_data', $fields); $this->customProcessing($event,'before'); if ( $object->isLoaded() ) { // Update if such combination already exists if( $object->Update() ) { $this->customProcessing($event,'after'); $event->status=kEvent::erSUCCESS; } } else { if( $object->Create($event->getEventParam('ForceCreateId')) ) { $this->customProcessing($event,'after'); $event->status=kEvent::erSUCCESS; } } } } function UpdateCombinations(kEvent $event, $fields, $current_option=null) { $recursed = false; $combination = $fields['Combination']; foreach ($combination as $option_id => $option) { if ($option_id == $current_option || $recursed) continue; if ($option == '_ANY_') { $recursed = true; $values = $this->GetOptionValues($event, $option_id); foreach ($values as $a_value) { $fields['Combination'][$option_id] = $a_value; $this->UpdateCombinations($event, $fields, $option_id); } } } if (!$recursed) { $object = $event->getObject(); /* @var $object kDBItem */ $edit_id = $object->GetId(); $salt = $fields['Combination']; ksort($salt); // try to load combination by salt - if loaded, it will update the combination $object->Load(kUtil::crc32(serialize($salt)), 'CombinationCRC'); if ( !$object->isLoaded() ) { $object->Load($edit_id); } $object->SetFieldsFromHash($fields); $event->setEventParam('form_data', $fields); $this->customProcessing($event,'before'); if( $object->Update() ) { $this->customProcessing($event,'after'); $event->status=kEvent::erSUCCESS; } } } /** * Creates new kDBItem * * @param kEvent $event * @return void * @access protected */ protected function OnCreate(kEvent $event) { $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); if ( !$items_info ) { return; } list($id, $field_values) = each($items_info); $object->setID($id); $object->SetFieldsFromHash($field_values); $event->setEventParam('form_data', $field_values); if ( !$object->Validate() ) { $event->status = kEvent::erFAIL; $event->redirect = false; $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate'); return; } $this->CreateCombinations($event, $field_values); } /** * Updates kDBItem * * @param kEvent $event * @return void * @access protected */ protected function OnUpdate(kEvent $event) { $object = $event->getObject( Array('skip_autoload' => true) ); /* @var $object kDBItem */ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); if($items_info) { foreach($items_info as $id => $field_values) { $object->Load($id); $object->SetFieldsFromHash($field_values); $event->setEventParam('form_data', $field_values); if (!$object->Validate()) { $event->status = kEvent::erFAIL; $event->redirect = false; return; } $this->UpdateCombinations($event, $field_values); /*$this->customProcessing($event, 'before'); if( $object->Update($id) ) { $this->customProcessing($event, 'after'); $event->status=kEvent::erSUCCESS; } else { $event->status=kEvent::erFAIL; $event->redirect=false; break; }*/ } } $this->Application->SetVar($event->GetPrefixSpecial().'_id', ''); } /** * Builds item (loads if needed) * * Pattern: Prototype Manager * * @param kEvent $event * @access protected */ protected function OnItemBuild(kEvent $event) { $object = $event->getObject(); /* @var $object kDBItem */ $this->dbBuild($object, $event); $sql = $this->ItemPrepareQuery($event); $sql = $this->Application->ReplaceLanguageTags($sql); $object->setSelectSQL($sql); // 2. loads if allowed $auto_load = $this->Application->getUnitOption($event->Prefix, 'AutoLoad'); $skip_autoload = $event->getEventParam('skip_autoload'); if ( $auto_load && !$skip_autoload ) { $this->LoadItem($event); } $actions = $this->Application->recallObject('kActions'); /* @var $actions Params */ $actions->Set($event->getPrefixSpecial() . '_GoTab', ''); $actions->Set($event->getPrefixSpecial() . '_GoId', ''); } /** * Load item if id is available * * @param kEvent $event * @return void * @access protected */ protected function LoadItem(kEvent $event) { $object = $event->getObject(); /* @var $object kDBItem */ $id = $this->getPassedID($event); if ( !$id ) { $event->CallSubEvent('OnNew'); return; } if ( $object->Load($id) ) { $actions = $this->Application->recallObject('kActions'); /* @var $actions Params */ $actions->Set($event->getPrefixSpecial() . '_id', $object->GetId()); } } /** * Returns special of main item for linking with sub-item * * @param kEvent $event * @return string * @access protected */ protected function getMainSpecial(kEvent $event) { $special = $event->getEventParam('main_special'); if ( $special === false || $special == '$main_special' ) { $special = $event->Special; } if ( $special == 'grid' ) { $special = ''; } return $special; } /** * Occurs before an item has been cloned * Id of newly created item is passed as event' 'id' param * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeClone(kEvent $event) { parent::OnBeforeClone($event); $event->Init($event->Prefix, '-item'); $object = $event->getObject(); /* @var $object kDBItem */ $options_mapping = $this->Application->GetVar('poc_mapping'); if ( !$options_mapping ) { return; } foreach ($options_mapping as $original => $new) { $n_combs = array (); $comb_data = unserialize($object->GetDBField('Combination')); foreach ($comb_data as $key => $val) { $n_key = $key == $original ? $new : $key; $n_combs[$n_key] = $val; } ksort($n_combs); $n_combs = serialize($n_combs); $n_crc = kUtil::crc32($n_combs); $object->SetDBField('Combination', $n_combs); $object->SetDBField('CombinationCRC', $n_crc); } } /** * Restore back values from live table to temp table before overwriting live with temp * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeDeleteFromLive(kEvent $event) { parent::OnBeforeDeleteFromLive($event); // check if product inventory management is via options and then proceed $id = $event->getEventParam('id'); $products_table = $this->Application->getUnitOption('p', 'TableName'); $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName'); $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); $sql = 'SELECT p.InventoryStatus FROM ' . $products_table . ' p LEFT JOIN ' . $table_name . ' poc ON poc.ProductId = p.ProductId WHERE poc.' . $id_field . ' = ' . $id; $inventory_status = $this->Conn->GetOne($sql); if ( $inventory_status == ProductInventory::BY_OPTIONS ) { $live_object = $this->Application->recallObject($event->Prefix . '.itemlive', null, Array ('skip_autoload' => true)); /* @var $live_object kDBItem */ $live_object->SwitchToLive(); $live_object->Load($id); $temp_object = $this->Application->recallObject($event->Prefix . '.itemtemp', null, Array ('skip_autoload' => true)); /* @var $temp_object kDBItem */ $temp_object->SwitchToTemp(); $temp_object->Load($id); $temp_object->SetDBFieldsFromHash($live_object->GetFieldValues(), Array ('QtyInStock', 'QtyReserved', 'QtyBackOrdered', 'QtyOnOrder')); $temp_object->Update(); } } /** * Create search filters based on search query * * @param kEvent $event * @return void * @access protected */ protected function OnSearch(kEvent $event) { parent::OnSearch($event); $this->_saveProduct($event); } /** * Clear search keywords * * @param kEvent $event * @return void * @access protected */ protected function OnSearchReset(kEvent $event) { parent::OnSearchReset($event); $this->_saveProduct($event); } /** * Makes event remember product id (if passed) * * @param kEvent $event */ function _saveProduct($event) { $product_id = $this->Application->GetVar('p_id'); if ($product_id) { $event->SetRedirectParam('p_id', $product_id); } } }