Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,24 +90,24 @@ jobs:
- name: Verify release package layout
run: |
mkdir -p release
rsync -av --exclude-from=.distignore . release/hellotext-wordpress/
rsync -av --exclude-from=.distignore . release/hellotext/

test -f release/hellotext-wordpress/hellotext.php
test -d release/hellotext-wordpress/src
test -f release/hellotext-wordpress/vendor/autoload.php
test -f release/hellotext-wordpress/assets/hellotext-service-worker.js
test -f release/hellotext-wordpress/assets/storefront.js
test -f release/hellotext/hellotext.php
test -d release/hellotext/src
test -f release/hellotext/vendor/autoload.php
test -f release/hellotext/assets/hellotext-service-worker.js
test -f release/hellotext/assets/storefront.js

for path in \
release/hellotext-wordpress/tests \
release/hellotext-wordpress/composer.json \
release/hellotext-wordpress/composer.lock \
release/hellotext-wordpress/.github \
release/hellotext-wordpress/.php-cs-fixer.cache \
release/hellotext-wordpress/.php-cs-fixer.php \
release/hellotext-wordpress/DEVELOPMENT.md \
release/hellotext-wordpress/API.md \
release/hellotext-wordpress/release; do
release/hellotext/tests \
release/hellotext/composer.json \
release/hellotext/composer.lock \
release/hellotext/.github \
release/hellotext/.php-cs-fixer.cache \
release/hellotext/.php-cs-fixer.php \
release/hellotext/DEVELOPMENT.md \
release/hellotext/API.md \
release/hellotext/release; do
if [ -e "$path" ]; then
echo "Unexpected development file in release package: $path"
exit 1
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ jobs:
- name: Create release zip
run: |
mkdir -p release
rsync -av --exclude-from=.distignore . release/hellotext-wordpress/
rsync -av --exclude-from=.distignore . release/hellotext/
cd release
zip -r hellotext-wordpress.zip hellotext-wordpress
zip -r hellotext.zip hellotext

- name: Create GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
files: release/hellotext-wordpress.zip
files: release/hellotext.zip
generate_release_notes: true
8 changes: 8 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
** Hellotext for WooCommerce Changelog **

2026-11-07 - version 2.0.2

* Run on PHP 7.4 again: 2.0.0 failed to load there.
* Declare the supported WordPress, WooCommerce and PHP versions, and compatibility with High-Performance Order Storage.
* Log failed Hellotext requests to the WooCommerce logs (source "hellotext") when WP_DEBUG is on.
* Sanitize the checkout link's products and the Webchat card's source before reading them.
* The release zip is hellotext.zip and installs to the hellotext folder, as the Woo Marketplace requires.

2026-11-06 - version 2.0.1

* Declare WooCommerce as a required plugin: WordPress 6.5 and later only activate Hellotext while WooCommerce is active.
Expand Down
20 changes: 19 additions & 1 deletion hellotext.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@
* Plugin Name: Hellotext
* Plugin URI: https://github.com/hellotext/hellotext-wordpress
* Description: Integrates Hellotext tracking to WooCommerce.
* Version: 2.0.1
* Version: 2.0.2
* Requires at least: 6.5
* Tested up to: 7.1
* Requires PHP: 7.4
* Requires Plugins: woocommerce
* WC requires at least: 8.0
* WC tested up to: 11.2
* Author: Hellotext
* Author URI: https://www.hellotext.com
* License: GPL v2
Expand Down Expand Up @@ -39,6 +44,19 @@
register_activation_hook(__FILE__, 'hellotext_activate');
register_deactivation_hook(__FILE__, 'hellotext_deactivate');

/**
* Declare compatibility with High-Performance Order Storage: orders are only
* read and written through the WooCommerce order API.
*
* @return void
*/
function hellotext_declare_compatibility() {
if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
}
}
add_action('before_woocommerce_init', 'hellotext_declare_compatibility');

/**
* Check for plugin updates from GitHub.
* Caches result for 24 hours to avoid rate limiting.
Expand Down
5 changes: 4 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
=== Hellotext ===
Contributors: ricardohellotext
Stable tag: 2.0.1
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 2.0.2
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Expand Down
4 changes: 2 additions & 2 deletions src/Adapters/OrderAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class OrderAdapter {
*
* @var \WC_Order|false
*/
public \WC_Order|false $order;
public $order;

/**
* Adapted order items.
Expand All @@ -30,7 +30,7 @@ class OrderAdapter {
* @param int|\WC_Order $order Order ID or order instance.
* @param array $products Pre-adapted products list.
*/
public function __construct(int|\WC_Order $order, array $products = []) {
public function __construct($order, array $products = []) {
$this->order = is_numeric($order) ? wc_get_order($order) : $order;
$this->products = $products;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Adapters/PriceAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class PriceAdapter {
*
* @var float|string
*/
public float|string $price;
public $price;

/**
* Currency code.
Expand All @@ -30,7 +30,7 @@ class PriceAdapter {
* @param float|string $price Raw price amount.
* @param string|null $currency Currency code or null to use store default.
*/
public function __construct(float|string $price, ?string $currency = null) {
public function __construct($price, ?string $currency = null) {
$this->price = $price;
$this->currency = is_null($currency) ? get_woocommerce_currency() : $currency;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Adapters/ProductAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ class ProductAdapter {
*
* @var \WC_Product|false
*/
public \WC_Product|false $product;
public $product;

/**
* Create a new adapter instance.
*
* @param int|\WC_Product $product Product ID or product instance.
*/
public function __construct(int|\WC_Product $product) {
public function __construct($product) {
$this->product = is_numeric($product) ? wc_get_product($product) : $product;
}

Expand Down
12 changes: 6 additions & 6 deletions src/Api/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ public static function request(string $method = 'GET', string $path = '/', array
// Handle errors
if (is_wp_error($response)) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log(sprintf(
'[Hellotext] API request failed: %s %s - Error: %s',
wc_get_logger()->error(sprintf(
'API request failed: %s %s - Error: %s',
$method,
$request_url,
$response->get_error_message()
));
), ['source' => 'hellotext']);
}

return [
Expand All @@ -70,12 +70,12 @@ public static function request(string $method = 'GET', string $path = '/', array

// Log non-2xx responses
if (defined('WP_DEBUG') && WP_DEBUG && ($status_code < 200 || $status_code >= 300)) {
error_log(sprintf(
'[Hellotext] API request returned %d: %s %s',
wc_get_logger()->error(sprintf(
'API request returned %d: %s %s',
$status_code,
$method,
$request_url
));
), ['source' => 'hellotext']);
}

return [
Expand Down
6 changes: 3 additions & 3 deletions src/Api/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ public function track(string $action, array $payload): void {

// Only log if there's an error and debug is enabled
if (is_wp_error($response) && defined('WP_DEBUG') && WP_DEBUG) {
error_log(sprintf(
'[Hellotext] Event tracking failed for action "%s": %s',
wc_get_logger()->error(sprintf(
'Event tracking failed for action "%s": %s',
$action,
$response->get_error_message()
));
), ['source' => 'hellotext']);
}
}
}
4 changes: 2 additions & 2 deletions src/Events/AppInstalled.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function hellotext_connect(): void {
* @param mixed $value Access token being saved.
* @return mixed
*/
function hellotext_retry_failed_connection(mixed $value): mixed {
function hellotext_retry_failed_connection($value) {
if (get_option(Constants::OPTION_CONNECTION_FAILED)) {
hellotext_schedule_connect();
}
Expand Down Expand Up @@ -139,7 +139,7 @@ function hellotext_schedule_connect(): void {
* @param mixed $new_value New value.
* @return void
*/
function hellotext_business_id_updated(mixed $old_value, mixed $new_value): void {
function hellotext_business_id_updated($old_value, $new_value): void {
if ($old_value && $old_value !== $new_value) {
hellotext_disconnect((string) $old_value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Events/CartUpdates.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ function hellotext_cart_event_source(): ?array {
return null;
}

$source = json_decode(wp_unslash($_POST['hellotext_source']), true);
$source = json_decode(sanitize_text_field(wp_unslash($_POST['hellotext_source'])), true);

if (!is_array($source)) {
return null;
Expand Down
4 changes: 2 additions & 2 deletions src/Events/CheckoutLink.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ function hellotext_checkout_link(): void {
* cart, with WooCommerce's notices, when nothing could be added.
*/
function hellotext_fill_checkout_link_cart(): string {
$products = wp_unslash($_GET['products'] ?? '');
$lines = is_string($products) ? hellotext_checkout_link_lines($products) : [];
$products = sanitize_text_field(wp_unslash($_GET['products'] ?? ''));
$lines = hellotext_checkout_link_lines($products);

if (empty($lines)) {
return wc_get_cart_url();
Expand Down
2 changes: 1 addition & 1 deletion src/Events/CustomerProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @param mixed $customer Guest billing details, a user ID, or null for the current user.
* @return void
*/
add_action('hellotext_create_profile', function (mixed $customer = null): void {
add_action('hellotext_create_profile', function ($customer = null): void {
if (is_array($customer)) {
(new CreateProfile(null, $customer))->process();
return;
Expand Down
2 changes: 1 addition & 1 deletion src/Events/OrderPlaced.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function hellotext_capture_checkout(\WC_Order $order): void {
* @param mixed $order_id Order ID.
* @return void
*/
function hellotext_thankyou(mixed $order_id): void {
function hellotext_thankyou($order_id): void {
$order = wc_get_order($order_id);

if (!$order) {
Expand Down
6 changes: 3 additions & 3 deletions src/Events/OrderStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ function hellotext_order_status_changed(int $order_id, string $old_status, strin
hellotext_order_placed($order);
}

$action = match ($new_status) {
$actions = [
'processing' => Constants::EVENT_ORDER_CONFIRMED,
'cancelled' => Constants::EVENT_ORDER_CANCELLED,
'completed' => Constants::EVENT_ORDER_DELIVERED,
default => null,
};
];
$action = $actions[$new_status] ?? null;

if (!$action) {
return;
Expand Down
6 changes: 3 additions & 3 deletions src/Services/CreateProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ public function create_hellotext_profile(): ?string {
private function attribute(string $name): ?string {
if ($this->user_id) {
$user = get_user_by('id', $this->user_id);
$value = match ($name) {
$values = [
'first_name' => $user->first_name ?? '',
'last_name' => $user->last_name ?? '',
'email' => $user->user_email ?? '',
default => '',
};
];
$value = $values[$name] ?? '';

if ('' === $value) {
$value = (string) get_user_meta($this->user_id, "billing_{$name}", true);
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static function encrypt(?string $session = null): string {
* @param mixed $encrypted_data Encrypted session data.
* @return string|false
*/
public static function decrypt(mixed $encrypted_data = null): string|false {
public static function decrypt($encrypted_data = null) {
if (!is_string($encrypted_data) || '' === $encrypted_data) {
return false;
}
Expand Down
Loading