/** * Saves the sort of subcategories to the categories in the DB. * * @author Alexander Girin * @param array $catSortOrderArray the array of categories id, whose order * defines sort_order of the categories. * @return */ function setCategorySortOrder($catSortOrderArray) { global $application; /** * <pre> * BEFORE * * | * +-\ root (L_root, R_root) * | | L_1 = L_root + 1 * | |-- subnode1 (L_1, R_1) * | |-- subnode2 (L_2, R_2) * | |-- subnode3 (L_3, R_3) * | R_3 = R_root - 1 * | * * AFTER (new order: subnode2, subnode3, subnode1 * * | * +-\ root (L_root, R_root) * | | * = L_root + 1 * | |-- subnode2 ( * , * + (R_2 - L_2)) * | |-- subnode3 ( * , * + (R_3 - L_3)) * | |-- subnode1 ( * , * + (R_1 - L_1)) * | (* + (R_1 - L_1)) = R_root - 1 * | * </pre> */ /** * To make changes just update the indexes 'left' and 'right' only * into the subtree, whose root is the parent category for all sorted ones. * It can be used for optimization. The problem: how to change them all * together at once? If update the categories separately, then the errors * occur in the tree structure. */ /** * Here is one of the answers to the previous question */ // getting the exclusive rights $application->enterCriticalSection('setCategorySortOrder'); // firstly we check if all the subcategories belong to the same category $parent_ids = execQuery('SELECT_PARENT_CATEGORY_IDS_FOR_CATEGORIES', array('cat_ids' => $catSortOrderArray)); // if there are several parent categories (or none of them) then do nothing, category tree was changed if (count($parent_ids) != 1) { $application->leaveCriticalSection(); return; } $parent_cat_id = $parent_ids[0]['parent_id']; // secondly we check if these subcategories are ALL subcategories of the parent category $other_cats = execQuery('SELECT_OTHER_SUBCATEGORIES_FOR_A_CATEGORY', array('id' => $parent_cat_id, 'cat_ids' => $catSortOrderArray)); // if there are other subcategories then do nothing, category tree was changed if (!empty($other_cats)) { $application->leaveCriticalSection(); return; } // getting base info for parent category $ParentCatInfo = $this->fetchCategoryInfo($parent_cat_id); // locking tables $query = new DB_MYSQL_Lock_Tables(); $query->addTableToLock('categories', DB_LOCK_MODE_WRITE); $query->addTableToLock('categories_descr', DB_LOCK_MODE_WRITE); $query->addTableToLock('products', DB_LOCK_MODE_WRITE); $query->addTableToLock('store_settings', DB_LOCK_MODE_WRITE); $query->addTableToLock('products_to_categories', DB_LOCK_MODE_WRITE); $query->addTableToLock('events_manager', DB_LOCK_MODE_WRITE); $application->db->PrepareSQL($query); $application->db->DB_Exec($query); // clearing "old" sort data execQuery('UPDATE_CLEAR_SORT_CATEGORY_FIELD', array()); // setting up the new offset inside the parent category. Based on it the current offset for each subcategory will be calculated $offset = $ParentCatInfo['left'] + 1; foreach ($catSortOrderArray as $cat_id) { // getting base info for the subcategory $CatInfo = $this->fetchCategoryInfo($cat_id); // calculating the offset for the category execQuery('UPDATE_SET_SORT_CATEGORY_FIELD', array('left' => $CatInfo['left'], 'right' => $CatInfo['right'], 'sort_order' => $offset - $CatInfo['left'])); // recalculating the offset $offset += $CatInfo['right'] - $CatInfo['left'] + 1; } // all is done -> resorting... but a paranoidal check before if ($offset == $ParentCatInfo['right']) { execQuery('UPDATE_SORT_CATEGORIES', array()); modApiFunc('EventsManager', 'throwEvent', 'CategorySortOrderChanged', $parent_cat_id); } else { execQuery('UPDATE_CLEAR_SORT_CATEGORY_FIELD', array()); } // unlocking tables $query = new DB_MYSQL_Unlock_Tables(); $application->db->PrepareSQL($query); $application->db->DB_Exec($query); $application->leaveCriticalSection(); }
/** * Gets database data dump, including the database structure. * * @return array data array */ function getDataDump($tables, $currentTable, $currentLimit, $recordsExported, $fp, $link = 'db_link') { global ${$link}; global $application; $table_engine = CConf::get('mysql_table_engine'); $data = ""; if ($currentTable == 0) { fwrite($fp, "-- --------------------------------------------------------\n-- Avactis Shopping Cart Software\n-- Database Backup\n-- Generation Time: " . date("M d, Y at h:i A", time()) . "\n-- --------------------------------------------------------\n"); } $start_time = time(); while (isset($tables[$currentTable])) { $query = new DB_MYSQL_Lock_Tables(); $query->addTableToLock($tables[$currentTable]['table_name'], DB_LOCK_MODE_WRITE); $this->DB_Exec($query); if (!(time() - $start_time >= 2)) { if ($currentLimit == 0) { $query = " SHOW CREATE TABLE " . $tables[$currentTable]['table_name']; $query_result = $this->DB_Query($query); $result = $this->DB_Fetch_Array($query_result, QUERY_RESULT_NUM); $create_table_query = _ml_substr($result[1], 0, _ml_strrpos($result[1], "\n") + 1) . ") ENGINE={$table_engine};"; $data = "\n\n-- \n-- Table structure for table `" . $tables[$currentTable]['table_name'] . "`\n-- \n\nDROP TABLE IF EXISTS `" . $tables[$currentTable]['table_name'] . "`;\n"; $data .= $create_table_query; $data .= "\n\n-- \n-- Dumping data for table `" . $tables[$currentTable]['table_name'] . "`\n-- \n\n"; fwrite($fp, $data); } $query = " SHOW COLUMNS FROM " . $tables[$currentTable]['table_name']; $query = $this->DB_Query($query); $columns = array(); while ($table_column = $this->DB_Fetch_Array($query, QUERY_RESULT_ASSOC)) { $columns[] = $table_column["Field"]; } $query = " SELECT * FROM " . $tables[$currentTable]['table_name'] . " LIMIT " . 100 * $currentLimit . ", 100"; $query = $this->DB_Query($query); $insert = true; $data = ""; while ($row_data = $this->DB_Fetch_Array($query, QUERY_RESULT_ASSOC)) { if ($insert) { $table_name = $tables[$currentTable]['table_name']; $data .= "LOCK TABLES `{$table_name}` WRITE;\nINSERT INTO `{$table_name}` (`" . implode("`, `", $columns) . "`) VALUES \n"; $insert = false; } $row = array(); foreach ($row_data as $key => $value) { if (!is_int($key)) { $row[] = "'" . addcslashes(addslashes($value), "..") . "'"; } } $data .= "(" . implode(", ", $row) . "),\n"; $recordsExported++; } if ($data && $data[_byte_strlen($data) - 2] == ",") { $data[_byte_strlen($data) - 2] = ";"; fwrite($fp, $data . "UNLOCK TABLES;\n"); } $currentLimit++; if ($currentLimit * 100 >= $tables[$currentTable]['records_count']) { $currentLimit = 0; $currentTable++; } } else { $query = new DB_MYSQL_Unlock_Tables(); $this->DB_Exec($query); break; } } $retval = array("currentTable" => $currentTable, "currentLimit" => $currentLimit, "recordsExported" => $recordsExported); return $retval; }