/** * Saves all relations between products and his attributes * * @param int $productId The UID of the product * @param array $fieldArray Field array * * @return void */ protected function saveProductRelations($productId, array $fieldArray = NULL) { $productId = (int) $productId; // first step is to save all relations between this product and all attributes // of this product. // We don't have to check for any parent categories, because the attributes // from them should already be saved for this product. $database = $this->getDatabaseConnection(); // create an article and a new price for a new product if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][COMMERCE_EXTKEY]['extConf']['simpleMode'] && $productId != NULL) { // search for an article of this product $res = $database->exec_SELECTquery('*', 'tx_commerce_articles', 'uid_product = ' . $productId, '', '', 1); $aRes = array(); if ($database->sql_num_rows($res) == 0) { // create a new article if no one exists $pRes = $database->exec_SELECTquery('title', 'tx_commerce_products', 'uid = ' . $productId, '', '', 1); $productData = $database->sql_fetch_assoc($pRes); $database->exec_INSERTquery('tx_commerce_articles', array('pid' => $fieldArray['pid'], 'tstamp' => $GLOBALS['EXEC_TIME'], 'crdate' => $GLOBALS['EXEC_TIME'], 'uid_product' => $productId, 'article_type_uid' => 1, 'title' => $productData['title'])); $aUid = $database->sql_insert_id(); } else { $aRes = $database->sql_fetch_assoc($res); $aUid = $aRes['uid']; } // check if the article has already a price $res = $database->exec_SELECTquery('*', 'tx_commerce_article_prices', 'uid_article = ' . $aUid, '', '', 1); if ($database->sql_num_rows($res) == 0 && $aRes['sys_language_uid'] < 1) { // create a new price if no one exists $database->exec_INSERTquery('tx_commerce_article_prices', array('pid' => $fieldArray['pid'], 'uid_article' => $aUid, 'tstamp' => $GLOBALS['EXEC_TIME'], 'crdate' => $GLOBALS['EXEC_TIME'])); } } $delete = TRUE; if (isset($fieldArray['categories'])) { $catList = array(); $res = $database->exec_SELECTquery('uid_foreign', 'tx_commerce_products_categories_mm', 'uid_local = ' . $productId); while ($sres = $database->sql_fetch_assoc($res)) { $catList[] = $sres['uid_foreign']; } $paList = $this->belib->getAttributesForCategoryList($catList); $uidList = $this->belib->extractFieldArray($paList, 'uid_foreign', TRUE, array('uid_correlationtype')); $this->belib->saveRelations($productId, $uidList, 'tx_commerce_products_attributes_mm', FALSE, FALSE); $this->belib->updateXML('attributes', 'tx_commerce_products', $productId, 'product', $catList); $delete = FALSE; } $articles = FALSE; if (isset($fieldArray['attributes'])) { // get all correlation types $correlationTypeList = $this->belib->getAllCorrelationTypes(); $paList = array(); // extract all attributes from FlexForm $ffData = GeneralUtility::xml2array($fieldArray['attributes']); if (is_array($ffData)) { $this->belib->mergeAttributeListFromFFData($ffData['data']['sDEF']['lDEF'], 'ct_', $correlationTypeList, $productId, $paList); } // get the list of uid_foreign and save relations for this category $uidList = $this->belib->extractFieldArray($paList, 'uid_foreign', TRUE, array('uid_correlationtype')); // get all ct4 attributes $ct4Attributes = array(); if (is_array($uidList)) { foreach ($uidList as $uidItem) { if ($uidItem['uid_correlationtype'] == 4) { $ct4Attributes[] = $uidItem['uid_foreign']; } } } $this->belib->saveRelations($productId, $uidList, 'tx_commerce_products_attributes_mm', $delete, FALSE); /** * Rebuild the XML (last param set to true) * Fixes that l10n of products had invalid XML attributes */ $this->belib->updateXML('attributes', 'tx_commerce_products', $productId, 'product', $correlationTypeList, TRUE); // update the XML for this product, we remove everything that is not // set for current attributes $pXml = $database->exec_SELECTquery('attributesedit', 'tx_commerce_products', 'uid = ' . $productId); $pXml = $database->sql_fetch_assoc($pXml); if (!empty($pXml['attributesedit'])) { $pXml = GeneralUtility::xml2array($pXml['attributesedit']); if (is_array($pXml['data']['sDEF']['lDEF'])) { foreach (array_keys($pXml['data']['sDEF']['lDEF']) as $key) { $data = array(); $uid = $this->belib->getUIdFromKey($key, $data); if (!in_array($uid, $ct4Attributes)) { unset($pXml['data']['sDEF']['lDEF'][$key]); } } } if (is_array($pXml) && is_array($pXml['data']) && is_array($pXml['data']['sDEF'])) { $pXml = GeneralUtility::array2xml($pXml, '', 0, 'T3FlexForms'); $fieldArray['attributesedit'] = $pXml; } } // now get all articles that where created from this product $articles = $this->belib->getArticlesOfProduct($productId); // build relation table if (is_array($articles) && count($articles)) { $uidList = $this->belib->extractFieldArray($paList, 'uid_foreign', TRUE); foreach ($articles as $article) { $this->belib->saveRelations($article['uid'], $uidList, 'tx_commerce_articles_article_attributes_mm', TRUE, FALSE); } } } $updateArrays = array(); // update all articles of this product if (!empty($fieldArray['attributesedit'])) { $ffData = (array) GeneralUtility::xml2array($fieldArray['attributesedit']); if (is_array($ffData['data']) && is_array($ffData['data']['sDEF']['lDEF'])) { // get articles if they are not already there if (!$articles) { $articles = $this->belib->getArticlesOfProduct($productId); } // update this product $articleRelations = array(); $counter = 0; foreach ($ffData['data']['sDEF']['lDEF'] as $ffDataItemKey => $ffDataItem) { $counter++; $attributeKey = $this->belib->getUidFromKey($ffDataItemKey, $keyData); $attributeData = $this->belib->getAttributeData($attributeKey, 'has_valuelist,multiple'); // check if the attribute has more than one value, if that is true, // we have to create a relation for each value if ($attributeData['multiple'] == 1) { // if we have a multiple valuelist we need to handle the attributes a little // bit different first we delete all existing attributes $database->exec_DELETEquery('tx_commerce_products_attributes_mm', 'uid_local = ' . $productId . ' AND uid_foreign = ' . $attributeKey); // now explode the data $attributeValues = GeneralUtility::trimExplode(',', $ffDataItem['vDEF'], TRUE); foreach ($attributeValues as $attributeValue) { // The first time an attribute value is selected, TYPO3 returns them // INCLUDING an empty value! This would cause an unnecessary entry in the // database, so we have to filter this here. if (empty($attributeValue)) { continue; } $updateData = $this->belib->getUpdateData($attributeData, $attributeValue, $productId); $database->exec_INSERTquery('tx_commerce_products_attributes_mm', array_merge(array('uid_local' => $productId, 'uid_foreign' => $attributeKey, 'uid_correlationtype' => 4), $updateData[0])); } } else { // update a simple valuelist and normal attributes as usual $updateArrays = $this->belib->getUpdateData($attributeData, $ffDataItem['vDEF'], $productId); $database->exec_UPDATEquery('tx_commerce_products_attributes_mm', 'uid_local = ' . $productId . ' AND uid_foreign = ' . $attributeKey, $updateArrays[0]); } // update articles if (is_array($articles) && count($articles) > 0) { foreach ($articles as $article) { if ($attributeData['multiple'] == 1) { // if we have a multiple valuelist we need to handle the attributes a little // bit different first we delete all existing attributes $database->exec_DELETEquery('tx_commerce_articles_article_attributes_mm', 'uid_local = ' . $article['uid'] . ' AND uid_foreign = ' . $attributeKey); // now explode the data $attributeValues = GeneralUtility::trimExplode(',', $ffDataItem['vDEF'], TRUE); $attributeCount = 0; $attributeValue = ''; foreach ($attributeValues as $attributeValue) { if (empty($attributeValue)) { continue; } $attributeCount++; $updateData = $this->belib->getUpdateData($attributeData, $attributeValue, $productId); $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', array_merge(array('uid_local' => $article['uid'], 'uid_foreign' => $attributeKey, 'uid_product' => $productId, 'sorting' => $counter), $updateData[1])); } // create at least an empty relation if no attributes where set if ($attributeCount == 0) { $updateData = $this->belib->getUpdateData(array(), $attributeValue, $productId); $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', array_merge(array('uid_local' => $article['uid'], 'uid_foreign' => $attributeKey, 'uid_product' => $productId, 'sorting' => $counter), $updateData[1])); } } else { // if the article has already this attribute, we have to insert so try // to select this attribute for this article $res = $database->exec_SELECTquery('uid_local, uid_foreign', 'tx_commerce_articles_article_attributes_mm', 'uid_local = ' . $article['uid'] . ' AND uid_foreign = ' . $attributeKey); if ($database->sql_num_rows($res) > 0) { $database->exec_UPDATEquery('tx_commerce_articles_article_attributes_mm', 'uid_local = ' . $article['uid'] . ' AND uid_foreign = ' . $attributeKey, array_merge($updateArrays[1], array('sorting' => $counter))); } else { $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', array_merge($updateArrays[1], array('uid_local' => $article['uid'], 'uid_product' => $productId, 'uid_foreign' => $attributeKey, 'sorting' => $counter))); } } $relArray = $updateArrays[0]; $relArray['uid_foreign'] = $attributeKey; if (!in_array($relArray, $articleRelations)) { $articleRelations[] = $relArray; } $this->belib->updateArticleHash($article['uid']); } } } // Finally update the Felxform for this Product $this->belib->updateArticleXML($articleRelations, FALSE, NULL, $productId); // And add those datas from the database to the articles if (is_array($articles) && count($articles) > 0) { foreach ($articles as $article) { $thisArticleRelations = $this->belib->getAttributesForArticle($article['uid']); $this->belib->updateArticleXML($thisArticleRelations, FALSE, $article['uid'], NULL); } } } } // Check if we do have some localized products an call the method recursivly $resLocalised = $database->exec_SELECTquery('uid', 'tx_commerce_products', 'deleted = 0 and l18n_parent = ' . $productId); while ($rowLocalised = $database->sql_fetch_assoc($resLocalised)) { $this->saveProductRelations($rowLocalised['uid'], $fieldArray); } }
/** * Creates an article in the database and all needed releations to attributes * and values. It also creates a new prices and assignes it to the new article. * * @param array $parameter Parameter * @param string $key The key in the POST var array * * @return int Returns the new articleUid if success */ protected function createArticle(array $parameter, $key) { $database = $this->getDatabaseConnection(); // get the create data $data = GeneralUtility::_GP('createData'); $hash = ''; if (is_array($data)) { $data = $data[$key]; $hash = md5($data); $data = unserialize($data); } $database->debugOutput = 1; $database->store_lastBuiltQuery = TRUE; // get the highest sorting $sorting = $database->exec_SELECTgetSingleRow('uid, sorting', 'tx_commerce_articles', 'uid_product = ' . $this->uid, '', 'sorting DESC', 1); $sorting = is_array($sorting) && isset($sorting['sorting']) ? $sorting['sorting'] + 20 : 0; // create article data array $articleData = array('pid' => $this->pid, 'crdate' => time(), 'title' => strip_tags($this->createArticleTitleFromAttributes($parameter, (array) $data)), 'uid_product' => (int) $this->uid, 'sorting' => $sorting, 'article_attributes' => count($this->attributes['rest']) + count($data), 'attribute_hash' => $hash, 'article_type_uid' => 1); $temp = BackendUtility::getModTSconfig($this->pid, 'mod.commerce.category'); if ($temp) { $moduleConfig = BackendUtility::implodeTSParams($temp['properties']); $defaultTax = (int) $moduleConfig['defaultTaxValue']; if ($defaultTax > 0) { $articleData['tax'] = $defaultTax; } } if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/class.tx_commerce_articlecreator.php']['preinsert'])) { GeneralUtility::deprecationLog(' hook $GLOBALS[\'TYPO3_CONF_VARS\'][\'EXTCONF\'][\'commerce/class.tx_commerce_articlecreator.php\'][\'preinsert\'] is deprecated since commerce 1.0.0, it will be removed in commerce 1.4.0, please use instead $GLOBALS[\'TYPO3_CONF_VARS\'][\'EXTCONF\'][\'commerce/lib/class.tx_commerce_basket.php\'][\'createArticlePreInsert\'] '); foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/class.tx_commerce_articlecreator.php']['preinsert'] as $classRef) { $hookObj =& GeneralUtility::getUserObj($classRef); if (method_exists($hookObj, 'preinsert')) { $hookObj->preinsert($articleData); } } } if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/Classes/Utility/ArticleCreatorUtility.php']['createArticlePreInsert'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/Classes/Utility/ArticleCreatorUtility.php']['createArticlePreInsert'] as $classRef) { $hookObj =& GeneralUtility::getUserObj($classRef); if (method_exists($hookObj, 'preinsert')) { $hookObj->preinsert($articleData); } } } // create the article $database->exec_INSERTquery('tx_commerce_articles', $articleData); $articleUid = $database->sql_insert_id(); // create a new price that is assigned to the new article $database->exec_INSERTquery('tx_commerce_article_prices', array('pid' => $this->pid, 'crdate' => time(), 'tstamp' => time(), 'uid_article' => $articleUid)); // now write all relations between article and attributes into the database $relationBaseData = array('uid_local' => $articleUid); $createdArticleRelations = array(); $relationCreateData = $relationBaseData; $productsAttributesRes = $database->exec_SELECTquery('sorting, uid_local, uid_foreign', 'tx_commerce_products_attributes_mm', 'uid_local = ' . (int) $this->uid); $attributesSorting = array(); while ($productsAttributes = $database->sql_fetch_assoc($productsAttributesRes)) { $attributesSorting[$productsAttributes['uid_foreign']] = $productsAttributes['sorting']; } if (is_array($data)) { foreach ($data as $selectAttributeUid => $selectAttributeValueUid) { $relationCreateData['uid_foreign'] = $selectAttributeUid; $relationCreateData['uid_valuelist'] = $selectAttributeValueUid; $relationCreateData['sorting'] = $attributesSorting[$selectAttributeUid]; $createdArticleRelations[] = $relationCreateData; $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', $relationCreateData); } } if (is_array($this->attributes['rest'])) { foreach ($this->attributes['rest'] as $attribute) { if (empty($attribute['attributeData']['uid'])) { continue; } $relationCreateData = $relationBaseData; $relationCreateData['sorting'] = $attribute['sorting']; $relationCreateData['uid_foreign'] = $attribute['attributeData']['uid']; if ($attribute['uid_correlationtype'] == 4) { $relationCreateData['uid_product'] = $this->uid; } $relationCreateData['default_value'] = ''; $relationCreateData['value_char'] = ''; $relationCreateData['uid_valuelist'] = $attribute['uid_valuelist']; if (!$this->belib->isNumber($attribute['default_value'])) { $relationCreateData['default_value'] = $attribute['default_value']; } else { $relationCreateData['value_char'] = $attribute['default_value']; } $createdArticleRelations[] = $relationCreateData; $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', $relationCreateData); } } // update the article // we have to write the xml datastructure for this article. This is needed // to have the correct values inserted on first call of the article. $this->belib->updateArticleXML($createdArticleRelations, FALSE, $articleUid); // Now check, if the parent Product is already lokalised, so creat Article in // the lokalised version Select from Database different localisations $resOricArticle = $database->exec_SELECTquery('*', 'tx_commerce_articles', 'uid=' . (int) $articleUid . ' and deleted = 0'); $origArticle = $database->sql_fetch_assoc($resOricArticle); $resLocalizedProducts = $database->exec_SELECTquery('*', 'tx_commerce_products', 'l18n_parent = ' . (int) $this->uid . ' AND deleted = 0'); if ($resLocalizedProducts && $database->sql_num_rows($resLocalizedProducts) > 0) { // Only if there are products while ($localizedProducts = $database->sql_fetch_assoc($resLocalizedProducts)) { // walk thru and create articles $destLanguage = $localizedProducts['sys_language_uid']; // get the highest sorting $langIsoCode = BackendUtility::getRecord('sys_language', (int) $destLanguage, 'static_lang_isocode'); $langIdent = BackendUtility::getRecord('static_languages', (int) $langIsoCode['static_lang_isocode'], 'lg_typo3'); $langIdent = strtoupper($langIdent['lg_typo3']); // create article data array $articleData = array('pid' => $this->pid, 'crdate' => time(), 'title' => $parameter['title'], 'uid_product' => $localizedProducts['uid'], 'sys_language_uid' => $localizedProducts['sys_language_uid'], 'l18n_parent' => $articleUid, 'sorting' => $sorting['sorting'] + 20, 'article_attributes' => count($this->attributes['rest']) + count($data), 'attribute_hash' => $hash, 'article_type_uid' => 1, 'attributesedit' => $this->belib->buildLocalisedAttributeValues($origArticle['attributesedit'], $langIdent)); // create the article $database->exec_INSERTquery('tx_commerce_articles', $articleData); $localizedArticleUid = $database->sql_insert_id(); // get all relations to attributes from the old article and copy them // to new article $res = $database->exec_SELECTquery('*', 'tx_commerce_articles_article_attributes_mm', 'uid_local = ' . (int) $origArticle['uid'] . ' AND uid_valuelist = 0'); while ($origRelation = $database->sql_fetch_assoc($res)) { $origRelation['uid_local'] = $localizedArticleUid; $database->exec_INSERTquery('tx_commerce_articles_article_attributes_mm', $origRelation); } $this->belib->updateArticleXML($createdArticleRelations, FALSE, $localizedArticleUid); } } return $articleUid; }