OpenXE/classes/Modules/Ebay/Gateway/EbayListingGateway.php
2021-05-21 08:49:41 +02:00

357 lines
12 KiB
PHP

<?php
declare(strict_types=1);
namespace Xentral\Modules\Ebay\Gateway;
use Xentral\Components\Database\Database;
use Xentral\Modules\Ebay\Data\StagingListingData;
use Xentral\Modules\Ebay\Data\StagingListingVariationData;
use Xentral\Modules\Ebay\Exception\InvalidArgumentException;
use Xentral\Modules\Ebay\Exception\ValidationFailedException;
final class EbayListingGateway
{
/** @var Database $db */
private $db;
/**
* @param Database $database
*/
public function __construct(Database $database)
{
$this->db = $database;
}
/**
* @param int $itemId
*
* @throws ValidationFailedException
*
* @return int
*/
public function tryGetStagingListingIdByItemId($itemId): int
{
$sql = 'SELECT e.*
FROM `ebay_staging_listing` AS `e`
WHERE e.item_id_external = :item_id';
$values = ['item_id' => $itemId];
$stagingListingData = $this->db->fetchRow($sql, $values);
if (empty($stagingListingData)) {
return 0;
}
return $stagingListingData['id'];
}
/**
* @param int $id
*
* @throws InvalidArgumentException
* @throws ValidationFailedException
*
* @return StagingListingData
*/
public function getStagingListingByDatabaseId(int $id): StagingListingData
{
$sql = 'SELECT e.*
FROM `ebay_staging_listing` AS `e`
WHERE e.id = :listing_id';
$values = ['listing_id' => $id];
$stagingListingData = $this->db->fetchRow($sql, $values);
if (empty($stagingListingData)) {
throw new InvalidArgumentException('Required argument "id" is empty or invalid.');
}
$stagingListing = StagingListingData::fromDbState($stagingListingData);
$stagingListing->setVariations($this->getStagingListingVariations($stagingListing->getId()));
$validationErrors = $stagingListing->validate();
if (!empty($validationErrors)) {
throw ValidationFailedException::fromErrors($validationErrors);
}
return $stagingListing;
}
/**
* @param int $stagingListingId
*
* @throws InvalidArgumentException
* @return array
*/
protected function getStagingListingVariations(int $stagingListingId): array
{
if (empty($stagingListingId)) {
throw new InvalidArgumentException('Required argument "stagingListingId" is empty or invalid.');
}
$variations = [];
$sql = 'SELECT e.id, e.sku, e.ebay_staging_listing_id, e.article_id
FROM `ebay_staging_listing_variant` AS `e`
WHERE e.ebay_staging_listing_id = :listing_id';
$values = ['listing_id' => $stagingListingId];
$stagingListingVariations = $this->db->fetchAll($sql, $values);
if (empty($stagingListingVariations)) {
return $variations;
}
foreach ($stagingListingVariations as $variation) {
$sql = 'SELECT e.property, e.value
FROM ebay_staging_listing_variant_specific AS `e`
WHERE e.ebay_staging_listing_variant_id = :variation_id';
$values = ['variation_id' => $variation['id']];
$allSpecificsInDatabase = $this->db->fetchAll($sql, $values);
$specifics = [];
foreach ($allSpecificsInDatabase as $specificsInDatabase) {
$specifics[$specificsInDatabase['property']] = $specificsInDatabase['value'];
}
$stagingListingVariation = StagingListingVariationData::fromArray($variation, $specifics);
$variations[] = $stagingListingVariation;
}
return $variations;
}
/**
* @param int $shopId
*
* @return array
*/
public function getPaymentBusinessPolicies($shopId): array
{
return $this->findBusinessPolicies($shopId, 'PAYMENT');
}
/**
* @param int $shopId
* @param string $type
*
* @throws InvalidArgumentException
*
* @return array
*/
protected function findBusinessPolicies($shopId, $type): array
{
if (empty($shopId)) {
throw new InvalidArgumentException('Required argument "shopId" is empty or invalid.');
}
if (empty($type)) {
throw new InvalidArgumentException('Required argument "type" is empty.');
}
$sql = 'SELECT
e.id, e.aktiv AS active, e.profilid AS profile_id_external,
e.profilname AS profile_name, e.profilsummary AS profile_summary
FROM ebay_rahmenbedingungen AS `e`
WHERE e.shop=:shopid AND e.profiltype=:profiltype';
$values = [
'shopid' => $shopId,
'profiltype' => $type,
];
return $this->db->fetchAll($sql, $values);
}
/**
* @param int $shopId
*
* @return array
*/
public function getShippingBusinessPolicies($shopId): array
{
return $this->findBusinessPolicies($shopId, 'SHIPPING');
}
/**
* @param int $shopId
*
* @return array
*/
public function getReturnBusinessPolicies($shopId): array
{
return $this->findBusinessPolicies($shopId, 'RETURN_POLICY');
}
/**
* @return array
*/
public function getTemplates(): array
{
$sql = 'SELECT e.id, e.bezeichnung AS template_name
FROM `ebay_template` AS `e`
WHERE e.aktiv = 1';
return $this->db->fetchAll($sql);
}
/**
* @param int $shopId
*
* @throws InvalidArgumentException
* @return array
*/
public function getStoreCategories(int $shopId): array
{
if ($shopId <= 0) {
throw new InvalidArgumentException('Required argument "shopId" is invalid.');
}
$sql = 'SELECT e.id, e.kategorie AS `category_id_external`, e.bezeichnung AS description
FROM `ebay_storekategorien` AS `e`
WHERE shop = :shop_id';
$values = ['shop_id' => $shopId];
return $this->db->fetchAll($sql, $values);
}
/**
* @param StagingListingData $stagingListing
*
* @return int
*/
public function searchForMatchingArticleId(StagingListingData $stagingListing): int
{
if (!empty($stagingListing->getArticleId())) {
return $stagingListing->getArticleId();
}
//associate by listing id in foreign numbers
$sql =
"SELECT af.artikel
FROM `artikelnummer_fremdnummern` AS `af`
JOIN `artikel` AS `a` ON af.artikel = a.id
WHERE af.shopid = :shop_id AND LOWER(af.bezeichnung) = 'ebaylisting' AND af.nummer = :article_number
AND a.nummer <> 'DEL' AND a.geloescht = 0 AND a.intern_gesperrt = 0
LIMIT 1";
$values = [
'shop_id' => $stagingListing->getShopId(),
'article_number' => $stagingListing->getItemId(),
];
$articleId = $this->db->fetchValue($sql, $values);
if (empty($articleId)) {
//associate by sku
$sql = 'SELECT a.id
FROM `artikel` AS `a`
WHERE a.geloescht = 0 AND a.intern_gesperrt=0 AND a.nummer=:article_number';
$values = ['article_number' => $stagingListing->getSku()];
$articleId = $this->db->fetchValue($sql, $values);
}
if (empty($articleId)) {
//associate by foreign number
$sql = "SELECT a.id
FROM `artikel` AS `a`
JOIN `artikelnummer_fremdnummern` AS `af` ON af.artikel = a.id
WHERE a.geloescht = 0 AND a.intern_gesperrt = 0 AND a.nummer <> ''
AND af.aktiv = 1 AND (LOWER(af.bezeichnung) = 'sku' OR LOWER(af.bezeichnung) = 'bestandseinheit')
AND af.nummer = :article_number AND (af.shopid = :shop_id OR af.shopid = 0)
ORDER BY af.shopid DESC LIMIT 1";
$values = [
'article_number' => $stagingListing->getSku(),
'shop_id' => $stagingListing->getShopId(),
];
$articleId = $this->db->fetchValue($sql, $values);
}
return (int)$articleId;
}
/**
* @param StagingListingVariationData $variation
* @param int $shopId
* @param int $parentArticleId
*
* @return int
*/
public function searchForMatchingArticleIdForVariation(
StagingListingVariationData $variation,
int $shopId,
int $parentArticleId
): int {
if (!empty($variation->getArticleId())) {
return $variation->getArticleId();
}
//associate by sku
$sql = 'SELECT a.id
FROM `artikel` AS a
WHERE a.geloescht = 0 AND a.intern_gesperrt = 0 AND a.nummer = :article_number';
$values = ['article_number' => $variation->getSku()];
$articleId = $this->db->fetchValue($sql, $values);
if (empty($articleId)) {
//associate by foreign number
$sql = "SELECT a.id
FROM `artikel` AS `a`
JOIN `artikelnummer_fremdnummern` AS `af` ON af.artikel = a.id
WHERE a.geloescht = 0 AND a.intern_gesperrt = 0 AND a.nummer <> ''
AND af.aktiv = 1 AND (LOWER(af.bezeichnung) = 'sku' OR LOWER(af.bezeichnung) = 'bestandseinheit')
AND af.nummer = :sku AND (af.shopid = :shop_id OR af.shopid = 0)
ORDER BY af.shopid DESC LIMIT 1";
$values = [
'sku' => $variation->getSku(),
'shop_id' => $shopId,
];
$articleId = $this->db->fetchValue($sql, $values);
}
if (empty($articleId)) {
//associate by matrix combination
$specifics = [];
foreach ($variation->listSpecifics() as $dimension => $value) {
$specifics[] = sprintf('(ma.name = %s AND mea.name = %s)',
$this->db->escapeString($dimension),
$this->db->escapeString($value));
}
$query = sprintf(
'
SELECT x.artikel AS `artikelId`
FROM (
SELECT moza.artikel
FROM `matrixprodukt_eigenschaftengruppen_artikel` AS `ma`
JOIN `matrixprodukt_eigenschaftenoptionen_artikel` AS `mea` on ma.id = mea.gruppe
JOIN `matrixprodukt_optionen_zu_artikel` AS `moza` ON moza.option_id = mea.id
WHERE ma.artikel = %d AND (%s)
) AS `x`
GROUP BY x.artikel
HAVING COUNT(x.artikel) = %d',
$parentArticleId,
implode(' OR ', $specifics),
count($specifics)
);
$foundCombinations = $this->db->fetchAll($query);
if (count($foundCombinations) === 1) {
$articleId = $foundCombinations[0]['artikelId'];
}
}
return (int)$articleId;
}
/**
* @param int $articleId
* @param int $shopId
*
* @return bool
*/
public function existsStagingListingsForArticleId(int $articleId, int $shopId): bool
{
$sql = "SELECT e.id
FROM `ebay_staging_listing` AS `e`
LEFT JOIN `ebay_staging_listing_variant` AS `v` ON e.id = v.ebay_staging_listing_id
WHERE (e.article_id = :article_id or v.article_id = :article_id) AND e.shop_id = :shop_id AND e.status = 'Aktiv'";
$values = [
'article_id' => $articleId,
'shop_id' => $shopId
];
$stagingId = $this->db->fetchValue($sql, $values);
return !empty($stagingId);
}
}