Changeset 3381414
- Timestamp:
- 10/20/2025 03:35:43 PM (4 months ago)
- Location:
- insim/trunk
- Files:
-
- 86 added
- 8 edited
-
README.txt (modified) (1 diff)
-
admin/css/campaign-tabs-modern.css (added)
-
admin/css/sim-to-shop-filters-modern.css (added)
-
admin/css/sim-to-shop-filters.css (added)
-
admin/js/campaign-tabs-modern.js (added)
-
admin/js/sim-to-shop-filter-final.js (added)
-
admin/js/sim-to-shop-filter-manager-modern.js (added)
-
admin/js/sim-to-shop-filter-manager.js (added)
-
admin/js/sim-to-shop-filter-simple.js (added)
-
admin/models/sim-to-shop-campaign-model.php (modified) (6 diffs)
-
admin/models/sim-to-shop-filter-engine.php (added)
-
admin/partials/campaign-filter-interface-final.php (added)
-
admin/partials/campaign-filter-interface-modern.php (added)
-
admin/partials/campaign-filter-interface-simple.php (added)
-
admin/partials/campaign-filter-interface-ultimate-v2.php (added)
-
admin/partials/campaign-filter-interface-ultimate.php (added)
-
admin/partials/campaign-filter-interface.php (added)
-
admin/partials/html-admin-page.php (modified) (2 diffs)
-
admin/sim-to-shop-admin.php (modified) (2 diffs)
-
admin/sim-to-shop-ajax-handlers.php (added)
-
admin/sim-to-shop-generic-campaign-tab.php (modified) (16 diffs)
-
admin/sim-to-shop-send-tab.php (modified) (6 diffs)
-
coverage (added)
-
inSIM.php (modified) (6 diffs)
-
includes/sim-to-shop.php (modified) (1 diff)
-
insim.png (added)
-
public/LICENSE.txt (added)
-
public/README.txt (added)
-
public/admin (added)
-
public/admin/API_SMS_PHP_SimToShop (added)
-
public/admin/API_SMS_PHP_SimToShop/balance.php (added)
-
public/admin/API_SMS_PHP_SimToShop/campagne.php (added)
-
public/admin/API_SMS_PHP_SimToShop/config.inc.php (added)
-
public/admin/API_SMS_PHP_SimToShop/create_sub_account.php (added)
-
public/admin/API_SMS_PHP_SimToShop/credit_sub_account.php (added)
-
public/admin/API_SMS_PHP_SimToShop/edit_options.php (added)
-
public/admin/API_SMS_PHP_SimToShop/get_user_info.php (added)
-
public/admin/API_SMS_PHP_SimToShop/sim-to-shop_web_services.inc.php (added)
-
public/admin/API_SMS_PHP_SimToShop/sms.inc.php (added)
-
public/admin/API_SMS_PHP_SimToShop/sms_batch.php (added)
-
public/admin/API_SMS_PHP_SimToShop/sms_parts.php (added)
-
public/admin/css (added)
-
public/admin/css/font.css (added)
-
public/admin/css/jquery-ui.css (added)
-
public/admin/img (added)
-
public/admin/img/coming-soon-icon.webp (added)
-
public/admin/img/edit_trash.gif (added)
-
public/admin/img/information.png (added)
-
public/admin/img/no.png (added)
-
public/admin/img/solo_new.png (added)
-
public/admin/img/solo_new0.png (added)
-
public/admin/img/to_top.png (added)
-
public/admin/img/yes.png (added)
-
public/admin/index.php (added)
-
public/admin/js (added)
-
public/admin/js/sim-to-shop-admin.js (added)
-
public/admin/models (added)
-
public/admin/models/sim-to-shop-campaign-model.php (added)
-
public/admin/models/sim-to-shop-campaign.php (added)
-
public/admin/models/sim-to-shop-recipient.php (added)
-
public/admin/partials (added)
-
public/admin/partials/html-admin-page.php (added)
-
public/admin/partials/html-sim-to-shop-settings.php (added)
-
public/admin/sim-to-shop-admin.php (added)
-
public/admin/sim-to-shop-api.php (added)
-
public/admin/sim-to-shop-campaign-list.php (added)
-
public/admin/sim-to-shop-generic-campaign-tab.php (added)
-
public/admin/sim-to-shop-history-tab.php (added)
-
public/admin/sim-to-shop-messages.php (added)
-
public/admin/sim-to-shop-news.php (added)
-
public/admin/sim-to-shop-page.php (added)
-
public/admin/sim-to-shop-recipient-list.php (added)
-
public/admin/sim-to-shop-reports.php (added)
-
public/admin/sim-to-shop-send-tab.php (added)
-
public/admin/sim-to-shop-settings.php (added)
-
public/includes (added)
-
public/includes/index.php (added)
-
public/includes/sim-to-shop-activator.php (added)
-
public/includes/sim-to-shop-deactivator.php (added)
-
public/includes/sim-to-shop-i18n.php (added)
-
public/includes/sim-to-shop-loader.php (added)
-
public/includes/sim-to-shop.php (added)
-
public/languages (added)
-
public/public (added)
-
public/public/css (added)
-
public/public/css/font.css (added)
-
public/public/css/sim-to-shop-public.css (added)
-
public/public/index.php (added)
-
public/public/js (added)
-
public/public/js/sim-to-shop-public.js (added)
-
public/public/partials (added)
-
public/public/partials/sim-to-shop-public-display.php (added)
-
public/public/sim-to-shop-public.php (added)
-
public/uninstall.php (added)
Legend:
- Unmodified
- Added
- Removed
-
insim/trunk/README.txt
r3301645 r3381414 92 92 = 3.0.0 = 93 93 * Fix bugs in recipient list creation 94 95 = 4.0 = 96 * Add new criteria to create recipient list 97 * Update the design 98 * Add sms count and message preview in Campaign creation -
insim/trunk/admin/models/sim-to-shop-campaign-model.php
r3301630 r3381414 232 232 private function get_recipient_query($count = false) { 233 233 global $wpdb; 234 235 $query_select = "SELECT *, meta2.meta_value AS billing_phone, meta4.meta_value AS billing_country, meta6.meta_value AS billing_lastname, meta7.meta_value AS billing_firstname"236 . ", (SELECT COUNT(*) FROM $wpdb->posts post LEFT JOIN $wpdb->postmeta meta0 ON (meta0.post_id = post.ID) WHERE post.post_type='shop_order' AND meta0.meta_key='_customer_user' AND meta0.meta_value=wp_users.ID) AS order_nbr";237 234 235 $query_select = "SELECT DISTINCT wp_users.ID, wp_users.*, meta2.meta_value AS billing_phone, meta4.meta_value AS billing_country, meta6.meta_value AS billing_lastname, meta7.meta_value AS billing_firstname" 236 . ", (SELECT COUNT(*) FROM $wpdb->posts post LEFT JOIN $wpdb->postmeta meta0 ON (meta0.post_id = post.ID) WHERE post.post_type='shop_order' AND post.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold') AND meta0.meta_key='_customer_user' AND meta0.meta_value=wp_users.ID) AS order_nbr"; 237 238 238 if ($count) { 239 $query_select = "SELECT COUNT( *) AS total_rows";239 $query_select = "SELECT COUNT(DISTINCT wp_users.ID) AS total_rows"; 240 240 } 241 241 … … 274 274 // } 275 275 276 private function execute_recipient_query($query, $count = false, $countryCode = null) {276 private function execute_recipient_query($query, $count = false, $countryCodes = null) { 277 277 global $wpdb; 278 278 … … 291 291 $mergedResult = $mainResult; 292 292 293 // Only run the additional query if $countryCode is set and not empty 294 if (isset($countryCode) && $countryCode !== "") { 293 // Run additional query for country filters (finds customers from orders who don't have user accounts) 294 // Only run if we have country codes and it's a single country (to avoid complexity with multiple OR countries) 295 if (is_array($countryCodes) && count($countryCodes) === 1 && !empty($countryCodes[0])) { 296 $countryCode = $countryCodes[0]; 295 297 $additionalQuery = " 296 298 SELECT ID, 297 CONCAT_WS(' ', 299 CONCAT_WS(' ', 298 300 (SELECT meta_value FROM $wpdb->postmeta WHERE post_id = p.ID AND meta_key = '_billing_first_name' LIMIT 1), 299 301 (SELECT meta_value FROM $wpdb->postmeta WHERE post_id = p.ID AND meta_key = '_billing_last_name' LIMIT 1) … … 318 320 } 319 321 $mergedResult = $this->mergeResults($mainResult, $additionalResult); 322 323 if (WP_DEBUG) { 324 error_log("Additional order query ran for country: " . $countryCode); 325 } 326 } else if (is_array($countryCodes) && count($countryCodes) > 1) { 327 // Multiple countries with OR - skip additional query to avoid complexity 328 // The main query with DISTINCT should handle everything correctly 329 if (WP_DEBUG) { 330 error_log("Multiple countries detected (" . implode(', ', $countryCodes) . "), skipping additional order query"); 331 } 320 332 } 321 333 322 334 if (WP_DEBUG) { 323 error_log("Merged and Unique Result : " . print_r($mergedResult, true));335 error_log("Merged and Unique Result count: " . count($mergedResult)); 324 336 } 325 337 … … 371 383 } 372 384 373 374 385 /** 386 * Build SQL WHERE clause for a single filter 387 */ 388 private function build_filter_clause($field, $operator, $value, $value2, &$country_keys) { 389 global $wpdb; 390 391 // Sanitize inputs 392 $value = sanitize_text_field($value); 393 $value2 = sanitize_text_field($value2); 394 395 switch ($field) { 396 case 'country': 397 // Store country_keys as array for execute_recipient_query (used for additional order query) 398 if (!is_array($country_keys)) { 399 $country_keys = array(); 400 } 401 if (!in_array($value, $country_keys)) { 402 $country_keys[] = $value; 403 } 404 405 if ($operator === 'is') { 406 return "wp_users.ID IN ( 407 SELECT user_id FROM $wpdb->usermeta 408 WHERE (meta_key = 'billing_country' AND meta_value = '" . esc_sql($value) . "') 409 OR (meta_key = 'shipping_country' AND meta_value = '" . esc_sql($value) . "') 410 )"; 411 } elseif ($operator === 'is_not') { 412 return "wp_users.ID NOT IN ( 413 SELECT user_id FROM $wpdb->usermeta 414 WHERE (meta_key = 'billing_country' AND meta_value = '" . esc_sql($value) . "') 415 OR (meta_key = 'shipping_country' AND meta_value = '" . esc_sql($value) . "') 416 )"; 417 } 418 break; 419 420 case 'registration_date': 421 return $this->build_date_clause('wp_users.user_registered', $operator, $value, $value2); 422 423 case 'last_login': 424 return $this->build_date_clause('meta3.meta_value', $operator, $value, $value2); 425 426 case 'order_count': 427 $order_count_subquery = "(SELECT COUNT(*) FROM $wpdb->posts post 428 LEFT JOIN $wpdb->postmeta meta0 ON (meta0.post_id = post.ID) 429 WHERE post.post_type='shop_order' 430 AND post.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold') 431 AND meta0.meta_key='_customer_user' 432 AND meta0.meta_value=wp_users.ID)"; 433 434 if ($operator === 'equals') { 435 return "$order_count_subquery = " . intval($value); 436 } elseif ($operator === 'greater_than') { 437 return "$order_count_subquery > " . intval($value); 438 } elseif ($operator === 'less_than') { 439 return "$order_count_subquery < " . intval($value); 440 } elseif ($operator === 'between' && $value2) { 441 return "$order_count_subquery BETWEEN " . intval($value) . " AND " . intval($value2); 442 } 443 break; 444 445 case 'total_spent': 446 // Calculate total spent per customer 447 $total_spent_subquery = "(SELECT COALESCE(SUM(meta_total.meta_value), 0) FROM $wpdb->posts post 448 LEFT JOIN $wpdb->postmeta meta_customer ON (meta_customer.post_id = post.ID AND meta_customer.meta_key = '_customer_user') 449 LEFT JOIN $wpdb->postmeta meta_total ON (meta_total.post_id = post.ID AND meta_total.meta_key = '_order_total') 450 WHERE post.post_type = 'shop_order' 451 AND post.post_status IN ('wc-completed', 'wc-processing') 452 AND meta_customer.meta_value = wp_users.ID)"; 453 454 if ($operator === 'greater_than') { 455 return "$total_spent_subquery > " . floatval($value); 456 } elseif ($operator === 'less_than') { 457 return "$total_spent_subquery < " . floatval($value); 458 } elseif ($operator === 'between' && $value2) { 459 return "$total_spent_subquery BETWEEN " . floatval($value) . " AND " . floatval($value2); 460 } 461 break; 462 463 case 'average_order': 464 // Calculate average order value per customer 465 $avg_order_subquery = "(SELECT COALESCE(AVG(meta_total.meta_value), 0) FROM $wpdb->posts post 466 LEFT JOIN $wpdb->postmeta meta_customer ON (meta_customer.post_id = post.ID AND meta_customer.meta_key = '_customer_user') 467 LEFT JOIN $wpdb->postmeta meta_total ON (meta_total.post_id = post.ID AND meta_total.meta_key = '_order_total') 468 WHERE post.post_type = 'shop_order' 469 AND post.post_status IN ('wc-completed', 'wc-processing') 470 AND meta_customer.meta_value = wp_users.ID)"; 471 472 if ($operator === 'greater_than') { 473 return "$avg_order_subquery > " . floatval($value); 474 } elseif ($operator === 'less_than') { 475 return "$avg_order_subquery < " . floatval($value); 476 } elseif ($operator === 'between' && $value2) { 477 return "$avg_order_subquery BETWEEN " . floatval($value) . " AND " . floatval($value2); 478 } 479 break; 480 481 case 'last_order_date': 482 // Get the most recent order date for the customer 483 $last_order_subquery = "(SELECT MAX(post.post_date) FROM $wpdb->posts post 484 LEFT JOIN $wpdb->postmeta meta_customer ON (meta_customer.post_id = post.ID AND meta_customer.meta_key = '_customer_user') 485 WHERE post.post_type = 'shop_order' 486 AND post.post_status IN ('wc-completed', 'wc-processing', 'wc-on-hold') 487 AND meta_customer.meta_value = wp_users.ID)"; 488 489 return $this->build_date_clause($last_order_subquery, $operator, $value, $value2); 490 491 case 'email_domain': 492 if ($operator === 'is') { 493 return "wp_users.user_email LIKE '%" . esc_sql($value) . "'"; 494 } elseif ($operator === 'contains') { 495 return "wp_users.user_email LIKE '%" . esc_sql($value) . "%'"; 496 } elseif ($operator === 'not_contains') { 497 return "wp_users.user_email NOT LIKE '%" . esc_sql($value) . "%'"; 498 } 499 break; 500 501 case 'customer_role': 502 if ($operator === 'is') { 503 return "meta5.meta_value LIKE '%" . esc_sql($value) . "%'"; 504 } elseif ($operator === 'is_not') { 505 return "meta5.meta_value NOT LIKE '%" . esc_sql($value) . "%'"; 506 } 507 break; 508 } 509 510 return null; 511 } 512 513 /** 514 * Build date-based WHERE clause 515 */ 516 private function build_date_clause($field_expression, $operator, $value, $value2) { 517 global $wpdb; 518 519 if ($operator === 'between' && $value && $value2) { 520 $date1 = date('Y-m-d 00:00:00', strtotime($value)); 521 $date2 = date('Y-m-d 23:59:59', strtotime($value2)); 522 return "DATE($field_expression) BETWEEN '" . esc_sql($date1) . "' AND '" . esc_sql($date2) . "'"; 523 } elseif ($operator === 'before' && $value) { 524 $date = date('Y-m-d 00:00:00', strtotime($value)); 525 return "DATE($field_expression) < '" . esc_sql($date) . "'"; 526 } elseif ($operator === 'after' && $value) { 527 $date = date('Y-m-d 23:59:59', strtotime($value)); 528 return "DATE($field_expression) > '" . esc_sql($date) . "'"; 529 } elseif ($operator === 'in_last_days' && $value) { 530 $days = intval($value); 531 return "DATE($field_expression) >= DATE_SUB(CURDATE(), INTERVAL $days DAY)"; 532 } elseif ($operator === 'older_than_days' && $value) { 533 $days = intval($value); 534 return "DATE($field_expression) < DATE_SUB(CURDATE(), INTERVAL $days DAY)"; 535 } 536 537 return null; 538 } 375 539 376 540 /** … … 381 545 if (WP_DEBUG) 382 546 error_log("Request: " . print_r($_REQUEST, true)); 383 //the query 384 547 548 // Get base query 385 549 $query = $this->get_recipient_query($count); 386 387 550 $query_where = ""; 388 //take parameter into account 389 $post = sanitize_post($_REQUEST); 390 391 $register_format = $lastvisit_format = '%Y-%m-%d'; 392 //if only year is checked 393 if (isset($post['sendsms_query_registered_years'])) 394 $register_format = '%m-%d'; 395 if (isset($post['sendsms_query_connected_years'])) 396 $lastvisit_format = '%m-%d'; 397 398 if ($post['sendsms_query_country'] && !empty($post['sendsms_query_country'])) { 399 $country_code = sanitize_text_field($post['sendsms_query_country']); 400 $country_data = explode('|', sanitize_text_field($post['sendsms_query_country'])); 401 $country_key = $country_data[0]; 402 $country_value = strtoupper($country_data[1]); 403 $query_where .= " AND ID IN ( 404 SELECT user_id FROM $wpdb->usermeta 405 WHERE (meta_key = 'billing_country' AND meta_value = '$country_key') 406 OR (meta_key = 'shipping_country' AND UPPER(meta_value) = '$country_key') 407 )"; 408 } 409 410 if ($post['sendsms_query_registered_from']) { 411 $date = strtotime($post['sendsms_query_registered_from'] . ' 00:00:00'); 412 $date = date_i18n('Y-m-d H:i:s', $date); 413 $query_where .= ' AND ( DATE_FORMAT(wp_users.user_registered , \'' . $register_format . '\') >= DATE_FORMAT(\'' . $date . '\', \'' . $register_format . '\') ) '; 414 } 415 if ($post['sendsms_query_registered_to']) { 416 $date = strtotime($post['sendsms_query_registered_to'] . ' 00:00:00'); 417 $date = date_i18n('Y-m-d H:i:s', $date); 418 $query_where .= ' AND ( DATE_FORMAT(wp_users.user_registered , \'' . $register_format . '\') <= DATE_FORMAT(\'' . $date . '\', \'' . $register_format . '\') ) '; 419 } 420 //TODO finish with others parameters 421 if ($post['sendsms_query_connected_from']) { 422 $date = strtotime($post['sendsms_query_connected_from'] . ' 00:00:00'); 423 $date = date_i18n('Y-m-d H:i:s', $date); 424 $query_where .= ' AND ( DATE_FORMAT(meta3.meta_value , \'' . $register_format . '\') >= DATE_FORMAT(\'' . $date . '\', \'' . $lastvisit_format . '\') ) '; 425 } 426 if ($post['sendsms_query_connected_to']) { 427 $date = strtotime($post['sendsms_query_connected_to'] . ' 00:00:00'); 428 $date = date_i18n('Y-m-d H:i:s', $date); 429 $query_where .= ' AND ( DATE_FORMAT(meta3.meta_value , \'' . $register_format . '\') <= DATE_FORMAT(\'' . $date . '\', \'' . $lastvisit_format . '\') ) '; 430 } 431 432 //order number 433 if ((isset($post['sendsms_query_orders_from']) && !empty($post['sendsms_query_orders_from'])) 434 || (isset($post['sendsms_query_orders_to']) && !empty($post['sendsms_query_orders_to'])) 435 || (isset($post['sendsms_query_orders_none'])) && !empty($post['sendsms_query_orders_none'])) { 436 $query_where .= ' AND ('; 437 438 if ($post['sendsms_query_orders_from']) { 551 $country_keys = array(); 552 553 // Check if we have dynamic filters 554 if (isset($_REQUEST['dynamic_filters']) && !empty($_REQUEST['dynamic_filters'])) { 555 // NEW: Process dynamic filter structure 556 $dynamic_filters = json_decode(stripslashes($_REQUEST['dynamic_filters']), true); 557 558 if (WP_DEBUG) { 559 error_log("Dynamic filters received: " . print_r($dynamic_filters, true)); 560 } 561 562 if ($dynamic_filters && isset($dynamic_filters['groups']) && is_array($dynamic_filters['groups'])) { 563 $group_clauses = array(); 564 $group_operators = isset($dynamic_filters['group_operators']) ? $dynamic_filters['group_operators'] : array(); 565 566 foreach ($dynamic_filters['groups'] as $group_index => $group) { 567 if (!isset($group['filters']) || !is_array($group['filters']) || empty($group['filters'])) { 568 continue; 569 } 570 571 $filter_clauses = array(); 572 573 foreach ($group['filters'] as $filter) { 574 $field = isset($filter['field']) ? $filter['field'] : ''; 575 $operator = isset($filter['operator']) ? $filter['operator'] : ''; 576 $value = isset($filter['value']) ? $filter['value'] : ''; 577 $value2 = isset($filter['value2']) ? $filter['value2'] : ''; 578 579 if (empty($field) || empty($operator)) { 580 continue; 581 } 582 583 $clause = $this->build_filter_clause($field, $operator, $value, $value2, $country_keys); 584 if ($clause) { 585 $filter_clauses[] = $clause; 586 } 587 } 588 589 // Combine filters within group using AND 590 if (!empty($filter_clauses)) { 591 $group_clauses[] = '(' . implode(' AND ', $filter_clauses) . ')'; 592 } 593 } 594 595 // Combine groups using their operators (AND/OR) 596 if (!empty($group_clauses)) { 597 if (count($group_clauses) === 1) { 598 $query_where = ' AND ' . $group_clauses[0]; 599 } else { 600 $combined = $group_clauses[0]; 601 for ($i = 1; $i < count($group_clauses); $i++) { 602 $operator_between_groups = isset($group_operators[$i - 1]) ? strtoupper($group_operators[$i - 1]) : 'AND'; 603 if ($operator_between_groups !== 'AND' && $operator_between_groups !== 'OR') { 604 $operator_between_groups = 'AND'; 605 } 606 $combined .= ' ' . $operator_between_groups . ' ' . $group_clauses[$i]; 607 } 608 $query_where = ' AND (' . $combined . ')'; 609 } 610 } 611 } 612 } else { 613 // LEGACY: Process old-style static filters (for backward compatibility) 614 $post = sanitize_post($_REQUEST); 615 $register_format = $lastvisit_format = '%Y-%m-%d'; 616 617 if (isset($post['sendsms_query_registered_years'])) 618 $register_format = '%m-%d'; 619 if (isset($post['sendsms_query_connected_years'])) 620 $lastvisit_format = '%m-%d'; 621 622 if ($post['sendsms_query_country'] && !empty($post['sendsms_query_country'])) { 623 $country_code = sanitize_text_field($post['sendsms_query_country']); 624 $country_data = explode('|', sanitize_text_field($post['sendsms_query_country'])); 625 $country_key = $country_data[0]; 626 $country_value = strtoupper($country_data[1]); 627 $query_where .= " AND ID IN ( 628 SELECT user_id FROM $wpdb->usermeta 629 WHERE (meta_key = 'billing_country' AND meta_value = '$country_key') 630 OR (meta_key = 'shipping_country' AND UPPER(meta_value) = '$country_key') 631 )"; 632 } 633 634 if ($post['sendsms_query_registered_from']) { 635 $date = strtotime($post['sendsms_query_registered_from'] . ' 00:00:00'); 636 $date = date_i18n('Y-m-d H:i:s', $date); 637 $query_where .= ' AND ( DATE_FORMAT(wp_users.user_registered , \'' . $register_format . '\') >= DATE_FORMAT(\'' . $date . '\', \'' . $register_format . '\') ) '; 638 } 639 if ($post['sendsms_query_registered_to']) { 640 $date = strtotime($post['sendsms_query_registered_to'] . ' 00:00:00'); 641 $date = date_i18n('Y-m-d H:i:s', $date); 642 $query_where .= ' AND ( DATE_FORMAT(wp_users.user_registered , \'' . $register_format . '\') <= DATE_FORMAT(\'' . $date . '\', \'' . $register_format . '\') ) '; 643 } 644 645 if ($post['sendsms_query_connected_from']) { 646 $date = strtotime($post['sendsms_query_connected_from'] . ' 00:00:00'); 647 $date = date_i18n('Y-m-d H:i:s', $date); 648 $query_where .= ' AND ( DATE_FORMAT(meta3.meta_value , \'' . $register_format . '\') >= DATE_FORMAT(\'' . $date . '\', \'' . $lastvisit_format . '\') ) '; 649 } 650 if ($post['sendsms_query_connected_to']) { 651 $date = strtotime($post['sendsms_query_connected_to'] . ' 00:00:00'); 652 $date = date_i18n('Y-m-d H:i:s', $date); 653 $query_where .= ' AND ( DATE_FORMAT(meta3.meta_value , \'' . $register_format . '\') <= DATE_FORMAT(\'' . $date . '\', \'' . $lastvisit_format . '\') ) '; 654 } 655 656 if ((isset($post['sendsms_query_orders_from']) && !empty($post['sendsms_query_orders_from'])) 657 || (isset($post['sendsms_query_orders_to']) && !empty($post['sendsms_query_orders_to'])) 658 || (isset($post['sendsms_query_orders_none'])) && !empty($post['sendsms_query_orders_none'])) { 659 $query_where .= ' AND ('; 660 661 if ($post['sendsms_query_orders_from']) { 662 if ($post['sendsms_query_orders_to']) { 663 $query_where .= ' ( '; 664 } 665 $query_where .= " (select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) >= " . $post['sendsms_query_orders_from']; 666 } 439 667 if ($post['sendsms_query_orders_to']) { 440 $query_where .= ' ( '; 441 } 442 $query_where .= " (select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) >= " . $post['sendsms_query_orders_from']; 443 } 444 if ($post['sendsms_query_orders_to']) { 445 if ($post['sendsms_query_orders_from']) { 446 $query_where .= ' AND '; 447 } 448 $query_where .= "(select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) <= " . $post['sendsms_query_orders_to']; 449 if ($post['sendsms_query_orders_from']) { 450 $query_where .= ' ) '; 451 } 452 } 453 if (array_key_exists('sendsms_query_orders_none',$post) && isset($post['sendsms_query_orders_none'])) { 454 $query_where .= "(select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) = 0 "; 455 } 456 $query_where .= ') '; 668 if ($post['sendsms_query_orders_from']) { 669 $query_where .= ' AND '; 670 } 671 $query_where .= "(select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) <= " . $post['sendsms_query_orders_to']; 672 if ($post['sendsms_query_orders_from']) { 673 $query_where .= ' ) '; 674 } 675 } 676 if (array_key_exists('sendsms_query_orders_none',$post) && isset($post['sendsms_query_orders_none'])) { 677 $query_where .= "(select count(*) from wp_posts post left join wp_postmeta meta0 on (meta0.post_id = post.ID) where post.post_type='shop_order' and meta0.meta_key='_customer_user' and meta0.meta_value=wp_users.ID) = 0 "; 678 } 679 $query_where .= ') '; 680 } 457 681 } 458 682 459 683 $query .= " $query_where"; 460 // print_r($query); die(); 461 return $this->execute_recipient_query($query,$count,$country_key); 684 685 // Add LIMIT to prevent server overload (max 3000 results) 686 if (!$count) { 687 $query .= " LIMIT 3000"; 688 } 689 690 if (WP_DEBUG) { 691 error_log("Final query: " . $query); 692 } 693 694 return $this->execute_recipient_query($query, $count, $country_keys); 462 695 } 463 696 -
insim/trunk/admin/partials/html-admin-page.php
r3326386 r3381414 41 41 if ( null != get_option('setting_change') && get_option('setting_change') == true ) { 42 42 $tabs = array( 43 'campaigns' => __('SMS Campaigns', 'insim'), 43 44 'automations' => __('SMS Automations', 'insim'), 44 45 45 46 //'history' => __('History', 'insim'), 46 47 'helpdesk' => __('SMS Helpdesk CRM', 'insim'), 47 'campaigns' => __('SMS Campaigns (Beta evrsion)', 'insim'),48 48 'settings2' => __('Settings', 'insim'), 49 49 'contact_us' => __('Contact us', 'insim') … … 52 52 $tabs = array( 53 53 'settings' => __('Settings', 'insim'), 54 'campaigns' => __('SMS Campaigns', 'insim'), 54 55 'automations' => __('SMS Automations', 'insim'), 55 56 56 57 //'history' => __('History', 'insim'), 57 58 'helpdesk' => __('SMS Helpdesk CRM', 'insim'), 58 'campaigns' => __('SMS Campaigns (Beta version)', 'insim'),59 59 60 'contact_us' => __('Contact us', 'insim') 60 61 ); -
insim/trunk/admin/sim-to-shop-admin.php
r3022860 r3381414 112 112 //icon of woocommerce 113 113 wp_enqueue_style(ABSPATH . 'wp-content/plugin/woocommerce.assets/css/mixins.css'); 114 } 114 } 115 115 } 116 116 … … 123 123 124 124 wp_enqueue_script($this->sim_to_shop, plugin_dir_url(__FILE__) . 'js/sim-to-shop-admin.js', array('jquery'), $this->version, false); 125 125 126 // Enqueue ULTIMATE MODERN filter manager JavaScript 127 wp_enqueue_script('insim-filter-modern', plugin_dir_url(__FILE__) . 'js/sim-to-shop-filter-manager-modern.js', array('jquery'), $this->version, false); 128 129 // Localize script for AJAX 130 wp_localize_script('insim-filter-modern', 'insimUltimateData', array( 131 'ajaxUrl' => admin_url('admin-ajax.php'), 132 'campaignId' => isset($GLOBALS['insim_current_campaign_id']) ? $GLOBALS['insim_current_campaign_id'] : 0 133 )); 134 126 135 wp_enqueue_script( 'jquery-ui-datepicker' ); 127 136 128 137 129 138 wp_register_style( 'jquery-ui', plugin_dir_url(__FILE__) . 'css/jquery-ui.css'); 130 131 wp_enqueue_style( 'jquery-ui' ); 139 140 wp_enqueue_style( 'jquery-ui' ); 132 141 } 133 142 -
insim/trunk/admin/sim-to-shop-generic-campaign-tab.php
r3301630 r3381414 253 253 254 254 </Style> 255 <button style ="border-radius: 15px 0 0 0; background-color: #777" class="tablink" onclick=" stp=1;document.getElementById('next_step').style.display = 'block'; document.getElementById('defaultOpen2').style.backgroundColor= '#555';document.getElementById('defaultOpen1').style.backgroundColor= '#777'; 255 <button style ="border-radius: 15px 0 0 0; background-color: #777" class="tablink" onclick=" stp=1;document.getElementById('next_step').style.display = 'block'; document.getElementById('defaultOpen2').style.backgroundColor= '#555';document.getElementById('defaultOpen1').style.backgroundColor= '#777'; 256 256 document.getElementById('defaultOpen3').style.backgroundColor= '#555'; 257 257 document.getElementById('defaultOpen4').style.backgroundColor= '#555'; 258 258 document.getElementById('postbox-container-2').style.display = 'none'; 259 document.getElementById('sendsms_choose_recipient').style.display = 'block'; 260 document.getElementById('sendsms_recipient').style.display = 'block'; 259 document.getElementById('insim-ultimate-filter-container').style.display = 'block'; 261 260 document.getElementById('sendsms_msg').style.display = 'none'; 262 261 document.getElementById('sendsms_titleA').style.display = 'none'; … … 274 273 " id="defaultOpen1"><div style ="font-size:20px;color:#765f5f;text-align:center;line-height:0; 0;border-radius:50%;background:white; margin-right: 10px; padding: 7px 14px; display: inline;">1</div>Recipients</button> 275 274 276 <button class="tablink" onclick=" stp=2; document.getElementById('next_step').style.display = 'block';document.getElementById('defaultOpen2').style.backgroundColor= '#777'; 277 document.getElementById('defaultOpen1').style.backgroundColor= '#555'; 278 document.getElementById('defaultOpen3').style.backgroundColor= '#555'; 279 document.getElementById('defaultOpen4').style.backgroundColor= '#555'; 280 document.getElementById('postbox-container-2').style.display = 'block'; document.getElementById('sendsms_choose_recipient').style.display = 'none';281 document.getElementById(' sendsms_recipient').style.display = 'none';275 <button class="tablink" onclick=" stp=2; document.getElementById('next_step').style.display = 'block';document.getElementById('defaultOpen2').style.backgroundColor= '#777'; 276 document.getElementById('defaultOpen1').style.backgroundColor= '#555'; 277 document.getElementById('defaultOpen3').style.backgroundColor= '#555'; 278 document.getElementById('defaultOpen4').style.backgroundColor= '#555'; 279 document.getElementById('postbox-container-2').style.display = 'block'; 280 document.getElementById('insim-ultimate-filter-container').style.display = 'none'; 282 281 document.getElementById('sendsms_titleA').style.display = 'none'; 283 282 document.getElementById('sendsms_titleB').style.display = 'none'; … … 286 285 287 286 document.getElementById('url_track').style.display = 'block'; 288 document.getElementById('sendsms_choose_recipient').style.display = 'none';289 287 document.getElementById('meesageLength').style.display = 'block'; 288 document.getElementById('sms_preview_container').style.display = 'flex'; 289 document.getElementById('sms_metrics').style.display = 'block'; 290 290 document.getElementById('sendsms_titleB').style.display = 'none'; 291 291 document.getElementById('cmp_details').style.display = 'none'; … … 304 304 305 305 document.getElementById('meesageLength').innerHTML = document.querySelector('[name = \'sendsms_message\']').value.length+`/160`; 306 if (typeof updateMessageMetrics === 'function') { updateMessageMetrics(); } 306 307 document.querySelector('[name = \'sendsms_message\']').addEventListener('keyup', () => { 307 308 document.getElementById('meesageLength').innerHTML = document.querySelector('[name = \'sendsms_message\']').value.length+`/160`; 309 if (typeof updateMessageMetrics === 'function') { updateMessageMetrics(); } 308 310 }); 309 311 … … 319 321 document.getElementById('defaultOpen3').style.backgroundColor= '#777'; 320 322 document.getElementById('postbox-container-2').style.display = 'block'; 321 document.getElementById(' sendsms_recipient').style.display = 'none';323 document.getElementById('insim-ultimate-filter-container').style.display = 'none'; 322 324 document.getElementById('sendsms_titleA').style.display = 'block'; 323 325 document.getElementById('sendsms_titleB').style.display = 'block'; 324 326 325 327 document.getElementById('sendsms_msg').style.display = 'none'; 326 document.getElementById('sendsms_choose_recipient').style.display = 'none';327 328 document.getElementById('url_track').style.display = 'none'; 328 329 document.getElementById('sendsms_msg2').style.display = 'none'; 329 330 document.getElementById('meesageLength').style.display = 'none'; 331 document.getElementById('sms_preview_container').style.display = 'none'; 332 document.getElementById('sms_metrics').style.display = 'none'; 330 333 document.getElementById('cmp_details').style.display = 'none'; 331 334 document.getElementById('sendsms_buttons').style.display = 'none'; … … 342 345 document.getElementById('defaultOpen3').style.backgroundColor= '#555'; 343 346 document.getElementById('defaultOpen4').style.backgroundColor= '#777'; 344 document.getElementById(' sendsms_recipient').style.display = 'none';347 document.getElementById('insim-ultimate-filter-container').style.display = 'none'; 345 348 document.getElementById('postbox-container-2').style.display = 'block'; 346 349 document.getElementById('sendsms_titleA').style.display = 'none'; … … 348 351 document.getElementById('sendsms_msg2').style.display = 'none'; 349 352 350 document.getElementById('sendsms_choose_recipient').style.display = 'none';351 353 document.getElementById('url_track').style.display = 'none'; 352 354 document.getElementById('meesageLength').style.display = 'none'; 353 355 document.getElementById('sendsms_titleB').style.display = 'none'; 356 document.getElementById('sms_preview_container').style.display = 'none'; 357 document.getElementById('sms_metrics').style.display = 'none'; 354 358 document.getElementById('cmp_details').style.display = 'block'; 355 359 document.getElementById('sendsms_buttons').style.display = 'block'; … … 376 380 <input id ="next_step" class="btn btn-lg btn-primary float-right" style ="margin-left: 25px; margin-top: 25px;" type="submit" value ="<?php _e('Next Step', 'insim'); ?>" /> 377 381 378 <div style = "width: 600px; display: none; margin-top: 40px;" id="postbox-container-2" class="postbox-container"><!-- left column-->382 <div style = "width: 860px; display: none; margin-top: 40px;" id="postbox-container-2" class="postbox-container"><!-- left column--> 379 383 <div class="postbox"> 380 384 <div class="panel-wrap woocommerce "> … … 396 400 <!-- Campaign details --> 397 401 <div id= "cmp_details"> 398 <div class="card" style="box-shadow: 5px 5px lightgrey; margin-bottom: 50px;">399 <div class="card-header" >400 <strong >Resume :</strong>402 <div class="card" style="box-shadow: 0 6px 18px rgba(0,0,0,0.06); border-radius:14px; overflow:hidden; margin-bottom: 32px; border:1px solid #ececec;"> 403 <div class="card-header" style="background:#f9fafb; padding:14px 16px; border-bottom:1px solid #ececec;"> 404 <strong style="font-size:15px; color:#111827;">Summary</strong> 401 405 </div> 402 <div class="card-body"> 403 <p style= "margin-top: 10px;"><span id ="nbrecres" style =" font-size: large;">Number of recipients : </span><?php echo ($this->_campaign->title != '' ? '<span style="background-color: #f7f1f1;">'.$this->_campaign->nb_recipients : '<span style="color: #1930df; background: #f3eeee;">The number will be calculated once the campaign is saved' ) ?></span> 404 </p> 405 <br /> 406 <p style= "margin-top: 10px;"><span style =" font-size: large;">Title : </span><span id ="titleres" style="background-color: #f7f1f1;"></span> 407 </p> 408 <br /> 409 <p style= "margin-top: 10px;"><span style =" font-size: large;">Message : </span><span id ="msgres" style="background-color: #f7f1f1;"></span> 410 </p> 411 <br /> 412 <p style= "margin-top: 10px;"> <span style =" font-size: large;">Send date : </span><span id ="senddateres" style="background-color: #f7f1f1;"></span> 413 </p> 406 <div class="card-body" style="padding:16px;"> 407 <div style="display:flex; gap:16px; flex-wrap:wrap;"> 408 <div style="flex:1 1 230px; min-width:210px; border:1px dashed #e5e7eb; border-radius:10px; padding:12px; background:#ffffff;"> 409 <div style="font-size:12px; color:#6b7280; margin-bottom:6px;">Recipients</div> 410 <div id="cmp_nb_recipients" style="font-size:16px; color:#111827; font-weight:600;"> 411 <?php echo '<span>'.intval($this->_campaign->nb_recipients).'</span>'; ?> 414 412 </div> 413 </div> 414 <div style="flex:1 1 230px; min-width:210px; border:1px dashed #e5e7eb; border-radius:10px; padding:12px; background:#ffffff;"> 415 <div style="font-size:12px; color:#6b7280; margin-bottom:6px;">Title</div> 416 <div id ="titleres" style="font-size:16px; color:#111827; font-weight:600;"></div> 417 </div> 418 <div style="flex:1 1 100%; min-width:210px; border:1px dashed #e5e7eb; border-radius:10px; padding:12px; background:#ffffff;"> 419 <div style="font-size:12px; color:#6b7280; margin-bottom:6px;">Message</div> 420 <div id ="msgres" style="font-size:14px; color:#111827; white-space:pre-wrap; word-wrap:break-word;"></div> 421 </div> 422 <div style="flex:1 1 230px; min-width:210px; border:1px dashed #e5e7eb; border-radius:10px; padding:12px; background:#ffffff;"> 423 <div style="font-size:12px; color:#6b7280; margin-bottom:6px;">Send date</div> 424 <div id ="senddateres" style="font-size:16px; color:#111827; font-weight:600;"></div> 425 </div> 426 </div> 427 </div> 428 <!-- Action buttons are already present below; avoid duplicates here. --> 415 429 </div> 416 430 <style> … … 514 528 </div> 515 529 </div> 516 <!-- campaign title --> 517 <p id="sendsms_titleA" class="form-field form-field-wide"> 518 <label for="sendsms_title"><span style ="font-size: x-large;"><?php _e('Title of the campaign', 'insim') ?></span></label><br/> 519 <input style="margin-top: 20px;" type="text" id="sendsms_title" name="sendsms_title" maxlength="255" value="<?php echo htmlentities($this->_campaign->title, ENT_QUOTES, 'utf-8'); ?>" /> 520 </p> 530 <!-- campaign title (modern card) --> 531 <div id="sendsms_titleA" class="form-field form-field-wide" style="display:none;"> 532 <div style="padding:16px; border:1px solid #e6e6e6; border-radius:12px; background:#fff; box-shadow:0 2px 8px rgba(0,0,0,0.03); border-top:4px solid #6a5cff;"> 533 <label for="sendsms_title" style="display:block; font-size:14px; font-weight:600; color:#444; margin-bottom:8px;">Titre de la campagne</label> 534 <input type="text" id="sendsms_title" name="sendsms_title" maxlength="255" value="<?php echo htmlentities($this->_campaign->title, ENT_QUOTES, 'utf-8'); ?>" style="width:100%; max-width:520px; padding:10px 12px; border:1px solid #dcdcdc; border-radius:8px;" /> 535 </div> 536 </div> 521 537 522 538 <!-- campaign message--> 523 <p id ="sendsms_msg" class="form-field form-field-wide"> 524 <label for="sendsms_title"><span style ="font-size: x-large;"><?php _e('Message') ?></span></label><br/> 525 <br/><span id="sendsms_msg2" style="margin-top: -10px;"><?php _e('Variables you can use : {firstname}, {lastname}', 'insim'); ?></span><br/> 526 <textarea class="form-control" style="margin-top: -10px;" 539 <div id ="sendsms_msg" class="form-field form-field-wide" style="display:none;"> 540 <div style="display:flex; gap:16px; align-items:flex-start;"> 541 <!-- Editor column --> 542 <div style="flex:1 1 66%; min-width:420px; background:#fff; border:1px solid #e6e6e6; border-radius:12px; padding:14px; box-shadow:0 2px 8px rgba(0,0,0,0.03); border-top:4px solid #6a5cff;"> 543 <label for="sendsms_title" style="display:block; font-size:14px; font-weight:600; color:#444;"><?php _e('Message') ?></label> 544 <div style="margin:8px 0 6px 0; display:flex; gap:8px; flex-wrap:wrap;"> 545 <button type="button" class="button" style="background:#2271b1; color:#fff; border-color:#1f5f99;" onclick="insertToken('{firstname}')">{firstname}</button> 546 <button type="button" class="button" style="background:#2271b1; color:#fff; border-color:#1f5f99;" onclick="insertToken('{lastname}')">{lastname}</button> 547 </div> 548 <span id="sendsms_msg2" style="display:block; color:#6b7280; font-size:12px;">Variables disponibles : {firstname}, {lastname}</span> 549 <div style="position:relative; margin-top:6px;"> 550 <textarea class="form-control" style="width:100%; max-width:100%; padding:12px 12px 22px 12px; border:1px solid #dcdcdc; border-radius:8px; min-height:200px;" 527 551 <?php echo ($this->_campaign->status == 0 ? '' : 'readonly') ?> 528 rows="5" cols="50" name="sendsms_message" ><?php echo htmlentities($this->_campaign->message, ENT_QUOTES, 'utf-8'); ?></textarea> 529 <div id = "meesageLength" style="margin-left: 517px; margin-top: -33px; display: block!important;">0/160</div> 530 <div id ="url_track" style="disply: inline-block; margin-top: 15px;" onclick="clickInsetTrackingUrl();"> 552 rows="8" cols="50" name="sendsms_message" ><?php echo htmlentities($this->_campaign->message, ENT_QUOTES, 'utf-8'); ?></textarea> 553 <div id = "meesageLength" style="position:absolute; right:10px; bottom:6px; color:#6b7280; font-size:12px;">0/160</div> 554 </div> 555 <div style="display:flex; justify-content:flex-end; align-items:center; margin-top:10px;"> 556 <style> 557 .insim-chip{display:inline-flex; align-items:center; gap:6px; padding:6px 10px; border-radius:999px; background:#f1f5ff; color:#1f3a8a; border:1px solid #dbe6ff; font-size:12px; font-weight:600;} 558 </style> 559 <div id="sms_metrics" style="display:none; gap:10px;"> 560 <span class="insim-chip">SMS :<strong id="sms_segments">0</strong></span> 561 <span class="insim-chip" style="display:none;">Coût estimé :<strong id="sms_cost_estimate">—</strong></span> 562 </div> 563 </div> 564 <div id ="url_track" style="margin-top: 12px; display:flex; flex-direction:column; gap:8px;" onclick="clickInsetTrackingUrl();"> 565 <span style="font-size:12px; color:#444;"><b>Insert trackable URL</b><sup>(1)</sup> <span style="font-style: oblique; color: #1aadba; font-weight: bold;">PREMIUM option</span><sup>(2)</sup></span> 566 <div style="display:flex; gap:8px; align-items:center;"> 567 <input id ="url_tracking_value" style="flex:1; min-width:0; padding:8px 10px; border:1px solid #dcdcdc; border-radius:8px;" type="text" placeholder="https://www.ardary-insim.com/example"> 568 <button id ="url_tracking" class="button" <?php echo (get_option('is_premium') == false ? 'disabled title ="You can not use this option until you pay a subscription !"' : ''); ?> style="height:34px; cursor:pointer; white-space:nowrap; background:#2271b1; color:#fff; border-color:#1f5f99;"> <?php _e('Insert in message', 'insim'); ?> </button> 569 </div> 570 <p id ='url_tracking_alert' style='display: none; color: red; padding-left: 5px;'><b style="font-weight: 900;"></b> You can not use this option until you pay a subscription ! </p> 571 <p style="margin-bottom: 0px!important; font-size:12px; color:#666;">(1) We create automatically a trackable short URL that allows you to get detailled analytics.</p> 572 <?php if ( get_option('is_premium') == false){ 573 echo '<p style="margin-top: 0; font-size:12px; color:#666;">(2) This is a PREMIUM feature. <a href="https://insim.app/" target ="_blank">Get PREMIUM</a>.</p>'; 574 } else { 575 echo '<p style="margin-top: 0; font-size:12px; color:#666;">(2) You are currently in the PREMIUM trial period, this feature is available to you.</p>'; 576 } 577 ?> 578 </div> 579 </div> 580 <!-- Preview column --> 581 <div id="sms_preview_container" style="flex:0 0 260px; display:none;"> 582 <div style="margin-top:8px; padding:12px; border:1px solid #e0e0e0; border-radius:16px; background:#f9fafb; box-shadow: 0 2px 8px rgba(0,0,0,0.05);"> 583 <style> 584 .telnewsim{border-left:5px solid rgb(86,85,85);border-right:5px solid rgb(86,85,85);border-bottom:5px solid rgb(86,85,85);border-radius:0 0 12px 12px;background-color:#f2eeee;width:228px;height:280px;position:relative;margin:0 auto;} 585 .smsnewsim{border-radius:6px;background-color:rgb(29,168,183);color:#fff;position:absolute;top:55px;right:10px;width:180px;padding:6px 8px;max-height:190px;overflow:auto;font-size:12px;line-height:1.4;word-wrap:break-word;white-space:pre-wrap;} 586 .bottom-button-wrapper{position:absolute;bottom:-3px;height:12px;width:100%;} 587 .bottom-button{height:10px;width:50px;border-radius:20px 20px 0 0;background-color:rgb(86,85,85);margin:0 auto;} 588 .top-bar{height:28px;background:#f5f5f7;border-bottom:1px solid #ececec;display:flex;align-items:center;justify-content:center;color:#666;font-size:11px;border-top-left-radius:12px;border-top-right-radius:12px;} 589 </style> 590 <div class="telnewsim"> 591 <div class="top-bar">Preview</div> 592 <div class="smsnewsim" id="sms_preview_text"></div> 593 <div class="bottom-button-wrapper"><div class="bottom-button"></div></div> 594 </div> 595 </div> 596 </div> 597 </div> 598 </div> 599 <div id ="url_track_old" style="display:none;" onclick="clickInsetTrackingUrl();"> 531 600 <br><span ><b>Insert trackable URL</b><sup>(1)</sup> <span style="font-style: oblique; color: #1aadba; font-weight: bold;">PREMIUM option</span><sup>(2)</sup></span></br> 532 601 <input id ="url_tracking_value" style="width: 73%; disply: inline-block; margin-top: 15px;" type="text" placeholder="https://www.ardary-insim.com/example"> … … 541 610 ?> 542 611 </div> 543 </p>544 612 545 613 <!-- campaign date --> 546 <div style ="margin-top: 70px; display:inline-block;" id="sendsms_titleB" class="form-field form-field-wide"><label for="sendsms_date"><span style ="font-size: x-large;"><?php _e('Send date', 'insim') ?></span></label><br/> 547 <input style="margin-top: 20px; display: inline-block; width: 42%;" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="date-picker-field datepicker" name="sendsms_date" id="sendsms_date" maxlength="10" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('Y-m-d', strtotime($this->_campaign->date_send)) : '' ?>" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" /> 548 @<input style="margin-top: 20px; display: inline-block; width: 20%" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="hour" style="width:2.5em" placeholder="<?php _e('h', 'insim') ?>" name="sendsms_date_hour" id="sendsms_date_hour" maxlength="2" size="2" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('H', strtotime($this->_campaign->date_send)) : '' ?>" pattern="\-?\d+(\.\d{0,})?" /> 549 :<input style="margin-top: 20px; display: inline-block; width: 20%;" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="minute" style="width:2.5em" placeholder="<?php _e('m', 'insim') ?>" name="sendsms_date_minute" id="sendsms_date_minute" maxlength="2" size="2" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('i', strtotime($this->_campaign->date_send)) : '' ?>" pattern="\-?\d+(\.\d{0,})?" /> 550 <br><?php echo __('Time Zone:', 'insim') . ' ' . date_default_timezone_get(); ?> 614 <div style ="margin-top: 20px; display:none;" id="sendsms_titleB" class="form-field form-field-wide"> 615 <div style="padding:16px; border:1px solid #e6e6e6; border-radius:12px; background:#fff; box-shadow: 0 2px 8px rgba(0,0,0,0.03); border-top:4px solid #1eacba;"> 616 <label for="sendsms_date" style="display:block; font-size:14px; font-weight:600; color:#444; margin-bottom:8px;"><?php _e('Send date', 'insim') ?></label> 617 <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;"> 618 <input style="margin-top: 4px; width: 180px; padding:10px 12px; border:1px solid #dcdcdc; border-radius:8px;" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="date-picker-field datepicker" name="sendsms_date" id="sendsms_date" maxlength="10" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('Y-m-d', strtotime($this->_campaign->date_send)) : '' ?>" pattern="[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" /> 619 <span style="opacity:.6;">@</span> 620 <input style="margin-top: 4px; width: 80px; padding:10px 12px; border:1px solid #dcdcdc; border-radius:8px;" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="hour" placeholder="<?php _e('h', 'insim') ?>" name="sendsms_date_hour" id="sendsms_date_hour" maxlength="2" size="2" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('H', strtotime($this->_campaign->date_send)) : '' ?>" pattern="\-?\d+(\.\d{0,})?" /> 621 <span style="opacity:.6;">:</span> 622 <input style="margin-top: 4px; width: 80px; padding:10px 12px; border:1px solid #dcdcdc; border-radius:8px;" type="text" <?php echo ($this->_campaign->status < 2 ? '' : 'readonly') ?> class="minute" placeholder="<?php _e('m', 'insim') ?>" name="sendsms_date_minute" id="sendsms_date_minute" maxlength="2" size="2" value="<?php echo $this->_campaign->date_send != "0000-00-00 00:00:00" && $this->_campaign->date_send !="" ? date_i18n('i', strtotime($this->_campaign->date_send)) : '' ?>" pattern="\-?\d+(\.\d{0,})?" /> 623 </div> 624 <div style="margin-top:8px; color:#666; font-size:12px;"><?php echo __('Time Zone:', 'insim') . ' ' . date_default_timezone_get(); ?></div> 625 </div> 551 626 </div> 552 627 … … 588 663 </Style> 589 664 590 <div style ="margin-left: 40px; display: inline-block;" id="sendsms_recipient" class="postbox-container postbox">665 <div style ="margin-left: 40px; display: none !important; visibility: hidden !important;" id="sendsms_recipient" class="postbox-container postbox"> 591 666 <?php 592 667 $myListTable = new Sim_To_Shop_Recipient_List(array('campaign' => $this->_campaign)); … … 599 674 $myListTable->prepare_items(); 600 675 $myListTable->display(); 601 ?> 676 ?> 602 677 </div> 603 678 <?php … … 719 794 function output_choose_recipient() { 720 795 if (get_class($this) == 'Sim_To_Shop_Send_Tab' && $this->_campaign->status == 0) { 796 // Set campaign ID for filter interface 797 global $insim_current_campaign_id; 798 $insim_current_campaign_id = $this->_campaign->id_sendsms_campaign; 721 799 ?> 722 800 <div class="poststuff"> 723 <div id="sendsms_choose_recipient" class="postbox"> 801 <!-- ULTIMATE MODERN FILTER INTERFACE --> 802 <?php include_once(plugin_dir_path(__FILE__) . 'partials/campaign-filter-interface-ultimate.php'); ?> 803 804 <div id="sendsms_choose_recipient" class="postbox" style="display: none !important; visibility: hidden !important; height: 0 !important; overflow: hidden !important;"> 724 805 <style> 725 806 #add_recipient { … … 903 984 document.getElementById('sendsms_validate').setAttribute('disabled', 'disabled'); 904 985 document.getElementById('sendsms_validate').setAttribute('title', 'You have to save the modifications first !'); 986 if (typeof updateMessageMetrics === 'function') { updateMessageMetrics(); } 905 987 }); 906 988 document.getElementById('url_tracking_value').addEventListener('input', function() { … … 1039 1121 1040 1122 1123 // Message metrics and preview 1124 function isGsm7(txt){ 1125 try { 1126 // Basic heuristic: if all chars are in 0x00-0x7F and not requiring UCS-2 1127 return /^[\u0000-\u007F]*$/.test(txt); 1128 } catch(e){ return true; } 1129 } 1130 function computeSegments(txt){ 1131 var gsm7 = isGsm7(txt); 1132 var perSeg = gsm7 ? 160 : 70; 1133 // Concatenated segments length: 153 for GSM7, 67 for UCS2 1134 var concatLen = gsm7 ? 153 : 67; 1135 var len = txt.length; 1136 if (len <= perSeg) return {segments: (len>0?1:0), perSeg: perSeg}; 1137 return {segments: Math.ceil(len / concatLen), perSeg: concatLen}; 1138 } 1139 function formatMoneyFR(n){ 1140 if (isNaN(n)) return '—'; 1141 return (Math.round(n*100)/100).toFixed(2).replace('.', ',') + ' €'; 1142 } 1143 window.updateMessageMetrics = function(){ 1144 var ta = document.getElementsByName('sendsms_message')[0]; 1145 if (!ta) return; 1146 var txt = ta.value || ''; 1147 var previewEl = document.getElementById('sms_preview_text'); 1148 if (previewEl){ previewEl.textContent = txt; } 1149 var seg = computeSegments(txt); 1150 var segEl = document.getElementById('sms_segments'); 1151 if (segEl){ segEl.textContent = seg.segments; } 1152 // Auto-cost: use stored recipient count and default per-SMS if not yet priced 1153 var defaultPerSms = 0.05; 1154 var recipients = 0; 1155 var nbRecEl = document.getElementById('nb_recipients'); 1156 if (nbRecEl){ 1157 var v = nbRecEl.textContent || nbRecEl.innerText || '0'; 1158 recipients = parseInt(v.replace(/[^0-9]/g,'')||'0',10) || 0; 1159 } 1160 // Fallback: if hidden nb_recipients is 0, try reading summary box live 1161 if (!recipients) { 1162 var cmpBox = document.getElementById('cmp_nb_recipients'); 1163 if (cmpBox){ 1164 var vv = cmpBox.textContent || cmpBox.innerText || '0'; 1165 recipients = parseInt(vv.replace(/[^0-9]/g,'')||'0',10) || 0; 1166 } 1167 } 1168 var estimatedPrice = recipients * seg.segments * defaultPerSms; 1169 // Prefer dynamic estimate unless a non-zero price already exists from backend computation 1170 var backendPrice = <?php echo isset($this->_campaign) && $this->_campaign->price ? floatval($this->_campaign->price) : 0; ?>; 1171 var estimate = backendPrice > 0 ? backendPrice : estimatedPrice; 1172 var costEl = document.getElementById('sms_cost_estimate'); 1173 if (costEl){ costEl.textContent = formatMoneyFR(estimate); } 1174 if (typeof console !== 'undefined') { 1175 console.log('[inSIM] Metrics update', { smsSegments: seg.segments, recipients, defaultPerSms, backendPrice, estimate }); 1176 } 1177 }; 1178 updateMessageMetrics(); 1179 1180 // Token insertion helper 1181 window.insertToken = function(token){ 1182 var ta = document.getElementsByName('sendsms_message')[0]; 1183 if (!ta) return; 1184 var start = ta.selectionStart || ta.value.length; 1185 var end = ta.selectionEnd || ta.value.length; 1186 var before = ta.value.substring(0, start); 1187 var after = ta.value.substring(end); 1188 ta.value = before + token + after; 1189 // move caret after inserted token 1190 var pos = start + token.length; 1191 if (ta.setSelectionRange){ ta.setSelectionRange(pos, pos); } 1192 ta.focus(); 1193 if (typeof updateMessageMetrics === 'function') { updateMessageMetrics(); } 1194 // refresh 160 counter 1195 document.getElementById('meesageLength').innerHTML = ta.value.length+"/160"; 1196 }; 1197 1041 1198 }); 1042 1199 function changeSendMod(){ -
insim/trunk/admin/sim-to-shop-send-tab.php
r3301630 r3381414 263 263 ORDER BY id_sendsms_recipient ASC 264 264 LIMIT 200'); 265 if (WP_DEBUG) error_log('[inSIM] transmitOWS() fetched recipients size='.(is_array($result)?count($result):0)); 265 266 $size = count($result); 266 267 $total_rows = $wpdb->get_var('SELECT FOUND_ROWS()'); … … 321 322 $campaign->date_send = current_time('mysql'); 322 323 $campaign->compute_campaign(1); 324 if (WP_DEBUG) error_log('[inSIM] After compute_campaign nb_recipients='.$campaign->nb_recipients.' price='.$campaign->price); 323 325 $campaign->status_label = Sim_To_Shop_Admin::get_instance()->get_status($campaign->status); 324 326 } else { … … 427 429 $campaign = new Sim_To_Shop_Campaign(sanitize_key($_REQUEST['id_sendsms_campaign'])); 428 430 $result = $campaign->get_recipients_from_query(false); 429 wp_send_json(array('total_rows' => sizeof($result))); 431 432 // Get pagination parameters (default: show first 10) 433 $page = isset($_REQUEST['page']) ? intval($_REQUEST['page']) : 1; 434 $per_page = isset($_REQUEST['per_page']) ? intval($_REQUEST['per_page']) : 10; 435 $offset = ($page - 1) * $per_page; 436 437 $total_rows = is_array($result) ? sizeof($result) : 0; 438 439 // Debug logging 440 if (WP_DEBUG) { 441 error_log('[inSIM AJAX] Query result count: ' . $total_rows); 442 error_log('[inSIM AJAX] Page: ' . $page . ', Per page: ' . $per_page . ', Offset: ' . $offset); 443 if ($total_rows > 0 && isset($result[0])) { 444 error_log('[inSIM AJAX] First customer sample: ' . print_r($result[0], true)); 445 } 446 } 447 448 // Paginate results 449 $paginated_result = is_array($result) ? array_slice($result, $offset, $per_page) : array(); 450 451 // Format customer data for display 452 $customers = array(); 453 foreach ($paginated_result as $customer) { 454 // Check both possible field names for order count 455 $order_count = 0; 456 if (isset($customer->order_nbr)) { 457 $order_count = intval($customer->order_nbr); 458 } elseif (isset($customer->nb_order)) { 459 $order_count = intval($customer->nb_order); 460 } 461 462 $customers[] = array( 463 'ID' => isset($customer->ID) ? $customer->ID : '', 464 'name' => isset($customer->display_name) ? $customer->display_name : '', 465 'display_name' => isset($customer->display_name) ? $customer->display_name : '', 466 'user_login' => isset($customer->user_login) ? $customer->user_login : '', 467 'email' => isset($customer->user_email) ? $customer->user_email : '', 468 'user_email' => isset($customer->user_email) ? $customer->user_email : '', 469 'phone' => isset($customer->billing_phone) ? $customer->billing_phone : '', 470 'billing_phone' => isset($customer->billing_phone) ? $customer->billing_phone : '', 471 'orders_count' => $order_count, 472 'country' => isset($customer->billing_country) ? $customer->billing_country : '' 473 ); 474 } 475 476 // Debug logging 477 if (WP_DEBUG) { 478 error_log('[inSIM AJAX] Paginated result count: ' . count($paginated_result)); 479 error_log('[inSIM AJAX] Formatted customers count: ' . count($customers)); 480 } 481 482 wp_send_json(array( 483 'total_rows' => $total_rows, 484 'customers' => $customers, 485 'page' => $page, 486 'per_page' => $per_page, 487 'total_pages' => $total_rows > 0 ? ceil($total_rows / $per_page) : 0 488 )); 430 489 } 431 490 … … 442 501 $campaign->isteam = sanitize_key($post['isteam']); 443 502 $campaign->save(); 503 // Ensure subsequent UI reloads point to the newly created campaign 504 $_REQUEST['id_sendsms_campaign'] = $campaign->id_sendsms_campaign; 444 505 } else { 445 506 $campaign = new Sim_To_Shop_Campaign(sanitize_key($_REQUEST['id_sendsms_campaign'])); … … 465 526 $recipient->lastname = isset($row->billing_lastname) && $row->billing_lastname != '' ? $row->billing_lastname : $row->display_name; 466 527 $recipient->lastname = preg_replace('/[0-9]+/', '', $recipient->lastname); 467 $phone = Sim_To_Shop_API::convert_phone_to_international($row->billing_phone, $row->billing_country); 528 // Use API instance (method is not static) 529 $phone = Sim_To_Shop_API::get_instance()->convert_phone_to_international($row->billing_phone, $row->billing_country); 468 530 $recipient->phone = $phone; 469 531 $recipient->iso_country = $row->billing_country; … … 627 689 if ($res) { 628 690 $campaign->compute_campaign(); 629 wp_send_json(array('campaign' => $campaign, 'recipient' => $recipient ));691 wp_send_json(array('campaign' => $campaign, 'recipient' => $recipient, 'id_sendsms_campaign' => $campaign->id_sendsms_campaign)); 630 692 } else 631 693 wp_send_json(array('error' => __('That phone number is already in the list.', 'insim'))); -
insim/trunk/inSIM.php
r3301645 r3381414 16 16 * Plugin URI: https://ardary-insim.com/ 17 17 * Description: This plugin allows to create an automation or a campaign in order to send sms to a list of recipients as you can do with emails and newsletters. 18 * Version: 3.0.018 * Version: 4.0 19 19 * Author: 2WS Technologies 20 20 * Author URI: https://ardary-insim.com/ … … 117 117 'frompluguin' => true 118 118 ], 119 'versionPlug' =>' 3.0.0',119 'versionPlug' =>'4.0', 120 120 'shop_name' =>get_bloginfo(), 121 121 'shop_url' =>home_url(), … … 153 153 'admin_mail' => get_bloginfo('admin_email'), 154 154 'admin_phone' => get_user_meta(get_current_user_id(),'phone_number',true), 155 'plugin_version' => ' 3.0.0',155 'plugin_version' => '4.0', 156 156 'shop_version' => $versionB, 157 157 'is_multi' => $isMulti … … 313 313 'admin_phone' => get_user_meta(get_current_user_id(),'phone_number',true), 314 314 'shop_url' => home_url(), 315 'plugin_version' => ' 3.0.0',315 'plugin_version' => '4.0', 316 316 'type' => 'e-shop', 317 317 'name' => 'wooc', … … 351 351 'admin_phone' => get_user_meta(get_current_user_id(),'phone_number',true), 352 352 'shop_url' => home_url(), 353 'plugin_version' => ' 3.0.0',353 'plugin_version' => '4.0', 354 354 'type' => 'e-shop', 355 355 'name' => 'wooc', … … 383 383 384 384 require plugin_dir_path(__FILE__) . 'includes'.DIRECTORY_SEPARATOR.'sim-to-shop.php'; 385 386 // Load new advanced filter system AJAX handlers 387 require_once plugin_dir_path(__FILE__) . 'admin'.DIRECTORY_SEPARATOR.'sim-to-shop-ajax-handlers.php'; 385 388 386 389 /** -
insim/trunk/includes/sim-to-shop.php
r2837412 r3381414 184 184 $this->loader->add_action('wp_ajax_addRecipientsFromQuery', $plugin_admin, 'action_add_recipients_from_query'); 185 185 $this->loader->add_action('wp_ajax_countRecipientFromQuery', $plugin_admin, 'action_count_recipients_from_query'); 186 // NEW: Add modern interface actions with underscores 187 $this->loader->add_action('wp_ajax_sim_to_shop_add_recipients_from_query', $plugin_admin, 'action_add_recipients_from_query'); 188 $this->loader->add_action('wp_ajax_sim_to_shop_count_recipients_from_query', $plugin_admin, 'action_count_recipients_from_query'); 186 189 $this->loader->add_action('wp_ajax__ajax_fetch_custom_list', $plugin_admin, '_ajax_fetch_custom_list_callback'); 187 190 $this->loader->add_action('wp_ajax__ajax_fetch_recipient_list', $plugin_admin, '_ajax_fetch_recipient_list_callback');
Note: See TracChangeset
for help on using the changeset viewer.