/** * 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 (SettingsFactory::getInstance()->getExtConf('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)) { $aRes = $database->sql_fetch_assoc($res); $aUid = $aRes['uid']; } else { // 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(); } // check if the article has already a price $row = $database->exec_SELECTgetSingleRow('*', 'tx_commerce_article_prices', 'uid_article = ' . $productId); if (empty($row) && $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) && !empty($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) && !empty($articles)) { 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)) { $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) && !empty($articles)) { 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); } }