1
0
mirror of synced 2025-02-21 01:13:13 +03:00

Add product description to ICML

This commit is contained in:
Dima Uryvskiy 2022-05-26 11:58:54 +03:00 committed by GitHub
parent 01e3ad71ee
commit e1e7331f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 145 additions and 52 deletions

View File

@ -1,4 +1,12 @@
### Настройки каталога *(статусы товаров)*
### Настройки каталога
В версии 4.4.4 добавлен функционал передачи описания товара в каталог. В настройках каталога необходимо выбрать, какое описание передавать краткое или полное. По умолчанию передается полное описание товара.
Поле description(описание) выводится в карточке товара, так же его можно использовать в twig-шаблонах. Например, для вывода в печатных формах.
Пример получения описание торгового предложения:
```twig
{% for availableOrderProduct in order.availableOrderProducts %} {{ availableOrderProduct.getOffer().getDescription() }} {% endfor %}
```
В настройке представлены статусы товаров в WooCommerce *(Товары -> карточка товара -> блок Опубликовано)*. Из товаров, чей статус будет соответствовать выбранному, будет сгенерирован ICML-файл каталога. Для выбора необходимо поставить галочку напротив нужного статуса и сохранить настройки.

View File

@ -317,4 +317,16 @@ msgid "Attention!"
msgstr "¡Atención!"
msgid "If payment type linked to the CRM integration module choosed, payment must be proceed in the CRM"
msgstr "Al seleccionar en el enlace de tipos de pago un método de pago de integración en CRM, el pago se debe realizar por parte del CRM"
msgstr "Al seleccionar en el enlace de tipos de pago un método de pago de integración en CRM, el pago se debe realizar por parte del CRM"
msgid "Product description"
msgstr "Descripción del Producto"
msgid "Full description"
msgstr "Descripción completa"
msgid "Short description"
msgstr "Descripción corta"
msgid "In the catalog, you can use a full or short description of the product"
msgstr "En el catálogo, puedes utilizar una descripción del producto corta o completa"

View File

@ -328,5 +328,15 @@ msgstr "Внимание!"
msgid "If payment type linked to the CRM integration module choosed, payment must be proceed in the CRM"
msgstr "При указании в соответствии типа оплаты, привязанного к интеграционному модулю в CRM, оплата должна происходить на стороне CRM"
msgid "Product description"
msgstr "Описание товара"
msgid "Full description"
msgstr "Полное описание"
msgid "Short description"
msgstr "Краткое описание"
msgid "In the catalog, you can use a full or short description of the product"
msgstr "В каталоге можно использовать полное или краткое описание товара"

View File

@ -1,5 +1,6 @@
.whatsapp-icon {
position: fixed;
z-index: 999;
left: 0;
bottom: 55px;
width: 60px;

View File

@ -1 +1 @@
.whatsapp-icon{position:fixed;left:0;bottom:55px;width:60px;height:60px;box-sizing:border-box}.whatsapp-icon_left{left:32px;right:auto}.whatsapp-icon_right{right:32px;left:auto}.whatsapp-icon__icon{width:100%;height:100%}.chat-btn__text{color:#8A96A6;font-weight:600;font-size:12px;line-height:14px;text-align:center;margin:8px 0 0}
.whatsapp-icon{position:fixed;z-index: 999;left:0;bottom:55px;width:60px;height:60px;box-sizing:border-box}.whatsapp-icon_left{left:32px;right:auto}.whatsapp-icon_right{right:32px;left:auto}.whatsapp-icon__icon{width:100%;height:100%}.chat-btn__text{color:#8A96A6;font-weight:600;font-size:12px;line-height:14px;text-align:center;margin:8px 0 0}

View File

@ -127,6 +127,21 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
'id' => 'catalog_options'
);
$this->form_fields['product_description'] = [
'type' => 'select',
'class' => 'select',
'title' => __('Product description', 'retailcrm'),
'options' => [
'full' => __('Full description', 'retailcrm'),
'short' => __('Short description', 'retailcrm'),
],
'desc_tip' => true,
'description' => __(
'In the catalog, you can use a full or short description of the product',
'retailcrm'
),
];
foreach (get_post_statuses() as $status_key => $status_value) {
$this->form_fields['p_' . $status_key] = array(
'title' => $status_value,
@ -134,7 +149,7 @@ abstract class WC_Retailcrm_Abstracts_Settings extends WC_Integration
'description' => '',
'class' => 'checkbox',
'type' => 'checkbox',
'desc_tip' => true,
'desc_tip' => true,
);
}

View File

@ -1,4 +1,5 @@
<?php
/**
* PHP version 5.6
*
@ -18,7 +19,7 @@ if (!class_exists('WC_Retailcrm_Icml')) :
protected $file;
protected $tmpFile;
protected $properties = array(
protected $properties = [
'name',
'productName',
'price',
@ -28,7 +29,7 @@ if (!class_exists('WC_Retailcrm_Icml')) :
'url',
'xmlId',
'productActivity'
);
];
protected $xml;
@ -51,7 +52,7 @@ if (!class_exists('WC_Retailcrm_Icml')) :
public function __construct()
{
$this->settings = get_option(WC_Retailcrm_Base::$option_key);
$this->shop = get_bloginfo( 'name' );
$this->shop = get_bloginfo('name');
$this->file = ABSPATH . 'simla.xml';
$this->tmpFile = sprintf('%s.tmp', $this->file);
}
@ -80,8 +81,11 @@ if (!class_exists('WC_Retailcrm_Icml')) :
$status_args = $this->checkPostStatuses();
$this->get_wc_products_taxonomies($status_args);
$dom = dom_import_simplexml(simplexml_load_file($this->tmpFile))->ownerDocument;
$dom->formatOutput = true;
$formatted = $dom->saveXML();
unset($dom, $this->xml);
@ -170,7 +174,7 @@ if (!class_exists('WC_Retailcrm_Icml')) :
{
$categories = self::filterRecursive($categories);
foreach($categories as $category) {
foreach ($categories as $category) {
if (!array_key_exists('name', $category) || !array_key_exists('id', $category)) {
continue;
}
@ -278,7 +282,8 @@ if (!class_exists('WC_Retailcrm_Icml')) :
* @param $key
* @param $e
*/
private function setOffersProperties($value, $key, &$e) {
private function setOffersProperties($value, $key, &$e)
{
if (in_array($key, $this->properties) && $key != 'params') {
/** @var SimpleXMLElement $e */
$e->addChild($key, htmlspecialchars($value));
@ -292,7 +297,8 @@ if (!class_exists('WC_Retailcrm_Icml')) :
* @param $key
* @param $e
*/
private function setOffersParams($value, $key, &$e) {
private function setOffersParams($value, $key, &$e)
{
if (
array_key_exists('code', $value) &&
array_key_exists('name', $value) &&
@ -323,7 +329,8 @@ if (!class_exists('WC_Retailcrm_Icml')) :
$haystack[$key] = self::filterRecursive($haystack[$key]);
}
if (is_null($haystack[$key])
if (
is_null($haystack[$key])
|| $haystack[$key] === ''
|| (is_array($haystack[$key]) && count($haystack[$key]) == 0)
) {
@ -341,26 +348,27 @@ if (!class_exists('WC_Retailcrm_Icml')) :
*
* @return void
*/
private function get_wc_products_taxonomies($status_args) {
private function get_wc_products_taxonomies($status_args)
{
if (!$status_args) {
$status_args = array('publish');
$status_args = ['publish'];
}
$attribute_taxonomies = wc_get_attribute_taxonomies();
$product_attributes = array();
$product_attributes = [];
foreach ($attribute_taxonomies as $product_attribute) {
$attribute_id = wc_attribute_taxonomy_name_by_id(intval($product_attribute->attribute_id));
$product_attributes[$attribute_id] = $product_attribute->attribute_label;
}
$full_product_list = array();
$full_product_list = [];
$products = wc_get_products(
array(
[
'limit' => -1,
'status' => $status_args
)
]
);
foreach ($products as $offer) {
@ -391,8 +399,9 @@ if (!class_exists('WC_Retailcrm_Icml')) :
*
* @return array
*/
private function get_wc_categories_taxonomies() {
$categories = array();
private function get_wc_categories_taxonomies()
{
$categories = [];
$taxonomy = 'product_cat';
$orderby = 'parent';
$show_count = 0; // 1 for yes, 0 for no
@ -401,7 +410,7 @@ if (!class_exists('WC_Retailcrm_Icml')) :
$title = '';
$empty = 0;
$args = array(
$args = [
'taxonomy' => $taxonomy,
'orderby' => $orderby,
'show_count' => $show_count,
@ -409,16 +418,16 @@ if (!class_exists('WC_Retailcrm_Icml')) :
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
];
$wcatTerms = get_categories($args);
foreach ($wcatTerms as $term) {
$category = array(
$category = [
'id' => $term->term_id,
'parentId' => $term->parent,
'name' => $term->name
);
];
$thumbnail_id = function_exists('get_term_meta')
? get_term_meta($term->term_id, 'thumbnail_id', true)
@ -533,13 +542,25 @@ if (!class_exists('WC_Retailcrm_Icml')) :
];
if ($product->get_sku() != '') {
$params[] = array('code' => 'article', 'name' => 'Артикул', 'value' => $product->get_sku());
$params[] = ['code' => 'article', 'name' => 'Article', 'value' => $product->get_sku()];
if (isset($this->settings['bind_by_sku']) && $this->settings['bind_by_sku'] == WC_Retailcrm_Base::YES) {
$product_data['xmlId'] = $product->get_sku();
}
}
if (isset($this->settings['product_description'])) {
$productDescription = $this->getDescription($product);
if (empty($productDescription) && $parent instanceof WC_Product_Variable) {
$this->getDescription($parent);
}
if ($productDescription != '') {
$params[] = ['code' => 'description', 'name' => 'Description', 'value' => $productDescription];
}
}
if (!empty($params)) {
$product_data['params'] = $params;
}
@ -556,8 +577,9 @@ if (!class_exists('WC_Retailcrm_Icml')) :
*
* @return array
*/
private function checkPostStatuses() {
$status_args = array();
private function checkPostStatuses()
{
$status_args = [];
foreach (get_post_statuses() as $key => $value) {
if (isset($this->settings['p_' . $key]) && $this->settings['p_' . $key] == WC_Retailcrm_Base::YES) {
@ -567,6 +589,20 @@ if (!class_exists('WC_Retailcrm_Icml')) :
return $status_args;
}
/**
* Get product description
*
* @param WC_Product | WC_Product_Variable $product WC product.
*
* @return string
*/
private function getDescription($product)
{
return $this->settings['product_description'] == 'full'
? $product->get_description()
: $product->get_short_description();
}
}
endif;

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,5 @@
<?php
/**
* PHP version 5.6
*
@ -61,6 +62,7 @@ class WC_Retailcrm_Test_Case_Helper extends WC_Unit_Test_Case
'debug-info' => '',
'order-meta-data-retailcrm' => json_encode(['woo_order' => 'crm_order']),
'customer-meta-data-retailcrm' => json_encode(['woo_customer' => 'crm_customer']),
'product_description' => 'full',
];
update_option(WC_Retailcrm_Base::$option_key, $options);
@ -78,16 +80,18 @@ class WC_Retailcrm_Test_Case_Helper extends WC_Unit_Test_Case
} else {
global $wpdb;
foreach ([
$wpdb->posts,
$wpdb->postmeta,
$wpdb->comments,
$wpdb->commentmeta,
$wpdb->term_relationships,
$wpdb->termmeta,
] as $table ) {
foreach (
[
$wpdb->posts,
$wpdb->postmeta,
$wpdb->comments,
$wpdb->commentmeta,
$wpdb->term_relationships,
$wpdb->termmeta,
] as $table
) {
//phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( "DELETE FROM {$table}" );
$wpdb->query("DELETE FROM {$table}");
}
foreach ([$wpdb->terms, $wpdb->term_taxonomy] as $table) {

View File

@ -119,6 +119,7 @@ class WC_Retailcrm_Base_Test extends WC_Retailcrm_Test_Case_Helper
$this->assertArrayHasKey('deactivate_update_order', $this->baseRetailcrm->form_fields);
$this->assertArrayHasKey('bind_by_sku', $this->baseRetailcrm->form_fields);
$this->assertArrayHasKey('update_number', $this->baseRetailcrm->form_fields);
$this->assertArrayHasKey('product_description', $this->baseRetailcrm->form_fields);
}
public function test_retailcrm_form_fields_value()

View File

@ -14,33 +14,39 @@ class WC_Retailcrm_Icml_Test extends WC_Retailcrm_Test_Case_Helper
{
public function setUp()
{
for ($i = 0; $i < 10; $i++) {
WC_Helper_Product::create_simple_product();
}
wp_insert_term(
'Test', // the term
'product_cat', // the taxonomy
array(
'description'=> 'Test',
'slug' => 'test'
)
);
WC_Helper_Product::create_simple_product();
WC_Helper_Product::create_variation_product();
}
public function testGenerate()
{
$icml = new WC_Retailcrm_Icml();
$icml->generate();
$this->assertFileExists(ABSPATH . 'simla.xml');
$xml = simplexml_load_file(ABSPATH . 'simla.xml');
$res = $xml->xpath('/yml_catalog/shop/categories/category[@id]');
$this->assertNotEmpty($res);
$this->assertNotEmpty($xml);
foreach ($res as $node) {
$this->assertEquals('category', $node->getName());
$xmlArray = json_decode(json_encode($xml), true);
$this->assertNotEmpty($xmlArray['shop']['categories']['category']);
$this->assertCount(2, $xmlArray['shop']['categories']['category']);
$this->assertNotEmpty($xmlArray['shop']['offers']['offer']);
$this->assertCount(7, $xmlArray['shop']['offers']['offer']);
$this->assertNotEmpty($xmlArray['shop']['offers']['offer'][0]);
$this->assertNotEmpty($xmlArray['shop']['offers']['offer'][1]);
foreach ($xmlArray['shop']['offers']['offer'] as $product) {
$this->assertNotEmpty($product['name']);
$this->assertNotEmpty($product['productName']);
$this->assertNotEmpty($product['price']);
$this->assertNotEmpty($product['url']);
$this->assertNotEmpty($product['param']);
$this->assertNotEmpty($product['vatRate']);
$this->assertEquals('none', $product['vatRate']);
$this->assertContains('Dummy', $product['productName']);
}
}
}