# sync-basalam/1.10.17/includes/Services/Products/CreateSingleProductService.php

ووسلام – همگام سازی ووکامرس و باسلام, version 1.10.17. 210 lines.

- Page: https://pluginprobe.com/plugins/sync-basalam/1.10.17/code/includes/Services/Products/CreateSingleProductService.php
- Raw: https://pluginprobe.com/plugins/sync-basalam/1.10.17/raw/includes/Services/Products/CreateSingleProductService.php
- Modified: 2026-09-09T08:33:38+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/sync-basalam/1.10.17/code/includes/Services/Products/CreateSingleProductService.php#L10-L20`.

```php
<?php

namespace SyncBasalam\Services\Products;

use SyncBasalam\Admin\Product\Data\Validators\CreateProductDataValidator;
use SyncBasalam\Admin\Settings\SettingsConfig;
use SyncBasalam\Config\Endpoints;
use SyncBasalam\Services\ApiServiceManager;
use SyncBasalam\Jobs\Exceptions\RetryableException;
use SyncBasalam\Jobs\Exceptions\NonRetryableException;
use SyncBasalam\Utilities\ProductMetaKey;
use SyncBasalam\Services\VendorSyncPolicy;

defined('ABSPATH') || exit;

class CreateSingleProductService
{
    private $apiservice;
    private $validator;

    public function __construct($validator = null)
    {
        $this->apiservice = syncBasalamContainer()->get(ApiServiceManager::class);
        $this->validator = $validator ?: new CreateProductDataValidator();
    }

    public function createProductInBasalam($productData, $productId)
    {
        $vendorSyncPolicy = syncBasalamContainer()->get(VendorSyncPolicy::class);
        if (!$vendorSyncPolicy->canCreate()) {
            throw NonRetryableException::invalidData($vendorSyncPolicy->getRestrictionMessage(false));
        }

        $productData = apply_filters('sync_basalam_product_data_before_create', $productData, $productId);
        $this->ValidCreateProductData($productData, $productId);

        do_action('sync_basalam_before_create_product_api', $productId, $productData);

        $vendorId = syncBasalamSettings()->getSettings(SettingsConfig::VENDOR_ID);

        $url = sprintf(Endpoints::PRODUCT_CREATE, $vendorId);

        $maxDescriptionRetries = 3;
        $descriptionRetry = 0;

        while (true) {
            try {
                $request = $this->apiservice->post($url, $productData);
                break;
            } catch (RetryableException $e) {
                throw $e;
            } catch (NonRetryableException $e) {
                if ($descriptionRetry < $maxDescriptionRetries && $this->stripForbiddenDescription($e, $productData, $productId, $descriptionRetry)) {
                    $descriptionRetry++;
                    continue;
                }
                throw $e;
            } catch (\Exception $e) {
                throw new \Exception(esc_html($e->getMessage()));
            }
        }

        if ($request['status_code'] != 201 && isset($request['status_code'])) {

            $body = $request['body'] ?? '';

            if (is_string($body))
                $responseData = json_decode($body, true);
            else $responseData = $body;

            if (!is_array($responseData)) $responseData = [];

            if ($responseData && isset($responseData['messages'][0])) {
                $message = $responseData['messages'][0]['message'] ?? 'خطای نامشخص';
                $field = $responseData['messages'][0]['fields'][0] ?? '';
            } else {
                $message = 'درخواست با تایم اوت مواجه شد.';
                $field = '';
            }

            $errorMessage = 'فرایند اضافه کردن محصول ناموفق بود: ' . esc_html($message);
            if ($field) $errorMessage .= ' (فیلد: ' . esc_html($field) . ')';

            throw new \Exception(esc_html($errorMessage));
        }

        if (is_wp_error($request)) {
            $body = $request['body'] ?? '';

            if (is_string($body))
                $responseData = json_decode($body, true);
            else $responseData = $body;

            $message = $responseData[0]['message'] ?? 'خطای نامشخص';
            throw new \Exception('درخواست موفقیت آمیز نبود: ' . esc_html($message));
        }

        $responseData = json_decode($request['body'], true);
        if (isset($responseData['id'])) {
            if (isset($responseData['variants'])) {
                $product = wc_get_product($productId);

                if ($product && $product->is_type('variable')) {
                    $wcVariations = [];
                    $attributes = $product->get_attributes();

                    foreach ($product->get_children() as $variationId) {
                        $variation = wc_get_product($variationId);
                        $attributeValues = [];

                        foreach ($attributes as $attributeName => $attribute) {
                            if ($attribute->get_variation()) {
                                $cleanAttributeName = str_replace('attribute_', '', $attributeName);
                                $value = $variation->get_attribute($cleanAttributeName);

                                $value = urldecode($value);
                                $value = trim($value);
                                $value = mb_strtolower($value, 'UTF-8');
                                $value = str_replace(['ي', 'ك'], ['ی', 'ک'], $value);
                                $value = str_replace(['-', '_', '–', '—'], ' ', $value);
                                $value = preg_replace('/\s+/', ' ', $value);

                                if (!empty($value)) {
                                    $attributeValues[] = $value;
                                }
                            }
                        }

                        if (!empty($attributeValues)) {
                            $key = implode("_", $attributeValues);
                            $wcVariations[$key] = $variationId;
                        }
                    }

                    $syncBasalamVariations = [];
                    foreach ($responseData['variants'] as $variant) {
                        $attributeValues = [];
                        if (!empty($variant['properties'])) {
                            foreach ($variant['properties'] as $property) {
                                $val = trim($property['value']['title']);
                                $val = mb_strtolower($val, 'UTF-8');
                                $val = str_replace(['ي', 'ك'], ['ی', 'ک'], $val);
                                $val = str_replace(['-', '_', '–', '—'], ' ', $val);
                                $val = preg_replace('/\s+/', ' ', $val);
                                if (!empty($val)) {
                                    $attributeValues[] = $val;
                                }
                            }
                        }

                        if (!empty($attributeValues)) {
                            $key = implode("_", $attributeValues);
                            $syncBasalamVariations[$key] = $variant['id'];
                        }
                    }

                    $variationMapping = [];
                    foreach ($wcVariations as $key => $wcVarId) {
                        if (isset($syncBasalamVariations[$key])) {
                            $variationMapping[$wcVarId] = $syncBasalamVariations[$key];
                            update_post_meta($wcVarId, 'sync_basalam_variation_id', $syncBasalamVariations[$key]);
                        }
                    }
                }
            }

            update_post_meta($productId, ProductMetaKey::basalamProductId(), $responseData['id']);
            update_post_meta($productId, ProductMetaKey::basalamProductStatus(), 2976);
            update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced');

            $result = [
                'success'     => true,
                'message'     => 'محصول با موفقیت به باسلام اضافه شد.',
                'status_code' => 200,
                'basalam_id'  => $responseData['id'],
            ];

            do_action('sync_basalam_after_create_product_api', $productId, $responseData, $result);

            return $result;
        }

        throw new \Exception("فرایند اضافه کردن محصول ناموفق بود");
    }

    private function stripForbiddenDescription(NonRetryableException $e, array &$productData, int $productId, int $attempt): bool
    {
        if (!isset($productData['description']) || !is_string($productData['description'])) return false;

        $values = DescriptionErrorSanitizer::extractDescriptionValues($e->getResponseData());
        if (empty($values)) return false;

        $cleaned = DescriptionErrorSanitizer::sanitize($productData['description'], $values);
        if ($cleaned === $productData['description']) return false;

        $productData['description'] = $cleaned;

        return true;
    }

    private function ValidCreateProductData(array $productData, int $productId): void
    {
        $validation = $this->validator->validate($productData, $productId);

        if (!$validation['valid']) {
            throw NonRetryableException::invalidData(esc_html($validation['message']));
        }
    }
}

```
