Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance: support for additional CPT's #1483

Merged

Conversation

sapayth
Copy link
Member

@sapayth sapayth commented Sep 30, 2024

fixes #637

Description: In the revamped Subscriptions Module of WP User Frontend, we previously handled a number of additional options originating from other plugins (e.g., the number of events for Event Calendar). However, after the recent update, while the previously supported options continue to work, new additional options generated from other plugins are not functioning as expected.

Current Behavior:

  • Existing Additional Options: Function as expected.
  • New Additional Options (Generated by other plugins): Do not work or are not recognized by the subscription module.

Expected Behavior:

  • Newly generated additional options (from external plugins) should be recognized and handled properly by the subscription module, similar to how the previously supported options were handled.

Steps to Reproduce:

  1. Install a plugin that generates additional options.
  2. Check if newly created additional options working in the subscription feature.
  3. Notice that new options are not being handled correctly, find details in the Slack issue with video reference.

Proposed Enhancement:

  • Extend the logic applied to the subscription module to handle dynamic additional options generated by third-party plugins.
  • Ensure that these new options integrate seamlessly with the subscription settings, allowing users to set limits as expected.

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced subscription management with the introduction of additional_cpt_options, allowing for more flexible metadata handling.
    • Improved handling of non-recurring subscriptions, including better management of expiration settings and user notifications.
    • New validation for form submissions, ensuring content restrictions are enforced based on user input.
  • Bug Fixes

    • Refined logic for form submissions, ensuring clearer conditions based on user subscription status and payment settings.
    • Enhanced tax calculation logic to ensure valid numeric values are returned.
  • Improvements

    • Updates to user profile management related to subscription packs, ensuring accurate data handling.
    • Adjustments to guest posting features, improving user experience and content validation.

Copy link

coderabbitai bot commented Sep 30, 2024

Walkthrough

The changes introduce significant enhancements to the subscription management system across multiple files. Key modifications include the addition of a new meta field for handling custom post type options, improved logic for managing non-recurring subscriptions, and refined validation for form submissions. These updates aim to provide a more structured and flexible approach to subscription data handling and user interactions.

Changes

Files Change Summary
assets/js/stores/subscription.js Updated modifyCurrentSubscription method to include a conditional check for meta_value type, ensuring consistent handling of subscription data.
class/subscription.php Introduced additional_cpt_options meta field in get_subscription_meta and save_form_meta methods, updated insert_free_pack_subscribers and enhanced non-recurring subscription methods.
includes/Admin/Admin_Subscription.php Modified third_party_cpt_options and enqueue_admin_scripts methods for improved data storage and script handling, refined logic in profile_subscription_update.
includes/Ajax/Frontend_Form_Ajax.php Introduced $form_fields property, expanded submit_post method to include content restrictions and improved handling of guest posts and subscription pack checks.
includes/Api/Subscription.php Updated create_or_update_item method to handle additional_cpt_options, enhancing subscription management capabilities.
includes/Traits/TaxableTrait.php Enhanced tax calculation methods to ensure robust handling of tax rates and defaults.
includes/User_Subscription.php Introduced $additional_cpt_options in add_pack method for improved handling of subscription packs and expiration settings.

Assessment against linked issues

Objective Addressed Explanation
Fix publish time input option in the Date/Time field ( #637 ) Unclear if changes directly address this issue.

Possibly related PRs

Suggested labels

bug, needs: developer feedback

Poem

🐇 In the meadow where subscriptions grow,
New fields sprout, as updates flow.
With options added, and logic refined,
A brighter path for users we find.
Hooray for the changes, let’s hop with glee,
For a smoother journey, just wait and see! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Outside diff range and nitpick comments (19)
includes/Api/Subscription.php (1)

422-424: LGTM! Consider adding a comment for clarity.

The addition of additional_cpt_options is well-implemented and aligns with the PR objective to support additional CPTs. The value is properly sanitized before being used.

Consider adding a brief comment explaining the purpose of additional_cpt_options for better code readability:

+        // Store additional custom post type options for extended functionality
         update_post_meta( $id, 'additional_cpt_options', $additional_cpt_options );

Also applies to: 499-499

includes/Ajax/Frontend_Form_Ajax.php (9)

Line range hint 47-93: Use of strlen() May Not Handle Multibyte Characters Correctly

The strlen() function counts bytes rather than characters, which can lead to incorrect character counts for multibyte character sets like UTF-8. This may result in validation errors for users inputting non-ASCII characters. Consider using mb_strlen() to accurately count the number of characters.

Apply this diff to replace strlen() with mb_strlen():

 if ( 'character' === $restriction_type && 'min' === $restriction_to ) {
-    if ( strlen( $current_data ) > 0 && strlen( $current_data ) < $restricted_num ) {
+    if ( mb_strlen( $current_data ) > 0 && mb_strlen( $current_data ) < $restricted_num ) {
         wpuf()->ajax->send_error(
             sprintf(
                 __( 'Minimum %d character is required for %s', 'wp-user-frontend' ), $restricted_num, $label
             )
         );
     }
 } elseif ( 'character' === $restriction_type && 'max' === $restriction_to ) {
-    if ( strlen( $current_data ) > 0 && strlen( $current_data ) > $restricted_num ) {
+    if ( mb_strlen( $current_data ) > 0 && mb_strlen( $current_data ) > $restricted_num ) {
         wpuf()->ajax->send_error(
             sprintf(
                 __( 'Maximum %d character is allowed for %s', 'wp-user-frontend' ), $restricted_num, $label
             )
         );
     }
 }

Line range hint 47-93: str_word_count() May Not Accurately Count Words in All Languages

The str_word_count() function may not correctly count words in languages that use multibyte characters or non-Latin scripts. This could lead to inaccurate validation for such users. Consider using a more robust method or a library that supports multibyte string word counts.

As an alternative, you might use mb_strlen() in conjunction with regex patterns to count words accurately:

$word_count = preg_match_all( '/\pL+/u', $current_data, $matches );

Line range hint 70-93: Error Messages Lack Proper Pluralization

The error messages do not account for singular and plural forms, which may cause grammatical inaccuracies. Utilize the _n() function to handle pluralization in translations, providing a better user experience.

Apply this diff to implement pluralization:

 // For character count restrictions
- __( 'Minimum %d character is required for %s', 'wp-user-frontend' )
+ sprintf( _n( 'Minimum %d character is required for %s', 'Minimum %d characters are required for %s', $restricted_num, 'wp-user-frontend' ), $restricted_num, $label )

 // Similarly for other messages
- __( 'Maximum %d word is allowed for %s', 'wp-user-frontend' )
+ sprintf( _n( 'Maximum %d word is allowed for %s', 'Maximum %d words are allowed for %s', $restricted_num, 'wp-user-frontend' ), $restricted_num, $label )

Line range hint 47-93: Refactor Content Restriction Logic to Reduce Duplication

The content restriction checks for character and word counts contain repetitive code blocks for each condition. Refactoring this logic into a single function or using a mapping strategy can enhance readability and maintainability.

Consider creating a helper function to handle the restriction checks:

private function check_content_restriction( $restriction_type, $restriction_to, $restricted_num, $current_data, $label ) {
    // Implement combined logic here
}

Line range hint 95-114: Ensure Multibyte Support in Shortcode Restriction Checks

When checking for restricted shortcodes, using strpos() may not accurately detect shortcodes with multibyte characters. Consider using mb_strpos() for multibyte support.

Apply this diff to use mb_strpos():

 if ( mb_strpos( $current_data, $search_for ) !== false ) {
     wpuf()->ajax->send_error( sprintf( __( 'Using %s as shortcode is restricted', 'wp-user-frontend' ), $shortcode ) );
 }

Line range hint 550-565: Inconsistent Error Handling Method

The code uses echo json_encode() followed by die() to return an error, which is inconsistent with the use of wpuf()->ajax->send_error() elsewhere. This may lead to confusion and potential maintenance issues. Align the error handling mechanism for consistency.

Apply this diff to standardize error handling:

- echo json_encode(
-     [
-         'success' => false,
-         'error'   => __( 'Invalid email address.', 'wp-user-frontend' ),
-     ]
- );
- die();
+ wpuf()->ajax->send_error( __( 'Invalid email address.', 'wp-user-frontend' ) );

Line range hint 550-580: Remove Commented-Out Code for Cleanliness

There are blocks of commented-out code which may clutter the source and hinder readability. It's good practice to remove such code if it's no longer needed, as version control systems keep track of code changes.

Apply this diff to remove unnecessary commented code:

- //                    $this->send_error( __( 'Invalid email address.', 'wp-user-frontend' ) );
- //                    wp_send_json(
- //                        [
- //                            'success'     => false,
- //                            'error'       => __( "You already have an account in our site. Please login to continue.\n\nClicking 'OK' will redirect you to the login page and you will lose the form data.\nClick 'Cancel' to stay at this page.", 'wp-user-frontend' ),
- //                            'type'        => 'login',
- //                            'redirect_to' => wp_login_url( get_permalink( $page_id ) ),
- //                        ]
- //                    );
- // wpuf()->ajax->send_error( __( 'Invalid email address.', 'wp-user-frontend' ) );

Line range hint 600-648: Sanitize User Input When Registering New Users

When creating a new user account, ensure all user-provided data, such as $username, is properly sanitized to prevent security issues like SQL injection or invalid usernames.

Apply this diff to sanitize the username:

$errors = new WP_Error();

+ $username = sanitize_user( $username );

do_action( 'register_post', $username, $guest_email, $errors );

Line range hint 744-773: Potential Undefined Index in Custom Field Replacement

In the prepare_mail_body() method, when replacing custom fields in the email content, there might be cases where $matches does not contain expected indices, potentially causing an undefined index notice. Add checks to ensure indices exist before using them.

Apply this diff to prevent undefined index errors:

- [ $search, $replace ] = $matches;
+ if ( isset( $matches[0], $matches[1] ) ) {
+     $search  = $matches[0];
+     $replace = $matches[1];
+ } else {
+     $search  = [];
+     $replace = [];
+ }
class/subscription.php (2)

296-296: Inconsistent meta key naming for 'additional_cpt_options'

The meta key 'additional_cpt_options' is not prefixed with an underscore, unlike other meta keys in this method (e.g., '_billing_amount'). For consistency and to follow WordPress conventions, consider prefixing the meta key with an underscore.


Line range hint 597-612: Incorrect usage of $userdata object in insert_free_pack_subscribers

The method insert_free_pack_subscribers is accessing properties of the $userdata object incorrectly. User ID should be accessed via $userdata->ID, and display name via $userdata->display_name. Currently, the code uses $userdata->id and $userdata->user->data->display_name, which may not retrieve the correct information.

Apply this diff to correct the property accesses:

-public function insert_free_pack_subscribers( $pack_id, $userdata ) {
+public function insert_free_pack_subscribers( $pack_id, $user ) {
    global $wpdb;

    $subscription = wpuf()->subscription->get_subscription( $pack_id );

-    if ( $userdata->id && $subscription ) {
-        $user_sub             = self::get_user_pack( $userdata->id );
+    if ( $user->ID && $subscription ) {
+        $user_sub             = self::get_user_pack( $user->ID );
        $post_expiration_time = wpuf_date2mysql( $user_sub['expire'] );

        $table_data = [
-            'user_id'             => $userdata->id,
-            'name'                => $userdata->user->data->display_name,
+            'user_id'             => $user->ID,
+            'name'                => $user->display_name,
            'subscribtion_id'     => $pack_id,
            'subscribtion_status' => 'free',
            'gateway'             => 'free',
            'transaction_id'      => 'free',
            'starts_from'         => gmdate( 'd-m-Y' ),
            'expire'              => empty( $post_expiration_time ) ? 'recurring' : $post_expiration_time,
        ];

        $wpdb->insert( $wpdb->prefix . 'wpuf_subscribers', $table_data );
    }
}
includes/Admin/Admin_Subscription.php (7)

80-80: Undefined Index in Array

There is an extra comma at the end of the array on line 80, which could lead to a ParseError in PHP versions earlier than 7.3.

Remove the trailing comma to ensure compatibility with older PHP versions:

-    'default'       => '-1',
+    'default'       => '-1'

Line range hint 294-296: Inefficient Use of intval for Amount Comparison

In lines 294-296, you are using intval( $amount ) == 0 to check if the amount is zero. This might not handle string amounts correctly and could lead to unexpected results if $amount is not numeric.

Consider using a strict comparison and ensuring that $amount is properly sanitized and validated as a float:

-    if ( intval( $amount ) == 0 ) {
+    if ( floatval( $amount ) === 0.0 ) {

Also, ensure $amount is sanitized:

$amount = floatval( get_post_meta( $post_ID, '_billing_amount', true ) );

Line range hint 653-653: Unnecessary Escaping Function

On line 653, esc_attr is used when outputting a URL within admin_url(), but admin_url() already returns a safe URL, and echoing it within esc_attr() inside an HTML attribute is appropriate.

For clarity and correctness, use esc_url instead when outputting URLs:

-    echo esc_attr( admin_url( 'edit.php?post_type=wpuf_subscription' ) )
+    echo esc_url( admin_url( 'edit.php?post_type=wpuf_subscription' ) )

Line range hint 670-670: Avoid Using Deprecated Constructor Syntax

In line 670, you have an instance where the class name is used as a constructor. This syntax is deprecated as of PHP 7.0.

Ensure that all constructors use the __construct method instead of the class name. Review the class definitions and update accordingly.


Line range hint 727-731: Mismatch in Translation Function

In lines 727-731, the printf function is used without wrapping the placeholder text with a translation function, which can cause issues with localization.

Wrap the placeholder text within the translation function:

-__( 'You may use: %1$s %2$s %3$s %4$s %5$s', 'wp-user-frontend' ),
+printf(
+    __( 'You may use: %1$s %2$s %3$s %4$s %5$s', 'wp-user-frontend' ),
+    '{post_author}',
+    '{post_url}',
+    '{blogname}',
+    '{post_title}',
+    '{post_status}'
)

Ensure that the placeholders are correctly passed to sprintf() or printf().


Line range hint 1399-1401: Potential Variable Collision

In lines 1399-1401, the variable $fields is being redefined multiple times throughout the method. This can lead to confusion and potential errors.

Consider renaming the variables or combining the arrays to prevent overwriting:

$fields = [
    'subscription_details'   => array_merge( $overview_fields, $access_fields, $expiration_fields ),
    'payment_settings'       => $payment_fields,
    'advanced_configuration' => array_merge( $content_limit_fields, $design_element_fields, $additional_options_fields ),
];

Line range hint 1561-1561: Hardcoded URL in Helper Text

On line 1561, there is a hardcoded URL within a translation function, which can cause issues if the URL needs to be updated or if it's different in other languages.

Use sprintf to separate the URL from the translatable text:

-__( 'Use the <a href="%s">classic UI</a>.', 'wp-user-frontend' ), admin_url( 'edit.php?post_type=wpuf_subscription' )
+sprintf(
+    __( 'Use the <a href="%s">classic UI</a>.', 'wp-user-frontend' ),
+    esc_url( admin_url( 'edit.php?post_type=wpuf_subscription' ) )
+)

Also, ensure that esc_url is used to sanitize the URL.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9466787 and 7abde4c.

⛔ Files ignored due to path filters (1)
  • assets/js/subscriptions.min.js is excluded by !**/*.min.js
📒 Files selected for processing (9)
  • assets/js/stores/subscription.js (1 hunks)
  • class/subscription.php (2 hunks)
  • includes/Admin/Admin_Subscription.php (1 hunks)
  • includes/Admin/Forms/Form.php (0 hunks)
  • includes/Admin/Subscription.php (2 hunks)
  • includes/Ajax/Frontend_Form_Ajax.php (1 hunks)
  • includes/Api/Subscription.php (2 hunks)
  • includes/Traits/TaxableTrait.php (1 hunks)
  • includes/User_Subscription.php (1 hunks)
💤 Files with no reviewable changes (1)
  • includes/Admin/Forms/Form.php
🔇 Additional comments (3)
assets/js/stores/subscription.js (1)

Line range hint 1-458: Ensure alignment with PR objectives and conduct thorough testing

The changes in the modifyCurrentSubscription method appear to be aimed at improving the handling of custom post type options, which aligns with the PR objective of enhancing support for additional CPTs. However, it's crucial to ensure that this change fully addresses the issue of new options not being recognized by the subscription module.

To validate that the changes meet the PR objectives and don't introduce unintended side effects:

  1. Test the integration with plugins that generate new additional options:

    • Install a plugin that generates additional options.
    • Verify that these new options are correctly recognized and processed by the subscription module.
    • Ensure that existing additional options continue to function as expected.
  2. Check for any impacts on the publish time input option mentioned in the linked issue Fix: publish time input option in the Date/Time field, is not working… #637:

    • Verify that the publish time input in the Date/Time field is functioning correctly after these changes.
  3. Run comprehensive unit and integration tests focusing on subscription data handling, especially for custom post types and meta values.

Please provide the results of these tests to ensure the changes fully address the PR objectives without introducing new issues.

includes/Api/Subscription.php (1)

422-424: Verify usage of the new additional_cpt_options field

While the implementation looks good, it's important to ensure that other parts of the system can handle this new meta field.

Let's check if there are any other places in the codebase that might need to be updated to work with this new field:

Also applies to: 499-499

✅ Verification successful

Further verify the integration of additional_cpt_options with wpuf_subscription

The initial search did not reveal any get_post_meta calls related to wpuf_subscription. To ensure comprehensive coverage, please run the following additional checks:


Further investigate interactions between wpuf_subscription and additional_cpt_options

The previous search did not reveal any interactions between wpuf_subscription and additional_cpt_options. To ensure comprehensive verification, please run the following additional checks:


Usage of additional_cpt_options is properly verified

The additional_cpt_options field is consistently handled across the codebase without interfering with existing wpuf_subscription functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of 'additional_cpt_options' in PHP files
rg --type php 'additional_cpt_options'

# Search for get_post_meta calls that might need to include this new field
rg --type php 'get_post_meta.*wpuf_subscription'

Length of output: 1532


Script:

#!/bin/bash
# Search for any interactions between 'wpuf_subscription' and 'additional_cpt_options'
rg --type php 'wpuf_subscription.*additional_cpt_options'

Length of output: 59


Script:

#!/bin/bash
# Search for any usage of 'wpuf_subscription' in PHP files
rg --type php 'wpuf_subscription'

# Search for any usage of 'additional_cpt_options' in PHP files
rg --type php 'additional_cpt_options'

# Search for any functions or methods that handle both 'wpuf_subscription' and 'additional_cpt_options'
rg --type php 'wpuf_subscription.*additional_cpt_options|additional_cpt_options.*wpuf_subscription'

Length of output: 15508

class/subscription.php (1)

Line range hint 597-612: Verify usage of insert_free_pack_subscribers method

Please ensure that the newly added method insert_free_pack_subscribers is being called appropriately within the codebase so that free pack subscribers are properly inserted into the subscribers list.

Run the following script to check for calls to insert_free_pack_subscribers:

✅ Verification successful

Verified usage of insert_free_pack_subscribers method

The method insert_free_pack_subscribers is properly called in includes/User_Subscription.php as expected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for calls to `insert_free_pack_subscribers` method in PHP files.

# Test: Search for method calls to `insert_free_pack_subscribers`. Expect at least one occurrence.
rg --type php '->insert_free_pack_subscribers\s*\('

Length of output: 458


Script:

#!/bin/bash
# Description: Search for calls to `insert_free_pack_subscribers` method in PHP files using the correct rg syntax.

# Corrected Test: Search for method calls to `insert_free_pack_subscribers`. Expect at least one occurrence.
rg --type php -e '->insert_free_pack_subscribers\s*\('

Length of output: 180

Comment on lines 199 to 202
if ( typeof this.currentSubscription.meta_value[key] === 'string' ) {
this.currentSubscription.meta_value[key] = {};
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Conversion of meta_value[key] from String to Object Affects Multiple Components

The verification indicates that meta_value is utilized in various parts of the codebase. Changing meta_value[key] from a string to an object in the modifyCurrentSubscription method may lead to inconsistencies and unexpected behaviors in other components that expect it to be a string.

Potential Issues:

  1. Data Inconsistency: Other parts of the application may assume meta_value[key] is a string, leading to type errors or unexpected behavior.
  2. Data Loss: Converting a string to an empty object discards the original value, which could result in loss of important data.
  3. Lack of Error Handling: Without logging or error reporting, debugging issues related to this change may become challenging.

Recommendations:

  1. Preserve Original Data:
    if (typeof this.currentSubscription.meta_value[key] === 'string') {
      const originalValue = this.currentSubscription.meta_value[key];
      console.warn(`Converting meta_value[${key}] from string to object. Original value: ${originalValue}`);
      this.currentSubscription.meta_value[key] = { originalValue };
    }
  2. Audit Dependent Code: Review all instances where meta_value is used to ensure they handle the new object structure appropriately.
  3. Implement Comprehensive Logging: Add logging mechanisms to track when and why conversions occur, aiding in future debugging efforts.
  4. Investigate Root Cause: Determine why meta_value[key] is a string in the first place and address any underlying data handling inconsistencies.
🔗 Analysis chain

Ensure data integrity when converting meta_value[key] to an object

The added type check and conversion for meta_value[key] prevents errors when assigning properties to a string. However, there are some potential issues to consider:

  1. This change might alter existing data structures, affecting parts of the application that expect meta_value[key] to be a string.
  2. Converting to an empty object discards any existing string value, which could lead to data loss.

Consider the following improvements:

  1. Add error logging when this conversion occurs to aid in debugging:
if (typeof this.currentSubscription.meta_value[key] === 'string') {
  console.warn(`Converting meta_value[${key}] from string to object. Original value: ${this.currentSubscription.meta_value[key]}`);
  this.currentSubscription.meta_value[key] = {};
}
  1. Instead of converting to an empty object, consider preserving the original string value:
if (typeof this.currentSubscription.meta_value[key] === 'string') {
  const originalValue = this.currentSubscription.meta_value[key];
  this.currentSubscription.meta_value[key] = { originalValue };
}
  1. Investigate why meta_value[key] might be a string and address the root cause if possible.

To ensure this change doesn't introduce regressions, please run the following script to check for other occurrences of meta_value usage:

This will help identify other parts of the code that might be affected by this change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of meta_value in the codebase
rg --type js "meta_value" -C 3

Length of output: 11996

Comment on lines 178 to 179
$additional_cpt_options = ! empty( $subscription->meta_value['additional_cpt_options'] ) ? $subscription->meta_value['additional_cpt_options'] : [];

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use Null Coalescing Operator for Default Value Assignment

For improved readability and cleaner code, consider using the null coalescing operator ?? instead of the ! empty() check with a ternary operator.

Apply this diff:

-$additional_cpt_options = ! empty( $subscription->meta_value['additional_cpt_options'] ) ? $subscription->meta_value['additional_cpt_options'] : [];
+$additional_cpt_options = $subscription->meta_value['additional_cpt_options'] ?? [];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$additional_cpt_options = ! empty( $subscription->meta_value['additional_cpt_options'] ) ? $subscription->meta_value['additional_cpt_options'] : [];
$additional_cpt_options = $subscription->meta_value['additional_cpt_options'] ?? [];

includes/User_Subscription.php Outdated Show resolved Hide resolved
@@ -384,7 +384,7 @@ function wpuf_tax_rate_country_state( $country, $state ) {
continue;
}
if ( $rate['state'] === $state && $rate['country'] === $country ) {
$tax_amount = $rate['rate'];
$tax_amount = ! empty( $rate['rate'] ) ? $rate['rate'] : 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the check for 'rate' to accurately handle zero values

Using ! empty( $rate['rate'] ) may inadvertently treat a valid zero tax rate (0 or '0') as empty, causing $tax_amount to default to 0 even when a specific zero rate is intended. To ensure that zero rates are correctly assigned, consider using isset( $rate['rate'] ) instead.

Apply this diff to fix the condition:

-                    $tax_amount = ! empty( $rate['rate'] ) ? $rate['rate'] : 0;
+                    $tax_amount = isset( $rate['rate'] ) ? $rate['rate'] : 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$tax_amount = ! empty( $rate['rate'] ) ? $rate['rate'] : 0;
$tax_amount = isset( $rate['rate'] ) ? $rate['rate'] : 0;

Comment on lines 22 to 25
/**
* @var array
*/
private $form_fields;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Proper Documentation for New Property

The new private property $form_fields lacks a descriptive docblock explaining its purpose. Consider adding a meaningful description to enhance code readability and maintainability.

Apply this diff to add documentation:

 /**
- * @var array
+ * An array of form fields retrieved from the form configuration.
+ *
+ * @var array
  */
 private $form_fields;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @var array
*/
private $form_fields;
/**
* An array of form fields retrieved from the form configuration.
*
* @var array
*/
private $form_fields;

@@ -418,6 +419,7 @@ public function save_form_meta( $subscription_id, $post ) {
update_post_meta( $subscription_id, '_trial_duration', $trial_duration );
update_post_meta( $subscription_id, '_trial_duration_type', $trial_duration_type );
update_post_meta( $subscription_id, '_post_type_name', array_map( 'sanitize_text_field', $post_data['post_type_name'] ) );
update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure 'additional_cpt_options' exists in $post_data before accessing it

To prevent potential undefined index notices, please check if 'additional_cpt_options' exists in $post_data before accessing it.

Apply this diff to add the necessary check:

+if ( isset( $post_data['additional_cpt_options'] ) ) {
    update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
if ( isset( $post_data['additional_cpt_options'] ) ) {
update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
}

@@ -304,6 +304,7 @@ public static function get_subscription_meta( $subscription_id, $pack_post = nul
$meta['_trial_duration_type'] = $meta['trial_duration_type'];
$meta['post_type_name'] = get_post_meta( $subscription_id, '_post_type_name', true );
$meta['_post_type_name'] = $meta['post_type_name'];
$meta['additional_cpt_options'] = get_post_meta( $subscription_id, 'additional_cpt_options', true );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use consistent meta key naming with underscore prefix

In the existing code, meta keys are stored with an underscore prefix (e.g., _billing_amount, _expiration_number). For consistency and to prevent unintended exposure via the WordPress API, consider prefixing 'additional_cpt_options' with an underscore when retrieving the meta value.

Apply this diff to adjust the meta key:

-$meta['additional_cpt_options']     = get_post_meta( $subscription_id, 'additional_cpt_options', true );
+$meta['_additional_cpt_options']    = get_post_meta( $subscription_id, '_additional_cpt_options', true );
+$meta['additional_cpt_options']     = $meta['_additional_cpt_options'];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$meta['additional_cpt_options'] = get_post_meta( $subscription_id, 'additional_cpt_options', true );
$meta['_additional_cpt_options'] = get_post_meta( $subscription_id, '_additional_cpt_options', true );
$meta['additional_cpt_options'] = $meta['_additional_cpt_options'];

@@ -431,6 +432,7 @@
update_post_meta( $subscription_id, '_trial_duration', $trial_duration );
update_post_meta( $subscription_id, '_trial_duration_type', $trial_duration_type );
update_post_meta( $subscription_id, '_post_type_name', array_map( 'sanitize_text_field', $post_data['post_type_name'] ) );
update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add check for 'additional_cpt_options' existence before updating meta

To prevent undefined index notices, ensure that 'additional_cpt_options' exists in $post_data before using it. This check prevents potential PHP warnings if the key is not set. Additionally, consider prefixing the meta key with an underscore for consistency.

Apply this diff to add the necessary check and adjust the meta key:

+if ( ! empty( $post_data['additional_cpt_options'] ) && is_array( $post_data['additional_cpt_options'] ) ) {
+    $sanitized_options = array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] );
+    update_post_meta( $subscription_id, '_additional_cpt_options', $sanitized_options );
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
update_post_meta( $subscription_id, 'additional_cpt_options', array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] ) );
if ( ! empty( $post_data['additional_cpt_options'] ) && is_array( $post_data['additional_cpt_options'] ) ) {
$sanitized_options = array_map( 'sanitize_text_field', $post_data['additional_cpt_options'] );
update_post_meta( $subscription_id, '_additional_cpt_options', $sanitized_options );
}

Comment on lines +69 to +73
'id' => $key,
'name' => $key,
'db_key' => 'additional_cpt_options',
'db_type' => 'meta_serialized',
'serialize_key' => $key,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improper Use of Meta Keys and Serialization

The array keys 'db_key' and 'serialize_key' in lines 71 and 73 might cause confusion. You're setting 'db_key' to 'additional_cpt_options' and 'serialize_key' to $key, which could lead to inconsistent data storage and retrieval, especially when handling serialized meta values.

Consider refactoring to ensure that each custom post type option has a unique and coherent meta key. For example:

-    'db_key'        => 'additional_cpt_options',
-    'db_type'       => 'meta_serialized',
-    'serialize_key' => $key,
+    'db_key'        => 'additional_cpt_options_' . $key,
+    'db_type'       => 'meta',
+    'serialize_key' => null,

This change assigns a unique meta key for each post type option and avoids complex serialization.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'id' => $key,
'name' => $key,
'db_key' => 'additional_cpt_options',
'db_type' => 'meta_serialized',
'serialize_key' => $key,
'id' => $key,
'name' => $key,
'db_key' => 'additional_cpt_options_' . $key,
'db_type' => 'meta',
'serialize_key' => null,

Comment on lines 75 to 76
'label' => sprintf( 'Number of %s', esc_html( $post_type_object->label ) ),
'tooltip' => sprintf(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Internationalization (i18n) Issue in String Formatting

The usage of sprintf with plain strings on lines 75 and 76 isn't prepared for translation. Strings should be wrapped with __() or _e() before being passed to sprintf for proper localization.

Update the code to wrap the strings with translation functions:

-    'label'         => sprintf( 'Number of %s', esc_html( $post_type_object->label ) ),
-    'tooltip'       => sprintf(
-        'Set the maximum number of %s users can create within their subscription period. Enter -1 for unlimited',
+    'label'         => sprintf( __( 'Number of %s', 'wp-user-frontend' ), esc_html( $post_type_object->label ) ),
+    'tooltip'       => sprintf(
+        __( 'Set the maximum number of %s users can create within their subscription period. Enter -1 for unlimited', 'wp-user-frontend' ),

Committable suggestion was skipped due to low confidence.

@Rubaiyat-E-Mohammad
Copy link

Issue still exists. Please check the video @sapayth vai

@Rubaiyat-E-Mohammad Rubaiyat-E-Mohammad added bug needs: dev review This PR needs review by a developer QA Approved This PR is approved by the QA team Ready to Merge This PR is now ready to be merged and removed needs: testing bug needs: dev review This PR needs review by a developer labels Oct 11, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (6)
includes/Ajax/Frontend_Form_Ajax.php (6)

Line range hint 59-87: Use mb_strlen() for Multibyte Character Support

The use of strlen() may not correctly handle multibyte characters, leading to incorrect character counts for non-ASCII input. Consider using mb_strlen() to accurately count the number of characters in $current_data.

Apply this diff to replace strlen() with mb_strlen():

- if ( strlen( $current_data ) > 0 && strlen( $current_data ) < $restricted_num ) {
+ if ( mb_strlen( $current_data ) > 0 && mb_strlen( $current_data ) < $restricted_num ) {

Ensure that the mbstring PHP extension is enabled on the server.


Line range hint 71-87: Improve Word Count Handling for Internationalization

str_word_count() may not accurately count words in languages with multibyte characters or different word delimiters. This could lead to incorrect validation results for some users.

Consider using a more reliable method for word counting that supports multibyte characters:

$word_count = count( preg_split( '/\s+/u', $current_data, -1, PREG_SPLIT_NO_EMPTY ) );

Replace str_word_count( $current_data ) with $word_count for accurate word counts.


Line range hint 90-103: Use has_shortcode() for Accurate Shortcode Detection

Using strpos() to detect shortcodes may lead to false positives if the shortcode name appears in the content but not as an actual shortcode. The has_shortcode() function provides a reliable way to check for shortcodes in content.

Replace the shortcode detection logic with:

if ( ! empty( $current_data ) ) {
    foreach ( $protected_shortcodes as $shortcode ) {
        if ( has_shortcode( $current_data, $shortcode ) ) {
            wpuf()->ajax->send_error( sprintf( __( 'Using %s shortcode is restricted', 'wp-user-frontend' ), $shortcode ) );
        }
    }
}

Ensure that this code runs in a context where has_shortcode() is available.


Line range hint 536-544: Consistent Error Handling with wpuf()->ajax->send_error()

Using echo json_encode() followed by die(); is inconsistent with the rest of the codebase, which primarily uses wpuf()->ajax->send_error() for error responses. This inconsistency can lead to unexpected behavior and maintainability issues.

Replace the error handling code with:

wpuf()->ajax->send_error( __( 'Invalid email address.', 'wp-user-frontend' ) );

Remove the echo and die(); statements to maintain consistency.


Line range hint 536-544: Remove Commented-Out Code to Improve Readability

There are several blocks of commented-out code within the wpuf_get_post_user() method. Commented code can clutter the codebase and make it harder to maintain.

Consider removing the commented-out code unless it's necessary for future development.


Line range hint 604-608: Simplify Value Concatenation Logic in prepare_mail_body()

The logic used to concatenate values in the custom fields replacement section seems unnecessarily complex and may result in duplicated commas.

Review and simplify the concatenation logic to ensure accurate and clean replacement values. For example:

if ( is_array( $value ) ) {
    $original_value = implode( ', ', array_map( function ( $val ) {
        return wp_get_attachment_url( $val ) ?: $val;
    }, $value ) );
} else {
    $original_value = wp_get_attachment_url( $value ) ?: $value;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c921651 and dff2c51.

📒 Files selected for processing (2)
  • includes/Admin/Forms/Form.php (0 hunks)
  • includes/Ajax/Frontend_Form_Ajax.php (1 hunks)
💤 Files with no reviewable changes (1)
  • includes/Admin/Forms/Form.php
🧰 Additional context used
🔇 Additional comments (3)
includes/Ajax/Frontend_Form_Ajax.php (3)

24-27: Good Documentation Added for $form_fields

The docblock for the new private property $form_fields clearly explains its purpose, enhancing code readability and maintainability.


Line range hint 53-55: Proper Initialization of $this->form_fields

Storing the form fields in the class property $this->form_fields improves code organization and allows for easier access throughout the class methods.


Line range hint 151-151: Verify PHP Version Compatibility for Array Destructuring

The use of array destructuring with the list syntax requires PHP 7.1 or higher. Ensure that the minimum PHP version requirement for this project is at least 7.1 to avoid compatibility issues.

Check the project's PHP version compatibility by reviewing the server configuration or project documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
QA Approved This PR is approved by the QA team Ready to Merge This PR is now ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants