/** * Imports language items from an XML file into this language. * Updates the relevant language files automatically. * * @param \wcf\util\XML $xml * @param integer $packageID * @param boolean $updateFiles * @param boolean $updateExistingItems */ public function updateFromXML(XML $xml, $packageID, $updateFiles = true, $updateExistingItems = true) { $xpath = $xml->xpath(); $usedCategories = array(); // fetch categories $categories = $xpath->query('/ns:language/ns:category'); foreach ($categories as $category) { $usedCategories[$category->getAttribute('name')] = 0; } if (empty($usedCategories)) { return; } // select existing categories $conditions = new PreparedStatementConditionBuilder(); $conditions->add("languageCategory IN (?)", array(array_keys($usedCategories))); $sql = "SELECT\tlanguageCategoryID, languageCategory\n\t\t\tFROM\twcf" . WCF_N . "_language_category\n\t\t\t" . $conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { $usedCategories[$row['languageCategory']] = $row['languageCategoryID']; } // create new categories foreach ($usedCategories as $categoryName => $categoryID) { if ($categoryID) { continue; } $category = LanguageCategoryEditor::create(array('languageCategory' => $categoryName)); $usedCategories[$categoryName] = $category->languageCategoryID; } // loop through categories to import items $itemData = array(); foreach ($categories as $category) { $categoryName = $category->getAttribute('name'); $categoryID = $usedCategories[$categoryName]; // loop through items $elements = $xpath->query('child::*', $category); foreach ($elements as $element) { $itemName = $element->getAttribute('name'); $itemValue = $element->nodeValue; $itemData[] = $this->languageID; $itemData[] = $itemName; $itemData[] = $itemValue; $itemData[] = $categoryID; if ($packageID) { $itemData[] = $packageID == -1 ? PACKAGE_ID : $packageID; } } } if (!empty($itemData)) { // insert/update a maximum of 50 items per run (prevents issues with max_allowed_packet) $step = $packageID ? 5 : 4; WCF::getDB()->beginTransaction(); for ($i = 0, $length = count($itemData); $i < $length; $i += 50 * $step) { $parameters = array_slice($itemData, $i, 50 * $step); $repeat = count($parameters) / $step; $sql = "INSERT" . (!$updateExistingItems ? " IGNORE" : "") . " INTO\t\twcf" . WCF_N . "_language_item\n\t\t\t\t\t\t\t\t(languageID, languageItem, languageItemValue, languageCategoryID" . ($packageID ? ", packageID" : "") . ")\n\t\t\t\t\tVALUES\t\t\t" . substr(str_repeat('(?, ?, ?, ?' . ($packageID ? ', ?' : '') . '), ', $repeat), 0, -2); if ($updateExistingItems) { if ($packageID > 0) { // do not update anything if language item is owned by a different package $sql .= "\tON DUPLICATE KEY\n\t\t\t\t\t\t\t\tUPDATE\t\t\tlanguageUseCustomValue = IF(packageID = " . $packageID . ", IF(languageItemValue = VALUES(languageItemValue), languageUseCustomValue, 0), languageUseCustomValue),\n\t\t\t\t\t\t\t\t\t\t\tlanguageItemValue = IF(packageID = " . $packageID . ", IF(languageItemOriginIsSystem = 0, languageItemValue, VALUES(languageItemValue)), languageItemValue),\n\t\t\t\t\t\t\t\t\t\t\tlanguageCategoryID = IF(packageID = " . $packageID . ", VALUES(languageCategoryID), languageCategoryID)"; } else { // skip package id check during WCFSetup (packageID = 0) or if using the ACP form (packageID = -1) $sql .= "\tON DUPLICATE KEY\n\t\t\t\t\t\t\t\tUPDATE\t\t\tlanguageUseCustomValue = IF(languageItemValue = VALUES(languageItemValue), languageUseCustomValue, 0),\n\t\t\t\t\t\t\t\t\t\t\tlanguageItemValue = IF(languageItemOriginIsSystem = 0, languageItemValue, VALUES(languageItemValue)),\n\t\t\t\t\t\t\t\t\t\t\tlanguageCategoryID = VALUES(languageCategoryID)"; } } $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($parameters); } WCF::getDB()->commitTransaction(); } // update the relevant language files if ($updateFiles) { self::deleteLanguageFiles($this->languageID); } // delete relevant template compilations $this->deleteCompiledTemplates(); }
/** * Imports language items from an XML file into this language. * Updates the relevant language files automatically. * * @param wcf\util\XML $xml * @param integer $packageID * @param boolean $updateFiles */ public function updateFromXML(XML $xml, $packageID, $updateFiles = true) { $xpath = $xml->xpath(); $usedCategories = array(); // fetch categories $categories = $xpath->query('/ns:language/ns:category'); foreach ($categories as $category) { $usedCategories[$category->getAttribute('name')] = 0; } if (empty($usedCategories)) return; // select existing categories $conditions = new PreparedStatementConditionBuilder(); $conditions->add("languageCategory IN (?)", array(array_keys($usedCategories))); $sql = "SELECT languageCategoryID, languageCategory FROM wcf".WCF_N."_language_category ".$conditions; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); while ($row = $statement->fetchArray()) { $usedCategories[$row['languageCategory']] = $row['languageCategoryID']; } // create new categories foreach ($usedCategories as $categoryName => $categoryID) { if ($categoryID) continue; $category = LanguageCategoryEditor::create(array( 'languageCategory' => $categoryName )); $usedCategories[$categoryName] = $category->languageCategoryID; } // loop through categories to import items $items = array(); foreach ($categories as $category) { $categoryName = $category->getAttribute('name'); $categoryID = $usedCategories[$categoryName]; // loop through items $elements = $xpath->query('child::*', $category); foreach ($elements as $element) { $itemName = $element->getAttribute('name'); $itemValue = $element->nodeValue; $items[$itemName] = array( 'name' => $itemName, 'value' => $itemValue, 'categoryID' => $categoryID ); } } if (!empty($items)) { $existingItems = $statementParameters = array(); // find existing items $itemList = new LanguageItemList(); $itemList->getConditionBuilder()->add("language_item.languageItem IN (?)", array(array_keys($items))); $itemList->getConditionBuilder()->add("language_item.languageID = ?", array($this->languageID)); $itemList->readObjects(); foreach ($itemList->getObjects() as $languageItem) { $existingItems[$languageItem->languageItem] = $languageItem; } foreach ($items as $item) { if (isset($existingItems[$item['name']])) { // update existing item $itemEditor = new LanguageItemEditor($existingItems[$item['name']]); $itemEditor->update(array( 'languageItemValue' => $item['value'], 'languageCategoryID' => $item['categoryID'], 'languageUseCustomValue' => 0, 'languageItem' => $item['name'] )); } else { // store item for later insert $statementParameters[] = $item; } } if (!empty($statementParameters)) { if ($packageID) { $sql = "INSERT INTO wcf".WCF_N."_language_item (languageID, languageItem, languageItemValue, languageCategoryID, packageID) VALUES (?, ?, ?, ?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($statementParameters as $item) { $statement->execute(array( $this->languageID, $item['name'], $item['value'], $item['categoryID'], $packageID )); } } else { $sql = "INSERT INTO wcf".WCF_N."_language_item (languageID, languageItem, languageItemValue, languageCategoryID) VALUES (?, ?, ?, ?)"; $statement = WCF::getDB()->prepareStatement($sql); foreach ($statementParameters as $item) { $statement->execute(array( $this->languageID, $item['name'], $item['value'], $item['categoryID'] )); } } } } // update the relevant language files if ($updateFiles) { self::deleteLanguageFiles($this->languageID); } // delete relevant template compilations $this->deleteCompiledTemplates(); }