Skip to content

Sales API Phase 2#2318

Merged
Crabcyborg merged 10 commits into
masterfrom
sales_api_phase_2
Apr 30, 2025
Merged

Sales API Phase 2#2318
Crabcyborg merged 10 commits into
masterfrom
sales_api_phase_2

Conversation

@Crabcyborg
Copy link
Copy Markdown
Contributor

@Crabcyborg Crabcyborg commented Apr 17, 2025

Fixes https://github.com/Strategy11/formidable-pro/issues/5569

TODO

  • The inbox count icon displayed in the menu will include active sales banners that have not yet been dismissed, adding 1 to the current inbox count displayed.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2025

## Walkthrough

A new banner display mechanism was integrated into the admin interface. The `FrmSalesApi` class now includes a `maybe_show_banner` method, which determines if a sale banner should be shown and outputs it with customizable content and styles. The `FrmAppHelper::print_admin_banner` method was updated to call this new method early, preventing other banners from displaying if the sale banner is shown. Additionally, new CSS rules were introduced to style the sale banner and its elements for consistent appearance in the admin area. JavaScript was added to handle click and dismiss interactions on the sale banner in the admin UI. An AJAX action hook was registered to handle banner dismissal requests.

## Changes

| File(s)                           | Change Summary                                                                                                      |
|----------------------------------|---------------------------------------------------------------------------------------------------------------------|
| classes/models/FrmSalesApi.php   | Added `maybe_show_banner` method to output a customizable sale banner; added `dismiss_banner` and `is_banner_dismissed` methods; extended `fill_sale` with banner-related fields. |
| classes/helpers/FrmAppHelper.php | Updated `print_admin_banner` to call `FrmSalesApi::maybe_show_banner` and return early if a sale banner is shown.   |
| css/frm_admin.css                | Added CSS rules for styling the new `#frm_sale_banner` and its child elements.                                      |
| js/formidable_admin.js           | Added event listeners to handle click and dismiss actions on the sale banner element in the admin interface.        |
| classes/controllers/FrmHooksController.php | Registered new AJAX action hook `wp_ajax_frm_sale_banner_dismiss` mapped to `FrmSalesApi::dismiss_banner`.          |
| resources/scss/admin/components/sales/banner.scss | Added SCSS styles for the sale banner component defining layout and appearance.                                    |
| resources/scss/admin/frm_admin.scss | Added import statement for the new sales banner SCSS component.                                                    |
| .gitignore                      | Updated to ignore JavaScript source map files (`**/*.js.map`).                                                     |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant AdminUser
    participant FrmAppHelper
    participant FrmSalesApi

    AdminUser->>FrmAppHelper: print_admin_banner()
    FrmAppHelper->>FrmSalesApi: maybe_show_banner()
    FrmSalesApi->>FrmSalesApi: Check for active sale with banner fields
    alt Sale banner found
        FrmSalesApi->>AdminUser: Output sale banner HTML
        FrmSalesApi-->>FrmAppHelper: return true
        FrmAppHelper-->>AdminUser: return (no further banners)
    else No sale banner
        FrmSalesApi-->>FrmAppHelper: return false
        FrmAppHelper->>FrmAppHelper: Continue with other banner checks
    end

Possibly related PRs

  • New sales API #2205: Adds the call to FrmSalesApi::maybe_show_banner() inside FrmAppHelper::print_admin_banner, directly related to the new banner display logic in FrmSalesApi.
  • Move AJAX hooks into load_ajax_hooks function #2091: Adds AJAX action hook registration in FrmHooksController for dismissing the sale banner, related to the dismissal functionality added here.

Suggested labels

deploy

Suggested reviewers

  • truongwp
  • tuguirazvan

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Strategy11/formidable-forms&utm_content=2318):

- 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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this 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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (4)
css/frm_admin.css (4)

10152-10159: Consider extracting banner dimensions into variables
The container uses a hard‑coded height: 90px. For consistency with the design system, consider defining a custom property such as --sale-banner-height and referencing it here.


10161-10165: Make the icon container width responsive
Setting width: 150px may cause overflow on narrow screens. You could switch to a relative or max width (e.g. max-width: 20% or use a breakpoint rule) to ensure the icon always stays visible.


10171-10174: Use design token for horizontal spacing
Instead of margin-right: 50px, prefer a gap variable for consistency (var(--gap-md) or var(--gap-lg)).

- margin-left: auto;
- margin-right: 50px;
+ margin-left: auto;
+ margin-right: var(--gap-md);

10176-10192: Enhance CTA link styling for accessibility and theming
The CTA uses static colors (#fff/#000) and lacks hover/focus feedback. Switch to theme variables and add interactive states:

- background-color: #fff;
- color: #000;
+ background-color: var(--primary-500);
+ color: var(--primary-25);
+
+ /* Interactive states */
+ &:hover,
+ &:focus {
+   background-color: var(--primary-700);
+   outline: 2px solid var(--primary-700);
+   color: var(--primary-25);
+ }

This will improve contrast, maintain design consistency, and provide necessary keyboard focus visibility.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05b6a15 and d74579e.

⛔ Files ignored due to path filters (8)
  • images/sales/anniversary.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/back-to-school.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/black-friday.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/fall.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/geek-week.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/generic.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/no-brainer.svg is excluded by !**/*.svg, !**/*.svg
  • images/sales/summer.svg is excluded by !**/*.svg, !**/*.svg
📒 Files selected for processing (3)
  • classes/helpers/FrmAppHelper.php (1 hunks)
  • classes/models/FrmSalesApi.php (2 hunks)
  • css/frm_admin.css (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
classes/models/FrmSalesApi.php (1)
classes/helpers/FrmAppHelper.php (4)
  • FrmAppHelper (6-4478)
  • admin_upgrade_link (121-162)
  • array_to_html_params (1338-1347)
  • plugin_url (65-68)
🔇 Additional comments (3)
classes/models/FrmSalesApi.php (2)

127-135: Well-structured field additions for banner customization.

The new default fields for banners are well-organized and provide comprehensive customization options for sale banners including title, body, colors, and CTA elements.


239-331: Solid implementation of the banner display mechanism.

The maybe_show_banner method is well-implemented with:

  • Proper singleton instance handling
  • Validation of required banner fields (title and body)
  • Default values for optional attributes
  • Secure output with proper escaping via FrmAppHelper::array_to_html_params
  • Clean HTML structure for the banner

The method effectively constructs a customizable banner UI with appropriate styling options and clickable behavior. The gradual fallback for CSS attributes (like colors and links) is a nice touch.

I would suggest adding a dismissible option in a future update as mentioned in the PR objectives ("sales banners should be made dismissible").

classes/helpers/FrmAppHelper.php (1)

1420-1422: Good integration with existing banner system.

The code correctly checks if the sales banner should be displayed early in the function, preventing other banners from showing if a sales banner is displayed. This creates a clean priority system for banner display.

@Crabcyborg Crabcyborg added this to the 6.21 milestone Apr 17, 2025
Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (2)
classes/models/FrmSalesApi.php (2)

239-246: Update version in PHPDoc comment

The PHPDoc comment uses a placeholder version number "x.x" which should be updated with the actual version number before release.

- * @since x.x
+ * @since 6.x

346-347: Update version in PHPDoc comment

Similar to the earlier method, update the placeholder version number in the PHPDoc comment.

- * @since x.x
+ * @since 6.x
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 843dada and 1263a48.

📒 Files selected for processing (3)
  • classes/controllers/FrmHooksController.php (1 hunks)
  • classes/models/FrmSalesApi.php (2 hunks)
  • js/formidable_admin.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • js/formidable_admin.js
🧰 Additional context used
🧬 Code Graph Analysis (1)
classes/models/FrmSalesApi.php (1)
classes/helpers/FrmAppHelper.php (6)
  • FrmAppHelper (6-4474)
  • admin_upgrade_link (121-162)
  • array_to_html_params (1338-1347)
  • plugin_url (65-68)
  • icon_by_class (1199-1236)
  • permission_check (2063-2071)
🔇 Additional comments (5)
classes/models/FrmSalesApi.php (4)

127-135: New banner display fields added correctly

The new default fields for the banner display have been properly added to the fill_sale method, providing all necessary configuration options for customizing the banner appearance and content.


246-341: Banner display implementation looks good

The implementation correctly:

  • Checks for valid sales data and required fields
  • Verifies if the user has already dismissed the banner
  • Applies appropriate fallbacks for optional configuration values
  • Properly escapes output with esc_html and esc_attr
  • Uses the array_to_html_params helper method for attribute generation
  • Returns boolean to indicate whether a banner was shown

This approach allows for flexible banner configuration with sensible defaults.


348-370: Banner dismissal AJAX handler implemented securely

The implementation correctly:

  • Verifies user permissions with FrmAppHelper::permission_check
  • Validates the request with nonce checking
  • Properly updates user options
  • Returns appropriate JSON responses

Good security practices are followed throughout this method.


372-379: Well-implemented helper method

This helper method correctly checks if a user has dismissed a specific sale banner, with proper validation of the dismissed sales array.

classes/controllers/FrmHooksController.php (1)

307-307: AJAX hook correctly registered

The AJAX action hook for dismissing the sale banner has been properly registered, following the same pattern as other AJAX hooks in this file. This allows the banner dismissal functionality to work in the admin interface.

Copy link
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (4)
classes/models/FrmSalesApi.php (4)

239-246: Update version placeholder in PHPDoc.

The @since x.x in the PHPDoc should be updated with the actual version number.

- * @since x.x
+ * @since 6.18

286-343: Consider breaking down the maybe_show_banner method into smaller functions.

This method is quite long and handles multiple responsibilities: attribute preparation, HTML generation, and conditional logic. Consider refactoring it into smaller helper methods for better maintainability.

 public static function maybe_show_banner() {
     if ( ! isset( self::$instance ) ) {
         self::$instance = new FrmSalesApi();
     }

     $sale = self::$instance->get_best_sale();
     if ( ! $sale || ! is_array( $sale ) ) {
         return false;
     }

     if ( ! self::should_show_banner( $sale ) ) {
         return false;
     }

     self::render_banner( $sale );
     return true;
 }

+/**
+ * Check if the banner should be shown based on sale data and dismissal status
+ *
+ * @since 6.18
+ * @param array $sale The sale data
+ * @return bool
+ */
+private static function should_show_banner( $sale ) {
+    $banner_title = ! empty( $sale['banner_title'] ) ? $sale['banner_title'] : false;
+    $banner_body  = ! empty( $sale['banner_body'] ) ? $sale['banner_body'] : false;
+
+    if ( false === $banner_title || false === $banner_body ) {
+        return false;
+    }
+
+    return ! self::is_banner_dismissed( $sale['key'] );
+}
+
+/**
+ * Render the banner HTML
+ *
+ * @since 6.18
+ * @param array $sale The sale data
+ * @return void
+ */
+private static function render_banner( $sale ) {
+    $banner_attrs = self::get_banner_attributes( $sale );
+    $content_attrs = self::get_content_attributes( $sale );
+    $cta_attrs = self::get_cta_attributes( $sale );
+    $dismiss_attrs = self::get_dismiss_attributes( $sale );
+    $banner_icon = ! empty( $sale['banner_icon'] ) ? $sale['banner_icon'] : 'generic';
+    $banner_title = $sale['banner_title'];
+    $banner_body = $sale['banner_body'];
+    $banner_cta_text = ! empty( $sale['banner_cta_text'] ) ? $sale['banner_cta_text'] : sprintf( __( 'GET %s OFF NOW', 'formidable' ), $sale['discount_percent'] . '%' );

348-350: Update version placeholder in PHPDoc for dismiss_banner method.

Similar to the previous method, update the @since x.x in the PHPDoc with the actual version number.

- * @since x.x
+ * @since 6.18

374-381: Missing PHPDoc @since tag for is_banner_dismissed method.

Add a @since tag to maintain consistency with other methods.

 /**
  * @param string $key
  * @return bool
+ * @since 6.18
  */
 private static function is_banner_dismissed( $key ) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f2b91e9 and 97256d7.

📒 Files selected for processing (1)
  • classes/models/FrmSalesApi.php (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: PHP 7.4 tests in WP trunk
  • GitHub Check: PHP 8 tests in WP trunk
  • GitHub Check: Cypress
🔇 Additional comments (4)
classes/models/FrmSalesApi.php (4)

127-135: Banner properties added to the sale defaults look good.

The new banner-related fields have been properly added to the defaults array, providing a complete set of customization options for the sale banners.


246-265: Error handling looks good for banner validation.

The implementation properly checks for the presence of the instance, an active sale, and required banner content before proceeding. Early returns prevent unnecessary code execution when conditions aren't met.


267-284: Default values and fallbacks are well implemented.

The code provides sensible defaults for optional banner properties and generates a default CTA link using the existing upgrade link helper when none is provided.


350-372: Security checks in dismiss_banner are well implemented.

The method properly checks user permissions and the AJAX nonce before processing the dismissal request, which is good security practice.

Comment thread classes/models/FrmSalesApi.php
@Crabcyborg Crabcyborg merged commit 148b3e4 into master Apr 30, 2025
15 of 16 checks passed
@Crabcyborg Crabcyborg deleted the sales_api_phase_2 branch April 30, 2025 16:54
This was referenced Oct 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant