isWooCommerceFollowup($followupId)) {
return $this->pluginDescription;
}
return null;
}
public function textPopup(): void
{
?>
'.acym_translation('ACYM_ORDER').'';
$orderFields = [
'billing_email',
'status',
'total_amount',
'date_created_gmt',
'date_updated_gmt',
'date_completed',
'date_paid',
'billing_address',
'shipping_address',
'first_name',
'last_name',
'phone',
];
foreach ($orderFields as $orderFieldName) {
$text .= '
';
}
echo wp_kses(
$text,
[
'h1' => ['class' => []],
'div' => ['class' => [], 'onclick' => []],
]
);
}
public function replaceOrderInformation(object &$email, object &$user, bool $send = true)
{
$extractedTags = $this->pluginHelper->extractTags($email, 'wootag');
if (empty($extractedTags)) {
return;
}
$mailClass = new MailClass();
$queueClass = new QueueClass();
$params = $queueClass->getQueueParams($mailClass->getMainMailId($email->id), $user->id);
if (empty($params)) {
return;
}
$orderId = $params['woo_order_id'] ?? null;
if (empty($orderId)) {
return;
}
$order = wc_get_order($orderId);
if (empty($order)) {
return;
}
$tags = [];
$productTags = $this->processTags($order, $extractedTags);
$tags = array_merge($tags, $productTags);
$this->pluginHelper->replaceTags($email, $tags);
}
private function processTags(object $order, array $extractedTags): array
{
$tags = [];
foreach ($extractedTags as $tagKey => $oneTag) {
$field = $oneTag->id;
$value = $oneTag->default;
switch ($field) {
case 'billing_address':
$value = $order->get_formatted_billing_address();
break;
case 'shipping_address':
$value = $order->get_formatted_shipping_address();
break;
case 'date_created_gmt':
$value = $order->get_date_created() ? acym_date($order->get_date_created(), 'Y-m-d H:i:s', false) : null;
break;
case 'date_updated_gmt':
$value = $order->get_date_modified() ? acym_date($order->get_date_modified(), 'Y-m-d H:i:s', false) : null;
break;
case 'date_completed':
$value = $order->get_date_completed() ? acym_date($order->get_date_completed(), 'Y-m-d H:i:s', false) : null;
break;
case 'date_paid':
$value = $order->get_date_paid() ? acym_date($order->get_date_paid(), 'Y-m-d H:i:s', false) : null;
break;
case 'billing_email':
$value = $order->get_billing_email();
break;
case 'status':
$value = $order->get_status();
break;
case 'total_amount':
$currency = $order->get_currency();
$value = wc_price($order->get_total(), $currency);
break;
case 'first_name':
$value = $order->get_billing_first_name();
break;
case 'last_name':
$value = $order->get_billing_last_name();
break;
case 'phone':
$value = $order->get_billing_phone();
break;
default:
if (method_exists($order, "get_{$field}")) {
$value = $order->{"get_{$field}"}();
}
break;
}
$this->pluginHelper->formatString($value, $oneTag);
// Key on the tag as it was found, rebuilding it from the id alone would miss its parameters
$tags[$tagKey] = $value;
}
return $tags;
}
public function getStandardStructure(string &$customView): void
{
$tag = new stdClass();
$tag->id = 0;
$format = new stdClass();
$format->tag = $tag;
$format->title = '{title}';
$format->afterTitle = '{price}
{picthtml}';
$format->afterArticle = '';
$format->imagePath = '';
$format->description = '{shortdesc}';
$format->link = '{link}';
$format->customFields = [];
$customView = ''.$this->pluginHelper->getStandardDisplay($format).'
';
}
public function initReplaceOptionsCustomView(): void
{
$this->replaceOptions = [
'link' => ['ACYM_LINK'],
'picthtml' => ['ACYM_IMAGE'],
];
}
public function initElementOptionsCustomView(): void
{
$query = 'SELECT product.*
FROM #__posts AS product
WHERE product.post_type = "product"
AND product.post_status = "publish"';
$element = acym_loadObject($query);
if (empty($element)) return;
foreach ($element as $key => $value) {
$this->elementOptions[$key] = [$key];
}
}
public function insertionOptions(?object $defaultValues = null): void
{
if (empty($defaultValues)) {
$defaultValues = new stdClass();
}
$this->defaultValues = $defaultValues;
$this->prepareWPCategories('product_cat');
$this->tagvalues = acym_loadObjectList(
'SELECT tax.term_taxonomy_id, term.`name`
FROM #__terms AS term
JOIN #__term_taxonomy AS tax ON term.term_id = tax.term_id
WHERE tax.taxonomy = "product_tag"
ORDER BY term.`name`'
);
$wooCategories = [];
foreach ($this->categories as $oneCat) {
$wooCategories[$oneCat->id] = $oneCat->title;
}
$tabHelper = new TabHelper();
$identifier = $this->name;
$tabHelper->startTab(acym_translation('ACYM_ONE_BY_ONE'), !empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab);
$displayOptions = [
[
'title' => 'ACYM_DISPLAY',
'type' => 'checkbox',
'name' => 'display',
'options' => $this->displayOptions,
],
[
'title' => 'ACYM_CLICKABLE_TITLE',
'type' => 'boolean',
'name' => 'clickable',
'default' => true,
],
[
'title' => 'ACYM_CLICKABLE_IMAGE',
'type' => 'boolean',
'name' => 'clickableimg',
'default' => false,
],
[
'title' => 'ACYM_TRUNCATE',
'type' => 'intextfield',
'isNumber' => 1,
'name' => 'wrap',
'text' => 'ACYM_TRUNCATE_AFTER',
'default' => 0,
],
[
'title' => 'ACYM_DISPLAY_PICTURES',
'type' => 'pictures',
'name' => 'pictures',
],
];
$zoneContent = $this->getFilteringZone().$this->prepareListing();
$this->displaySelectionZone($zoneContent);
$this->pluginHelper->displayOptions($displayOptions, $identifier, 'individual', $this->defaultValues);
$tabHelper->endTab();
$identifier = 'auto'.$this->name;
$tabHelper->startTab(acym_translation('ACYM_BY_CATEGORY'), !empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab);
$catOptions = [
[
'title' => 'ACYM_ORDER_BY',
'type' => 'select',
'name' => 'order',
'options' => [
'ID' => 'ACYM_ID',
'post_date' => 'ACYM_PUBLISHING_DATE',
'post_modified' => 'ACYM_MODIFICATION_DATE',
'post_title' => 'ACYM_TITLE',
'menu_order' => 'ACYM_MENU_ORDER',
'rand' => 'ACYM_RANDOM',
],
],
];
$this->autoContentOptions($catOptions);
$this->autoCampaignOptions($catOptions);
$displayOptions = array_merge($displayOptions, $catOptions);
$this->displaySelectionZone($this->getCategoryListing());
$this->pluginHelper->displayOptions($displayOptions, $identifier, 'grouped', $this->defaultValues);
$tabHelper->endTab();
$identifier = $this->name.'_tags';
$tabHelper->startTab(acym_translation('ACYM_BY_TAG'), !empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab);
$this->displaySelectionZone($this->getTagListing());
$this->pluginHelper->displayOptions($displayOptions, $identifier, 'grouped', $this->defaultValues);
$tabHelper->endTab();
$identifier = $this->name.'_coupon';
$tabHelper->startTab(acym_translation('ACYM_COUPON'), !empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab);
$displayOptions = [
[
'title' => 'ACYM_DISCOUNT_CODE',
'type' => 'text',
'name' => 'code',
'default' => '[name][key][value]',
'class' => 'acym_plugin__larger_text_field',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Coupon expiry date', 'woocommerce'),
'type' => 'date',
'name' => 'end',
'default' => '',
'relativeDate' => '+',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Discount type', 'woocommerce'),
'type' => 'select',
'name' => 'type',
'options' => [
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'fixed_cart' => __('Fixed cart discount', 'woocommerce'),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'fixed_product' => __('Fixed product discount', 'woocommerce'),
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'percent' => __('Percentage discount', 'woocommerce'),
],
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Coupon amount', 'woocommerce'),
'type' => 'number',
'name' => 'amount',
'default' => '0',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Allow free shipping', 'woocommerce'),
'type' => 'boolean',
'name' => 'free',
'default' => false,
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Exclude sale items', 'woocommerce'),
'type' => 'boolean',
'name' => 'exclsale',
'default' => false,
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Minimum spend', 'woocommerce'),
'type' => 'number',
'name' => 'min',
'default' => '',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Maximum spend', 'woocommerce'),
'type' => 'number',
'name' => 'max',
'default' => '',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Usage limit per coupon', 'woocommerce'),
'type' => 'number',
'name' => 'use',
'default' => '1',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Limit usage to X items', 'woocommerce'),
'type' => 'number',
'name' => 'items',
'default' => '',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Products', 'woocommerce'),
'type' => 'text',
'name' => 'prod',
'class' => 'acym_plugin__larger_text_field',
'default' => '',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Exclude products', 'woocommerce'),
'type' => 'text',
'name' => 'exclprod',
'class' => 'acym_plugin__larger_text_field',
'default' => '',
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Product categories', 'woocommerce'),
'type' => 'multiselect',
'name' => 'cat',
'options' => $wooCategories,
],
[
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'title' => __('Exclude categories', 'woocommerce'),
'type' => 'multiselect',
'name' => 'exclcat',
'options' => $wooCategories,
],
];
$this->pluginHelper->displayOptions($displayOptions, $identifier, 'simple', $this->defaultValues);
$tabHelper->endTab();
$identifier = 'last'.$this->name;
$tabHelper->startTab(
acym_translation('ACYM_LAST_PURCHASED_PRODUCT'),
!empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab
);
$lastPurchasedOptions = [
[
'title' => 'ACYM_DISPLAY',
'type' => 'checkbox',
'name' => 'display',
'options' => $this->displayOptions,
],
[
'title' => 'ACYM_CLICKABLE_TITLE',
'type' => 'boolean',
'name' => 'clickable',
'default' => true,
],
[
'title' => 'ACYM_CLICKABLE_IMAGE',
'type' => 'boolean',
'name' => 'clickableimg',
'default' => false,
],
[
'title' => 'ACYM_TRUNCATE',
'type' => 'intextfield',
'isNumber' => 1,
'name' => 'wrap',
'text' => 'ACYM_TRUNCATE_AFTER',
'default' => 0,
],
[
'title' => 'ACYM_DISPLAY_PICTURES',
'type' => 'pictures',
'name' => 'pictures',
],
];
$this->displaySelectionZone($this->lastOrCartContentInsert('last'));
$this->pluginHelper->displayOptions($lastPurchasedOptions, $identifier, 'grouped', $this->defaultValues);
$tabHelper->endTab();
$followupTrigger = acym_getVar('string', 'followupTrigger');
if ($followupTrigger === 'woocommerce_purchase') {
$identifier = 'woocommerce_ordered';
$tabHelper->startTab(acym_translation('ACYM_BOUGHT_PRODUCT'), !empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab);
$boughtOptions = [
[
'title' => 'ACYM_DISPLAY',
'type' => 'checkbox',
'name' => 'display',
'options' => $this->displayOptions,
],
[
'title' => 'ACYM_CLICKABLE_TITLE',
'type' => 'boolean',
'name' => 'clickable',
'default' => true,
],
[
'title' => 'ACYM_CLICKABLE_IMAGE',
'type' => 'boolean',
'name' => 'clickableimg',
'default' => false,
],
[
'title' => 'ACYM_TRUNCATE',
'type' => 'intextfield',
'isNumber' => 1,
'name' => 'wrap',
'text' => 'ACYM_TRUNCATE_AFTER',
'default' => 0,
],
[
'title' => 'ACYM_DISPLAY_PICTURES',
'type' => 'pictures',
'name' => 'pictures',
],
[
'title' => 'ACYM_ORDER_BY',
'type' => 'select',
'name' => 'order',
'options' => [
'ID' => 'ACYM_ID',
'post_date' => 'ACYM_PUBLISHING_DATE',
'post_modified' => 'ACYM_MODIFICATION_DATE',
'post_title' => 'ACYM_TITLE',
'menu_order' => 'ACYM_MENU_ORDER',
'rand' => 'ACYM_RANDOM',
],
],
];
$this->pluginHelper->displayOptions($boughtOptions, $identifier, 'grouped', $this->defaultValues);
$tabHelper->endTab();
}
// Products in cart
$identifier = 'cart'.$this->name;
$tabHelper->startTab(
acym_translation('ACYM_CART_PRODUCTS'),
!empty($this->defaultValues->defaultPluginTab) && $identifier === $this->defaultValues->defaultPluginTab
);
$this->displaySelectionZone($this->lastOrCartContentInsert('cart'));
$this->pluginHelper->displayOptions($lastPurchasedOptions, $identifier, 'grouped', $this->defaultValues);
$tabHelper->endTab();
$tabHelper->display('plugin');
}
private function lastOrCartContentInsert($type = 'last')
{
if ($type === 'cart') {
$identifier = 'cart'.$this->name;
$partId = 'cart';
$endIdMin = 'min';
$endIdMax = 'max';
} else {
$identifier = 'last'.$this->name;
$partId = 'last__purchased';
$endIdMin = '';
$endIdMax = '';
}
$selectedArea = empty($this->defaultValues->id) ? [] : $this->getSelectedArea($this->defaultValues);
if (!isset($this->defaultValues->min) || (empty($this->defaultValues->min) && $this->defaultValues->min !== '0')) {
$this->defaultValues->min = $this->minProductDisplayLastPurchased;
}
if (!isset($this->defaultValues->max) || (empty($this->defaultValues->max) && $this->defaultValues->max !== '0')) {
$this->defaultValues->max = $this->maxProductDisplayLastPurchased;
}
ob_start();
?>
catvalues,
'cat',
$selectedArea,
[
'id' => 'acym__woocommerce__'.$partId.'__cat',
'onchange' => '_selectedRows'.$identifier.' = {}
for(let option of this.options){
if(option.selected) _selectedRows'.$identifier.'[option.value] = true;
}
updateDynamic'.$identifier.'();',
]
),
[
'select' => ['name' => [], 'id' => [], 'class' => [], 'multiple' => [], 'onchange' => []],
'option' => ['value' => [], 'selected' => [], 'disabled' => [], 'data-hidden' => []],
'optgroup' => ['label' => []],
]
);
?>
defaultValues->min_date) ? '' : $this->defaultValues->min_date,
'cell medium-6',
'onchange="addAdditionalInfo'.$identifier.'(\'min_date\', this.value)"'
),
SecurityHelper::ALLOWED_HTML_DATE
);
?>
querySelect = 'SELECT product.ID, product.post_title, product.post_date ';
$this->query = 'FROM #__posts AS product LEFT JOIN #__postmeta AS product_sku ON product.ID = product_sku.post_id AND product_sku.meta_key = "_sku" ';
$this->filters = [];
$this->filters[] = 'product.post_type = "product"';
$this->filters[] = 'product.post_status = "publish"';
$this->searchFields = ['product.ID', 'product.post_title', 'product_sku.meta_value'];
$this->pageInfo->order = 'product.ID';
$this->elementIdTable = 'product';
$this->elementIdColumn = 'ID';
parent::prepareListing();
if (!empty($this->pageInfo->filter_cat)) {
$this->query .= 'JOIN #__term_relationships AS cat ON product.ID = cat.object_id';
$this->filters[] = 'cat.term_taxonomy_id = '.intval($this->pageInfo->filter_cat);
}
$listingOptions = [
'header' => [
'post_title' => [
'label' => 'ACYM_TITLE',
'size' => '8',
],
'post_date' => [
'label' => 'ACYM_DATE_CREATED',
'size' => '3',
'type' => 'date',
],
'ID' => [
'label' => 'ACYM_ID',
'size' => '1',
'class' => 'text-center',
],
],
'id' => 'ID',
'rows' => $this->getElements(),
];
return $this->getElementsListing($listingOptions);
}
public function replaceContent(object &$email, bool $send = true): void
{
$this->replaceMultiple($email);
$this->replaceOne($email);
if ($send) $this->removeLastGeneratedPreview($email);
}
public function removeLastGeneratedPreview(&$email)
{
$tagsLast = $this->pluginHelper->extractTags($email, 'last'.$this->name);
$tagsCart = $this->pluginHelper->extractTags($email, 'cart'.$this->name);
$tags = array_merge($tagsLast, $tagsCart);
if (empty($tags)) return;
foreach ($tags as $tag => $parameter) {
$this->tags[$tag] = $tag;
}
$this->pluginHelper->replaceTags($email, $this->tags, true);
}
public function generateByCategory(object &$email): object
{
$tags = $this->pluginHelper->extractTags($email, 'auto'.$this->name);
$tags = array_merge($tags, $this->pluginHelper->extractTags($email, $this->name.'_tags'));
$this->tags = [];
if (empty($tags)) return $this->generateCampaignResult;
foreach ($tags as $oneTag => $parameter) {
if (isset($this->tags[$oneTag])) continue;
$query = 'SELECT DISTINCT product.`ID`
FROM #__posts AS product
LEFT JOIN #__term_relationships AS cat ON product.ID = cat.object_id';
$where = [];
$selectedArea = $this->getSelectedArea($parameter);
if (!empty($selectedArea)) {
$where[] = 'cat.term_taxonomy_id IN ('.implode(',', $selectedArea).')';
}
$where[] = 'product.post_type = "product"';
$where[] = 'product.post_status = "publish"';
if (!empty($parameter->min_publish)) {
$parameter->min_publish = acym_date(acym_replaceDate($parameter->min_publish), 'Y-m-d H:i:s', false);
$where[] = 'product.post_date_gmt >= '.acym_escapeDB($parameter->min_publish);
}
if (!empty($parameter->onlynew)) {
$lastGenerated = $this->getLastGenerated($email->id);
if (!empty($lastGenerated)) {
$where[] = 'product.post_date_gmt > '.acym_escapeDB(acym_date($lastGenerated, 'Y-m-d H:i:s', false));
}
}
$query .= ' WHERE ('.implode(') AND (', $where).')';
$this->tags[$oneTag] = $this->finalizeCategoryFormat($query, $parameter, 'product');
}
return $this->generateCampaignResult;
}
public function replaceIndividualContent(object $tag): string
{
$query = 'SELECT product.*
FROM #__posts AS product
WHERE product.post_type = "product"
AND product.post_status = "publish"
AND product.ID = '.intval($tag->id);
$element = $this->initIndividualContent($tag, $query);
$product = wc_get_product($tag->id);
if (empty($element) || empty($product)) return '';
$varFields = $this->getCustomLayoutVars($element);
$link = get_permalink($element->ID);
$varFields['{link}'] = $link;
$title = '';
$varFields['{title}'] = $element->post_title;
if (in_array('title', $tag->display)) $title = $varFields['{title}'];
$afterTitle = '';
$varFields['{price}'] = $product->get_price_html();
if (in_array('price', $tag->display)) $afterTitle .= $varFields['{price}'];
$imagePath = '';
$imageHTML = $product->get_image('full');
if (!empty($imageHTML)) {
$posURL = strpos($imageHTML, ' src="') + 6;
$imagePath = substr($imageHTML, $posURL, strpos($imageHTML, '"', $posURL) - $posURL);
}
// phpcs:ignore PluginCheck.CodeAnalysis.ImageFunctions.NonEnqueuedImage
$varFields['{picthtml}'] = '
';
if (empty($tag->pict)) $imagePath = '';
$contentText = '';
$varFields['{shortdesc}'] = $element->post_excerpt;
$varFields['{desc}'] = $this->cleanExtensionContent($element->post_content);
if (in_array('shortdesc', $tag->display)) $contentText .= $varFields['{shortdesc}'];
if (in_array('desc', $tag->display)) $contentText .= $varFields['{desc}'];
$customFields = [];
$varFields['{cats}'] = get_the_term_list($tag->id, 'product_cat', '', ', ');
if (in_array('cats', $tag->display)) {
$customFields[] = [
$varFields['{cats}'],
acym_translation('ACYM_CATEGORIES'),
];
}
$tmpCustomField = [];
$varFields['{attribs}'] = '';
$attributes = acym_loadResult('SELECT meta_value FROM #__postmeta WHERE meta_key = "_product_attributes" AND post_id = '.intval($tag->id));
if (is_string($attributes)) {
$attributes = unserialize($attributes);
if (!empty($attributes)) {
$varFields['{attribs}'] = [];
foreach ($attributes as $oneAttribute) {
if ($oneAttribute['is_visible'] != 1) continue;
$varFields['{attribs}'][] = $oneAttribute['name'].': '.str_replace('|', ', ', $oneAttribute['value']);
$tmpCustomField[] = [
str_replace('|', ', ', $oneAttribute['value']),
$oneAttribute['name'],
];
}
$varFields['{attribs}'] = implode('
', $varFields['{attribs}']);
}
}
if (in_array('attribs', $tag->display)) $customFields = array_merge($customFields, $tmpCustomField);
$format = new stdClass();
$format->tag = $tag;
$format->title = $title;
$format->afterTitle = $afterTitle;
$format->afterArticle = '';
$format->imagePath = $imagePath;
$format->description = $contentText;
$format->link = empty($tag->clickable) && empty($tag->clickableimg) ? '' : $link;
$format->customFields = $customFields;
$result = ''.$this->pluginHelper->getStandardDisplay($format).'
';
return $this->finalizeElementFormat($result, $tag, $varFields);
}
public function replaceUserInformation(object &$email, ?object &$user, bool $send = true): array
{
if (empty($user)) {
return [];
}
$this->replaceCoupons($email, $user, $send);
$this->replaceOrderInformation($email, $user, $send);
$this->replaceOrderedProducts($email, $user);
$generated = $this->replaceLastPurchased($email, $user, $send);
if ($generated === '' && (!isset($email->isTest) || $email->isTest !== true)) {
return [
'send' => false,
'emogrifier' => false,
'message' => acym_translationSprintf('ACYM_EMAIL_X_NOT_SENT_USER_X_NOT_BOUGHT_ENOUGH_PRODUCTS', $email->subject, $user->email),
];
}
$generatedCart = $this->replaceCart($email, $user, $send);
if ($generatedCart === '' && (!isset($email->isTest) || $email->isTest !== true)) {
return [
'send' => false,
'emogrifier' => false,
'message' => acym_translationSprintf('ACYM_EMAIL_X_NOT_SENT_USER_X_NOT_PRODUCTS_IN_CART', $email->subject, $user->email),
];
}
if ($generated == 1 || $generatedCart == 1) {
return ['send' => true, 'emogrifier' => true];
}
return [];
}
private function replaceLastPurchased(&$email, $user, $send)
{
$tags = $this->pluginHelper->extractTags($email, 'last'.$this->name);
$tags = array_merge($tags, $this->pluginHelper->extractTags($email, $this->name.'_tags'));
if (empty($tags)) {
return 0;
}
$this->tags = [];
foreach ($tags as $oneTag => $parameter) {
$minAtO = isset($parameter->min) && $parameter->min == 0;
//We get the lastest orders
if ($this->isHposActive()) {
$postTypesOrder = wc_get_order_types();
$postTypesOrder = array_map('acym_escapeDB', $postTypesOrder);
$postStatusesOrder = wc_get_is_paid_statuses();
$postStatusesOrder = array_map(function ($status) {
return 'wc-'.$status;
}, $postStatusesOrder);
$postStatusesOrder = array_map('acym_escapeDB', $postStatusesOrder);
$query = 'SELECT `order`.id AS ID
FROM #__wc_orders AS `order`
WHERE `order`.type IN ('.implode(',', $postTypesOrder).')
AND `order`.status IN ('.implode(',', $postStatusesOrder).') ';
$userFilter = '`order`.billing_email = '.acym_escapeDB($user->email);
if (!empty($user->cms_id)) {
$userFilter = '(`order`.customer_id = '.intval($user->cms_id).' OR '.$userFilter.') ';
}
$query .= ' AND '.$userFilter;
if (!empty($parameter->min_date)) {
$query .= ' AND `order`.date_created_gmt > '.acym_escapeDB(acym_date(acym_replaceDate($parameter->min_date), 'Y-m-d', false));
}
$customerOrders = acym_loadObjectList($query);
} else {
$userFilter = [
[
'key' => '_billing_email',
'value' => $user->email,
'compare' => '=',
],
];
if (!empty($user->cms_id)) {
$userFilter = array_merge(
[
'relation' => 'OR',
[
'key' => '_customer_user',
'value' => intval($user->cms_id),
'compare' => '=',
],
],
$userFilter
);
}
$postStatusesOrder = wc_get_is_paid_statuses();
$postStatusesOrder = array_map(function ($status) {
return 'wc-'.$status;
}, $postStatusesOrder);
$dataQuery = [
'numberposts' => -1,
'post_type' => wc_get_order_types(),
'post_status' => $postStatusesOrder,
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
'meta_query' => $userFilter,
];
if (!empty($parameter->min_date)) {
$minDate = acym_replaceDate($parameter->min_date);
$dataQuery['date_query'] = [
'after' => gmdate('Y-m-d', $minDate),
];
}
$customerOrders = get_posts($dataQuery);
}
if (empty($customerOrders)) {
$this->tags[$oneTag] = $minAtO ? '_EMPTYSEND_' : '';
continue;
}
//We get the products from the orders
$product_ids = [];
foreach ($customerOrders as $customerOrder) {
$order = wc_get_order($customerOrder->ID);
$items = $order->get_items();
foreach ($items as $item) {
$product_id = $item->get_product_id();
$product_ids[] = $product_id;
}
}
$query = 'SELECT DISTINCT product.`ID` FROM #__posts AS product ';
//We filters the products if we selected categories
if (!empty($parameter->id)) {
$selectedArea = $this->getSelectedArea($parameter);
if (!empty($selectedArea)) {
$product_ids = array_unique($product_ids);
acym_arrayToInteger($selectedArea);
$query .= ' JOIN #__term_relationships AS cat ON product.ID = cat.object_id
AND cat.term_taxonomy_id IN ('.implode(',', $selectedArea).')';
}
}
acym_arrayToInteger($product_ids);
$query .= ' WHERE product.ID IN ('.implode(',', $product_ids).')';
if ($send) {
$parameter->min = empty($parameter->min) && !$minAtO ? $this->minProductDisplayLastPurchased : $parameter->min;
} else {
$parameter->min = 0;
}
$parameter->max = empty($parameter->max) ? $this->maxProductDisplayLastPurchased : $parameter->max;
$this->tags[$oneTag] = $this->finalizeCategoryFormat($query, $parameter, 'product');
if ($this->generateCampaignResult->status == false && $send) $this->tags[$oneTag] = '';
}
$emptyTags = true;
$nbEmptySend = 0;
foreach ($this->tags as $i => $tag) {
if ($tag == '_EMPTYSEND_') {
$nbEmptySend++;
$this->tags[$i] = '';
}
if (!empty($tag)) {
$emptyTags = false;
}
}
$this->pluginHelper->replaceTags($email, $this->tags, true);
if (count($this->tags) == $nbEmptySend) return 0;
if ($emptyTags) return '';
$this->replaceOne($email);
return 1;
}
private function replaceOrderedProducts(object &$email, object &$user)
{
$tags = $this->pluginHelper->extractTags($email, 'woocommerce_ordered');
if (empty($tags)) {
return;
}
$tagsReplaced = [];
foreach ($tags as $i => $oneTag) {
if (isset($tagsReplaced[$i])) {
continue;
}
$tagsReplaced[$i] = $this->replaceOrderedProduct($oneTag, $user, $email);
}
$this->pluginHelper->replaceTags($email, $tagsReplaced, true);
$this->replaceOne($email);
}
private function replaceOrderedProduct(object $oneTag, object $user, object $email): string
{
if (empty($user->cms_id)) {
return '';
}
$queueClass = new QueueClass();
$mailClass = new MailClass();
$params = $queueClass->getQueueParams($mailClass->getMainMailId($email->id), $user->id);
$orderId = $params['woo_order_id'] ?? null;
if (empty($orderId)) {
//We get one random product
$query = 'SELECT product.`ID` FROM #__posts AS product WHERE product.post_type = "product" AND product.post_status = "publish" AND product.`ID` IS NOT NULL';
$oneTag->max = 1;
} else {
//We get the products from the orders
$product_ids = [];
$order = wc_get_order($orderId);
foreach ($order->get_items() as $item_id => $item) {
$product_id = $item->get_product_id();
$product_ids[] = $product_id;
}
$query = 'SELECT DISTINCT product.`ID` FROM #__posts AS product ';
$query .= ' WHERE product.ID IN ('.implode(',', $product_ids).')';
}
return $this->finalizeCategoryFormat($query, $oneTag, 'product');
}
private function replaceCart(&$email, $user, $send)
{
$tags = $this->pluginHelper->extractTags($email, 'cart'.$this->name);
$tags = array_merge($tags, $this->pluginHelper->extractTags($email, $this->name.'_tags'));
if (empty($tags)) return 0;
// Get user session
$sessionHandler = new \WC_Session_Handler();
$session = $sessionHandler->get_session(empty($user->cms_id) ? 0 : $user->cms_id);
$cart_items = maybe_unserialize($session['cart']);
$this->tags = [];
$noItems = empty($cart_items);
foreach ($tags as $oneTag => $parameter) {
$minAtO = isset($parameter->min) && $parameter->min == 0;
if ((empty($user->cms_id) || $noItems) && !$minAtO) {
$this->tags[$oneTag] = '';
continue;
}
if ($minAtO && $noItems) {
$this->tags[$oneTag] = '_EMPTYSEND_';
continue;
}
$product_ids = [];
foreach ($cart_items as $oneItem) {
$product_ids[] = $oneItem['product_id'];
}
$query = 'SELECT DISTINCT product.`ID` FROM #__posts AS product ';
//We filters the products if we selected categories
if (!empty($parameter->id)) {
$selectedArea = $this->getSelectedArea($parameter);
if (!empty($selectedArea)) {
$product_ids = array_unique($product_ids);
acym_arrayToInteger($selectedArea);
$query .= ' JOIN #__term_relationships AS cat ON product.ID = cat.object_id
AND cat.term_taxonomy_id IN ('.implode(',', $selectedArea).')';
}
}
acym_arrayToInteger($product_ids);
$query .= ' WHERE product.ID IN ('.implode(',', $product_ids).')';
if ($send) {
$parameter->min = empty($parameter->min) && !$minAtO ? $this->minProductDisplayLastPurchased : $parameter->min;
} else {
$parameter->min = 0;
}
$parameter->max = empty($parameter->max) ? $this->maxProductDisplayLastPurchased : $parameter->max;
$this->tags[$oneTag] = $this->finalizeCategoryFormat($query, $parameter, 'product');
if ($this->generateCampaignResult->status == false && $send) $this->tags[$oneTag] = '';
}
$emptyTags = true;
$nbEmptySend = 0;
foreach ($this->tags as $i => $tag) {
if ($tag == '_EMPTYSEND_') {
$nbEmptySend++;
$this->tags[$i] = '';
}
if (!empty($tag)) {
$emptyTags = false;
}
}
$this->pluginHelper->replaceTags($email, $this->tags, true);
if (count($this->tags) == $nbEmptySend) return 0;
if ($emptyTags) return '';
$this->replaceOne($email);
return 1;
}
private function replaceCoupons(&$email, &$user, $send = true)
{
$tags = $this->pluginHelper->extractTags($email, 'woocommerce_coupon');
if (empty($tags)) {
return;
}
$tagsReplaced = [];
foreach ($tags as $i => $oneTag) {
if (isset($tagsReplaced[$i])) {
continue;
}
if (!$send || empty($user->id)) {
$tagsReplaced[$i] = ''.acym_translation('ACYM_CHECK_EMAIL_COUPON').'';
} else {
$tagsReplaced[$i] = $this->generateCoupon($oneTag, $user);
}
}
$this->pluginHelper->replaceTags($email, $tagsReplaced, true);
}
private function generateCoupon($tag, $user)
{
if (empty($tag->code) || empty($tag->amount) || empty($tag->type) || !in_array($tag->type, ['fixed_cart', 'fixed_product', 'percent'])) return '';
$intAttributes = ['amount', 'free', 'min', 'max', 'exclsale', 'use', 'items'];
foreach ($intAttributes as $oneAttribute) {
if (empty($tag->$oneAttribute)) $tag->$oneAttribute = 0;
$tag->$oneAttribute = intval($tag->$oneAttribute);
}
if (empty($tag->amount)) return '';
$clean_name = strtoupper($user->name);
$space = strpos($clean_name, ' ');
if (!empty($space)) $clean_name = substr($clean_name, 0, $space);
$couponCode = str_replace(
[
'[name]',
'[userid]',
'[email]',
'[key]',
'[value]',
],
[
$clean_name,
$user->id,
$user->email,
acym_generateKey(5),
$tag->amount,
],
$tag->code
);
$coupon = [
'post_title' => $couponCode,
'post_content' => '',
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'shop_coupon',
];
$couponId = wp_insert_post($coupon);
// Add Details
update_post_meta($couponId, 'discount_type', $tag->type);
update_post_meta($couponId, 'coupon_amount', $tag->amount);
update_post_meta($couponId, 'expiry_date', empty($tag->end) ? '' : acym_date(acym_replaceDate($tag->end), 'Y-m-d'));
update_post_meta($couponId, 'date_expires', empty($tag->end) ? null : acym_replaceDate($tag->end));
update_post_meta($couponId, 'usage_limit', $tag->use);
update_post_meta($couponId, 'usage_limit_per_user', 0);
update_post_meta($couponId, 'limit_usage_to_x_items', $tag->items);
update_post_meta($couponId, 'usage_count', 0);
update_post_meta($couponId, 'minimum_amount', empty($tag->min) ? '' : $tag->min);
update_post_meta($couponId, 'maximum_amount', empty($tag->max) ? '' : $tag->max);
update_post_meta($couponId, 'free_shipping', empty($tag->free) ? 'no' : 'yes');
update_post_meta($couponId, 'exclude_sale_items', empty($tag->exclsale) ? 'no' : 'yes');
update_post_meta($couponId, 'product_ids', implode(',', $this->cleanElements($tag->prod)));
update_post_meta($couponId, 'exclude_product_ids', implode(',', $this->cleanElements($tag->exclprod)));
update_post_meta($couponId, 'product_categories', $this->cleanElements($tag->cat));
update_post_meta($couponId, 'exclude_product_categories', $this->cleanElements($tag->exclcat));
// Apply the coupon only to the current user
update_post_meta($couponId, 'individual_use', 'yes');
update_post_meta($couponId, 'customer_email', [$user->email]);
return $couponCode;
}
private function cleanElements($elements)
{
$elements = empty($elements) ? [] : explode(',', $elements);
acym_arrayToInteger($elements);
foreach ($elements as $i => $oneElement) {
if (empty($oneElement)) unset($elements[$i]);
}
return $elements;
}
private function isWooCommerceFollowup(int $followupId): bool
{
$followupClass = new FollowupClass();
$followup = $followupClass->getOneById($followupId);
if (!empty($followup->trigger) && $followup->trigger === 'woocommerce_purchase') {
return true;
}
return false;
}
}