public function handleMessage(Import $import, Message $message, Channel $channel) { if (!$import->getTmpFileName()) { $this->log->error("Import w/o tmp file name: {$message->content}."); $channel->ack($message); return; } if (!file_exists($import->getTmpFileName())) { $this->log->error("Tmp file name '{$import->getTmpFileName()}' does not exist."); $channel->ack($message); return; } $this->log->info("Got " . $message->content); // TODO: error handling $handle = fopen($import->getTmpFileName(), "r+"); while (fread($handle, 3) === "") { fseek($handle, -3, SEEK_CUR); fwrite($handle, " "); $this->log->info("Removed BOM in file '{$import->getTmpFileName()}'."); } fseek($handle, 0, SEEK_SET); $data = fread($handle, 1024); if (($sp = strpos($data, "<?xml")) !== false) { if (($ep = strpos($data, "?>")) !== false) { $newData = substr($data, $sp, $ep - $sp + 2) . str_repeat(" ", $sp) . substr($data, $ep + 2); fseek($handle, 0, SEEK_SET); fwrite($handle, $newData); } } fclose($handle); $eshopId = $import->getEshop()->getId(); $reader = new \XMLReader(); $reader->open($import->getTmpFileName()); while ($reader->read()) { if (strtoupper($reader->name) !== "SHOPITEM") { continue; } $item = @$reader->expand(); if ($item === false) { $this->log->error("XMLReader error: " . json_encode(libxml_get_last_error())); break; } $reader->next(); $product = new Product(); $product->setEshopId($eshopId); foreach ($item->childNodes as $child) { /** @var \DOMNode $child */ if ($child->nodeType !== XML_ELEMENT_NODE) { continue; } $textContent = trim($child->textContent); if (empty($textContent)) { $textContent = null; } switch ($name = strtoupper($child->nodeName)) { case "ITEM_GROUP_ID": $product->setItemGroupId($textContent); break; case "ITEM_ID": $product->setItemId($textContent); break; case "PRODUCTNAME": $product->setName($textContent); break; case "PRODUCT": $product->setLongName($textContent); break; case "DESCRIPTION": $product->setDescription($textContent); break; case "URL": // TODO: normalize URL $product->setUrl($textContent); break; case "PRICE_VAT": $product->setPrice(floatval(preg_replace("/[^0-9.]+/", "", str_replace(",", ".", $textContent)))); break; case "DELIVERY_DATE": $product->setDeliveryDate(intval(preg_replace("/[^0-9]+/", "", $textContent))); break; case "IMGURL": case "IMGURL_ALTERNATIVE": // TODO: normalize URL $image = new Image(); $image->setUrl($textContent); $product->addImage($image); break; case "EAN": $product->setEan($textContent); break; case "ISBN": $product->setIsbn($textContent); break; case "PRODUCTNO": $product->setProductno($textContent); break; case "MANUFACTURER": $product->setManufacturer($textContent); break; case "BRAND": $product->setBrand($textContent); break; case "CATEGORYTEXT": if (!empty($textContent)) { $product->addCategoryText($textContent); } break; case "ITEM_TYPE": try { $product->setItemType(ProductItemTypeEnum::fromXML($textContent)); } catch (\InvalidArgumentException $e) { $this->log->warning("Got exception while assigning ITEM_TYPE: " . $e->getMessage()); } break; case "EXTRA_MESSAGE": try { $product->addExtraMessage(ProductExtraMessageEnum::fromXML($textContent)); } catch (\InvalidArgumentException $e) { $this->log->warning("Got exception while assigning EXTRA_MESSAGE: " . $e->getMessage()); } break; } } if ($product->getUrl() === null) { $this->log->warning("Skipping product without URL: " . ProductMeta::toJson($product)); continue; } if ($product->getName() === null) { if ($product->getLongName() === null) { $this->log->warning("Skipping product without PRODUCT/PRODUCTNAME: " . ProductMeta::toJson($product)); continue; } else { $product->setName($product->getLongName()); } } if ($product->getItemId() === null) { $product->setItemId($product->getUrl()); } if ($product->getItemGroupId() === null) { $product->setItemGroupId($product->getItemId()); } for (;;) { $existing = $this->productRepository->findOneFromEshop($product); if (!$existing) { $this->fillCategoryIds($product); $ret = $this->productRepository->insert($product); if (isset($ret["ok"]) && $ret["ok"]) { $this->changeProducer->publish(Change::create()->setProduct($product), RoutingKeys::CHANGE_PRODUCT_CREATE); break; } } else { $this->mergeProducts($product, $existing); $this->fillCategoryIds($product); $ret = $this->productRepository->update(["_id" => $existing->getId(), "v" => $existing->getV()], ProductMeta::toArray($product)); if (isset($ret["ok"]) && $ret["ok"] && isset($ret["updatedExisting"]) && $ret["updatedExisting"]) { $this->changeProducer->publish(Change::create()->setProduct($product), RoutingKeys::CHANGE_PRODUCT_UPDATE); break; } } } } // TODO: delete products not present in feed $reader->close(); libxml_clear_errors(); unlink($import->getTmpFileName()); $channel->ack($message); }