mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-26 22:50:29 +01:00
449 lines
18 KiB
PHP
449 lines
18 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Xentral\Modules\Ebay\Service;
|
||
|
|
||
|
use Xentral\Components\Database\Database;
|
||
|
use Xentral\Modules\Ebay\Data\StagingListingData;
|
||
|
use Xentral\Modules\Ebay\Data\StagingListingPicture;
|
||
|
use Xentral\Modules\Ebay\Data\StagingListingVariationData;
|
||
|
use Xentral\Modules\Ebay\Exception\InvalidArgumentException;
|
||
|
use Xentral\Modules\Ebay\Exception\MissingValueException;
|
||
|
use Xentral\Modules\Ebay\Gateway\EbayListingGateway;
|
||
|
use Xentral\Modules\Ebay\Wrapper\EbayStockCalculationWrapperInterface;
|
||
|
use Xentral\Modules\Ebay\Wrapper\StockCalculationWrapper;
|
||
|
|
||
|
final class EbayListingService
|
||
|
{
|
||
|
/** @var Database $db */
|
||
|
private $db;
|
||
|
|
||
|
/** @var EbayListingGateway $gateway */
|
||
|
private $gateway;
|
||
|
|
||
|
/** @var EbayListingXmlSerializer $serializer */
|
||
|
private $serializer;
|
||
|
|
||
|
/** @var StockCalculationWrapper $stockCalculationWrapper */
|
||
|
private $stockCalculationWrapper;
|
||
|
|
||
|
/**
|
||
|
* @param EbayListingGateway $gateway
|
||
|
* @param Database $database
|
||
|
* @param EbayListingXmlSerializer $serializer
|
||
|
* @param EbayStockCalculationWrapperInterface $wrapper
|
||
|
*/
|
||
|
public function __construct(
|
||
|
EbayListingGateway $gateway,
|
||
|
Database $database,
|
||
|
EbayListingXmlSerializer $serializer,
|
||
|
EbayStockCalculationWrapperInterface $wrapper
|
||
|
) {
|
||
|
$this->gateway = $gateway;
|
||
|
$this->db = $database;
|
||
|
$this->serializer = $serializer;
|
||
|
$this->stockCalculationWrapper = $wrapper;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $stagingListingId
|
||
|
*
|
||
|
* @return StagingListingData
|
||
|
*/
|
||
|
public function associateStagingListing($stagingListingId): StagingListingData
|
||
|
{
|
||
|
$stagingListing = $this->gateway->getStagingListingByDatabaseId($stagingListingId);
|
||
|
|
||
|
$stagingListing = $this->associateArticle($stagingListing);
|
||
|
|
||
|
$stagingListing = $this->associateVariants($stagingListing);
|
||
|
|
||
|
$this->saveStagingListing($stagingListing);
|
||
|
|
||
|
return $stagingListing;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param StagingListingData $stagingListing
|
||
|
*
|
||
|
* @return StagingListingData
|
||
|
*/
|
||
|
private function associateArticle(StagingListingData $stagingListing): StagingListingData
|
||
|
{
|
||
|
$articleId = $this->gateway->searchForMatchingArticleId($stagingListing);
|
||
|
$stagingListing->setArticleId($articleId);
|
||
|
|
||
|
return $stagingListing;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param StagingListingData $stagingListing
|
||
|
*
|
||
|
* @return StagingListingData
|
||
|
*/
|
||
|
private function associateVariants(StagingListingData $stagingListing): StagingListingData
|
||
|
{
|
||
|
if (empty($stagingListing->getArticleId()) || empty($stagingListing->getVariations())) {
|
||
|
return $stagingListing;
|
||
|
}
|
||
|
foreach ($stagingListing->getVariations() as $variation) {
|
||
|
$articleId = $this->gateway->searchForMatchingArticleIdForVariation(
|
||
|
$variation,
|
||
|
$stagingListing->getShopId(),
|
||
|
$stagingListing->getArticleId()
|
||
|
);
|
||
|
$variation->setArticleId($articleId);
|
||
|
}
|
||
|
|
||
|
return $stagingListing;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param StagingListingData $stagingListing
|
||
|
*
|
||
|
* @throws MissingValueException
|
||
|
*
|
||
|
* @return StagingListingData
|
||
|
*/
|
||
|
public function saveStagingListing($stagingListing): StagingListingData
|
||
|
{
|
||
|
$stagingListingId = $stagingListing->getId();
|
||
|
|
||
|
if (empty($stagingListingId)) {
|
||
|
$query = sprintf(
|
||
|
'INSERT INTO `ebay_staging_listing` (`shop_id`) VALUES (%d)',
|
||
|
$stagingListing->getShopId()
|
||
|
);
|
||
|
$this->db->exec($query);
|
||
|
$stagingListingId = $this->db->lastInsertId();
|
||
|
}
|
||
|
|
||
|
if(!empty($stagingListingId)){
|
||
|
$sql = 'SELECT esl.id FROM `ebay_staging_listing` AS `esl` WHERE esl.id=:id';
|
||
|
$stagingListingId = $this->db->fetchValue($sql,['id' => $stagingListingId]);
|
||
|
}
|
||
|
|
||
|
if (empty($stagingListingId)) {
|
||
|
throw new MissingValueException('ID for Staging Listing dataset could not be found or created.');
|
||
|
}
|
||
|
|
||
|
$sql = 'UPDATE `ebay_staging_listing` SET
|
||
|
`article_id` = :article_id,
|
||
|
`type` = :listing_type,
|
||
|
`title` = :title,
|
||
|
`status` = :listing_status,
|
||
|
`sku` = :sku,
|
||
|
`description` = :description,
|
||
|
`ebay_primary_category_id_external` = :primary_category,
|
||
|
`ebay_secondary_category_id_external` = :secondary_category,
|
||
|
`ebay_primary_store_category_id_external` = :primary_store_category,
|
||
|
`ebay_secondary_store_category_id_external` = :secondary_store_category,
|
||
|
`ebay_shipping_profile_id_external` = :shipping_profile,
|
||
|
`ebay_payment_profile_id_external` = :payment_profile,
|
||
|
`ebay_return_profile_id_external` = :return_profile,
|
||
|
`ebay_plus` = :ebayplus,
|
||
|
`ebay_price_suggestion` = :price_suggestion,
|
||
|
`ebay_private_listing` = :private_listing,
|
||
|
`condition_id_external` = :condition_id,
|
||
|
`condition_display_name` = :condition_display_name,
|
||
|
`condition_description` = :condition_description,
|
||
|
`listing_duration` = :listing_duration,
|
||
|
`inventory_tracking_method` = :inventory_tracking_method,
|
||
|
`item_id_external` = :item_id,
|
||
|
`delivery_time` = :delivery_time,
|
||
|
`template_id` = :template_id
|
||
|
WHERE id = :listing_id';
|
||
|
$values = [
|
||
|
'article_id' => $stagingListing->getArticleId(),
|
||
|
'listing_type' => $stagingListing->getType(),
|
||
|
'title' => $stagingListing->getTitle(),
|
||
|
'listing_status' => $stagingListing->getStatus(),
|
||
|
'sku' => $stagingListing->getSku(),
|
||
|
'description' => $stagingListing->getDescription(),
|
||
|
'primary_category' => $stagingListing->getPrimaryCategoryId(),
|
||
|
'secondary_category' => $stagingListing->getSecondaryCategoryId(),
|
||
|
'primary_store_category' => $stagingListing->getPrimaryStoreCategoryId(),
|
||
|
'secondary_store_category' => $stagingListing->getSecondaryStoreCategoryId(),
|
||
|
'shipping_profile' => $stagingListing->getShippingProfileId(),
|
||
|
'payment_profile' => $stagingListing->getPaymentProfileId(),
|
||
|
'return_profile' => $stagingListing->getReturnProfileId(),
|
||
|
'ebayplus' => $stagingListing->isEbayPlus(),
|
||
|
'price_suggestion' => $stagingListing->isPriceSuggestion(),
|
||
|
'private_listing' => $stagingListing->isPrivateListing(),
|
||
|
'condition_id' => $stagingListing->getConditionId(),
|
||
|
'condition_display_name' => $stagingListing->getConditionDisplayName(),
|
||
|
'condition_description' => $stagingListing->getConditionDescription(),
|
||
|
'listing_duration' => $stagingListing->getListingDuration(),
|
||
|
'inventory_tracking_method' => $stagingListing->getInventoryTrackingMethod(),
|
||
|
'item_id' => $stagingListing->getItemId(),
|
||
|
'delivery_time' => $stagingListing->getDeliveryTime(),
|
||
|
'template_id' => $stagingListing->getTemplateId(),
|
||
|
'listing_id' => $stagingListingId,
|
||
|
];
|
||
|
$this->db->perform($sql, $values);
|
||
|
|
||
|
foreach ($stagingListing->listSpecifics() as $specificName => $specificValue) {
|
||
|
$this->saveSpecific($stagingListingId, $specificName, $specificValue);
|
||
|
}
|
||
|
|
||
|
if (!empty($stagingListing->getVariations())) {
|
||
|
foreach ($stagingListing->getVariations() as $variation) {
|
||
|
$this->saveStagingListingVariation($stagingListingId, $variation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!empty($stagingListing->listPictures())) {
|
||
|
foreach ($stagingListing->listPictures() as $picture) {
|
||
|
$picture->setStagingListingId($stagingListingId);
|
||
|
$this->savePictureHostingServicePicture($picture);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->gateway->getStagingListingByDatabaseId($stagingListingId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $stagingListingId
|
||
|
* @param string $specificName
|
||
|
* @param string $specificValue
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*/
|
||
|
private function saveSpecific($stagingListingId, $specificName, $specificValue): void
|
||
|
{
|
||
|
if (empty($specificName)) {
|
||
|
throw new InvalidArgumentException('Required argument "specificName" is empty or invalid.');
|
||
|
}
|
||
|
if (empty($stagingListingId)) {
|
||
|
throw new InvalidArgumentException('Required argument "stagingListingId" is empty or invalid.');
|
||
|
}
|
||
|
|
||
|
$sql = 'SELECT esls.id FROM `ebay_staging_listing_specific` AS `esls`
|
||
|
WHERE `ebay_staging_listing_id` = :listing_id AND `property` = :specific_name';
|
||
|
$values = [
|
||
|
'listing_id' => $stagingListingId,
|
||
|
'specific_name' => $specificName,
|
||
|
];
|
||
|
$specificId = $this->db->fetchValue($sql, $values);
|
||
|
|
||
|
$sql = 'UPDATE `ebay_staging_listing_specific` SET `value` = :value WHERE `id` = :specific_id';
|
||
|
$values = [
|
||
|
'value' => $specificValue,
|
||
|
'specific_id' => $specificId,
|
||
|
];
|
||
|
|
||
|
if (empty($specificId)) {
|
||
|
$sql = 'INSERT INTO `ebay_staging_listing_specific`
|
||
|
(`ebay_staging_listing_id`, `property`, `value`) VALUES (:listing_id, :specific_name, :value)';
|
||
|
$values = [
|
||
|
'listing_id' => $stagingListingId,
|
||
|
'specific_name' => $specificName,
|
||
|
'value' => $specificValue,
|
||
|
];
|
||
|
}
|
||
|
$this->db->perform($sql, $values);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $stagingListingId
|
||
|
* @param StagingListingVariationData $variation
|
||
|
*/
|
||
|
private function saveStagingListingVariation($stagingListingId, $variation): void
|
||
|
{
|
||
|
$specifics = $variation->listSpecifics();
|
||
|
$conditions = [];
|
||
|
foreach ($specifics as $property => $value) {
|
||
|
$conditions[] = sprintf(
|
||
|
'(eslvs.property = %s AND eslvs.value = %s)',
|
||
|
$this->db->escapeString($property),
|
||
|
$this->db->escapeString($value)
|
||
|
);
|
||
|
}
|
||
|
$condition = implode(' OR ', $conditions);
|
||
|
if (empty($conditions)) {
|
||
|
$condition = 0;
|
||
|
}
|
||
|
|
||
|
$query = sprintf(
|
||
|
'
|
||
|
SELECT eslv.id
|
||
|
FROM `ebay_staging_listing_variant_specific` AS `eslvs`
|
||
|
JOIN `ebay_staging_listing_variant` AS `eslv` ON eslv.id = eslvs.ebay_staging_listing_variant_id
|
||
|
WHERE eslv.ebay_staging_listing_id = %s AND (%s)
|
||
|
GROUP BY eslv.id
|
||
|
HAVING COUNT(eslv.id) = %d',
|
||
|
$stagingListingId,
|
||
|
$condition,
|
||
|
count($conditions)
|
||
|
);
|
||
|
$stagingListingVariationId = $this->db->fetchValue($query);
|
||
|
if (empty($stagingListingVariationId)) {
|
||
|
$query = 'INSERT INTO `ebay_staging_listing_variant` () VALUES ()';
|
||
|
$this->db->exec($query);
|
||
|
$stagingListingVariationId = $this->db->lastInsertId();
|
||
|
}
|
||
|
|
||
|
$sql = 'UPDATE `ebay_staging_listing_variant` SET
|
||
|
`article_id` = :article_id, `sku` = :sku, `ebay_staging_listing_id` = :listing_id
|
||
|
WHERE id = :variation_id';
|
||
|
$values = [
|
||
|
'article_id' => $variation->getArticleId(),
|
||
|
'sku' => $variation->getSku(),
|
||
|
'listing_id' => $stagingListingId,
|
||
|
'variation_id' => $stagingListingVariationId,
|
||
|
];
|
||
|
$this->db->perform($sql, $values);
|
||
|
|
||
|
foreach ($specifics as $property => $value) {
|
||
|
$sql = 'SELECT `id`
|
||
|
FROM `ebay_staging_listing_variant_specific`
|
||
|
WHERE `ebay_staging_listing_variant_id`=:variation_id AND `property`=:property AND `value`=:value';
|
||
|
$values = [
|
||
|
'variation_id' => $stagingListingVariationId,
|
||
|
'property' => $property,
|
||
|
'value' => $value,
|
||
|
];
|
||
|
$specificMissing = empty($this->db->fetchValue($sql, $values));
|
||
|
|
||
|
if ($specificMissing) {
|
||
|
$sql = 'INSERT INTO `ebay_staging_listing_variant_specific`
|
||
|
(`ebay_staging_listing_variant_id`, `property`, `value`)
|
||
|
VALUES (:variation_id, :property, :value)';
|
||
|
$this->db->perform($sql, $values);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param StagingListingPicture $picture
|
||
|
*/
|
||
|
private function savePictureHostingServicePicture(StagingListingPicture $picture): void
|
||
|
{
|
||
|
$sql = 'SELECT `id` FROM `ebay_picture_hosting_service`
|
||
|
WHERE `url`=:url
|
||
|
AND `ebay_staging_listing_id`=:listing_id
|
||
|
AND `ebay_staging_listing_variation_id`=:variation_id';
|
||
|
$values = [
|
||
|
'url' => $picture->getUrl(),
|
||
|
'listing_id' => $picture->getStagingListingId(),
|
||
|
'variation_id' => $picture->getStagingListingVariantId(),
|
||
|
];
|
||
|
|
||
|
$pictureId = $this->db->fetchValue($sql, $values);
|
||
|
if (!empty($pictureId)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$sql = 'INSERT INTO `ebay_picture_hosting_service`
|
||
|
(`ebay_staging_listing_id`, `ebay_staging_listing_variation_id`, `file_id`, `url`)
|
||
|
VALUES
|
||
|
(:listing_id,:variation_id,:file_id,:url)';
|
||
|
$values = [
|
||
|
'listing_id' => $picture->getStagingListingId(),
|
||
|
'variation_id' => $picture->getStagingListingVariantId(),
|
||
|
'file_id' => $picture->getFileId(),
|
||
|
'url' => $picture->getUrl(),
|
||
|
];
|
||
|
$this->db->perform($sql, $values);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $shopId
|
||
|
* @param object $item
|
||
|
*
|
||
|
* @return StagingListingData
|
||
|
*/
|
||
|
public function synchronizeItemData($shopId, $item): StagingListingData
|
||
|
{
|
||
|
$stagingListing = new StagingListingData($shopId);
|
||
|
|
||
|
$stagingListingId = $this->gateway->tryGetStagingListingIdByItemId((string)$item->ItemID);
|
||
|
if (!empty($stagingListingId)) {
|
||
|
$stagingListing = $this->gateway->getStagingListingByDatabaseId($stagingListingId);
|
||
|
}
|
||
|
|
||
|
$listingStatus = 'Aktiv';
|
||
|
if (!empty($item->ListingDetails->EndingReason)) {
|
||
|
$listingStatus = 'Beendet';
|
||
|
}
|
||
|
$stagingListing->setType((string)$item->ListingType);
|
||
|
$stagingListing->setTitle((string)$item->Title);
|
||
|
$stagingListing->setSku((string)$item->SKU);
|
||
|
$stagingListing->setDescription('');
|
||
|
$stagingListing->setPrimaryCategoryId((string)$item->PrimaryCategory->CategoryID);
|
||
|
$stagingListing->setPrimaryStoreCategoryId((string)$item->Storefront->StoreCategoryID);
|
||
|
$stagingListing->setSecondaryStoreCategoryId((string)$item->Storefront->StoreCategoryID2);
|
||
|
$stagingListing->setShippingProfileId((string)$item->SellerProfiles->SellerShippingProfile->ShippingProfileID);
|
||
|
$stagingListing->setPaymentProfileId((string)$item->SellerProfiles->SellerPaymentProfile->PaymentProfileID);
|
||
|
$stagingListing->setReturnProfileId((string)$item->SellerProfiles->SellerReturnProfile->ReturnProfileID);
|
||
|
$stagingListing->setDeliveryTime((string)$item->DispatchTimeMax);
|
||
|
$stagingListing->setItemId((string)$item->ItemID);
|
||
|
$stagingListing->setInventoryTrackingMethod((string)$item->InventoryTrackingMethod);
|
||
|
$stagingListing->setConditionId((string)$item->ConditionID);
|
||
|
$stagingListing->setListingDuration((string)$item->ListingDuration);
|
||
|
$stagingListing->setConditionDisplayName((string)$item->ConditionDisplayName);
|
||
|
$stagingListing->setConditionDescription((string)$item->ConditionDescription);
|
||
|
$stagingListing->setPrivateListing(strtolower((string)$item->PrivateListing) === 'true');
|
||
|
$stagingListing->setEbayPlus(strtolower((string)$item->eBayPlus) === 'true');
|
||
|
$stagingListing->setStatus($listingStatus);
|
||
|
|
||
|
if (!empty($item->ItemSpecifics->NameValueList)) {
|
||
|
$stagingListing->setSpecifics([]);
|
||
|
foreach ($item->ItemSpecifics->NameValueList as $itemSpecific) {
|
||
|
$stagingListing->addSpecific((string)$itemSpecific->Name, (string)$itemSpecific->Value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!empty($item->PictureDetails->PictureURL)) {
|
||
|
foreach ($item->PictureDetails->PictureURL as $pictureUrl) {
|
||
|
$stagingListing->addPicture(
|
||
|
new StagingListingPicture(
|
||
|
str_replace('$_1.', '$_10.', (string)$pictureUrl)
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!empty($item->Variations)) {
|
||
|
foreach ($item->Variations->Variation as $variation) {
|
||
|
$stagingListingVariation = new StagingListingVariationData();
|
||
|
$stagingListingVariation->setSku((string)$variation->SKU);
|
||
|
foreach ($variation->VariationSpecifics->NameValueList as $specifics) {
|
||
|
$stagingListingVariation->addSpecifics((string)$specifics->Name, (string)$specifics->Value);
|
||
|
}
|
||
|
$stagingListing->addVariation($stagingListingVariation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->saveStagingListing($stagingListing);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $stagingId
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getStockSyncBody($stagingId): string
|
||
|
{
|
||
|
$staging = $this->gateway->getStagingListingByDatabaseId($stagingId);
|
||
|
|
||
|
$stocksForArticles = [];
|
||
|
|
||
|
$stocksForArticles[$staging->getArticleId()] = $this->stockCalculationWrapper->calculateStock(
|
||
|
$staging->getArticleId(),
|
||
|
$staging->getShopId()
|
||
|
);
|
||
|
foreach ($staging->getVariations() as $variation) {
|
||
|
if (!empty($variation->getArticleId()) && !isset($stocksForArticles[$variation->getArticleId()])) {
|
||
|
$stocksForArticles[$variation->getArticleId()] = $this->stockCalculationWrapper->calculateStock(
|
||
|
$variation->getArticleId(),
|
||
|
$staging->getShopId()
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->serializer->createStockSyncXmlString($staging, $stocksForArticles);
|
||
|
}
|
||
|
}
|