Как можно преобразовать локальные атрибуты товара в глобальные при его сохранении в WooCommerce?

Какова задача: при сохранении товара необходимо проверять его атрибуты и, если они являются локальными, переводить их в глобальные, добавляя соответствующие опции и проверяя уникальность и другие параметры? У меня уже есть реализованная функция, но при сохранении товара атрибуты остаются локальными, хотя новые глобальные атрибуты добавляются вместе с опциями. Я добавил тестовую отладочную информацию, и вот что я наблюдаю в логах:

```
Product ID: 54624
Глобальный атрибут с именем <b>Длина</b> УЖЕ СУЩЕСТВУЕТ
Опция Длина -&gt; 10см УЖЕ СУЩЕСТВУЕТ (ID 1368)
Глобальный атрибут с именем <b>Бренд</b> УЖЕ СУЩЕСТВУЕТ
Опция Бренд -&gt; новый бренд УЖЕ СУЩЕСТВУЕТ (ID 1369)
Глобальный атрибут с именем <b>Тест</b> УЖЕ СУЩЕСТВУЕТ
Опция Тест -&gt; тест УЖЕ СУЩЕСТВУЕТ (ID 1370)
Глобальный атрибут с именем <b>newattr</b> УЖЕ СУЩЕСТВУЕТ
Опция newattr -&gt; newaattr УЖЕ СУЩЕСТВУЕТ (ID 1371)
Локальные атрибуты удалены
Сохраняем продукт
```

Тем не менее, в товаре по-прежнему отображаются локальные атрибуты, и они не заменяются на глобальные. Вот соответствующий код, который я использую:

```php
add_action('save_post_product', 'convert_local_to_global_attributes', 10, 3);

function convert_local_to_global_attributes($product_id, $post, $update) {

    $test_mode = false;
    $writelog = true;

    $logfile = __DIR__ . '/atrlog.txt';

    $logs = [];
    $logs[] = 'Product ID: ' . $product_id;

    $product = new \WC_Product($product_id);
    $product_attributes = $product-&gt;get_attributes();

    if (empty($product_attributes)) {
        $logs[] = 'Атрибуты для товара отсутствуют.';
        if ($writelog === true) {
            file_put_contents($logfile, implode(PHP_EOL, $logs) . 
```
  • 26 сентября 2024 г. 11:34
Ответы на вопрос 1
Чтобы преобразовать локальные атрибуты товара в глобальные атрибуты в WooCommerce, необходимо выполнить несколько шагов: проверить наличие атрибутов, их уникальность, создать глобальные атрибуты, а затем обновить товар, чтобы он использовал глобальные атрибуты вместо локальных. Проблема, с которой вы сталкиваетесь, может быть связана с тем, что вы не обновляете атрибуты товара после их преобразования.

Ваш код выглядит почти правильно. После удаления локальных атрибутов необходимо заново установить атрибуты у товара, чтобы они ссылаются на глобальные атрибуты. Давайте доработаем ваш код, чтобы убедиться, что атрибуты корректно обновляются. Также добавим недостающие действия, чтобы убедиться, что все идет корректно. 

Вот модифицированный код:

```php
add_action('save_post_product', 'convert_local_to_global_attributes', 10, 3);

function convert_local_to_global_attributes($product_id, $post, $update) {
    // Логирование
    $logfile = __DIR__ . '/atrlog.txt';
    $logs = [];
    $logs[] = 'Product ID: ' . $product_id;

    $product = new \WC_Product($product_id);
    $product_attributes = $product->get_attributes();

    // Предполагаем, что глобальные атрибуты уже созданы
    $global_attributes = [];

    foreach ($product_attributes as $attribute) {
        if ($attribute->get_variation() === false) { // Локальный атрибут
            $attribute_name = $attribute->get_name();
            $attribute_terms = $attribute->get_options();

            // Проверка на существование глобального атрибута
            if (!isset($global_attributes[$attribute_name])) {
                // Получаем объект глобального атрибута
                $global_attribute = wc_get_attribute(wc_attribute_taxonomy_id($attribute_name));

                if ($global_attribute) {
                    // Добавляем в массив глобальных атрибутов
                    $global_attributes[$attribute_name] = $global_attribute;
                    $logs[] = "Глобальный атрибут с именем <b>{$attribute_name}</b> УЖЕ СУЩЕСТВУЕТ";
                } else {
                    // Создать новый глобальный атрибут
                    $global_attribute_id = wp_insert_term($attribute_name, 'pa_' . sanitize_title($attribute_name));
                    if (!is_wp_error($global_attribute_id)) {
                        $global_attributes[$attribute_name] = $global_attribute_id['term_id'];
                        $logs[] = "Создан глобальный атрибут: {$attribute_name} (ID={$global_attribute_id['term_id']})";
                    }
                }
            }

            // Обработка терминов атрибута (опций)
            foreach ($attribute_terms as $term) {
                $term_id = term_exists($term, 'pa_' . sanitize_title($attribute_name));
                if (!$term_id) {
                    // Если термин не существует, создаем его
                    $term_id = wp_insert_term($term, 'pa_' . sanitize_title($attribute_name));
                    $logs[] = "Добавлена опция для атрибута {$attribute_name}: {$term} (ID={$term_id['term_id']})";
                }

                // Переход к ID атрибута
                $attribute_terms_ids[] = $term_id['term_id'];
            }

            // Удаляем локальный атрибут
            $product->remove_attribute($attribute->get_name());
        }
    }

    // Устанавливаем глобальные атрибуты товара
    if (!empty($global_attributes)) {
        foreach ($global_attributes as $name => $global_attribute_id) {
            // Обновляем атрибуты товара
            $product->add_attribute($name, $attribute_terms_ids, true);
        }
    }

    // Сохраняем изменения в продукте
    $product->save();

    // Логирование
    if (!empty($logs)) {
        file_put_contents($logfile, implode(PHP_EOL, $logs) . PHP_EOL, FILE_APPEND);
    }
}
```

### Основные изменения и дополнения:
1. **Проверка и создание глобальных атрибутов:** Введены проверки на существование глобальных атрибутов перед их созданием.
2. **Добавление опций (терминов):** Проверяется, существуют ли термины для глобального атрибута, и создаются только если они не найдены.
3. **Обновление атрибутов товара:** После удаления локальных атрибутов добавляются глобальные.
4
Похожие вопросы