From d9e182cd6ed553190f02dcb5648e1bea6915d4be Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 16 Jun 2025 13:35:48 +0300 Subject: [PATCH 001/338] Add a new UI\Branding class --- classes/ui/class-branding.php | 35 +++++++++++++++++++++++++++++++++++ views/admin-page-header.php | 8 +------- views/admin-page-settings.php | 8 +------- 3 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 classes/ui/class-branding.php diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php new file mode 100644 index 000000000..97b41d95e --- /dev/null +++ b/classes/ui/class-branding.php @@ -0,0 +1,35 @@ +the_asset( + \progress_planner()->is_pro_site() + ? 'images/logo_progress_planner_pro.svg' + : 'images/logo_progress_planner.svg' + ); + } +} diff --git a/views/admin-page-header.php b/views/admin-page-header.php index 435c59b2e..53c2bf55e 100644 --- a/views/admin-page-header.php +++ b/views/admin-page-header.php @@ -19,13 +19,7 @@ ?>
diff --git a/views/admin-page-settings.php b/views/admin-page-settings.php index 9dee69448..96cde80a4 100644 --- a/views/admin-page-settings.php +++ b/views/admin-page-settings.php @@ -14,13 +14,7 @@

From 96c958dcbe81e8e9aa12c87ea4427aef5cb7cd75 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 16 Jun 2025 13:45:07 +0300 Subject: [PATCH 002/338] Make the color-palette filterable --- assets/css/admin.css | 26 -------------------- classes/admin/class-page.php | 1 + classes/ui/class-branding.php | 45 +++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index ce430cbbb..586a49c26 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -12,32 +12,6 @@ --prpl-container-max-width: calc(var(--prpl-column-min-width) * var(--prpl-max-columns) + var(--prpl-gap) * (var(--prpl-max-columns) - 1) + var(--prpl-column-min-width)); - --prpl-color-gray-1: #e1e3e7; - --prpl-color-gray-2: #d1d5db; - --prpl-color-gray-3: #9ca3af; - --prpl-color-gray-4: #6b7280; - --prpl-color-gray-5: #4b5563; - --prpl-color-gray-6: #374151; - - --prpl-color-accent-red: #f43f5e; - --prpl-color-accent-orange: #faa310; - --prpl-color-400-orange: #f9b23c; - --prpl-color-accent-purple: #0d6b9e; - --prpl-color-accent-green: #14b8a6; - - --prpl-color-headings: #38296d; - --prpl-color-text: var(--prpl-color-gray-5); - --prpl-color-link: #1e40af; - - --prpl-color-notification-green: #16a34a; - --prpl-color-notification-red: #e73136; - - --prpl-background-orange: #fff9f0; - --prpl-background-purple: #f6f5fb; - --prpl-background-green: #f2faf9; - --prpl-background-red: #fff6f7; - --prpl-background-blue: #effbfe; - --prpl-font-size-xs: 0.75rem; /* 12px */ --prpl-font-size-small: 0.875rem; /* 14px */ --prpl-font-size-base: 1rem; /* 16px */ diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index bfb88e35d..db566d515 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -276,6 +276,7 @@ public function enqueue_styles() { } \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/admin' ); + \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/web-components/prpl-tooltip' ); if ( 'progress-planner_page_progress-planner-settings' === $current_screen->id ) { diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 97b41d95e..5c04ca64e 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -32,4 +32,49 @@ public static function the_logo(): void { : 'images/logo_progress_planner.svg' ); } + + /** + * Get the color palette. + * + * @return string + */ + public static function get_color_palette(): string { + $palette = \apply_filters( + 'progress_planner_color_palette', + [ + '--prpl-color-gray-1' => '#e1e3e7', + '--prpl-color-gray-2' => '#d1d5db', + '--prpl-color-gray-3' => '#9ca3af', + '--prpl-color-gray-4' => '#6b7280', + '--prpl-color-gray-5' => '#4b5563', + '--prpl-color-gray-6' => '#374151', + + '--prpl-color-accent-red' => '#f43f5e', + '--prpl-color-accent-orange' => '#faa310', + '--prpl-color-400-orange' => '#f9b23c', + '--prpl-color-accent-purple' => '#0d6b9e', + '--prpl-color-accent-green' => '#14b8a6', + + '--prpl-color-headings' => '#38296d', + '--prpl-color-text' => 'var(--prpl-color-gray-5)', + '--prpl-color-link' => '#1e40af', + + '--prpl-color-notification-green' => '#16a34a', + '--prpl-color-notification-red' => '#e73136', + + '--prpl-background-orange' => '#fff9f0', + '--prpl-background-purple' => '#f6f5fb', + '--prpl-background-green' => '#f2faf9', + '--prpl-background-red' => '#fff6f7', + '--prpl-background-blue' => '#effbfe', + ] + ); + + $palette_string = ''; + foreach ( $palette as $key => $value ) { + $palette_string .= $key . ': ' . $value . ';'; + } + + return ":root { $palette_string }"; + } } From ad42892d32c51693a856a3a9fd0e870b8d070c4d Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 16 Jun 2025 13:50:32 +0300 Subject: [PATCH 003/338] Add method for the menu branding --- classes/admin/class-page.php | 2 +- classes/ui/class-branding.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index db566d515..429fc64e0 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -96,7 +96,7 @@ public function add_page() { 'manage_options', $page_identifier, [ $this, 'render_page' ], - 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4=' + \progress_planner()->get_ui__branding()->get_admin_menu_icon() ); // Wipe notification bits from hooks. diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 5c04ca64e..7e6909e38 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -77,4 +77,21 @@ public static function get_color_palette(): string { return ":root { $palette_string }"; } + + /** + * Get the admin-menu icon. + * + * @return string + */ + public static function get_admin_menu_icon(): string { + $icon = 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4='; + + /** + * Filter the admin-menu icon. + * + * @param string $icon The icon. + * @return string + */ + return \apply_filters( 'progress_planner_admin_menu_icon', $icon ); + } } From 1ecd9b38b64e1100d4ad44e7506fa8c841330767 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 16 Jun 2025 13:51:06 +0300 Subject: [PATCH 004/338] inline docs tweak --- classes/class-base.php | 1 + classes/ui/class-branding.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/classes/class-base.php b/classes/class-base.php index c40f1df5e..21775f83f 100644 --- a/classes/class-base.php +++ b/classes/class-base.php @@ -37,6 +37,7 @@ * @method \Progress_Planner\Plugin_Migrations get_plugin_migrations() * @method \Progress_Planner\Suggested_Tasks get_suggested_tasks() * @method \Progress_Planner\Suggested_Tasks_DB get_suggested_tasks_db() + * @method \Progress_Planner\UI\Branding get_ui__branding() */ class Base { diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 7e6909e38..e2969bd6e 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -39,6 +39,12 @@ public static function the_logo(): void { * @return string */ public static function get_color_palette(): string { + /** + * Filter the color palette. + * + * @param array $palette The palette. + * @return array + */ $palette = \apply_filters( 'progress_planner_color_palette', [ From 5ac29dc8acad73e47a88658a10bf524245a825b6 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 18 Jun 2025 13:14:41 +0300 Subject: [PATCH 005/338] Filter strings --- classes/ui/class-branding.php | 20 ++++++++++++++++++++ views/dashboard-widgets/score.php | 2 +- views/page-widgets/suggested-tasks.php | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index e2969bd6e..99c3314f7 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -100,4 +100,24 @@ public static function get_admin_menu_icon(): string { */ return \apply_filters( 'progress_planner_admin_menu_icon', $icon ); } + + /** + * Get an array of strings used for branding purposes. + * + * @return array + */ + public static function get_strings(): array { + /** + * Filter the strings used for branding purposes. + * + * @param array $strings The strings. + * @return array + */ + return \apply_filters( + 'progress_planner_branding_strings', + [ + 'ravi-recommendations' => __( 'Ravi\'s Recommendations', 'progress-planner' ), + ] + ); + } } diff --git a/views/dashboard-widgets/score.php b/views/dashboard-widgets/score.php index 5474fb318..9e56167c0 100644 --- a/views/dashboard-widgets/score.php +++ b/views/dashboard-widgets/score.php @@ -43,7 +43,7 @@
-

+

get_ui__branding()->get_strings()['ravi-recommendations'] ); ?>

    diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index 3909a2d4c..996c0efac 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -17,7 +17,7 @@

    - + get_ui__branding()->get_strings()['ravi-recommendations'] ); ?>

    From e3acb7fbff4f5e154df8ce8aba587321887a9c05 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 23 Jun 2025 08:37:52 +0300 Subject: [PATCH 006/338] Filtering "Ravi" --- .../interactive/class-email-sending.php | 7 ++++--- classes/ui/class-branding.php | 2 +- views/page-widgets/suggested-tasks.php | 16 ++++++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/classes/suggested-tasks/providers/interactive/class-email-sending.php b/classes/suggested-tasks/providers/interactive/class-email-sending.php index c036defee..8b815f824 100644 --- a/classes/suggested-tasks/providers/interactive/class-email-sending.php +++ b/classes/suggested-tasks/providers/interactive/class-email-sending.php @@ -120,9 +120,10 @@ public function init() { $this->email_subject = \esc_html__( 'Your Progress Planner test message!', 'progress-planner' ); $this->email_content = sprintf( - // translators: %1$s the admin URL. - \__( 'You just used Progress Planner to verify if sending email works on your website.

    The good news; it does! Click here to mark Ravi\'s Recommendation as completed.', 'progress-planner' ), - \admin_url( 'admin.php?page=progress-planner&prpl_complete_task=' . $this->get_task_id() ) + /* translators: %1$s the admin URL. %2$s: "Ravi" */ + \__( 'You just used Progress Planner to verify if sending email works on your website.

    The good news; it does! Click here to mark %2$s’s Recommendation as completed.', 'progress-planner' ), + \admin_url( 'admin.php?page=progress-planner&prpl_complete_task=' . $this->get_task_id() ), + \esc_html( \progress_planner()->get_ui__branding()->get_strings()['ravi'] ) ); } diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 99c3314f7..45b80a081 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -116,7 +116,7 @@ public static function get_strings(): array { return \apply_filters( 'progress_planner_branding_strings', [ - 'ravi-recommendations' => __( 'Ravi\'s Recommendations', 'progress-planner' ), + 'ravi' => __( 'Ravi', 'progress-planner' ), ] ); } diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index 093384399..ece0f03c1 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -17,10 +17,22 @@

    - get_ui__branding()->get_strings()['ravi-recommendations'] ); ?> + get_ui__branding()->get_strings()['ravi'] ) + ); + ?>

    - + get_ui__branding()->get_strings()['ravi'] ) + ); + ?>

      From c5e4f0505161023debc7ca8ce72ddf76e80eb9df Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 30 Jun 2025 14:08:37 +0300 Subject: [PATCH 007/338] WIP - API-based responses for branding --- .../interactive/class-email-sending.php | 2 +- classes/ui/class-branding.php | 179 +++++++++++------- views/dashboard-widgets/score.php | 2 +- views/page-widgets/suggested-tasks.php | 4 +- 4 files changed, 113 insertions(+), 74 deletions(-) diff --git a/classes/suggested-tasks/providers/interactive/class-email-sending.php b/classes/suggested-tasks/providers/interactive/class-email-sending.php index f730fa20d..e6d2eaacb 100644 --- a/classes/suggested-tasks/providers/interactive/class-email-sending.php +++ b/classes/suggested-tasks/providers/interactive/class-email-sending.php @@ -123,7 +123,7 @@ public function init() { /* translators: %1$s the admin URL. %2$s: "Ravi" */ \__( 'You just used Progress Planner to verify if sending email works on your website.

      The good news; it does! Click here to mark %2$s’s Recommendation as completed.', 'progress-planner' ), \admin_url( 'admin.php?page=progress-planner&prpl_complete_task=' . $this->get_task_id() ), - \esc_html( \progress_planner()->get_ui__branding()->get_strings()['ravi'] ) + \esc_html( \progress_planner()->get_ui__branding()->get_ravi_name() ) ); } diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 45b80a081..8ca812052 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -12,25 +12,65 @@ */ final class Branding { + /** + * Default branding post-ID. + * + * @var int + */ + const DEFAULT_BRANDING_POST_ID = 4958; + + /** + * Get the api data. + * + * @return array + */ + public static function get_api_data(): array { + // TODO: Cache the response. + return self::get_response_from_api(); + } + + /** + * Get the response from the API. + * + * @return array + */ + public static function get_response_from_api(): array { + $response = \wp_remote_get( 'https://progressplanner.com/wp-json/wp/v2/pp-branding/' . self::DEFAULT_BRANDING_POST_ID ); + if ( \is_wp_error( $response ) ) { + return []; + } + + return \json_decode( $response['body'], true ); + } + /** * Print the logo. * * @return void */ public static function the_logo(): void { - if ( \has_action( 'progress_planner_branding_logo' ) ) { - /** - * Short-circuit the logo rendering. - */ - \do_action( 'progress_planner_branding_logo' ); - return; + // Get the logo ID from the API data. + $logo_id = self::get_api_data()['acf']['logo']; + $logo_found = false; + if ( $logo_id ) { + // Get the logo URL. + $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $logo_id ); + if ( ! \is_wp_error( $response ) ) { + $media = \json_decode( \wp_remote_retrieve_body( $response ), true ); + if ( isset( $media['source_url'] ) ) { + $logo_found = true; + echo 'Logo'; + } + } } - \progress_planner()->the_asset( - \progress_planner()->is_pro_site() - ? 'images/logo_progress_planner_pro.svg' - : 'images/logo_progress_planner.svg' - ); + if ( ! $logo_found ) { + \progress_planner()->the_asset( + \progress_planner()->is_pro_site() + ? 'images/logo_progress_planner_pro.svg' + : 'images/logo_progress_planner.svg' + ); + } } /** @@ -39,45 +79,39 @@ public static function the_logo(): void { * @return string */ public static function get_color_palette(): string { - /** - * Filter the color palette. - * - * @param array $palette The palette. - * @return array - */ - $palette = \apply_filters( - 'progress_planner_color_palette', - [ - '--prpl-color-gray-1' => '#e1e3e7', - '--prpl-color-gray-2' => '#d1d5db', - '--prpl-color-gray-3' => '#9ca3af', - '--prpl-color-gray-4' => '#6b7280', - '--prpl-color-gray-5' => '#4b5563', - '--prpl-color-gray-6' => '#374151', - - '--prpl-color-accent-red' => '#f43f5e', - '--prpl-color-accent-orange' => '#faa310', - '--prpl-color-400-orange' => '#f9b23c', - '--prpl-color-accent-purple' => '#0d6b9e', - '--prpl-color-accent-green' => '#14b8a6', - - '--prpl-color-headings' => '#38296d', - '--prpl-color-text' => 'var(--prpl-color-gray-5)', - '--prpl-color-link' => '#1e40af', - - '--prpl-color-notification-green' => '#16a34a', - '--prpl-color-notification-red' => '#e73136', - - '--prpl-background-orange' => '#fff9f0', - '--prpl-background-purple' => '#f6f5fb', - '--prpl-background-green' => '#f2faf9', - '--prpl-background-red' => '#fff6f7', - '--prpl-background-blue' => '#effbfe', - ] - ); + $defaults = [ + '--prpl-color-gray-1' => '#e1e3e7', + '--prpl-color-gray-2' => '#d1d5db', + '--prpl-color-gray-3' => '#9ca3af', + '--prpl-color-gray-4' => '#6b7280', + '--prpl-color-gray-5' => '#4b5563', + '--prpl-color-gray-6' => '#374151', + + '--prpl-color-accent-red' => '#f43f5e', + '--prpl-color-accent-orange' => '#faa310', + '--prpl-color-400-orange' => '#f9b23c', + '--prpl-color-accent-purple' => '#0d6b9e', + '--prpl-color-accent-green' => '#14b8a6', + + '--prpl-color-headings' => '#38296d', + '--prpl-color-text' => 'var(--prpl-color-gray-5)', + '--prpl-color-link' => '#1e40af', + + '--prpl-color-notification-green' => '#16a34a', + '--prpl-color-notification-red' => '#e73136', + + '--prpl-background-orange' => '#fff9f0', + '--prpl-background-purple' => '#f6f5fb', + '--prpl-background-green' => '#f2faf9', + '--prpl-background-red' => '#fff6f7', + '--prpl-background-blue' => '#effbfe', + ]; + + $api_colors = self::get_api_data()['acf']['colors']; + $colors = \wp_parse_args( $api_colors, $defaults ); $palette_string = ''; - foreach ( $palette as $key => $value ) { + foreach ( $colors as $key => $value ) { $palette_string .= $key . ': ' . $value . ';'; } @@ -92,32 +126,37 @@ public static function get_color_palette(): string { public static function get_admin_menu_icon(): string { $icon = 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4='; - /** - * Filter the admin-menu icon. - * - * @param string $icon The icon. - * @return string - */ - return \apply_filters( 'progress_planner_admin_menu_icon', $icon ); + $admin_menu_icon_id = self::get_api_data()['acf']['logo']; + if ( $admin_menu_icon_id ) { + // Get the logo URL. + $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $admin_menu_icon_id ); + if ( ! \is_wp_error( $response ) ) { + $media = \json_decode( \wp_remote_retrieve_body( $response ), true ); + if ( isset( $media['source_url'] ) ) { + // Get the content of the image. + $content = \wp_remote_get( $media['source_url'] ); + if ( ! \is_wp_error( $content ) ) { + $content = $content['body']; + if ( $content ) { + $icon = 'data:image/svg+xml;base64,' . \base64_encode( $content ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode + } + } + } + } + } + + return $icon; } /** - * Get an array of strings used for branding purposes. + * Get the Ravi name. * - * @return array + * @return string */ - public static function get_strings(): array { - /** - * Filter the strings used for branding purposes. - * - * @param array $strings The strings. - * @return array - */ - return \apply_filters( - 'progress_planner_branding_strings', - [ - 'ravi' => __( 'Ravi', 'progress-planner' ), - ] - ); + public static function get_ravi_name(): string { + $default = 'Ravi'; + $api_name = self::get_api_data()['acf']['ravis_name']; + + return $api_name ? $api_name : $default; } } diff --git a/views/dashboard-widgets/score.php b/views/dashboard-widgets/score.php index 5c261852a..6746a4524 100644 --- a/views/dashboard-widgets/score.php +++ b/views/dashboard-widgets/score.php @@ -43,7 +43,7 @@
      -

      get_ui__branding()->get_strings()['ravi-recommendations'] ); ?>

      +

      get_ui__branding()->get_ravi_name() ); ?>

        diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index fdad4625a..e852ebd55 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -21,7 +21,7 @@ printf( /* translators: %s: "Ravi" */ \esc_html__( '%s’s Recommendations', 'progress-planner' ), - \esc_html( \progress_planner()->get_ui__branding()->get_strings()['ravi'] ) + \esc_html( \progress_planner()->get_ui__branding()->get_ravi_name() ) ); ?>

        @@ -30,7 +30,7 @@ printf( /* translators: %s: "Ravi" */ \esc_html__( 'Complete a task from %s’s Recommendations to improve your site and earn points toward this month’s badge!', 'progress-planner' ), - \esc_html( \progress_planner()->get_ui__branding()->get_strings()['ravi'] ) + \esc_html( \progress_planner()->get_ui__branding()->get_ravi_name() ) ); ?>

        From 80143323a4d5cdb79f31133e656b527e862a721d Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 30 Jun 2025 14:51:08 +0300 Subject: [PATCH 008/338] More WIP --- classes/ui/class-branding.php | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 8ca812052..f810cd49b 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -19,14 +19,24 @@ final class Branding { */ const DEFAULT_BRANDING_POST_ID = 4958; + /** + * Get the branding ID. + * + * @return int + */ + public function get_branding_id(): int { + // TODO: Get branding ID depending on the host, agency etc. + return self::DEFAULT_BRANDING_POST_ID; + } + /** * Get the api data. * * @return array */ - public static function get_api_data(): array { + public function get_api_data(): array { // TODO: Cache the response. - return self::get_response_from_api(); + return $this->get_response_from_api(); } /** @@ -34,8 +44,8 @@ public static function get_api_data(): array { * * @return array */ - public static function get_response_from_api(): array { - $response = \wp_remote_get( 'https://progressplanner.com/wp-json/wp/v2/pp-branding/' . self::DEFAULT_BRANDING_POST_ID ); + public function get_response_from_api(): array { + $response = \wp_remote_get( 'https://progressplanner.com/wp-json/wp/v2/pp-branding/' . $this->get_branding_id() ); if ( \is_wp_error( $response ) ) { return []; } @@ -48,9 +58,9 @@ public static function get_response_from_api(): array { * * @return void */ - public static function the_logo(): void { + public function the_logo(): void { // Get the logo ID from the API data. - $logo_id = self::get_api_data()['acf']['logo']; + $logo_id = $this->get_api_data()['acf']['logo']; $logo_found = false; if ( $logo_id ) { // Get the logo URL. @@ -78,7 +88,7 @@ public static function the_logo(): void { * * @return string */ - public static function get_color_palette(): string { + public function get_color_palette(): string { $defaults = [ '--prpl-color-gray-1' => '#e1e3e7', '--prpl-color-gray-2' => '#d1d5db', @@ -107,7 +117,7 @@ public static function get_color_palette(): string { '--prpl-background-blue' => '#effbfe', ]; - $api_colors = self::get_api_data()['acf']['colors']; + $api_colors = $this->get_api_data()['acf']['colors']; $colors = \wp_parse_args( $api_colors, $defaults ); $palette_string = ''; @@ -123,10 +133,10 @@ public static function get_color_palette(): string { * * @return string */ - public static function get_admin_menu_icon(): string { + public function get_admin_menu_icon(): string { $icon = 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4='; - $admin_menu_icon_id = self::get_api_data()['acf']['logo']; + $admin_menu_icon_id = $this->get_api_data()['acf']['logo']; if ( $admin_menu_icon_id ) { // Get the logo URL. $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $admin_menu_icon_id ); @@ -153,9 +163,9 @@ public static function get_admin_menu_icon(): string { * * @return string */ - public static function get_ravi_name(): string { + public function get_ravi_name(): string { $default = 'Ravi'; - $api_name = self::get_api_data()['acf']['ravis_name']; + $api_name = $this->get_api_data()['acf']['ravis_name']; return $api_name ? $api_name : $default; } From 8b5505b33309be1fc1c1357fad5116285b28cea2 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 1 Jul 2025 08:23:15 +0300 Subject: [PATCH 009/338] cache responses and improve implementation --- classes/ui/class-branding.php | 116 +++++++++++++++---------- views/page-widgets/suggested-tasks.php | 4 +- 2 files changed, 74 insertions(+), 46 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index f810cd49b..e1d51a043 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -26,6 +26,10 @@ final class Branding { */ public function get_branding_id(): int { // TODO: Get branding ID depending on the host, agency etc. + if ( \defined( 'PROGRESS_PLANNER_BRANDING_ID' ) ) { + return PROGRESS_PLANNER_BRANDING_ID; + } + return self::DEFAULT_BRANDING_POST_ID; } @@ -35,22 +39,14 @@ public function get_branding_id(): int { * @return array */ public function get_api_data(): array { - // TODO: Cache the response. - return $this->get_response_from_api(); - } - - /** - * Get the response from the API. - * - * @return array - */ - public function get_response_from_api(): array { - $response = \wp_remote_get( 'https://progressplanner.com/wp-json/wp/v2/pp-branding/' . $this->get_branding_id() ); - if ( \is_wp_error( $response ) ) { + $response = $this->get_remote_data( + \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/pp-branding/' . $this->get_branding_id() + ); + if ( ! $response ) { return []; } - return \json_decode( $response['body'], true ); + return \is_array( $response ) ? $response : \json_decode( $response, true ); } /** @@ -60,27 +56,26 @@ public function get_response_from_api(): array { */ public function the_logo(): void { // Get the logo ID from the API data. - $logo_id = $this->get_api_data()['acf']['logo']; - $logo_found = false; - if ( $logo_id ) { - // Get the logo URL. - $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $logo_id ); - if ( ! \is_wp_error( $response ) ) { - $media = \json_decode( \wp_remote_retrieve_body( $response ), true ); - if ( isset( $media['source_url'] ) ) { - $logo_found = true; - echo 'Logo'; + if ( ! empty( $this->get_api_data() ) ) { + $logo_id = $this->get_api_data()['acf']['logo']; + if ( $logo_id ) { + // Get the logo URL. + $response = $this->get_remote_data( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $logo_id ); + if ( $response ) { + $media = \json_decode( $response, true ); + if ( isset( $media['source_url'] ) ) { + echo 'Logo'; + return; + } } } } - if ( ! $logo_found ) { - \progress_planner()->the_asset( - \progress_planner()->is_pro_site() - ? 'images/logo_progress_planner_pro.svg' - : 'images/logo_progress_planner.svg' - ); - } + \progress_planner()->the_asset( + \progress_planner()->is_pro_site() + ? 'images/logo_progress_planner_pro.svg' + : 'images/logo_progress_planner.svg' + ); } /** @@ -117,8 +112,12 @@ public function get_color_palette(): string { '--prpl-background-blue' => '#effbfe', ]; - $api_colors = $this->get_api_data()['acf']['colors']; - $colors = \wp_parse_args( $api_colors, $defaults ); + if ( ! empty( $this->get_api_data() ) ) { + $api_colors = $this->get_api_data()['acf']['colors']; + $colors = empty( $api_colors ) ? $defaults : \wp_parse_args( $api_colors, $defaults ); + } else { + $colors = $defaults; + } $palette_string = ''; foreach ( $colors as $key => $value ) { @@ -136,20 +135,18 @@ public function get_color_palette(): string { public function get_admin_menu_icon(): string { $icon = 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4='; - $admin_menu_icon_id = $this->get_api_data()['acf']['logo']; + $admin_menu_icon_id = empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['logo']; + if ( $admin_menu_icon_id ) { // Get the logo URL. - $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $admin_menu_icon_id ); - if ( ! \is_wp_error( $response ) ) { - $media = \json_decode( \wp_remote_retrieve_body( $response ), true ); - if ( isset( $media['source_url'] ) ) { + $response = $this->get_remote_data( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $admin_menu_icon_id ); + if ( $response ) { + $media = \json_decode( $response, true ); + if ( \is_array( $media ) && \array_key_exists( 'source_url', $media ) ) { // Get the content of the image. - $content = \wp_remote_get( $media['source_url'] ); - if ( ! \is_wp_error( $content ) ) { - $content = $content['body']; - if ( $content ) { - $icon = 'data:image/svg+xml;base64,' . \base64_encode( $content ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode - } + $content = $this->get_remote_data( $media['source_url'] ); + if ( $content ) { + $icon = 'data:image/svg+xml;base64,' . \base64_encode( $content ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode } } } @@ -165,8 +162,39 @@ public function get_admin_menu_icon(): string { */ public function get_ravi_name(): string { $default = 'Ravi'; - $api_name = $this->get_api_data()['acf']['ravis_name']; + $api_name = empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['ravis_name']; return $api_name ? $api_name : $default; } + + /** + * Get data from a remote URL, cached. + * + * @param string $url The URL to get the data from. + * @return mixed + */ + public function get_remote_data( $url ) { + $cache_key = \md5( $url ); + $cached = \progress_planner()->get_utils__cache()->get( $cache_key ); + if ( $cached ) { + return $cached; + } + + $response = \wp_remote_get( $url ); + if ( \is_wp_error( $response ) ) { + \progress_planner()->get_utils__cache()->set( $cache_key, [], 5 * MINUTE_IN_SECONDS ); + return false; + } + + if ( 200 !== (int) \wp_remote_retrieve_response_code( $response ) ) { + \progress_planner()->get_utils__cache()->set( $cache_key, [], 5 * MINUTE_IN_SECONDS ); + return false; + } + + $body = \wp_remote_retrieve_body( $response ); + + \progress_planner()->get_utils__cache()->set( $cache_key, $body, WEEK_IN_SECONDS ); + + return $body; + } } diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index e852ebd55..8629be323 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -18,7 +18,7 @@

        get_ui__branding()->get_ravi_name() ) @@ -27,7 +27,7 @@

        get_ui__branding()->get_ravi_name() ) From d48c543d9b46a54fd07da823d4df381b89fc2f93 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 1 Jul 2025 11:24:49 +0300 Subject: [PATCH 010/338] try to detect host --- classes/ui/class-branding.php | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index e1d51a043..cf7f1d58a 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -15,9 +15,11 @@ final class Branding { /** * Default branding post-ID. * - * @var int + * @var array */ - const DEFAULT_BRANDING_POST_ID = 4958; + const BRANDING_IDS = [ + 'default' => 4958, + ]; /** * Get the branding ID. @@ -27,10 +29,23 @@ final class Branding { public function get_branding_id(): int { // TODO: Get branding ID depending on the host, agency etc. if ( \defined( 'PROGRESS_PLANNER_BRANDING_ID' ) ) { - return PROGRESS_PLANNER_BRANDING_ID; + return \constant( 'PROGRESS_PLANNER_BRANDING_ID' ); } - return self::DEFAULT_BRANDING_POST_ID; + $hostname = (string) \gethostname(); + if ( \str_contains( $hostname, 'siteground' ) ) { + $hostname = 'siteground'; + } elseif ( \str_contains( $hostname, 'wpengine' ) ) { + $hostname = 'wpengine'; + } elseif ( \str_contains( $hostname, 'bluehost' ) ) { + $hostname = 'bluehost'; + } elseif ( \str_contains( $hostname, 'godaddy' ) ) { + $hostname = 'godaddy'; + } + + return isset( self::BRANDING_IDS[ $hostname ] ) + ? self::BRANDING_IDS[ $hostname ] + : self::BRANDING_IDS['default']; } /** From 07a019eba8ed72042bf037cbc074440dbdae26b6 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 18 Jul 2025 13:21:51 +0200 Subject: [PATCH 011/338] use admin_menu_icon (not logo) --- classes/ui/class-branding.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index cf7f1d58a..93c627390 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -150,7 +150,7 @@ public function get_color_palette(): string { public function get_admin_menu_icon(): string { $icon = 'data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIGFyaWEtaGlkZGVuPSJ0cnVlIiBmb2N1c2FibGU9ImZhbHNlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjggNTAwIj48cGF0aCBmaWxsPSIjMzgyOTZkIiBkPSJNMjE3LjQ2IDE3Mi45YzMuMjEuMTIgNS45NyAxLjc0IDcuNzMgNC4xNS0xLjg3LTEwLjI0LTEwLjY0LTE4LjE3LTIxLjQ4LTE4LjU2LTEyLjUyLS40NS0yMy4wMyA5LjMzLTIzLjQ4IDIxLjg1LS40NSAxMi41MiA5LjMzIDIzLjAzIDIxLjg1IDIzLjQ4IDkuNC4zNCAxNy42Ny01LjEgMjEuNC0xMy4xMy0xLjgzIDEuNTEtNC4xOCAyLjQyLTYuNzQgMi4zMy01LjU1LS4yLTkuODktNC44Ni05LjY5LTEwLjQxLjItNS41NSA0Ljg2LTkuODkgMTAuNDEtOS42OVpNMjQxLjUxIDMwNS44NGMuNTggMS45MiAxLjEzIDMuODYgMS43MyA1Ljc3IDE0LjA0IDQ0Ljk3IDMzLjk0IDg4Ljc1IDU2LjQyIDEyNC4yN2w2Ny43NS0xMzAuMDRoLTEyNS45Wk0yOTcuOTYgMjA1Ljk3YzEyLjEyLTQuNSAyMy41NC03LjE4IDMzLjY0LTguOTYtMjIuNTEtMjIuMjctNjEuMjQtMjcuMDYtNjEuNDctMjcuMDkgMS4yNyA2LjE3LjU4IDE1LjgtMi40NCAyNi40Ni0zLjMgMTEuNjYtOS4zOCAyNC41NC0xOC43IDM1LjQ4LTMuNDUgNC4wNi03LjM2IDcuODMtMTEuNzMgMTEuMTloLjA3di0uMDFjLjE2LjYyLjM4IDEuMi41OCAxLjc5IDIuNzQgOC4yNyA4LjYxIDEzLjc0IDE0LjkzIDE3LjE0IDYuNDggMy40OSAxMy4zNyA0LjgzIDE3LjY4IDQuODMgNi40IDAgMTEuODgtMy43OSAxNC40My05LjIyLjk3LTIuMDYgMS41NS00LjMzIDEuNTUtNi43NiAwLTMuODUtMS40Mi03LjM0LTMuNjktMTAuMS0xLjkyLTIuMzMtNC40Ni00LjA4LTcuMzktNS4wM2w0NC44Mi04LjY1Yy02LjYzLTYuMTItMTQuNzItMTEuNTktMjIuNzMtMTYuMjMtMS45Ny0xLjE0LTEuNjktNC4wNS40NS00Ljg0WiIvPjxwYXRoIGZpbGw9IiNmYWEzMTAiIGQ9Ik0yODEuMzcgNDU4LjM3Yy0yNS43OS0zOC44NC00OC42OC04OC4wNC02NC40NS0xMzguNTQtMS40NS00LjYzLTIuODMtOS4zMS00LjE3LTEzLjk5LTEuMTItMy45NC0yLjIyLTcuODgtMy4yNS0xMS44LTIuMDktNy45Mi05LjI4LTEzLjQ2LTE3LjQ4LTEzLjQ2aC0yNy45NWMtOC4yIDAtMTUuMzkgNS41My0xNy40OCAxMy40NS0yLjI4IDguNjUtNC43OCAxNy4zMi03LjQyIDI1Ljc5LTE1Ljc3IDUwLjUtMzguNjUgOTkuNy02NC40NSAxMzguNTQtNC4wMSA2LjAzLTEuNzggMTEuNjMtLjY0IDEzLjc2IDIuNCA0LjQ3IDYuODYgNy4xNCAxMS45NCA3LjE0aDY2LjAxbDMuOTcgNi45MmM0LjU0IDcuOSAxMi45OSAxMi44MSAyMi4wNSAxMi44MXMxNy41MS00LjkxIDIyLjA2LTEyLjgxbDMuOTgtNi45Mmg2NmMzLjIyIDAgNi4xOS0xLjA4IDguNTUtMy4wMiAxLjM1LTEuMTEgMi41MS0yLjQ5IDMuMzgtNC4xMy41Ny0xLjA3IDEuNDItMy4wMiAxLjYxLTUuNDYuMTktMi40MS0uMjYtNS4zMS0yLjI1LTguMzFaIi8+PHBhdGggZmlsbD0iIzM4Mjk2ZCIgZD0iTTI5NS43IDc2LjA2Yy03LjU0LTEyLjA1LTMyLjM4IDEtNTkuNTQgMi44Ni0xNS4wNCAxLjAzLTM3LjA1LTExMC42My03MS43Ny01Ni45OS0zOS41NiA2MS4xLTc5LjEyLTQ0LjY4LTg4LjY2LTE1LjgzLTIxLjExIDQzLjI3IDI1LjE1IDg0LjYxIDI1LjE1IDg0LjYxcy0xMi44NCA3LjkyLTIwLjYzIDEzLjkzYy01LjQ3IDQuMTctMTAuODIgOC42NS0xNi4wMyAxMy41MS0yMC40NSAxOS4wMy0zNi4wNCA0MC4zMi00Ni43NyA2My44NkM2LjcyIDIwNS41NSAxLjExIDIyOS41OS42MiAyNTQuMTVjLS40OSAyNC41NiA0LjAxIDQ5LjEgMTMuNTQgNzMuNjMgOS41MiAyNC41MyAyNC4xNyA0Ny40MiA0My45NSA2OC42OCA0LjAyIDQuMzIgOC4xMiA4LjQxIDEyLjMxIDEyLjMgNC4xLTYuMzEgNy45Ny0xMi43NCAxMS42NC0xOS4yNiA0LjM5LTcuOCA4LjUtMTUuNzIgMTIuMjUtMjMuNzgtLjMzLS4zNS0uNjYtLjY5LS45OS0xLjAzLS4xNy0uMTgtLjM0LS4zNS0uNTEtLjUzLTE1LjUzLTE2LjY5LTI3LjE3LTM0LjU5LTM0LjkzLTUzLjcyLTcuNzctMTkuMTMtMTEuNS0zOC4yNS0xMS4yLTU3LjM2LjI5LTE5LjEgNC40Ny0zNy42OCAxMi41My01NS43MiA4LjA2LTE4LjA1IDIwLjAyLTM0LjQ1IDM1LjktNDkuMjIgMTMuOTktMTMuMDIgMjguODQtMjIuODMgNDQuNTUtMjkuNDEgMTUuNy02LjU5IDMxLjYzLTkuOTggNDcuNzYtMTAuMTggOS4wNS0uMTEgMTkuMTEgMS4xNSAyOS41MSA0LjUgMTAuMzIgNC4yNyAxOS4yMiA5LjQ0IDI2LjYzIDE1LjM1IDEwLjE5IDguMTMgMTcuNjEgMTcuNjUgMjIuMjIgMjguMSAxLjkxIDQuMzIgMy4zNyA4LjggNC4zMiAxMy40MSAxNi4yNy0yOC4yNyAzNi43NS03NS45NiAyNS41Ny05My44M1oiLz48L3N2Zz4='; - $admin_menu_icon_id = empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['logo']; + $admin_menu_icon_id = empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['admin_menu_icon']; if ( $admin_menu_icon_id ) { // Get the logo URL. From a537009bd2a85805acf4a2508e7303413aae7d87 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 18 Jul 2025 13:35:24 +0200 Subject: [PATCH 012/338] dont add inline branding styles multiple times --- classes/admin/class-page.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index 5e134edc4..358c9af9d 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -12,6 +12,13 @@ */ class Page { + /** + * Whether the branding inline styles have been added. + * + * @var boolean + */ + protected static $branding_inline_styles_added = false; + /** * Constructor. */ @@ -277,7 +284,10 @@ public function enqueue_styles() { } \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/admin' ); - \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); + if ( ! static::$branding_inline_styles_added ) { + \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); + static::$branding_inline_styles_added = true; + } \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/web-components/prpl-tooltip' ); if ( 'progress-planner_page_progress-planner-settings' === $current_screen->id ) { From 743563bb41db3bb3e80d2139b571d870f27fc2a8 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 25 Jul 2025 12:19:59 +0300 Subject: [PATCH 013/338] Remove TODO comment --- classes/ui/class-branding.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 93c627390..64335fd2f 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -27,7 +27,7 @@ final class Branding { * @return int */ public function get_branding_id(): int { - // TODO: Get branding ID depending on the host, agency etc. + // Get branding ID depending on the host, agency etc. if ( \defined( 'PROGRESS_PLANNER_BRANDING_ID' ) ) { return \constant( 'PROGRESS_PLANNER_BRANDING_ID' ); } From 711c94c76fbd527bc08d40b66feb6f618c732dbe Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 28 Jul 2025 07:56:32 +0300 Subject: [PATCH 014/338] code simplifications --- classes/ui/class-branding.php | 37 ++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 64335fd2f..48118e0d7 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -71,17 +71,18 @@ public function get_api_data(): array { */ public function the_logo(): void { // Get the logo ID from the API data. - if ( ! empty( $this->get_api_data() ) ) { + if ( ! empty( $this->get_api_data() ) + && isset( $this->get_api_data()['acf']['logo'] ) + && ! empty( $this->get_api_data()['acf']['logo'] ) + ) { $logo_id = $this->get_api_data()['acf']['logo']; - if ( $logo_id ) { - // Get the logo URL. - $response = $this->get_remote_data( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $logo_id ); - if ( $response ) { - $media = \json_decode( $response, true ); - if ( isset( $media['source_url'] ) ) { - echo 'Logo'; - return; - } + // Get the logo URL. + $response = $this->get_remote_data( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/media/' . $logo_id ); + if ( $response ) { + $media = \json_decode( $response, true ); + if ( isset( $media['source_url'] ) ) { + echo 'Logo'; + return; } } } @@ -99,7 +100,7 @@ public function the_logo(): void { * @return string */ public function get_color_palette(): string { - $defaults = [ + $colors = [ '--prpl-color-gray-1' => '#e1e3e7', '--prpl-color-gray-2' => '#d1d5db', '--prpl-color-gray-3' => '#9ca3af', @@ -127,11 +128,8 @@ public function get_color_palette(): string { '--prpl-background-blue' => '#effbfe', ]; - if ( ! empty( $this->get_api_data() ) ) { - $api_colors = $this->get_api_data()['acf']['colors']; - $colors = empty( $api_colors ) ? $defaults : \wp_parse_args( $api_colors, $defaults ); - } else { - $colors = $defaults; + if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['colors'] ) ) { + $colors = \wp_parse_args( $this->get_api_data()['acf']['colors'], $colors ); } $palette_string = ''; @@ -176,10 +174,9 @@ public function get_admin_menu_icon(): string { * @return string */ public function get_ravi_name(): string { - $default = 'Ravi'; - $api_name = empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['ravis_name']; - - return $api_name ? $api_name : $default; + return empty( $this->get_api_data() ) + ? 'Ravi' + : $this->get_api_data()['acf']['ravis_name']; } /** From 8ced6b17c4d0d8bea3afe9efe91b96e10433c837 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 6 Aug 2025 11:03:15 +0300 Subject: [PATCH 015/338] Add support for body background color --- assets/css/admin.css | 10 ++++++---- classes/ui/class-branding.php | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index 3dd777fe3..87e8f28e0 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -7,8 +7,6 @@ --prpl-padding: 20px; --prpl-column-min-width: 22rem; --prpl-max-columns: 3; - --prpl-border-radius: 8px; - --prpl-border-radius-big: calc(var(--prpl-border-radius) * 2); --prpl-container-max-width: calc(var(--prpl-column-min-width) * var(--prpl-max-columns) + var(--prpl-gap) * (var(--prpl-max-columns) - 1) + var(--prpl-column-min-width)); @@ -24,6 +22,10 @@ --prpl-font-size-6xl: 4.5rem; /* 72px */ } +body.toplevel_page_progress-planner { /* stylelint-disable-line */ + background: var(--prpl-background-body); +} + /*------------------------------------*\ Styles for the container of the page. \*------------------------------------*/ @@ -276,7 +278,7 @@ button.prpl-info-icon { line-height: 1.25; box-shadow: none; border: none; - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); transition: all 0.25s ease-in-out; font-weight: 600; text-align: center; @@ -294,7 +296,7 @@ button.prpl-info-icon { top: 0; left: 0; z-index: -1; - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); transition: all 0.25s ease-in-out; } diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 48118e0d7..d81298e6f 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -121,6 +121,7 @@ public function get_color_palette(): string { '--prpl-color-notification-green' => '#16a34a', '--prpl-color-notification-red' => '#e73136', + '--prpl-background-body' => '#f0f0f1', '--prpl-background-orange' => '#fff9f0', '--prpl-background-purple' => '#f6f5fb', '--prpl-background-green' => '#f2faf9', From ba8f0e0f7f27beef5cef198741a52bd768995376 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 6 Aug 2025 11:04:04 +0300 Subject: [PATCH 016/338] Add support for border-radii --- assets/css/page-widgets/suggested-tasks.css | 12 +++++------ assets/css/settings-page.css | 4 ++-- classes/admin/class-page.php | 1 + classes/ui/class-branding.php | 24 +++++++++++++++++++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/assets/css/page-widgets/suggested-tasks.css b/assets/css/page-widgets/suggested-tasks.css index d0b1e4666..21c264613 100644 --- a/assets/css/page-widgets/suggested-tasks.css +++ b/assets/css/page-widgets/suggested-tasks.css @@ -192,7 +192,7 @@ .prpl-widget-title { padding: 0.5rem 1rem; - border-radius: 0.5rem; + border-radius: var(--prpl-border-radius); background: var(--prpl-background-orange); } @@ -382,7 +382,7 @@ padding: 0.75rem; color: #854d0e; font-size: var(--prpl-font-size-small); - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); background-color: #fefce8; .prpl-note-icon { @@ -428,7 +428,7 @@ padding: 1rem; /* WIP */ width: 100%; min-width: 300px; /* WIP */ - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); border: 1px solid var(--prpl-color-gray-2); } @@ -452,7 +452,7 @@ top: 0; left: 0; z-index: -1; - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); transition: all 0.25s ease-in-out; } @@ -473,7 +473,7 @@ textarea { width: 100%; min-height: 100px; - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05); border: 1px solid var(--prpl-color-gray-2); } @@ -529,7 +529,7 @@ .prpl-custom-control { border: 1px solid var(--prpl-input-gray); - border-radius: 6px; + border-radius: var(--prpl-border-radius-small); background: #fff; } diff --git a/assets/css/settings-page.css b/assets/css/settings-page.css index 638834814..82ae2bb2a 100644 --- a/assets/css/settings-page.css +++ b/assets/css/settings-page.css @@ -24,7 +24,7 @@ gap: 0.5rem; background: var(--prpl-background-orange); padding: 1.2rem; - border-radius: 0.5rem; + border-radius: var(--prpl-border-radius); margin-bottom: 2rem; .icon { @@ -56,7 +56,7 @@ gap: 0.5rem; background: var(--prpl-background-purple); padding: 1.2rem; - border-radius: 0.5rem; + border-radius: var(--prpl-border-radius); margin-bottom: var(--prpl-settings-page-gap); &:first-child { diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index 358c9af9d..5d0a5b3f7 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -286,6 +286,7 @@ public function enqueue_styles() { \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/admin' ); if ( ! static::$branding_inline_styles_added ) { \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); + \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_border_radii() ); static::$branding_inline_styles_added = true; } \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/web-components/prpl-tooltip' ); diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index d81298e6f..04dfaecbf 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -141,6 +141,30 @@ public function get_color_palette(): string { return ":root { $palette_string }"; } + /** + * Get the border radii. + * + * @return string + */ + public function get_border_radii(): string { + $radii = [ + '--prpl-border-radius' => '8px', + '--prpl-border-radius-small' => 'calc(var(--prpl-border-radius) * 0.75)', + '--prpl-border-radius-big' => 'calc(var(--prpl-border-radius) * 2)', + ]; + + if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['border-radii'] ) ) { + $radii = \wp_parse_args( $this->get_api_data()['acf']['border-radii'], $radii ); + } + + $radii_string = ''; + foreach ( $radii as $key => $value ) { + $radii_string .= $key . ': ' . $value . ';'; + } + + return ":root { $radii_string }"; + } + /** * Get the admin-menu icon. * From 4c5797c2f50e2fda9ba46ffbf7e732ecea25b651 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 6 Aug 2025 13:00:11 +0300 Subject: [PATCH 017/338] Add custom CSS --- classes/admin/class-page.php | 1 + classes/ui/class-branding.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index 5d0a5b3f7..f26df1f61 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -287,6 +287,7 @@ public function enqueue_styles() { if ( ! static::$branding_inline_styles_added ) { \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_border_radii() ); + \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_custom_css() ); static::$branding_inline_styles_added = true; } \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/web-components/prpl-tooltip' ); diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 04dfaecbf..cdd4ac20d 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -165,6 +165,15 @@ public function get_border_radii(): string { return ":root { $radii_string }"; } + /** + * Get the custom CSS. + * + * @return string + */ + public function get_custom_css(): string { + return empty( $this->get_api_data() ) ? '' : $this->get_api_data()['acf']['custom_css']; + } + /** * Get the admin-menu icon. * From 5a9b79a9051939ed98926bc309bd75de6c4369bf Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Thu, 7 Aug 2025 14:22:56 +0300 Subject: [PATCH 018/338] Allow changing the admin-menu name --- classes/admin/class-page.php | 4 ++-- classes/ui/class-branding.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index f26df1f61..bbaddeec7 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -98,8 +98,8 @@ public function add_page() { $page_identifier = 'progress-planner'; \add_menu_page( - 'Progress Planner', - 'Progress Planner' . $this->get_notification_counter(), + \progress_planner()->get_ui__branding()->get_admin_menu_name(), + \progress_planner()->get_ui__branding()->get_admin_menu_name() . $this->get_notification_counter(), 'manage_options', $page_identifier, [ $this, 'render_page' ], diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index cdd4ac20d..de195552f 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -202,6 +202,17 @@ public function get_admin_menu_icon(): string { return $icon; } + /** + * Get the admin-menu name. + * + * @return string + */ + public function get_admin_menu_name(): string { + return empty( $this->get_api_data() ) + ? 'Progress Planner' + : $this->get_api_data()['acf']['admin_menu_name']; + } + /** * Get the Ravi name. * From 6e349d408628ffeb2b3e6daff9f85f980b331bf0 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 8 Aug 2025 08:14:46 +0300 Subject: [PATCH 019/338] Allow using a different name for submenu --- classes/admin/class-page.php | 13 +++++++++++-- classes/ui/class-branding.php | 11 +++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index bbaddeec7..7b08b5add 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -98,14 +98,23 @@ public function add_page() { $page_identifier = 'progress-planner'; \add_menu_page( - \progress_planner()->get_ui__branding()->get_admin_menu_name(), + \progress_planner()->get_ui__branding()->get_admin_submenu_name(), \progress_planner()->get_ui__branding()->get_admin_menu_name() . $this->get_notification_counter(), 'manage_options', $page_identifier, - [ $this, 'render_page' ], + '__return_empty_string', \progress_planner()->get_ui__branding()->get_admin_menu_icon() ); + \add_submenu_page( + $page_identifier, + \progress_planner()->get_ui__branding()->get_admin_submenu_name(), + \progress_planner()->get_ui__branding()->get_admin_submenu_name() . $this->get_notification_counter(), + 'manage_options', + $page_identifier, + [ $this, 'render_page' ], + ); + // Wipe notification bits from hooks. // phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action. $admin_page_hooks[ $page_identifier ] = $page_identifier; diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index de195552f..e06f37a08 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -213,6 +213,17 @@ public function get_admin_menu_name(): string { : $this->get_api_data()['acf']['admin_menu_name']; } + /** + * Get the admin-submenu name. + * + * @return string + */ + public function get_admin_submenu_name(): string { + return empty( $this->get_api_data() ) + ? $this->get_admin_menu_name() + : $this->get_api_data()['acf']['admin_submenu_name']; + } + /** * Get the Ravi name. * From b082a20035f8a82c5bfc87a95119572ea063f1b1 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 8 Aug 2025 10:09:07 +0300 Subject: [PATCH 020/338] extra checks --- classes/ui/class-branding.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index e06f37a08..16028727c 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -208,7 +208,7 @@ public function get_admin_menu_icon(): string { * @return string */ public function get_admin_menu_name(): string { - return empty( $this->get_api_data() ) + return empty( $this->get_api_data() ) || ! isset( $this->get_api_data()['acf']['admin_menu_name'] ) ? 'Progress Planner' : $this->get_api_data()['acf']['admin_menu_name']; } @@ -219,7 +219,7 @@ public function get_admin_menu_name(): string { * @return string */ public function get_admin_submenu_name(): string { - return empty( $this->get_api_data() ) + return empty( $this->get_api_data() ) || ! isset( $this->get_api_data()['acf']['admin_submenu_name'] ) ? $this->get_admin_menu_name() : $this->get_api_data()['acf']['admin_submenu_name']; } From cde2f30ec6864033821068b86d19be049a445d4d Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 8 Aug 2025 11:39:58 +0300 Subject: [PATCH 021/338] WIP --- assets/css/admin.css | 9 ++++--- classes/admin/class-page.php | 3 +-- classes/ui/class-branding.php | 48 +++++++++++++---------------------- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index 87e8f28e0..4a923cf3c 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -30,8 +30,8 @@ body.toplevel_page_progress-planner { /* stylelint-disable-line */ Styles for the container of the page. \*------------------------------------*/ .prpl-wrap { - background: #fff; - border: 1px solid var(--prpl-color-gray-2); + background: var(--prpl-background-main, #fff); + border: 1px solid var(--prpl-main-area-border-color, var(--prpl-color-gray-2)); border-radius: var(--prpl-border-radius); padding: var(--prpl-settings-page-gap) calc(var(--prpl-padding) * 2); max-width: var(--prpl-container-max-width); @@ -210,13 +210,14 @@ button.prpl-info-icon { Generic styles for individual widgets. \*------------------------------------*/ .prpl-widget-wrapper { - border: 1px solid var(--prpl-color-gray-2); + border: 1px solid var(--prpl-paper-border-color); + background: var(--prpl-background-papers); border-radius: var(--prpl-border-radius); padding: var(--prpl-padding); min-width: 0; min-height: 0; margin-bottom: var(--prpl-gap); - box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.07), -2px 0 6px rgba(0, 0, 0, 0.07); + box-shadow: var(--prpl-papers-box-shadow); hr { margin-top: 1.25rem; diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index 7b08b5add..09044e38d 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -294,8 +294,7 @@ public function enqueue_styles() { \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/admin' ); if ( ! static::$branding_inline_styles_added ) { - \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_color_palette() ); - \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_border_radii() ); + \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_css_variables() ); \wp_add_inline_style( 'progress-planner/admin', \progress_planner()->get_ui__branding()->get_custom_css() ); static::$branding_inline_styles_added = true; } diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 16028727c..a4bb1e76c 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -18,7 +18,8 @@ final class Branding { * @var array */ const BRANDING_IDS = [ - 'default' => 4958, + // TODO: Change this to the default value of 4958. + 'default' => 5159, ]; /** @@ -99,8 +100,8 @@ public function the_logo(): void { * * @return string */ - public function get_color_palette(): string { - $colors = [ + public function get_css_variables(): string { + $vars = [ '--prpl-color-gray-1' => '#e1e3e7', '--prpl-color-gray-2' => '#d1d5db', '--prpl-color-gray-3' => '#9ca3af', @@ -122,47 +123,34 @@ public function get_color_palette(): string { '--prpl-color-notification-red' => '#e73136', '--prpl-background-body' => '#f0f0f1', + '--prpl-background-main' => '#ffffff', + '--prpl-background-papers' => '#ffffff', '--prpl-background-orange' => '#fff9f0', '--prpl-background-purple' => '#f6f5fb', '--prpl-background-green' => '#f2faf9', '--prpl-background-red' => '#fff6f7', '--prpl-background-blue' => '#effbfe', - ]; - if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['colors'] ) ) { - $colors = \wp_parse_args( $this->get_api_data()['acf']['colors'], $colors ); - } + '--prpl-main-area-border-color' => 'var(--prpl-color-gray-2)', + '--prpl-paper-border-color' => 'var(--prpl-color-gray-2)', - $palette_string = ''; - foreach ( $colors as $key => $value ) { - $palette_string .= $key . ': ' . $value . ';'; - } - - return ":root { $palette_string }"; - } + '--prpl-papers-box-shadow' => '4px 4px 10px rgba(0, 0, 0, 0.07), -2px 0 6px rgba(0, 0, 0, 0.07)', - /** - * Get the border radii. - * - * @return string - */ - public function get_border_radii(): string { - $radii = [ - '--prpl-border-radius' => '8px', - '--prpl-border-radius-small' => 'calc(var(--prpl-border-radius) * 0.75)', - '--prpl-border-radius-big' => 'calc(var(--prpl-border-radius) * 2)', + '--prpl-border-radius' => '8px', + '--prpl-border-radius-small' => 'calc(var(--prpl-border-radius) * 0.75)', + '--prpl-border-radius-big' => 'calc(var(--prpl-border-radius) * 2)', ]; - if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['border-radii'] ) ) { - $radii = \wp_parse_args( $this->get_api_data()['acf']['border-radii'], $radii ); + if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['css_variables'] ) ) { + $vars = \wp_parse_args( $this->get_api_data()['acf']['css_variables'], $vars ); } - $radii_string = ''; - foreach ( $radii as $key => $value ) { - $radii_string .= $key . ': ' . $value . ';'; + $vars_string = ''; + foreach ( $vars as $key => $value ) { + $vars_string .= $key . ': ' . $value . ';'; } - return ":root { $radii_string }"; + return ":root { $vars_string }"; } /** From 5ca89edce3db7900f6ae57e71a95ff2682f688b8 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 8 Aug 2025 12:17:12 +0300 Subject: [PATCH 022/338] Filtering the widgets to show --- classes/ui/class-branding.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index a4bb1e76c..32567327e 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -22,6 +22,13 @@ final class Branding { 'default' => 5159, ]; + /** + * Constructor. + */ + public function __construct() { + \add_filter( 'progress_planner_admin_widgets', [ $this, 'filter_widgets' ] ); + } + /** * Get the branding ID. * @@ -253,4 +260,29 @@ public function get_remote_data( $url ) { return $body; } + + /** + * Filter the widgets to be displayed on the admin page. + * + * @param array<\Progress_Planner\Admin\Widgets\Widget> $widgets The widgets. + * + * @return array<\Progress_Planner\Admin\Widgets\Widget> + */ + public function filter_widgets( $widgets ) { + if ( empty( $this->get_api_data() ) || ! isset( $this->get_api_data()['acf']['papers'] ) ) { + return $widgets; + } + + $show_papers = $this->get_api_data()['acf']['papers']; + if ( ! $show_papers ) { + return $widgets; + } + + return array_filter( + $widgets, + function ( $widget ) use ( $show_papers ) { + return \in_array( $widget->get_id(), $show_papers, true ); + } + ); + } } From 45e31d34660f1163c94706d198da452c5985287d Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 12 Aug 2025 09:06:14 +0300 Subject: [PATCH 023/338] Send the branding-ID when getting stats --- classes/rest/class-stats.php | 3 --- classes/utils/class-system-status.php | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/classes/rest/class-stats.php b/classes/rest/class-stats.php index 8f9447f74..12af150fa 100644 --- a/classes/rest/class-stats.php +++ b/classes/rest/class-stats.php @@ -12,9 +12,6 @@ namespace Progress_Planner\Rest; -use Progress_Planner\Base; -use Progress_Planner\Admin\Widgets\Activity_Scores; - /** * Rest_API_Stats class. */ diff --git a/classes/utils/class-system-status.php b/classes/utils/class-system-status.php index 8aeed9b5f..346f5ee50 100644 --- a/classes/utils/class-system-status.php +++ b/classes/utils/class-system-status.php @@ -144,6 +144,8 @@ public function get_system_status() { ]; } + $data['branding_id'] = \progress_planner()->get_branding_id()->get_branding_id(); + return $data; } } From dedcab02de6da421e8e2888208753ad91828adc5 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 12 Aug 2025 13:02:42 +0300 Subject: [PATCH 024/338] Use branding-ID to get badges --- assets/js/web-components/prpl-badge-progress-bar.js | 9 +++++++-- assets/js/web-components/prpl-badge.js | 13 +++++++++---- assets/js/web-components/prpl-gauge.js | 8 ++++++-- classes/utils/class-system-status.php | 2 +- views/dashboard-widgets/score.php | 1 + views/page-widgets/badge-streak.php | 7 ++++++- views/page-widgets/parts/monthly-badges.php | 1 + views/page-widgets/suggested-tasks.php | 7 ++++++- views/popovers/monthly-badges.php | 1 + views/popovers/parts/badge-streak-badge.php | 1 + 10 files changed, 39 insertions(+), 11 deletions(-) diff --git a/assets/js/web-components/prpl-badge-progress-bar.js b/assets/js/web-components/prpl-badge-progress-bar.js index 132fa4f8d..0fa9bc2b2 100644 --- a/assets/js/web-components/prpl-badge-progress-bar.js +++ b/assets/js/web-components/prpl-badge-progress-bar.js @@ -13,12 +13,13 @@ customElements.define( 'prpl-badge-progress-bar', class extends HTMLElement { - constructor( badgeId, points, maxPoints ) { + constructor( badgeId, points, maxPoints, brandingId = '' ) { // Get parent class properties super(); badgeId = badgeId || this.getAttribute( 'data-badge-id' ); points = points || this.getAttribute( 'data-points' ); maxPoints = maxPoints || this.getAttribute( 'data-max-points' ); + brandingId = brandingId || this.getAttribute( 'data-branding-id' ); const progress = ( points / maxPoints ) * 100; this.innerHTML = ` @@ -49,6 +50,7 @@ customElements.define( position: absolute; left: calc(${ progress }% - 2.5rem); top: -2.5rem;" + branding-id="${ brandingId }" >

        @@ -93,16 +95,19 @@ const prplUpdatePreviousMonthBadgeProgressBar = ( pointsDiff ) => { const badgeMaxPoints = progressBar.getAttribute( 'data-max-points' ); const badgeProgress = customElements.get( 'prpl-badge-progress-bar' ); const badgeNewPoints = parseInt( badgePoints ) + pointsDiff; + const brandingId = progressBar.getAttribute( 'data-branding-id' ); // Create a new badge progress bar. const newProgressBar = new badgeProgress( badgeId, badgeNewPoints, - badgeMaxPoints + badgeMaxPoints, + brandingId ); newProgressBar.setAttribute( 'data-badge-id', badgeId ); newProgressBar.setAttribute( 'data-points', badgeNewPoints ); newProgressBar.setAttribute( 'data-max-points', badgeMaxPoints ); + newProgressBar.setAttribute( 'data-branding-id', brandingId ); // Replace the old badge progress bar with the new one. progressBar.replaceWith( newProgressBar ); diff --git a/assets/js/web-components/prpl-badge.js b/assets/js/web-components/prpl-badge.js index e926e993e..3944dbdcb 100644 --- a/assets/js/web-components/prpl-badge.js +++ b/assets/js/web-components/prpl-badge.js @@ -13,16 +13,21 @@ customElements.define( 'prpl-badge', class extends HTMLElement { - constructor( badgeId ) { + constructor( badgeId, brandingId = '' ) { // Get parent class properties super(); badgeId = badgeId || this.getAttribute( 'badge-id' ); + brandingId = brandingId || this.getAttribute( 'branding-id' ); + + let url = `${ progressPlannerBadge.remoteServerRootUrl }/wp-json/progress-planner-saas/v1/badge-svg/?badge_id=${ badgeId }`; + if ( brandingId ) { + url += `&branding_id=${ brandingId }`; + } + this.innerHTML = ` ${ prplL10n( 'badge' ) } { contentPadding: 'var(--prpl-padding) var(--prpl-padding) calc(var(--prpl-padding) * 2) var(--prpl-padding)', marginBottom: 'var(--prpl-padding)', + brandingId: gaugeProps.brandingId, }, - `` + `` ); gauge.id = gaugeProps.id; gauge.setAttribute( 'background', gaugeProps.background ); @@ -157,6 +160,7 @@ const prplUpdateRaviGauge = ( pointsDiff ) => { gauge.setAttribute( 'data-max', gaugeProps.max ); gauge.setAttribute( 'data-value', newValue ); gauge.setAttribute( 'data-badge-id', gaugeProps.badgeId ); + gauge.setAttribute( 'data-branding-id', gaugeProps.brandingId ); // Replace the old gauge with the new one. const oldGauge = document.getElementById( gaugeProps.id ); diff --git a/classes/utils/class-system-status.php b/classes/utils/class-system-status.php index 346f5ee50..8edc9a482 100644 --- a/classes/utils/class-system-status.php +++ b/classes/utils/class-system-status.php @@ -144,7 +144,7 @@ public function get_system_status() { ]; } - $data['branding_id'] = \progress_planner()->get_branding_id()->get_branding_id(); + $data['branding_id'] = (int) \progress_planner()->get_ui__branding()->get_branding_id(); return $data; } diff --git a/views/dashboard-widgets/score.php b/views/dashboard-widgets/score.php index 6746a4524..d1086fd64 100644 --- a/views/dashboard-widgets/score.php +++ b/views/dashboard-widgets/score.php @@ -25,6 +25,7 @@ diff --git a/views/page-widgets/badge-streak.php b/views/page-widgets/badge-streak.php index c48dc466c..45cf706b6 100644 --- a/views/page-widgets/badge-streak.php +++ b/views/page-widgets/badge-streak.php @@ -66,7 +66,11 @@ - +
        @@ -98,6 +102,7 @@ class="prpl-badge"

        get_name() ); ?>

        diff --git a/views/page-widgets/parts/monthly-badges.php b/views/page-widgets/parts/monthly-badges.php index 80b14e6df..d00231ccb 100644 --- a/views/page-widgets/parts/monthly-badges.php +++ b/views/page-widgets/parts/monthly-badges.php @@ -85,6 +85,7 @@ class="prpl-badge prpl-badge-get_id() ); ?>"

        get_name() ); ?>

        diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index 8629be323..241e2bd01 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -62,7 +62,11 @@ data-badge-id="get_id() ); ?>" > - + @@ -94,6 +98,7 @@ class="prpl-previous-month-badge-progress-bar-wrapper" data-badge-id="get_id() ); ?>" data-points="progress_callback()['points']; ?>" data-max-points="" + data-branding-id="get_ui__branding()->get_branding_id(); ?>" >
        diff --git a/views/popovers/monthly-badges.php b/views/popovers/monthly-badges.php index 47e68a935..245e2b6a9 100644 --- a/views/popovers/monthly-badges.php +++ b/views/popovers/monthly-badges.php @@ -63,6 +63,7 @@ class="prpl-badge"

        get_name() ); ?>

        diff --git a/views/popovers/parts/badge-streak-badge.php b/views/popovers/parts/badge-streak-badge.php index 4ebfdf678..c8877d7bd 100644 --- a/views/popovers/parts/badge-streak-badge.php +++ b/views/popovers/parts/badge-streak-badge.php @@ -20,6 +20,7 @@ class="prpl-badge" get_name() ); ?>
        From fb2eb84ed7580f4e05182798e9cb360657f58384 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Wed, 13 Aug 2025 11:01:34 +0300 Subject: [PATCH 025/338] Allow changing titles from the API --- assets/css/admin.css | 1 - .../web-components/prpl-badge-progress-bar.js | 2 +- assets/js/web-components/prpl-badge.js | 2 +- assets/js/web-components/prpl-gauge.js | 2 +- classes/ui/class-branding.php | 22 +++++++++++++++++++ views/page-widgets/activity-scores.php | 7 +++++- views/page-widgets/badge-streak.php | 6 ++++- views/page-widgets/challenge.php | 7 +++++- views/page-widgets/content-activity.php | 7 +++++- views/page-widgets/latest-badge.php | 7 +++++- views/page-widgets/suggested-tasks.php | 11 ++++++---- views/page-widgets/todo.php | 9 +++++++- views/page-widgets/whats-new.php | 7 +++++- 13 files changed, 75 insertions(+), 15 deletions(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index 1aca68dc8..1c61ca866 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -491,4 +491,3 @@ button.prpl-info-icon { transform: rotate(360deg); } } - diff --git a/assets/js/web-components/prpl-badge-progress-bar.js b/assets/js/web-components/prpl-badge-progress-bar.js index 0fa9bc2b2..922b8bdb2 100644 --- a/assets/js/web-components/prpl-badge-progress-bar.js +++ b/assets/js/web-components/prpl-badge-progress-bar.js @@ -13,7 +13,7 @@ customElements.define( 'prpl-badge-progress-bar', class extends HTMLElement { - constructor( badgeId, points, maxPoints, brandingId = '' ) { + constructor( badgeId, points, maxPoints, brandingId = 0 ) { // Get parent class properties super(); badgeId = badgeId || this.getAttribute( 'data-badge-id' ); diff --git a/assets/js/web-components/prpl-badge.js b/assets/js/web-components/prpl-badge.js index 3944dbdcb..1944826e5 100644 --- a/assets/js/web-components/prpl-badge.js +++ b/assets/js/web-components/prpl-badge.js @@ -13,7 +13,7 @@ customElements.define( 'prpl-badge', class extends HTMLElement { - constructor( badgeId, brandingId = '' ) { + constructor( badgeId, brandingId = 0 ) { // Get parent class properties super(); diff --git a/assets/js/web-components/prpl-gauge.js b/assets/js/web-components/prpl-gauge.js index 437dd5a17..aa2e9be7e 100644 --- a/assets/js/web-components/prpl-gauge.js +++ b/assets/js/web-components/prpl-gauge.js @@ -26,7 +26,7 @@ customElements.define( contentPadding: 'var(--prpl-padding) var(--prpl-padding) calc(var(--prpl-padding) * 2) var(--prpl-padding)', marginBottom: 'var(--prpl-padding)', - brandingId: '', + brandingId: 0, }, content = '' ) { diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 32567327e..a7edcf63f 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -285,4 +285,26 @@ function ( $widget ) use ( $show_papers ) { } ); } + + /** + * Get the widget title. + * + * @param string $widget_id The widget ID. + * @param string $default_value The default value. + * + * @return string + */ + public function get_widget_title( $widget_id, $default_value = '' ) { + if ( empty( $this->get_api_data() ) || ! isset( $this->get_api_data()['acf']['widget_titles'] ) ) { + return $default_value; + } + + foreach ( $this->get_api_data()['acf']['widget_titles'] as $widget ) { + if ( $widget['widget_id'] === $widget_id && isset( $widget['title'] ) ) { + return $widget['title']; + } + } + + return $default_value; + } } diff --git a/views/page-widgets/activity-scores.php b/views/page-widgets/activity-scores.php index 5e4395c68..64fee5941 100644 --- a/views/page-widgets/activity-scores.php +++ b/views/page-widgets/activity-scores.php @@ -16,7 +16,12 @@ ?>

        - + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'activity-scores', + \esc_html__( 'Your website activity score', 'progress-planner' ) + ); + ?>
        diff --git a/views/page-widgets/badge-streak.php b/views/page-widgets/badge-streak.php index 45cf706b6..511882a15 100644 --- a/views/page-widgets/badge-streak.php +++ b/views/page-widgets/badge-streak.php @@ -48,7 +48,11 @@

        get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'badge-streak', + \esc_html__( 'Your streak badges', 'progress-planner' ) + ); + \progress_planner()->get_ui__popover()->the_popover( 'badge-streak' )->render_button( '', '' . \progress_planner()->get_asset( 'images/icon_info.svg' ) . ' ' . \esc_html__( 'More info', 'progress-planner' ) . '' diff --git a/views/page-widgets/challenge.php b/views/page-widgets/challenge.php index be0fc583e..b7051684c 100644 --- a/views/page-widgets/challenge.php +++ b/views/page-widgets/challenge.php @@ -12,7 +12,12 @@ $prpl_challenge = \progress_planner()->get_admin__widgets__challenge()->get_challenge(); ?>

        - + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'challenge', + \esc_html( $prpl_challenge['name'] ) + ); + ?>

        diff --git a/views/page-widgets/content-activity.php b/views/page-widgets/content-activity.php index 9755e201f..8e2db645c 100644 --- a/views/page-widgets/content-activity.php +++ b/views/page-widgets/content-activity.php @@ -89,7 +89,12 @@ function ( $activity ) use ( $prpl_tracked_post_types ) { ?>

        - + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'content-activity', + \esc_html__( 'Content activity', 'progress-planner' ) + ); + ?>

        diff --git a/views/page-widgets/latest-badge.php b/views/page-widgets/latest-badge.php index a6cf61954..8186065ad 100644 --- a/views/page-widgets/latest-badge.php +++ b/views/page-widgets/latest-badge.php @@ -14,7 +14,12 @@ ?>

        - + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'latest-badge', + \esc_html__( 'Latest new badge!', 'progress-planner' ) + ); + ?>

        diff --git a/views/page-widgets/suggested-tasks.php b/views/page-widgets/suggested-tasks.php index 241e2bd01..86b5fe0e0 100644 --- a/views/page-widgets/suggested-tasks.php +++ b/views/page-widgets/suggested-tasks.php @@ -18,10 +18,13 @@

        get_ui__branding()->get_ravi_name() ) + echo \progress_planner()->get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'suggested-tasks', + \sprintf( + /* translators: %s: "Ravi" */ + \esc_html__( '%s’s Recommendations', 'progress-planner' ), + \esc_html( \progress_planner()->get_ui__branding()->get_ravi_name() ) + ) ); ?>

        diff --git a/views/page-widgets/todo.php b/views/page-widgets/todo.php index e55353d9a..809e0f7e5 100644 --- a/views/page-widgets/todo.php +++ b/views/page-widgets/todo.php @@ -11,7 +11,14 @@ ?>

        - + + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'todo', + \esc_html__( 'My to-do list', 'progress-planner' ) + ); + ?> +

        diff --git a/views/page-widgets/whats-new.php b/views/page-widgets/whats-new.php index 986b765a7..0f82f79d5 100644 --- a/views/page-widgets/whats-new.php +++ b/views/page-widgets/whats-new.php @@ -13,7 +13,12 @@ ?>

        - + get_ui__branding()->get_widget_title( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + 'whats-new', + \esc_html__( 'What\'s new on the Progress Planner blog', 'progress-planner' ) + ); + ?>

          From 3a08dbb5ae84e696bbe090b6e81993ce26d9ef9f Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Thu, 14 Aug 2025 12:42:27 +0300 Subject: [PATCH 026/338] Allow defining the blog-feed URL server-side --- classes/admin/widgets/class-whats-new.php | 2 +- classes/ui/class-branding.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/classes/admin/widgets/class-whats-new.php b/classes/admin/widgets/class-whats-new.php index c343ddfd3..12cc6d7b0 100644 --- a/classes/admin/widgets/class-whats-new.php +++ b/classes/admin/widgets/class-whats-new.php @@ -55,7 +55,7 @@ public function get_blog_feed() { // Transient expired, fetch new feed. if ( $feed_data['expires'] < \time() ) { // Get the feed using the REST API. - $response = \wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/posts/?per_page=2' ); + $response = \wp_remote_get( \progress_planner()->get_ui__branding()->get_blog_feed_url() . '/wp-json/wp/v2/posts/?per_page=2' ); if ( 200 !== \wp_remote_retrieve_response_code( $response ) ) { // If we cant fetch the feed, we will try again later. diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index a7edcf63f..2db24ceec 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -307,4 +307,15 @@ public function get_widget_title( $widget_id, $default_value = '' ) { return $default_value; } + + /** + * Get the blog-feed URL. + * + * @return string + */ + public function get_blog_feed_url(): string { + return empty( $this->get_api_data() ) || ! isset( $this->get_api_data()['acf']['blog_feed_url'] ) + ? \progress_planner()->get_remote_server_root_url() + : $this->get_api_data()['acf']['blog_feed_url']; + } } From 7f42b291a2ce6285f265cd9f65cd19db83863bf7 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Thu, 14 Aug 2025 15:05:09 +0300 Subject: [PATCH 027/338] Get the cache key from the URL --- classes/admin/widgets/class-whats-new.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/classes/admin/widgets/class-whats-new.php b/classes/admin/widgets/class-whats-new.php index 12cc6d7b0..014f3472d 100644 --- a/classes/admin/widgets/class-whats-new.php +++ b/classes/admin/widgets/class-whats-new.php @@ -14,13 +14,6 @@ */ final class Whats_New extends Widget { - /** - * The cache key. - * - * @var string - */ - const CACHE_KEY = 'blog_feed'; - /** * The widget ID. * @@ -34,13 +27,13 @@ final class Whats_New extends Widget { * @return array */ public function get_blog_feed() { - $feed_data = \progress_planner()->get_utils__cache()->get( self::CACHE_KEY ); + $feed_data = \progress_planner()->get_utils__cache()->get( $this->get_cache_key() ); // Migrate old feed to new format. if ( \is_array( $feed_data ) && ! isset( $feed_data['expires'] ) && ! isset( $feed_data['feed'] ) ) { $feed_data = [ 'feed' => $feed_data, - 'expires' => \get_option( '_transient_timeout_' . Cache::CACHE_PREFIX . self::CACHE_KEY, 0 ), + 'expires' => \get_option( '_transient_timeout_' . Cache::CACHE_PREFIX . $this->get_cache_key(), 0 ), ]; } @@ -82,9 +75,18 @@ public function get_blog_feed() { } // Transient uses 'expires' key to determine if it's expired. - \progress_planner()->get_utils__cache()->set( self::CACHE_KEY, $feed_data, 0 ); + \progress_planner()->get_utils__cache()->set( $this->get_cache_key(), $feed_data, 0 ); } return $feed_data['feed']; } + + /** + * Get the cache key. + * + * @return string + */ + public function get_cache_key() { + return 'blog_feed_' . md5( \progress_planner()->get_ui__branding()->get_blog_feed_url() ); + } } From 2bb13f1c0a4eef0700be9d5cd865a6296b596998 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Mon, 18 Aug 2025 09:07:34 +0300 Subject: [PATCH 028/338] No need to have a default API response since it's already in the plugin --- classes/ui/class-branding.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 2db24ceec..c5dc3519c 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -18,7 +18,7 @@ final class Branding { * @var array */ const BRANDING_IDS = [ - // TODO: Change this to the default value of 4958. + // TODO: Change this to the default value of 0. 'default' => 5159, ]; @@ -62,6 +62,10 @@ public function get_branding_id(): int { * @return array */ public function get_api_data(): array { + if ( 0 === $this->get_branding_id() ) { + return []; + } + $response = $this->get_remote_data( \progress_planner()->get_remote_server_root_url() . '/wp-json/wp/v2/pp-branding/' . $this->get_branding_id() ); From 8975e3446107443a45a2c9bbe43f932dd8931584 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Tue, 26 Aug 2025 10:26:05 +0200 Subject: [PATCH 029/338] WIP: handle failed interactive task requests --- assets/js/recommendations/hello-world.js | 30 ++++-- assets/js/recommendations/interactive-task.js | 102 ++++++++++++------ assets/js/recommendations/sample-page.js | 30 ++++-- 3 files changed, 110 insertions(+), 52 deletions(-) diff --git a/assets/js/recommendations/hello-world.js b/assets/js/recommendations/hello-world.js index 5c75e94d6..c76b04f06 100644 --- a/assets/js/recommendations/hello-world.js +++ b/assets/js/recommendations/hello-world.js @@ -10,16 +10,28 @@ prplInteractiveTaskFormListener.customSubmit( { taskId: 'hello-world', popoverId: 'prpl-popover-hello-world', callback: () => { - const post = new wp.api.models.Post( { - id: helloWorldData.postId, - } ); - post.fetch().then( () => { - // Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true - const url = post.url().includes( 'rest_route=' ) - ? post.url() + '&force=true' - : post.url() + '?force=true'; + return new Promise( ( resolve, reject ) => { + const post = new wp.api.models.Post( { + id: helloWorldData.postId, + } ); + post.fetch() + .then( () => { + // Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true + const url = post.url().includes( 'rest_route=' ) + ? post.url() + '&force=true' + : post.url() + '?force=true'; - post.destroy( { url } ); + post.destroy( { url } ) + .then( () => { + resolve( { success: true } ); + } ) + .catch( ( error ) => { + reject( { success: false, error } ); + } ); + } ) + .catch( ( error ) => { + reject( { success: false, error } ); + } ); } ); }, } ); diff --git a/assets/js/recommendations/interactive-task.js b/assets/js/recommendations/interactive-task.js index 9ca1fcb06..e8e293072 100644 --- a/assets/js/recommendations/interactive-task.js +++ b/assets/js/recommendations/interactive-task.js @@ -50,10 +50,16 @@ const prplInteractiveTaskFormListener = { wp.api.loadPromise.done( () => { const settings = new wp.api.models.Settings( settingsToPass ); - settings.save().then( () => { + settings.save().then( ( response ) => { + console.log( response ); + if ( true !== response.success ) { + // TODO: Handle error. + return response; + } + const postId = parseInt( taskEl.dataset.postId ); if ( ! postId ) { - return; + return response; } // This will trigger the celebration event (confetti) as well. @@ -77,22 +83,36 @@ const prplInteractiveTaskFormListener = { formElement.addEventListener( 'submit', ( event ) => { event.preventDefault(); - callback(); + callback() + .then( ( response ) => { + console.log( response ); + if ( true !== response.success ) { + // TODO: Handle error. + return response; + } - const taskEl = document.querySelector( - `.prpl-suggested-task[data-task-id="${ taskId }"]` - ); + const taskEl = document.querySelector( + `.prpl-suggested-task[data-task-id="${ taskId }"]` + ); - const postId = parseInt( taskEl.dataset.postId ); - if ( ! postId ) { - return; - } + const postId = parseInt( taskEl.dataset.postId ); + if ( ! postId ) { + return; + } - // This will trigger the celebration event (confetti) as well. - prplSuggestedTask.maybeComplete( postId ).then( () => { - // Close popover. - document.getElementById( popoverId ).hidePopover(); - } ); + // This will trigger the celebration event (confetti) as well. + prplSuggestedTask.maybeComplete( postId ).then( () => { + // Close popover. + document.getElementById( popoverId ).hidePopover(); + } ); + } ) + .catch( ( error ) => { + console.error( + 'Error in interactive task callback:', + error + ); + // TODO: Handle the error appropriately. + } ); } ); }, @@ -129,26 +149,40 @@ const prplInteractiveTaskFormListener = { value: settingsToPass[ setting ], setting_path: settingPath, }, - } ).then( () => { - const taskEl = document.querySelector( - `.prpl-suggested-task[data-task-id="${ taskId }"]` - ); - - if ( ! taskEl ) { - return; - } - - const postId = parseInt( taskEl.dataset.postId ); - if ( ! postId ) { - return; - } - - // This will trigger the celebration event (confetti) as well. - prplSuggestedTask.maybeComplete( postId ).then( () => { - // Close popover. - document.getElementById( popoverId ).hidePopover(); + } ) + .then( ( response ) => { + console.log( response ); + if ( true !== response.success ) { + // TODO: Handle error. + return response; + } + + const taskEl = document.querySelector( + `.prpl-suggested-task[data-task-id="${ taskId }"]` + ); + + if ( ! taskEl ) { + return response; + } + + const postId = parseInt( taskEl.dataset.postId ); + if ( ! postId ) { + return response; + } + + // This will trigger the celebration event (confetti) as well. + prplSuggestedTask.maybeComplete( postId ).then( () => { + // Close popover. + document.getElementById( popoverId ).hidePopover(); + } ); + } ) + .catch( ( error ) => { + console.error( + 'Error in interactive task settings:', + error + ); + // TODO: Handle the error appropriately. } ); - } ); } ); }, }; diff --git a/assets/js/recommendations/sample-page.js b/assets/js/recommendations/sample-page.js index 7f07b357f..7b10ed1cb 100644 --- a/assets/js/recommendations/sample-page.js +++ b/assets/js/recommendations/sample-page.js @@ -10,16 +10,28 @@ prplInteractiveTaskFormListener.customSubmit( { taskId: 'sample-page', popoverId: 'prpl-popover-sample-page', callback: () => { - const post = new wp.api.models.Page( { - id: samplePageData.postId, - } ); - post.fetch().then( () => { - // Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true - const url = post.url().includes( 'rest_route=' ) - ? post.url() + '&force=true' - : post.url() + '?force=true'; + return new Promise( ( resolve, reject ) => { + const post = new wp.api.models.Page( { + id: samplePageData.postId, + } ); + post.fetch() + .then( () => { + // Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true + const url = post.url().includes( 'rest_route=' ) + ? post.url() + '&force=true' + : post.url() + '?force=true'; - post.destroy( { url } ); + post.destroy( { url } ) + .then( () => { + resolve( { success: true } ); + } ) + .catch( ( error ) => { + reject( { success: false, error } ); + } ); + } ) + .catch( ( error ) => { + reject( { success: false, error } ); + } ); } ); }, } ); From 2818725479c0a8b1e4623f2560935ce81701f400 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 29 Aug 2025 12:57:37 +0300 Subject: [PATCH 030/338] Add new vars - complimentary to previous merge --- classes/ui/class-branding.php | 77 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index c5dc3519c..d16790be9 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -113,43 +113,46 @@ public function the_logo(): void { */ public function get_css_variables(): string { $vars = [ - '--prpl-color-gray-1' => '#e1e3e7', - '--prpl-color-gray-2' => '#d1d5db', - '--prpl-color-gray-3' => '#9ca3af', - '--prpl-color-gray-4' => '#6b7280', - '--prpl-color-gray-5' => '#4b5563', - '--prpl-color-gray-6' => '#374151', - - '--prpl-color-accent-red' => '#f43f5e', - '--prpl-color-accent-orange' => '#faa310', - '--prpl-color-400-orange' => '#f9b23c', - '--prpl-color-accent-purple' => '#0d6b9e', - '--prpl-color-accent-green' => '#14b8a6', - - '--prpl-color-headings' => '#38296d', - '--prpl-color-text' => 'var(--prpl-color-gray-5)', - '--prpl-color-link' => '#1e40af', - - '--prpl-color-notification-green' => '#16a34a', - '--prpl-color-notification-red' => '#e73136', - - '--prpl-background-body' => '#f0f0f1', - '--prpl-background-main' => '#ffffff', - '--prpl-background-papers' => '#ffffff', - '--prpl-background-orange' => '#fff9f0', - '--prpl-background-purple' => '#f6f5fb', - '--prpl-background-green' => '#f2faf9', - '--prpl-background-red' => '#fff6f7', - '--prpl-background-blue' => '#effbfe', - - '--prpl-main-area-border-color' => 'var(--prpl-color-gray-2)', - '--prpl-paper-border-color' => 'var(--prpl-color-gray-2)', - - '--prpl-papers-box-shadow' => '4px 4px 10px rgba(0, 0, 0, 0.07), -2px 0 6px rgba(0, 0, 0, 0.07)', - - '--prpl-border-radius' => '8px', - '--prpl-border-radius-small' => 'calc(var(--prpl-border-radius) * 0.75)', - '--prpl-border-radius-big' => 'calc(var(--prpl-border-radius) * 2)', + '--prpl-color-gray-1' => '#e1e3e7', + '--prpl-color-gray-2' => '#d1d5db', + '--prpl-color-gray-3' => '#9ca3af', + '--prpl-color-gray-4' => '#6b7280', + '--prpl-color-gray-5' => '#4b5563', + '--prpl-color-gray-6' => '#374151', + + '--prpl-color-accent-red' => '#f43f5e', + '--prpl-color-accent-orange' => '#faa310', + '--prpl-color-400-orange' => '#f9b23c', + '--prpl-color-accent-purple' => '#0d6b9e', + '--prpl-color-accent-green' => '#14b8a6', + + '--prpl-color-headings' => '#38296d', + '--prpl-color-text' => 'var(--prpl-color-gray-5)', + '--prpl-color-link' => '#1e40af', + + '--prpl-color-notification-green' => '#16a34a', + '--prpl-color-notification-red' => '#e73136', + + '--prpl-background-body' => '#f0f0f1', + '--prpl-background-main' => '#ffffff', + '--prpl-background-papers' => '#ffffff', + '--prpl-background-orange' => '#fff9f0', + '--prpl-background-purple' => '#f6f5fb', + '--prpl-background-green' => '#f2faf9', + '--prpl-background-red' => '#fff6f7', + '--prpl-background-blue' => '#effbfe', + + '--prpl-color-button-primary-hover' => '#cf2441', + '--prpl-color-button-primary' => '#dd3244', + + '--prpl-main-area-border-color' => 'var(--prpl-color-gray-2)', + '--prpl-paper-border-color' => 'var(--prpl-color-gray-2)', + + '--prpl-papers-box-shadow' => '4px 4px 10px rgba(0, 0, 0, 0.07), -2px 0 6px rgba(0, 0, 0, 0.07)', + + '--prpl-border-radius' => '8px', + '--prpl-border-radius-small' => 'calc(var(--prpl-border-radius) * 0.75)', + '--prpl-border-radius-big' => 'calc(var(--prpl-border-radius) * 2)', ]; if ( ! empty( $this->get_api_data() ) && ! empty( $this->get_api_data()['acf']['css_variables'] ) ) { From 3c49d88bf77313049e5bffe0e06d7518aa9a4a5d Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 5 Sep 2025 10:09:59 +0200 Subject: [PATCH 031/338] use add_option for 'add task' lock --- classes/class-suggested-tasks-db.php | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/classes/class-suggested-tasks-db.php b/classes/class-suggested-tasks-db.php index 960886cf9..ca7f797bf 100644 --- a/classes/class-suggested-tasks-db.php +++ b/classes/class-suggested-tasks-db.php @@ -36,16 +36,25 @@ public function add( $data ) { return 0; } - // Set lock transient. - $transient_key = 'prpl_task_lock_' . $data['task_id']; + $lock_key = 'prpl_task_lock_' . $data['task_id']; + $lock_value = \time(); - // Check if the task is already being processed. - if ( \get_transient( $transient_key ) ) { - return 0; + // Try to acquire lock atomically, add_option will return false if the option already exists. + $got_lock = \add_option( $lock_key, $lock_value, '', false ); + + if ( ! $got_lock ) { + $current = \get_option( $lock_key ); + + // If lock is older than 30 seconds, consider it stale and replace it. + if ( $current && ( $current < time() - 30 ) ) { + update_option( $lock_key, $lock_value ); + $got_lock = true; + } } - // Set lock transient. - \set_transient( $transient_key, true, 5 ); + if ( ! $got_lock ) { + return 0; // Another process is already working. + } // Check if we have an existing task with the same title. $posts = $this->get_tasks_by( @@ -64,7 +73,7 @@ public function add( $data ) { // If we have an existing task, skip. if ( ! empty( $posts ) ) { - \delete_transient( $transient_key ); + \delete_option( $lock_key ); return $posts[0]->ID; } @@ -149,7 +158,7 @@ public function add( $data ) { \update_post_meta( $post_id, "prpl_$key", $value ); } - \delete_transient( $transient_key ); + \delete_option( $lock_key ); return $post_id; } From bfa216d6ba6f8979ba4a1fe126edc175abc11372 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 5 Sep 2025 12:05:24 +0200 Subject: [PATCH 032/338] a bit safer locking --- classes/class-suggested-tasks-db.php | 109 +++++++++++++-------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/classes/class-suggested-tasks-db.php b/classes/class-suggested-tasks-db.php index ca7f797bf..6793b5b08 100644 --- a/classes/class-suggested-tasks-db.php +++ b/classes/class-suggested-tasks-db.php @@ -39,23 +39,19 @@ public function add( $data ) { $lock_key = 'prpl_task_lock_' . $data['task_id']; $lock_value = \time(); - // Try to acquire lock atomically, add_option will return false if the option already exists. - $got_lock = \add_option( $lock_key, $lock_value, '', false ); - - if ( ! $got_lock ) { + // add_option will return false if the option is already there. + if ( ! \add_option( $lock_key, $lock_value, '', false ) ) { $current = \get_option( $lock_key ); - // If lock is older than 30 seconds, consider it stale and replace it. - if ( $current && ( $current < time() - 30 ) ) { - update_option( $lock_key, $lock_value ); - $got_lock = true; + // If lock is stale (older than 30s), take over. + if ( $current && ( $current < \time() - 30 ) ) { + \update_option( $lock_key, $lock_value ); + } else { + error_log( 'Lock for: ' . $data['task_id'] ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- TODO: remove this after testing. + return 0; // Other process is using it. } } - if ( ! $got_lock ) { - return 0; // Another process is already working. - } - // Check if we have an existing task with the same title. $posts = $this->get_tasks_by( [ @@ -109,57 +105,60 @@ public function add( $data ) { break; } - $post_id = \wp_insert_post( $args ); + try { + $post_id = \wp_insert_post( $args ); - // Add terms if they don't exist. - foreach ( [ 'category', 'provider_id' ] as $context ) { - $taxonomy_name = \str_replace( '_id', '', $context ); - $term = \get_term_by( 'name', $data[ $context ], "prpl_recommendations_$taxonomy_name" ); - if ( ! $term ) { - \wp_insert_term( $data[ $context ], "prpl_recommendations_$taxonomy_name" ); + // Add terms if they don't exist. + foreach ( [ 'category', 'provider_id' ] as $context ) { + $taxonomy_name = \str_replace( '_id', '', $context ); + $term = \get_term_by( 'name', $data[ $context ], "prpl_recommendations_$taxonomy_name" ); + if ( ! $term ) { + \wp_insert_term( $data[ $context ], "prpl_recommendations_$taxonomy_name" ); + } } - } - // Set the task category. - \wp_set_post_terms( $post_id, $data['category'], 'prpl_recommendations_category' ); - - // Set the task provider. - \wp_set_post_terms( $post_id, $data['provider_id'], 'prpl_recommendations_provider' ); - - // Set the task parent. - if ( ! empty( $data['parent'] ) ) { - $parent = \get_post( $data['parent'] ); - if ( $parent ) { - \wp_update_post( - [ - 'ID' => $post_id, - 'post_parent' => $parent->ID, - ] - ); + // Set the task category. + \wp_set_post_terms( $post_id, $data['category'], 'prpl_recommendations_category' ); + + // Set the task provider. + \wp_set_post_terms( $post_id, $data['provider_id'], 'prpl_recommendations_provider' ); + + // Set the task parent. + if ( ! empty( $data['parent'] ) ) { + $parent = \get_post( $data['parent'] ); + if ( $parent ) { + \wp_update_post( + [ + 'ID' => $post_id, + 'post_parent' => $parent->ID, + ] + ); + } } - } - // Set other meta. - $default_keys = [ - 'title', - 'description', - 'status', - 'category', - 'provider_id', - 'parent', - 'order', - 'post_status', - ]; - foreach ( $data as $key => $value ) { - if ( \in_array( $key, $default_keys, true ) ) { - continue; + // Set other meta. + $default_keys = [ + 'title', + 'description', + 'status', + 'category', + 'provider_id', + 'parent', + 'order', + 'post_status', + ]; + foreach ( $data as $key => $value ) { + if ( \in_array( $key, $default_keys, true ) ) { + continue; + } + + \update_post_meta( $post_id, "prpl_$key", $value ); } - - \update_post_meta( $post_id, "prpl_$key", $value ); + } finally { + // Delete the lock. This executes always. + \delete_option( $lock_key ); } - \delete_option( $lock_key ); - return $post_id; } From 99d62900ee20f7b1c33827fde0b8ee769fe6ebf9 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 5 Sep 2025 16:14:03 +0200 Subject: [PATCH 033/338] check for activities --- classes/class-suggested-tasks.php | 16 +++++++++++++++- .../providers/class-select-locale.php | 4 ++-- .../providers/class-select-timezone.php | 4 ++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/classes/class-suggested-tasks.php b/classes/class-suggested-tasks.php index bda582614..9e98e7f2d 100644 --- a/classes/class-suggested-tasks.php +++ b/classes/class-suggested-tasks.php @@ -177,7 +177,21 @@ public function get_tasks_manager(): Tasks_Manager { */ public function was_task_completed( $task_id ): bool { $task = \progress_planner()->get_suggested_tasks_db()->get_post( $task_id ); - return $task && $task->is_completed(); + + // Checks for task (post) status, trash or pending. + if ( $task && $task->is_completed() ) { + return true; + } + + // Checks for activity, if there is an activity for the task, it means that the task was completed (and post might already be deleted from the trash). + $activity = \progress_planner()->get_activities__query()->query_activities( + [ + 'category' => 'suggested_task', + 'data_id' => $task_id, + ] + ); + + return ! empty( $activity ); } /** diff --git a/classes/suggested-tasks/providers/class-select-locale.php b/classes/suggested-tasks/providers/class-select-locale.php index 8ed7405d4..d2d0b7a0f 100644 --- a/classes/suggested-tasks/providers/class-select-locale.php +++ b/classes/suggested-tasks/providers/class-select-locale.php @@ -175,14 +175,14 @@ function ( $locale ) { * @return bool */ public function is_task_completed( $task_id = '' ) { - $locale_activity = \progress_planner()->get_activities__query()->query_activities( + $activity = \progress_planner()->get_activities__query()->query_activities( [ 'category' => 'suggested_task', 'data_id' => static::PROVIDER_ID, ] ); - return ! empty( $locale_activity ); + return ! empty( $activity ); } /** diff --git a/classes/suggested-tasks/providers/class-select-timezone.php b/classes/suggested-tasks/providers/class-select-timezone.php index df1b1b994..fb53d4131 100644 --- a/classes/suggested-tasks/providers/class-select-timezone.php +++ b/classes/suggested-tasks/providers/class-select-timezone.php @@ -87,14 +87,14 @@ protected function get_description() { * @return bool */ public function should_add_task() { - $timezone_activity = \progress_planner()->get_activities__query()->query_activities( + $activity = \progress_planner()->get_activities__query()->query_activities( [ 'category' => 'suggested_task', 'data_id' => static::PROVIDER_ID, ] ); - return ! $timezone_activity; + return ! $activity; } /** From f8ee140c26efea0165b2da9dc5a8811f40cf0a49 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 9 Sep 2025 08:57:04 +0300 Subject: [PATCH 034/338] Get URLs from the API --- .../providers/class-blog-description.php | 2 +- .../providers/class-content-create.php | 4 ++-- .../providers/class-content-review.php | 2 +- .../providers/class-core-update.php | 2 +- .../providers/class-debug-display.php | 2 +- .../class-disable-comment-pagination.php | 4 ++-- .../providers/class-disable-comments.php | 2 +- .../providers/class-email-sending.php | 20 +++++++++-------- .../providers/class-fewer-tags.php | 2 +- .../providers/class-hello-world.php | 2 +- .../providers/class-permalink-structure.php | 2 +- .../providers/class-php-version.php | 2 +- .../class-remove-inactive-plugins.php | 2 +- .../class-remove-terms-without-posts.php | 2 +- .../class-rename-uncategorized-category.php | 2 +- .../providers/class-sample-page.php | 2 +- .../class-search-engine-visibility.php | 2 +- .../class-set-valuable-post-types.php | 2 +- .../providers/class-site-icon.php | 2 +- .../class-update-term-description.php | 2 +- .../yoast/class-archive-author.php | 2 +- .../integrations/yoast/class-archive-date.php | 2 +- .../yoast/class-archive-format.php | 2 +- .../yoast/class-cornerstone-workout.php | 2 +- .../class-crawl-settings-emoji-scripts.php | 2 +- .../class-crawl-settings-feed-authors.php | 2 +- ...ss-crawl-settings-feed-global-comments.php | 2 +- .../yoast/class-fix-orphaned-content.php | 4 ++-- .../integrations/yoast/class-media-pages.php | 2 +- .../yoast/class-organization-logo.php | 4 ++-- .../yoast/class-orphaned-content-workout.php | 2 +- classes/ui/class-branding.php | 22 +++++++++++++++++++ views/page-widgets/whats-new.php | 2 +- views/popovers/subscribe-form.php | 2 +- views/welcome.php | 6 ++--- 35 files changed, 72 insertions(+), 48 deletions(-) diff --git a/classes/suggested-tasks/providers/class-blog-description.php b/classes/suggested-tasks/providers/class-blog-description.php index 3af16ffaf..7baae20c4 100644 --- a/classes/suggested-tasks/providers/class-blog-description.php +++ b/classes/suggested-tasks/providers/class-blog-description.php @@ -51,7 +51,7 @@ protected function get_description() { return \sprintf( /* translators: %s:tagline link */ \esc_html__( 'Set the %s to make your website look more professional.', 'progress-planner' ), - '' . \esc_html__( 'tagline', 'progress-planner' ) . '' + '' . \esc_html__( 'tagline', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-content-create.php b/classes/suggested-tasks/providers/class-content-create.php index d45c22c2e..034688235 100644 --- a/classes/suggested-tasks/providers/class-content-create.php +++ b/classes/suggested-tasks/providers/class-content-create.php @@ -62,7 +62,7 @@ class Content_Create extends Tasks { * @return string */ protected function get_url() { - return 'https://prpl.fyi/valuable-content'; + return \progress_planner()->get_ui__branding()->get_url( 'https://prpl.fyi/valuable-content' ); } /** @@ -83,7 +83,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Time to add more valuable content to your site! Check our blog for inspiration. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-content-review.php b/classes/suggested-tasks/providers/class-content-review.php index 7174bf4cc..24573d253 100644 --- a/classes/suggested-tasks/providers/class-content-review.php +++ b/classes/suggested-tasks/providers/class-content-review.php @@ -167,7 +167,7 @@ protected function get_description_with_data( $task_data = [] ) { return '

          ' . \sprintf( /* translators: %1$s Review link, %2$s: The post title, %3$s: The number of months. */ \esc_html__( '%1$s the post "%2$s" as it was last updated more than %3$s months ago.', 'progress-planner' ), - '' . \esc_html__( 'Review', 'progress-planner' ) . '', + '' . \esc_html__( 'Review', 'progress-planner' ) . '', \esc_html( $post->post_title ), // @phpstan-ignore-line property.nonObject \esc_html( $months ) ) . '

          '; diff --git a/classes/suggested-tasks/providers/class-core-update.php b/classes/suggested-tasks/providers/class-core-update.php index 5564821a4..71cab82f8 100644 --- a/classes/suggested-tasks/providers/class-core-update.php +++ b/classes/suggested-tasks/providers/class-core-update.php @@ -85,7 +85,7 @@ protected function get_description() { return \sprintf( /* translators: %s:See why we recommend this link */ \esc_html__( 'Regular updates improve security and performance. %s.', 'progress-planner' ), - '' . \esc_html__( 'See why we recommend this', 'progress-planner' ) . '' + '' . \esc_html__( 'See why we recommend this', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-debug-display.php b/classes/suggested-tasks/providers/class-debug-display.php index c0789c055..fa35c1301 100644 --- a/classes/suggested-tasks/providers/class-debug-display.php +++ b/classes/suggested-tasks/providers/class-debug-display.php @@ -46,7 +46,7 @@ protected function get_description( $task_data = [] ) { // translators: %1$s is the name of the WP_DEBUG_DISPLAY constant, %2$s We recommend link. \esc_html__( '%1$s is enabled. This means that errors are shown to users. %2$s disabling it.', 'progress-planner' ), 'WP_DEBUG_DISPLAY', - '' . \esc_html__( 'We recommend', 'progress-planner' ) . '' + '' . \esc_html__( 'We recommend', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-disable-comment-pagination.php b/classes/suggested-tasks/providers/class-disable-comment-pagination.php index cc36d4ed7..12fe96a49 100644 --- a/classes/suggested-tasks/providers/class-disable-comment-pagination.php +++ b/classes/suggested-tasks/providers/class-disable-comment-pagination.php @@ -73,7 +73,7 @@ protected function get_description() { /* translators: %d is the number of comments per page, %s is the "recommend to disable comment pagination" link */ \esc_html__( 'When comment pagination is enabled, your site creates a new page for every %1$d comments. This is not helping your website in search engines, and can break up the ongoing conversation. That\'s why we %2$s.', 'progress-planner' ), (int) \get_option( 'comments_per_page' ), - '' . \esc_html__( 'recommend to disable comment pagination', 'progress-planner' ) . '' + '' . \esc_html__( 'recommend to disable comment pagination', 'progress-planner' ) . '' ); } @@ -109,7 +109,7 @@ public function print_popover_instructions() { /* translators: %d is the number of comments per page, %s is the "recommend to disable comment pagination" link */ \esc_html__( 'When comment pagination is enabled, your site creates a new page for every %1$d comments. This is not helping your website in search engines, and can break up the ongoing conversation. That\'s why we %2$s.', 'progress-planner' ), (int) \get_option( 'comments_per_page' ), - '' . \esc_html__( 'recommend to disable comment pagination', 'progress-planner' ) . '' + '' . \esc_html__( 'recommend to disable comment pagination', 'progress-planner' ) . '' ); echo '

          '; } diff --git a/classes/suggested-tasks/providers/class-disable-comments.php b/classes/suggested-tasks/providers/class-disable-comments.php index 2b957d7e5..491e9a1f5 100644 --- a/classes/suggested-tasks/providers/class-disable-comments.php +++ b/classes/suggested-tasks/providers/class-disable-comments.php @@ -80,7 +80,7 @@ protected function get_description() { ) ), (int) \wp_count_comments()->approved, - '' . \esc_html__( 'disabling them', 'progress-planner' ) . '', + '' . \esc_html__( 'disabling them', 'progress-planner' ) . '', ); } diff --git a/classes/suggested-tasks/providers/class-email-sending.php b/classes/suggested-tasks/providers/class-email-sending.php index 46f563a75..e0836a0ca 100644 --- a/classes/suggested-tasks/providers/class-email-sending.php +++ b/classes/suggested-tasks/providers/class-email-sending.php @@ -89,13 +89,6 @@ class Email_Sending extends Tasks_Interactive { */ protected $is_wp_mail_overridden = false; - /** - * The troubleshooting guide URL. - * - * @var string - */ - protected $troubleshooting_guide_url = 'https://prpl.fyi/troubleshoot-smtp'; - /** * Initialize the task provider. * @@ -124,6 +117,15 @@ public function init() { ); } + /** + * Get the troubleshooting guide URL. + * + * @return string + */ + protected function get_troubleshooting_guide_url() { + return \esc_url( \progress_planner()->get_ui__branding()->get_url( 'https://prpl.fyi/troubleshoot-smtp' ) ); + } + /** * We want task to be added always. * @@ -196,7 +198,7 @@ public function enqueue_scripts( $hook ) { 'ajax_url' => \admin_url( 'admin-ajax.php' ), 'nonce' => \wp_create_nonce( 'progress_planner' ), 'unknown_error' => \esc_html__( 'Unknown error', 'progress-planner' ), - 'troubleshooting_guide_url' => $this->troubleshooting_guide_url, + 'troubleshooting_guide_url' => $this->get_troubleshooting_guide_url(), ], ] ); @@ -287,7 +289,7 @@ public function the_popover_content() { 'prpl_provider_id' => $this->get_provider_id(), 'prpl_email_subject' => $this->email_subject, 'prpl_email_error' => $this->email_error, - 'prpl_troubleshooting_guide_url' => $this->troubleshooting_guide_url, + 'prpl_troubleshooting_guide_url' => $this->get_troubleshooting_guide_url(), 'prpl_is_there_sending_email_override' => $this->is_there_sending_email_override(), ] ); diff --git a/classes/suggested-tasks/providers/class-fewer-tags.php b/classes/suggested-tasks/providers/class-fewer-tags.php index 0bdf17cf2..4aadd774d 100644 --- a/classes/suggested-tasks/providers/class-fewer-tags.php +++ b/classes/suggested-tasks/providers/class-fewer-tags.php @@ -117,7 +117,7 @@ protected function get_description() { \esc_html__( 'We detected that you have %1$s tags and %2$s published posts. Consider installing the "Fewer Tags" plugin. %3$s', 'progress-planner' ), $this->post_tag_count_data_collector->collect(), $this->published_post_count_data_collector->collect(), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-hello-world.php b/classes/suggested-tasks/providers/class-hello-world.php index 59317f634..d36f5a72f 100644 --- a/classes/suggested-tasks/providers/class-hello-world.php +++ b/classes/suggested-tasks/providers/class-hello-world.php @@ -104,7 +104,7 @@ protected function get_description() { ) . '

          ' . \sprintf( /* translators: %s: URL to https://prpl.fyi/delete-sample-page */ \__( 'This post does not add value to your website and solely exists to show what a post can look like. Therefore, "Hello World!" is not needed and should be deleted.', 'progress-planner' ), - 'https://prpl.fyi/delete-hello-world-post' + \esc_url( \progress_planner()->get_ui__branding()->get_url( 'https://prpl.fyi/delete-hello-world-post' ) ) ) . '

          '; } diff --git a/classes/suggested-tasks/providers/class-permalink-structure.php b/classes/suggested-tasks/providers/class-permalink-structure.php index f0993387d..dd32bc40d 100644 --- a/classes/suggested-tasks/providers/class-permalink-structure.php +++ b/classes/suggested-tasks/providers/class-permalink-structure.php @@ -80,7 +80,7 @@ protected function get_description() { return \sprintf( /* translators: %1$s We recommend link */ \esc_html__( 'On install, WordPress sets the permalink structure to a format that is not SEO-friendly. %1$s changing it.', 'progress-planner' ), - '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', + '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', ); } diff --git a/classes/suggested-tasks/providers/class-php-version.php b/classes/suggested-tasks/providers/class-php-version.php index 8a97dc06f..36646349c 100644 --- a/classes/suggested-tasks/providers/class-php-version.php +++ b/classes/suggested-tasks/providers/class-php-version.php @@ -53,7 +53,7 @@ protected function get_description( $task_data = [] ) { /* translators: %1$s: php version, %2$s: We recommend link. %3$s: minimum PHP version recommended. */ \esc_html__( 'Your site is running on PHP version %1$s. %2$s updating to PHP version %3$s or higher.', 'progress-planner' ), \phpversion(), - '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', + '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', \esc_html( self::RECOMMENDED_PHP_VERSION ) ); } diff --git a/classes/suggested-tasks/providers/class-remove-inactive-plugins.php b/classes/suggested-tasks/providers/class-remove-inactive-plugins.php index 5145b0de1..ab4ed2843 100644 --- a/classes/suggested-tasks/providers/class-remove-inactive-plugins.php +++ b/classes/suggested-tasks/providers/class-remove-inactive-plugins.php @@ -62,7 +62,7 @@ protected function get_description() { return \sprintf( /* translators: %1$s removing any plugins link */ \esc_html__( 'You have inactive plugins. Consider %1$s that are not activated to free up resources, and improve security.', 'progress-planner' ), - '' . \esc_html__( 'removing any plugins', 'progress-planner' ) . '', + '' . \esc_html__( 'removing any plugins', 'progress-planner' ) . '', ); } diff --git a/classes/suggested-tasks/providers/class-remove-terms-without-posts.php b/classes/suggested-tasks/providers/class-remove-terms-without-posts.php index 1fd073e2c..34d5b032d 100644 --- a/classes/suggested-tasks/providers/class-remove-terms-without-posts.php +++ b/classes/suggested-tasks/providers/class-remove-terms-without-posts.php @@ -160,7 +160,7 @@ protected function get_description_with_data( $task_data = [] ) { /* translators: %1$s: The term name, %2$s Read more link */ \esc_html__( 'The "%1$s" term has one or less posts associated with it, we recommend removing it. %2$s', 'progress-planner' ), $term->name, - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ) : ''; } diff --git a/classes/suggested-tasks/providers/class-rename-uncategorized-category.php b/classes/suggested-tasks/providers/class-rename-uncategorized-category.php index f0ef97be5..edbf22280 100644 --- a/classes/suggested-tasks/providers/class-rename-uncategorized-category.php +++ b/classes/suggested-tasks/providers/class-rename-uncategorized-category.php @@ -69,7 +69,7 @@ protected function get_description() { return \sprintf( /* translators: %1$s We recommend link */ \esc_html__( 'The Uncategorized category is used for posts that don\'t have a category. %1$s renaming it to something that fits your site better.', 'progress-planner' ), - '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', + '' . \esc_html__( 'We recommend', 'progress-planner' ) . '', ); } diff --git a/classes/suggested-tasks/providers/class-sample-page.php b/classes/suggested-tasks/providers/class-sample-page.php index 39e848f3b..824a20562 100644 --- a/classes/suggested-tasks/providers/class-sample-page.php +++ b/classes/suggested-tasks/providers/class-sample-page.php @@ -103,7 +103,7 @@ protected function get_description() { ) . '

          ' . \sprintf( /* translators: %s: URL to https://prpl.fyi/delete-sample-page */ \__( 'This page does not add value to your website and solely exists to show what a page can look like. Therefore, "Sample Page" is not needed and should be deleted.', 'progress-planner' ), - 'https://prpl.fyi/delete-sample-page' + \esc_url( \progress_planner()->get_ui__branding()->get_url( 'https://prpl.fyi/delete-sample-page' ) ) ) . '

          '; } diff --git a/classes/suggested-tasks/providers/class-search-engine-visibility.php b/classes/suggested-tasks/providers/class-search-engine-visibility.php index d94ff4bde..029b7a99f 100644 --- a/classes/suggested-tasks/providers/class-search-engine-visibility.php +++ b/classes/suggested-tasks/providers/class-search-engine-visibility.php @@ -65,7 +65,7 @@ protected function get_description() { return \sprintf( /* translators: %1$s allowing search engines link */ \esc_html__( 'Your site is not currently visible to search engines. Consider %1$s to index your site.', 'progress-planner' ), - '' . \esc_html__( 'allowing search engines', 'progress-planner' ) . '', + '' . \esc_html__( 'allowing search engines', 'progress-planner' ) . '', ); } diff --git a/classes/suggested-tasks/providers/class-set-valuable-post-types.php b/classes/suggested-tasks/providers/class-set-valuable-post-types.php index 35d0db935..b8fcb4d2b 100644 --- a/classes/suggested-tasks/providers/class-set-valuable-post-types.php +++ b/classes/suggested-tasks/providers/class-set-valuable-post-types.php @@ -80,7 +80,7 @@ protected function get_description() { return \sprintf( /* translators: %s:Read more link */ \esc_html__( 'Tell us which post types matter most for your site. Go to your settings and select your valuable content types. %s', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-site-icon.php b/classes/suggested-tasks/providers/class-site-icon.php index 619ac9371..acc5da84a 100644 --- a/classes/suggested-tasks/providers/class-site-icon.php +++ b/classes/suggested-tasks/providers/class-site-icon.php @@ -65,7 +65,7 @@ protected function get_description() { return \sprintf( /* translators: %s:site icon link */ \esc_html__( 'Set the %s to make your website look more professional.', 'progress-planner' ), - '' . \esc_html__( 'site icon', 'progress-planner' ) . '' + '' . \esc_html__( 'site icon', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/class-update-term-description.php b/classes/suggested-tasks/providers/class-update-term-description.php index 94ac9c214..956fcf54c 100644 --- a/classes/suggested-tasks/providers/class-update-term-description.php +++ b/classes/suggested-tasks/providers/class-update-term-description.php @@ -142,7 +142,7 @@ public function get_description_with_data( $task_data = [] ) { /* translators: %1$s: The term name, %2$s Read more link */ \esc_html__( 'Your "%1$s" archives probably show the description of that specific term. %2$s', 'progress-planner' ), $term->name, - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ) : ''; } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php index ce13c6994..2e8b95a6e 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php @@ -62,7 +62,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Yoast SEO can disable the author archive when you have only one author, as it is the same as the homepage. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php index e5f0eba52..ac10a34d4 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php @@ -46,7 +46,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Yoast SEO can disable the date archive, which is really only useful for news sites and blogs. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php index 69bcc55a0..20f70894e 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php @@ -62,7 +62,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'WordPress creates an archive for each post format. This is not useful and can be disabled in the Yoast SEO settings. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php b/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php index 060331598..a804bd6fb 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php @@ -125,7 +125,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Improve your most important pages with Yoast SEO\'s Cornerstone Content Workout. %s.', 'progress-planner' ), - '' . \esc_html__( 'Learn more', 'progress-planner' ) . '' + '' . \esc_html__( 'Learn more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php index 4c1675d62..9aa135554 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php @@ -46,7 +46,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Remove JavaScript used for converting emoji characters in older browsers. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php index abcad1074..3dd8e396a 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php @@ -62,7 +62,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Remove URLs which provide information about recent posts by specific authors. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php index a4d512ad5..852554017 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php @@ -46,7 +46,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Remove URLs which provide an overview of recent comments on your site. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-fix-orphaned-content.php b/classes/suggested-tasks/providers/integrations/yoast/class-fix-orphaned-content.php index ca9d8602f..4192a16a9 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-fix-orphaned-content.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-fix-orphaned-content.php @@ -90,7 +90,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Yoast SEO detected that this article has no links pointing to it. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } @@ -102,7 +102,7 @@ protected function get_description() { * @return string */ protected function get_url_with_data( $task_data = [] ) { - return \get_post( $task_data['target_post_id'] ) ? 'https://prpl.fyi/fix-orphaned-content' : ''; + return \get_post( $task_data['target_post_id'] ) ? \esc_url( \progress_planner()->get_ui__branding()->get_url( 'https://prpl.fyi/fix-orphaned-content' ) ) : ''; } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php b/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php index c97bf383f..653454a38 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php @@ -46,7 +46,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Yoast SEO can disable the media / attachment pages, which are the pages that show the media files. You really don\'t need them, except when you are displaying photos or art on your site through them. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-organization-logo.php b/classes/suggested-tasks/providers/integrations/yoast/class-organization-logo.php index 90c7e22f3..d62b138ad 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-organization-logo.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-organization-logo.php @@ -63,11 +63,11 @@ protected function get_description() { ? \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'To make Yoast SEO output the correct Schema, you need to set your organization logo in the Yoast SEO settings. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ) : \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'To make Yoast SEO output the correct Schema, you need to set your person logo in the Yoast SEO settings. %s.', 'progress-planner' ), - '' . \esc_html__( 'Read more', 'progress-planner' ) . '' + '' . \esc_html__( 'Read more', 'progress-planner' ) . '' ); } diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php b/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php index effdeeb57..24fcd8f92 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php @@ -128,7 +128,7 @@ protected function get_description() { return \sprintf( /* translators: %s: "Read more" link. */ \esc_html__( 'Improve your internal linking structure with Yoast SEO\'s Orphaned Content Workout. %s.', 'progress-planner' ), - '' . \esc_html__( 'Lean more', 'progress-planner' ) . '' + '' . \esc_html__( 'Lean more', 'progress-planner' ) . '' ); } diff --git a/classes/ui/class-branding.php b/classes/ui/class-branding.php index 6d1366564..fe2fffc38 100644 --- a/classes/ui/class-branding.php +++ b/classes/ui/class-branding.php @@ -321,4 +321,26 @@ public function get_blog_feed_url(): string { ? \progress_planner()->get_remote_server_root_url() : $this->get_api_data()['acf']['blog_feed_url']; } + + /** + * Get a URL from the API data. + * + * @param string $default_url The default value. + * + * @return string + */ + public function get_url( $default_url = '' ) { + $api_data = $this->get_api_data(); + if ( empty( $api_data ) || ! isset( $api_data['acf']['links'] ) ) { + return $default_url; + } + + foreach ( $api_data['acf']['links'] as $link ) { + if ( $link['original_url'] === $default_url ) { + return $link['url']; + } + } + + return $default_url; + } } diff --git a/views/page-widgets/whats-new.php b/views/page-widgets/whats-new.php index 9666a519d..a4a879509 100644 --- a/views/page-widgets/whats-new.php +++ b/views/page-widgets/whats-new.php @@ -45,7 +45,7 @@
        diff --git a/views/popovers/subscribe-form.php b/views/popovers/subscribe-form.php index c59abb16f..3ca73a9b3 100644 --- a/views/popovers/subscribe-form.php +++ b/views/popovers/subscribe-form.php @@ -21,7 +21,7 @@ \printf( /* translators: %s: progressplanner.com link */ \esc_html__( 'We can send you weekly emails with your own to-do’s, your activity stats and nudges to keep you working on your site. To do this, we’ll create an account for you on %s.', 'progress-planner' ), - 'progressplanner.com' + 'progressplanner.com' ) ?>

        diff --git a/views/welcome.php b/views/welcome.php index 29612ef83..2e67cb7e8 100644 --- a/views/welcome.php +++ b/views/welcome.php @@ -59,7 +59,7 @@ \printf( /* translators: %s: progressplanner.com link */ \esc_html__( 'To send these updates, we’ll create an account for you on %s.', 'progress-planner' ), - 'progressplanner.com' + 'progressplanner.com' ) ?>
        @@ -130,7 +130,7 @@ class="prpl-input" \printf( /* translators: %s: progressplanner.com/privacy-policy link */ \esc_html__( 'I agree to the %s.', 'progress-planner' ), - 'Privacy policy' + 'Privacy policy' ); ?> @@ -160,7 +160,7 @@ class="prpl-button-secondary prpl-button-secondary--no-email prpl-hidden" \printf( /* translators: %s: progressplanner.com link */ \esc_html__( 'Success! We saved your data on %s so we can email you every week.', 'progress-planner' ), - 'ProgressPlanner.com' + 'ProgressPlanner.com' ); ?>

        From 2fdb4d3c30bbb639ad311c6b7146db09c10c1e6e Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Thu, 11 Sep 2025 10:30:13 +0300 Subject: [PATCH 035/338] WIP --- classes/class-suggested-tasks.php | 1 + 1 file changed, 1 insertion(+) diff --git a/classes/class-suggested-tasks.php b/classes/class-suggested-tasks.php index c4f501af5..976da395e 100644 --- a/classes/class-suggested-tasks.php +++ b/classes/class-suggested-tasks.php @@ -450,6 +450,7 @@ public function rest_prepare_recommendation( $response, $post ) { $response->data['prpl_task_actions'] = $provider->get_task_actions( $response->data ); } + $response->data['prpl_points'] = $provider->get_points(); } $category_term = \wp_get_object_terms( $post->ID, 'prpl_recommendations_category' ); From 59258640c4b83622400ea2a354e38852b27f7cfb Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 12 Sep 2025 09:04:29 +0300 Subject: [PATCH 036/338] Migrate the `prpl_task_id` post-meta to the post's slug --- classes/class-suggested-tasks-db.php | 15 +----- classes/class-suggested-tasks.php | 5 -- classes/class-todo.php | 7 ++- .../suggested-tasks/providers/class-tasks.php | 8 +-- .../class-update-term-description.php | 4 +- classes/update/class-update-190.php | 53 +++++++++++++++++++ progress-planner.php | 2 +- views/js-templates/suggested-task.html | 6 +-- 8 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 classes/update/class-update-190.php diff --git a/classes/class-suggested-tasks-db.php b/classes/class-suggested-tasks-db.php index 78fad2c10..6947dbf83 100644 --- a/classes/class-suggested-tasks-db.php +++ b/classes/class-suggested-tasks-db.php @@ -52,13 +52,7 @@ public function add( $data ) { [ 'post_status' => [ 'publish', 'trash', 'draft', 'future', 'pending' ], // 'any' doesn't include statuses which have 'exclude_from_search' set to true (trash and pending). 'numberposts' => 1, - 'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query - [ - 'key' => 'prpl_task_id', - 'value' => $data['task_id'], - 'compare' => '=', - ], - ], + 'name' => $data['task_id'], ] ); @@ -330,12 +324,7 @@ public function get_tasks_by( $params ) { break; case 'task_id': - $args['meta_query'] = isset( $args['meta_query'] ) ? $args['meta_query'] : []; // phpcs:ignore WordPress.DB.SlowDBQuery - $args['meta_query'][] = [ - 'key' => 'prpl_task_id', - 'value' => $value, - ]; - + $args['name'] = $value; unset( $params[ $param ] ); break; diff --git a/classes/class-suggested-tasks.php b/classes/class-suggested-tasks.php index d4ae693e6..a274f5481 100644 --- a/classes/class-suggested-tasks.php +++ b/classes/class-suggested-tasks.php @@ -293,11 +293,6 @@ public function register_post_type() { 'single' => true, 'show_in_rest' => true, ], - 'prpl_task_id' => [ - 'type' => 'string', - 'single' => true, - 'show_in_rest' => true, - ], 'prpl_url' => [ 'type' => 'string', 'single' => true, diff --git a/classes/class-todo.php b/classes/class-todo.php index 49ac52824..1fa39786a 100644 --- a/classes/class-todo.php +++ b/classes/class-todo.php @@ -81,7 +81,12 @@ public function handle_creating_user_task( $post, $request, $creating ) { } // Add task_id to the post. - \update_post_meta( $post->ID, 'prpl_task_id', 'user-' . $post->ID ); + \wp_update_post( + [ + 'ID' => $post->ID, + 'post_name' => 'user-' . $post->ID, + ] + ); // If it is first task ever created, it should be golden. $pending_items = \progress_planner()->get_suggested_tasks_db()->get_tasks_by( diff --git a/classes/suggested-tasks/providers/class-tasks.php b/classes/suggested-tasks/providers/class-tasks.php index c3d1be395..d20c135cc 100644 --- a/classes/suggested-tasks/providers/class-tasks.php +++ b/classes/suggested-tasks/providers/class-tasks.php @@ -629,12 +629,12 @@ public function get_task_actions( $data = [] ) { if ( $this->is_dismissable() && 'user' !== static::PROVIDER_ID ) { $actions[] = [ 'priority' => 20, - 'html' => '', + 'html' => '', ]; } if ( $this->is_snoozable() ) { - $snooze_html = ''; + $snooze_html = ''; $snooze_html .= '
        ' . \esc_html__( 'Snooze this task?', 'progress-planner' ) . '
        '; foreach ( [ @@ -645,7 +645,7 @@ public function get_task_actions( $data = [] ) { '1-year' => \esc_html__( '1 year', 'progress-planner' ), 'forever' => \esc_html__( 'forever', 'progress-planner' ), ] as $snooze_key => $snooze_value ) { - $snooze_html .= ''; + $snooze_html .= ''; } $snooze_html .= '
        '; $actions[] = [ @@ -662,7 +662,7 @@ public function get_task_actions( $data = [] ) { } elseif ( isset( $data['content']['rendered'] ) && $data['content']['rendered'] !== '' && ! $this instanceof Tasks_Interactive ) { $actions[] = [ 'priority' => 40, - 'html' => '' . \wp_kses_post( $data['content']['rendered'] ) . '', + 'html' => '' . \wp_kses_post( $data['content']['rendered'] ) . '', ]; } diff --git a/classes/suggested-tasks/providers/class-update-term-description.php b/classes/suggested-tasks/providers/class-update-term-description.php index 0fc31f9e6..78e5a352b 100644 --- a/classes/suggested-tasks/providers/class-update-term-description.php +++ b/classes/suggested-tasks/providers/class-update-term-description.php @@ -297,11 +297,11 @@ public function exclude_completed_terms( $exclude_term_ids ) { * @return array */ public function add_task_actions( $data = [], $actions = [] ) { - if ( ! isset( $data['meta']['prpl_task_id'] ) ) { + if ( ! isset( $data['slug'] ) ) { return $actions; } - $term = $this->get_term_from_task_id( $data['meta']['prpl_task_id'] ); + $term = $this->get_term_from_task_id( $data['slug'] ); if ( ! $term ) { return $actions; } diff --git a/classes/update/class-update-190.php b/classes/update/class-update-190.php new file mode 100644 index 000000000..1dfc41cbf --- /dev/null +++ b/classes/update/class-update-190.php @@ -0,0 +1,53 @@ +migrate_recommendations_slugs(); + } + + /** + * Migrate the recommendations slugs. + * + * @return void + */ + private function migrate_recommendations_slugs() { + // Get all recommendations. + $recommendations = \progress_planner()->get_suggested_tasks_db()->get(); + foreach ( $recommendations as $recommendation ) { + // Get the `prpl_task_id` meta. + $prpl_task_id = \get_post_meta( $recommendation->ID, 'prpl_task_id', true ); + if ( ! $prpl_task_id ) { + continue; + } + + // Set the slug. + \wp_update_post( + [ + 'ID' => $recommendation->ID, + 'post_name' => $prpl_task_id, + ] + ); + } + } +} diff --git a/progress-planner.php b/progress-planner.php index 07a09079f..b7eb26033 100644 --- a/progress-planner.php +++ b/progress-planner.php @@ -9,7 +9,7 @@ * Description: A plugin to help you fight procrastination and get things done. * Requires at least: 6.6 * Requires PHP: 7.4 - * Version: 1.8.0 + * Version: 1.9.0 * Author: Team Emilia Projects * Author URI: https://prpl.fyi/about * License: GPL-3.0+ diff --git a/views/js-templates/suggested-task.html b/views/js-templates/suggested-task.html index 7a6ca6751..f90a80b1e 100644 --- a/views/js-templates/suggested-task.html +++ b/views/js-templates/suggested-task.html @@ -1,5 +1,5 @@ the_view( 'js-templates/suggested-task.html' ); ?> diff --git a/views/js-templates/suggested-task.html b/views/js-templates/suggested-task.html index 0333d0d4b..f4723088c 100644 --- a/views/js-templates/suggested-task.html +++ b/views/js-templates/suggested-task.html @@ -3,7 +3,7 @@
        <# if ( 'user' === data.post.prpl_provider.slug ) { #> <# } else { #> @@ -15,7 +15,7 @@

        - contenteditable="plaintext-only" onkeydown="prplSuggestedTask.preventEnterKey( event ); prplSuggestedTask.updateTaskTitle( this );" data-post-id="{{ data.post.id }}"<# } #>>{{{ data.post.title.rendered }}} + contenteditable="plaintext-only" role="textbox" aria-label="Edit task title" aria-multiline="false" onkeydown="prplSuggestedTask.preventEnterKey( event ); prplSuggestedTask.updateTaskTitle( this );" data-post-id="{{ data.post.id }}"<# } #>>{{{ data.post.title.rendered }}}

        diff --git a/views/popovers/popover.php b/views/popovers/popover.php index d5b542fad..8fb6981ca 100644 --- a/views/popovers/popover.php +++ b/views/popovers/popover.php @@ -20,8 +20,9 @@ class="prpl-popover-close" popovertarget="prpl-popover-" popovertargetaction="hide" + aria-label="" > - - + +
        From 48cb90c623a42f4c85819968cd7108ffec6f8bdf Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 24 Oct 2025 13:27:58 +0300 Subject: [PATCH 326/338] Update classes/admin/class-enqueue.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- classes/admin/class-enqueue.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/admin/class-enqueue.php b/classes/admin/class-enqueue.php index 0f406b092..9b48aeff1 100644 --- a/classes/admin/class-enqueue.php +++ b/classes/admin/class-enqueue.php @@ -403,8 +403,8 @@ public function get_localized_strings() { 'showFewerRecommendations' => \esc_html__( 'Show fewer recommendations', 'progress-planner' ), 'loadingTasks' => \esc_html__( 'Loading tasks...', 'progress-planner' ), 'taskAddedSuccessfully' => \esc_html__( 'Task added successfully', 'progress-planner' ), - 'tasksDeleted' => \esc_html__( 'completed tasks deleted', 'progress-planner' ), - 'taskDeleted' => \esc_html__( 'completed task deleted', 'progress-planner' ), + 'tasksDeleted' => \esc_html__( 'Completed tasks deleted', 'progress-planner' ), + 'taskDeleted' => \esc_html__( 'Completed task deleted', 'progress-planner' ), 'moveUp' => \esc_html__( 'Move up', 'progress-planner' ), 'moveDown' => \esc_html__( 'Move down', 'progress-planner' ), /* translators: %d: The number of points. */ From 94668b481583cc15e15383747bf0901ed5248c2c Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 24 Oct 2025 14:13:17 +0200 Subject: [PATCH 327/338] add spinner to the interactive tasks --- assets/css/page-widgets/suggested-tasks.css | 17 +++++++ assets/js/recommendations/interactive-task.js | 47 ++++++++++++++++++- .../providers/class-blog-description.php | 8 ++-- .../class-disable-comment-pagination.php | 8 ++-- .../providers/class-disable-comments.php | 8 ++-- .../providers/class-hello-world.php | 8 ++-- .../providers/class-permalink-structure.php | 9 ++-- .../providers/class-sample-page.php | 8 ++-- .../class-search-engine-visibility.php | 8 ++-- .../providers/class-select-locale.php | 6 ++- .../providers/class-select-timezone.php | 6 ++- .../providers/class-set-date-format.php | 8 ++-- .../providers/class-site-icon.php | 8 ++-- .../class-update-term-description.php | 8 ++-- 14 files changed, 122 insertions(+), 35 deletions(-) diff --git a/assets/css/page-widgets/suggested-tasks.css b/assets/css/page-widgets/suggested-tasks.css index 14c90d395..9f43f4808 100644 --- a/assets/css/page-widgets/suggested-tasks.css +++ b/assets/css/page-widgets/suggested-tasks.css @@ -441,10 +441,22 @@ padding-top: 1rem; display: flex; justify-content: flex-end; + align-items: center; gap: 1rem; align-self: flex-end; width: 100%; + /* If there are no other elements in the form, align the button to the left. */ + &:only-child { + padding-top: 0; + justify-content: flex-start; + + /* Display the spinner after the button. */ + .prpl-spinner { + order: 99; + } + } + .prpl-button { cursor: pointer; margin: 0; @@ -456,6 +468,11 @@ } } + /* Display the spinner before the button. */ + .prpl-spinner { + order: -1; + } + } } diff --git a/assets/js/recommendations/interactive-task.js b/assets/js/recommendations/interactive-task.js index ca14cfb16..ffe697956 100644 --- a/assets/js/recommendations/interactive-task.js +++ b/assets/js/recommendations/interactive-task.js @@ -35,6 +35,8 @@ const prplInteractiveTaskFormListener = { formElement.addEventListener( 'submit', ( event ) => { event.preventDefault(); + prplInteractiveTaskFormListener.showLoading( formElement ); + // Get the form data. const formData = new FormData( formElement ); const settingsToPass = {}; @@ -56,6 +58,8 @@ const prplInteractiveTaskFormListener = { return response; } + prplInteractiveTaskFormListener.hideLoading( formElement ); + // This will trigger the celebration event (confetti) as well. prplSuggestedTask.maybeComplete( postId ).then( () => { // Close popover. @@ -76,6 +80,8 @@ const prplInteractiveTaskFormListener = { const formSubmitHandler = ( event ) => { event.preventDefault(); + prplInteractiveTaskFormListener.showLoading( formElement ); + callback() .then( ( response ) => { if ( true !== response.success ) { @@ -110,6 +116,9 @@ const prplInteractiveTaskFormListener = { ); } ) .finally( () => { + // Hide loading state. + prplInteractiveTaskFormListener.hideLoading( formElement ); + // Remove the form listener once the callback is executed. formElement.removeEventListener( 'submit', @@ -139,6 +148,8 @@ const prplInteractiveTaskFormListener = { formElement.addEventListener( 'submit', ( event ) => { event.preventDefault(); + prplInteractiveTaskFormListener.showLoading( formElement ); + const formData = new FormData( formElement ); const settingsToPass = {}; settingsToPass[ setting ] = settingCallbackValue( @@ -157,7 +168,6 @@ const prplInteractiveTaskFormListener = { }, } ) .then( ( response ) => { - console.log( response ); if ( true !== response.success ) { // Show error to the user. prplInteractiveTaskFormListener.showError( @@ -193,6 +203,10 @@ const prplInteractiveTaskFormListener = { error, popoverId ); + } ) + .finally( () => { + // Hide loading state. + prplInteractiveTaskFormListener.hideLoading( formElement ); } ); } ); }, @@ -241,4 +255,35 @@ const prplInteractiveTaskFormListener = { ); } }, + + /** + * Show loading state. + * + * @param {HTMLFormElement} formElement - The form element. + * @return {void} + */ + showLoading: ( formElement ) => { + // data-action="completeTask" + formElement.querySelector( 'button[type="submit"]' ).disabled = true; + + // Add spinner. + const spinner = document.createElement( 'span' ); + spinner.classList.add( 'prpl-spinner' ); + spinner.innerHTML = + ''; // WP spinner. + + // Append spinner after submit button. + formElement.querySelector( 'button[type="submit"]' ).after( spinner ); + }, + + /** + * Hide loading state. + * + * @param {HTMLFormElement} formElement - The form element. + * @return {void} + */ + hideLoading: ( formElement ) => { + formElement.querySelector( 'button[type="submit"]' ).disabled = false; + formElement.querySelector( 'span.prpl-spinner' )?.remove(); + }, }; diff --git a/classes/suggested-tasks/providers/class-blog-description.php b/classes/suggested-tasks/providers/class-blog-description.php index 91133ed0d..61ec8bb51 100644 --- a/classes/suggested-tasks/providers/class-blog-description.php +++ b/classes/suggested-tasks/providers/class-blog-description.php @@ -123,9 +123,11 @@ public function print_popover_form_contents() { placeholder="" > - +
        + +
        - +
        + +
        - +
        + +
        - +
        + +
        - + +
        + +
        - +
        + +
        - +
        + +
        +
        + + +
        +
        + + +
        - +
        + +
        - +
        + +
        - +
        + +
        Date: Fri, 24 Oct 2025 14:59:53 +0200 Subject: [PATCH 328/338] handle integrations, adjust error displaying of error message, add wpseo_titles --- assets/css/page-widgets/suggested-tasks.css | 4 ++ assets/js/recommendations/interactive-task.js | 48 +++++++++++-------- .../aioseo/class-archive-author.php | 8 ++-- .../aioseo/class-archive-date.php | 2 + .../class-crawl-settings-feed-authors.php | 8 ++-- .../class-crawl-settings-feed-comments.php | 8 ++-- .../yoast/class-add-yoast-providers.php | 1 + .../yoast/class-archive-author.php | 8 ++-- .../integrations/yoast/class-archive-date.php | 8 ++-- .../yoast/class-archive-format.php | 6 ++- .../class-crawl-settings-emoji-scripts.php | 8 ++-- .../class-crawl-settings-feed-authors.php | 8 ++-- ...ss-crawl-settings-feed-global-comments.php | 6 ++- .../integrations/yoast/class-media-pages.php | 8 ++-- .../yoast/class-organization-logo.php | 8 ++-- 15 files changed, 89 insertions(+), 50 deletions(-) diff --git a/assets/css/page-widgets/suggested-tasks.css b/assets/css/page-widgets/suggested-tasks.css index 9f43f4808..62a94dc27 100644 --- a/assets/css/page-widgets/suggested-tasks.css +++ b/assets/css/page-widgets/suggested-tasks.css @@ -206,6 +206,10 @@ &.prpl-note-error { color: var(--prpl-color-alert-error-text); background-color: var(--prpl-background-alert-error); + margin-bottom: 0; + + order: 98; /* One less than the spinner. */ + flex-grow: 1; .prpl-note-icon { color: var(--prpl-color-alert-error); diff --git a/assets/js/recommendations/interactive-task.js b/assets/js/recommendations/interactive-task.js index ffe697956..e7f511aa2 100644 --- a/assets/js/recommendations/interactive-task.js +++ b/assets/js/recommendations/interactive-task.js @@ -228,17 +228,12 @@ const prplInteractiveTaskFormListener = { console.error( 'Error in interactive task callback:', error ); - // Add error message. - const submitButton = formElement.querySelector( - 'button[type="submit"]' + // Check if there's already an error message

        element right after the form + const existingErrorElement = formElement.parentNode.querySelector( + 'p.prpl-interactive-task-error-message' ); - if ( - submitButton && - ! formElement.querySelector( - '.prpl-interactive-task-error-message' - ) - ) { + if ( ! existingErrorElement ) { // Add paragraph with error message. const errorParagraph = document.createElement( 'p' ); errorParagraph.classList.add( @@ -248,11 +243,8 @@ const prplInteractiveTaskFormListener = { ); errorParagraph.textContent = prplL10n( 'somethingWentWrong' ); - // Append before submit button. - submitButton.parentNode.insertBefore( - errorParagraph, - submitButton - ); + // Append after the form element. + formElement.insertAdjacentElement( 'afterend', errorParagraph ); } }, @@ -263,8 +255,15 @@ const prplInteractiveTaskFormListener = { * @return {void} */ showLoading: ( formElement ) => { - // data-action="completeTask" - formElement.querySelector( 'button[type="submit"]' ).disabled = true; + let submitButton = formElement.querySelector( 'button[type="submit"]' ); + + if ( ! submitButton ) { + submitButton = formElement.querySelector( + 'button[data-action="completeTask"]' + ); + } + + submitButton.disabled = true; // Add spinner. const spinner = document.createElement( 'span' ); @@ -273,7 +272,7 @@ const prplInteractiveTaskFormListener = { ''; // WP spinner. // Append spinner after submit button. - formElement.querySelector( 'button[type="submit"]' ).after( spinner ); + submitButton.after( spinner ); }, /** @@ -283,7 +282,18 @@ const prplInteractiveTaskFormListener = { * @return {void} */ hideLoading: ( formElement ) => { - formElement.querySelector( 'button[type="submit"]' ).disabled = false; - formElement.querySelector( 'span.prpl-spinner' )?.remove(); + let submitButton = formElement.querySelector( 'button[type="submit"]' ); + + if ( ! submitButton ) { + submitButton = formElement.querySelector( + 'button[data-action="completeTask"]' + ); + } + + submitButton.disabled = false; + const spinner = formElement.querySelector( 'span.prpl-spinner' ); + if ( spinner ) { + spinner.remove(); + } }, }; diff --git a/classes/suggested-tasks/providers/integrations/aioseo/class-archive-author.php b/classes/suggested-tasks/providers/integrations/aioseo/class-archive-author.php index d055b64ab..c4197f105 100644 --- a/classes/suggested-tasks/providers/integrations/aioseo/class-archive-author.php +++ b/classes/suggested-tasks/providers/integrations/aioseo/class-archive-author.php @@ -136,9 +136,11 @@ public function print_popover_instructions() { */ public function print_popover_form_contents() { ?> - +

        + +
        +
        +
        - +
        + +
        - +
        + +
        - +
        + +
        - +
        + +
        +
        + + +
        - +
        + +
        - +
        + +
        +
        + + +
        - +
        + +
        - +
        + +
        Date: Fri, 24 Oct 2025 15:17:43 +0200 Subject: [PATCH 329/338] fix order for special case --- classes/suggested-tasks/providers/class-disable-comments.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/suggested-tasks/providers/class-disable-comments.php b/classes/suggested-tasks/providers/class-disable-comments.php index dff1fc6dc..d9fdf364a 100644 --- a/classes/suggested-tasks/providers/class-disable-comments.php +++ b/classes/suggested-tasks/providers/class-disable-comments.php @@ -145,7 +145,7 @@ public function print_popover_instructions() { public function print_popover_form_contents() { ?>
        -
        From 9379a9f2d2a7d7d601de30895c17e9e82abc3629 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 24 Oct 2025 15:30:06 +0200 Subject: [PATCH 330/338] use spinner instead of success message --- assets/css/onboard.css | 5 +++++ assets/js/onboard.js | 34 ++++++++++++++++++++-------------- views/welcome.php | 15 --------------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/assets/css/onboard.css b/assets/css/onboard.css index 83510803e..bac24ea7d 100644 --- a/assets/css/onboard.css +++ b/assets/css/onboard.css @@ -16,3 +16,8 @@ display: block !important; } } + +#prpl-onboarding-submit-wrapper { + display: flex; + align-items: center; +} diff --git a/assets/js/onboard.js b/assets/js/onboard.js index eeceb259c..529b05831 100644 --- a/assets/js/onboard.js +++ b/assets/js/onboard.js @@ -35,17 +35,6 @@ const progressPlannerAjaxAPIRequest = ( data ) => { data, } ) .then( ( response ) => { - // Show success message. - document.getElementById( - 'no-license' === response.license_key - ? 'prpl-account-not-created-message' - : 'prpl-account-created-message' - ).style.display = 'block'; - - // Hide the form. - document.getElementById( 'prpl-onboarding-form' ).style.display = - 'none'; - // Make a local request to save the response data. progressPlannerSaveLicenseKey( response.license_key ).then( () => { // Refresh the page. @@ -144,9 +133,26 @@ if ( document.getElementById( 'prpl-onboarding-form' ) ) { return; } - document.querySelector( - '#prpl-onboarding-form input[type="submit"]' - ).disabled = true; + // Disable all (both buttons) submit buttons. + document + .querySelectorAll( + '#prpl-onboarding-form input[type="submit"]' + ) + .forEach( ( input ) => { + input.disabled = true; + } ); + + // Show the spinner. + const spinner = document.createElement( 'span' ); + spinner.classList.add( 'prpl-spinner' ); + spinner.innerHTML = + ''; // WP spinner. + + // Append spinner after submit button. + + document + .getElementById( 'prpl-onboarding-submit-wrapper' ) + .appendChild( spinner ); // Get all form data. const data = Object.fromEntries( new FormData( event.target ) ); diff --git a/views/welcome.php b/views/welcome.php index 92d34a32f..7ce64af38 100644 --- a/views/welcome.php +++ b/views/welcome.php @@ -145,21 +145,6 @@ class="prpl-button-secondary prpl-button-secondary--no-email prpl-hidden" >

        - -
        - - -
        Date: Fri, 24 Oct 2025 16:53:57 +0200 Subject: [PATCH 331/338] move submit wrapper & button to common method where possible --- .../class-disable-comment-pagination.php | 8 +------ .../providers/class-hello-world.php | 8 +------ .../providers/class-permalink-structure.php | 7 +------ .../providers/class-sample-page.php | 8 +------ .../class-search-engine-visibility.php | 8 +------ .../providers/class-select-locale.php | 9 ++------ .../providers/class-select-timezone.php | 6 +----- .../providers/class-set-date-format.php | 6 +----- .../providers/class-tasks-interactive.php | 21 +++++++++++++++++++ .../aioseo/class-archive-author.php | 8 +------ .../aioseo/class-archive-date.php | 8 +------ .../class-crawl-settings-feed-authors.php | 8 +------ .../class-crawl-settings-feed-comments.php | 8 +------ .../yoast/class-archive-author.php | 8 +------ .../integrations/yoast/class-archive-date.php | 8 +------ .../yoast/class-archive-format.php | 8 +------ .../class-crawl-settings-emoji-scripts.php | 8 +------ .../class-crawl-settings-feed-authors.php | 8 +------ ...ss-crawl-settings-feed-global-comments.php | 8 +------ .../integrations/yoast/class-media-pages.php | 8 +------ 20 files changed, 41 insertions(+), 128 deletions(-) diff --git a/classes/suggested-tasks/providers/class-disable-comment-pagination.php b/classes/suggested-tasks/providers/class-disable-comment-pagination.php index b6c02550a..3d46db9e2 100644 --- a/classes/suggested-tasks/providers/class-disable-comment-pagination.php +++ b/classes/suggested-tasks/providers/class-disable-comment-pagination.php @@ -120,13 +120,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable comment pagination', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-hello-world.php b/classes/suggested-tasks/providers/class-hello-world.php index 66ba95b5e..fe431f419 100644 --- a/classes/suggested-tasks/providers/class-hello-world.php +++ b/classes/suggested-tasks/providers/class-hello-world.php @@ -139,13 +139,7 @@ public function should_add_task() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Delete the "Hello World!" post', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-permalink-structure.php b/classes/suggested-tasks/providers/class-permalink-structure.php index 33c8ae315..40b546d22 100644 --- a/classes/suggested-tasks/providers/class-permalink-structure.php +++ b/classes/suggested-tasks/providers/class-permalink-structure.php @@ -236,13 +236,8 @@ public function print_popover_form_contents() {
        - -
        - -
        print_submit_button( \__( 'Set permalink structure', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-sample-page.php b/classes/suggested-tasks/providers/class-sample-page.php index 46609cfd7..e7ae313cf 100644 --- a/classes/suggested-tasks/providers/class-sample-page.php +++ b/classes/suggested-tasks/providers/class-sample-page.php @@ -138,13 +138,7 @@ public function should_add_task() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Delete the "Sample Page" page', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-search-engine-visibility.php b/classes/suggested-tasks/providers/class-search-engine-visibility.php index 8e779acb7..54ec0dd7f 100644 --- a/classes/suggested-tasks/providers/class-search-engine-visibility.php +++ b/classes/suggested-tasks/providers/class-search-engine-visibility.php @@ -112,13 +112,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Allow search engines to index your site', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-select-locale.php b/classes/suggested-tasks/providers/class-select-locale.php index a5bd352ef..5433671cb 100644 --- a/classes/suggested-tasks/providers/class-select-locale.php +++ b/classes/suggested-tasks/providers/class-select-locale.php @@ -225,13 +225,8 @@ public function print_popover_form_contents() { 'show_available_translations' => \current_user_can( 'install_languages' ) && \wp_can_install_language_pack(), ] ); - ?> -
        - -
        - print_submit_button( \__( 'Select locale', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-select-timezone.php b/classes/suggested-tasks/providers/class-select-timezone.php index 20be1ce4a..702010cc0 100644 --- a/classes/suggested-tasks/providers/class-select-timezone.php +++ b/classes/suggested-tasks/providers/class-select-timezone.php @@ -143,12 +143,8 @@ public function print_popover_form_contents() { -
        - -
        print_submit_button( \__( 'Set site timezone', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-set-date-format.php b/classes/suggested-tasks/providers/class-set-date-format.php index 7ce280063..fdd1f7128 100644 --- a/classes/suggested-tasks/providers/class-set-date-format.php +++ b/classes/suggested-tasks/providers/class-set-date-format.php @@ -242,12 +242,8 @@ public function print_popover_form_contents() {

        -
        - -
        print_submit_button( \__( 'Set date format', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/class-tasks-interactive.php b/classes/suggested-tasks/providers/class-tasks-interactive.php index 98941d027..97f721201 100644 --- a/classes/suggested-tasks/providers/class-tasks-interactive.php +++ b/classes/suggested-tasks/providers/class-tasks-interactive.php @@ -206,6 +206,27 @@ public function print_popover_instructions() { echo '

        ' . \wp_kses_post( $description ) . '

        '; } + /** + * Print the submit button. + * + * @param string $button_text The text for the button. + * If empty, the default text "Submit" will be used. + * + * @return void + */ + protected function print_submit_button( $button_text = '' ) { + if ( empty( $button_text ) ) { + $button_text = \__( 'Submit', 'progress-planner' ); + } + ?> +
        + +
        + -
        - -
        - print_submit_button( \__( 'Noindex the author archive', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/aioseo/class-archive-date.php b/classes/suggested-tasks/providers/integrations/aioseo/class-archive-date.php index 7ac42040b..86ed48d7b 100644 --- a/classes/suggested-tasks/providers/integrations/aioseo/class-archive-date.php +++ b/classes/suggested-tasks/providers/integrations/aioseo/class-archive-date.php @@ -121,13 +121,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Noindex the date archive', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-authors.php b/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-authors.php index c0413335c..ddcfcc05a 100644 --- a/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-authors.php +++ b/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-authors.php @@ -132,13 +132,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable author RSS feeds', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-comments.php b/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-comments.php index de84eaf1d..a0a42e7e5 100644 --- a/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-comments.php +++ b/classes/suggested-tasks/providers/integrations/aioseo/class-crawl-settings-feed-comments.php @@ -100,13 +100,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable comment RSS feeds', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php index d86e48fd0..367d98ac3 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-author.php @@ -125,13 +125,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php index c2c63837f..48173c5f7 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-date.php @@ -112,13 +112,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php b/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php index c8f509e57..0041f168c 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-archive-format.php @@ -125,13 +125,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php index 80fd93f6a..9867a75bc 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-emoji-scripts.php @@ -104,13 +104,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Remove', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php index 3bd3805ed..ff550f62e 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-authors.php @@ -136,13 +136,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Remove', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php index 012fa8e60..95af3c30e 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-crawl-settings-feed-global-comments.php @@ -104,13 +104,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Remove', 'progress-planner' ) ); } /** diff --git a/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php b/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php index f72e5ad8c..64371fa8e 100644 --- a/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php +++ b/classes/suggested-tasks/providers/integrations/yoast/class-media-pages.php @@ -98,13 +98,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - ?> -
        - -
        - print_submit_button( \__( 'Disable', 'progress-planner' ) ); } /** From 4e27a5bae6e4a6466e552c83457717ed49e64200 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Mon, 27 Oct 2025 10:30:29 +0100 Subject: [PATCH 332/338] adjust description form term interactive tasks --- .../remove-terms-without-posts.js | 28 +++++++++++++++---- .../update-term-description.js | 28 +++++++++++++++---- .../class-remove-terms-without-posts.php | 28 +++++++++++++------ .../class-update-term-description.php | 20 +++++++++---- 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/assets/js/recommendations/remove-terms-without-posts.js b/assets/js/recommendations/remove-terms-without-posts.js index 377672b32..2ed1fbbf6 100644 --- a/assets/js/recommendations/remove-terms-without-posts.js +++ b/assets/js/recommendations/remove-terms-without-posts.js @@ -43,6 +43,9 @@ taxonomyElement: popover.querySelector( '#prpl-delete-term-taxonomy' ), + taxonomyNameElement: popover.querySelector( + '#prpl-delete-term-taxonomy-name' + ), termIdField: popover.querySelector( '#prpl-delete-term-id' ), taxonomyField: popover.querySelector( '#prpl-delete-taxonomy' ), }; @@ -82,6 +85,9 @@ taxonomy: this.decodeHtmlEntities( event.detail.target_taxonomy ), + taxonomyName: this.decodeHtmlEntities( + event.detail.target_taxonomy_name + ), termName: this.decodeHtmlEntities( event.detail.target_term_name ), @@ -97,6 +103,7 @@ this.currentTermData.termId, this.currentTermData.taxonomy, this.currentTermData.termName, + this.currentTermData.taxonomyName, this.decodeHtmlEntities( event.detail.post_title ) ); } @@ -104,12 +111,19 @@ /** * Update the popover content. * - * @param {string} termId The term ID. - * @param {string} taxonomy The taxonomy. - * @param {string} termName The term name. - * @param {string} postTitle The post title. + * @param {string} termId The term ID. + * @param {string} taxonomy The taxonomy. + * @param {string} termName The term name. + * @param {string} taxonomyName The taxonomy name. + * @param {string} postTitle The post title. */ - updatePopoverContent( termId, taxonomy, termName, postTitle ) { + updatePopoverContent( + termId, + taxonomy, + termName, + taxonomyName, + postTitle + ) { if ( this.elements.popoverTitle ) { this.elements.popoverTitle.textContent = postTitle; } @@ -122,6 +136,10 @@ this.elements.taxonomyElement.textContent = taxonomy; } + if ( this.elements.taxonomyNameElement ) { + this.elements.taxonomyNameElement.textContent = taxonomyName; + } + if ( this.elements.termIdField ) { this.elements.termIdField.value = termId; } diff --git a/assets/js/recommendations/update-term-description.js b/assets/js/recommendations/update-term-description.js index 9135e901e..3eb925e17 100644 --- a/assets/js/recommendations/update-term-description.js +++ b/assets/js/recommendations/update-term-description.js @@ -44,6 +44,9 @@ taxonomyElement: popover.querySelector( '#prpl-update-term-taxonomy' ), + taxonomyNameElement: popover.querySelector( + '#prpl-update-term-taxonomy-name' + ), termIdField: popover.querySelector( '#prpl-update-term-id' ), taxonomyField: popover.querySelector( '#prpl-update-taxonomy' ), descriptionField: popover.querySelector( @@ -86,6 +89,9 @@ taxonomy: this.decodeHtmlEntities( event.detail.target_taxonomy ), + taxonomyName: this.decodeHtmlEntities( + event.detail.target_taxonomy_name + ), termName: this.decodeHtmlEntities( event.detail.target_term_name ), @@ -101,6 +107,7 @@ this.currentTermData.termId, this.currentTermData.taxonomy, this.currentTermData.termName, + this.currentTermData.taxonomyName, this.decodeHtmlEntities( event.detail.post_title ) ); } @@ -108,12 +115,19 @@ /** * Update the popover content. * - * @param {string} termId The term ID. - * @param {string} taxonomy The taxonomy. - * @param {string} termName The term name. - * @param {string} postTitle The post title. + * @param {string} termId The term ID. + * @param {string} taxonomy The taxonomy. + * @param {string} termName The term name. + * @param {string} taxonomyName The taxonomy name. + * @param {string} postTitle The post title. */ - updatePopoverContent( termId, taxonomy, termName, postTitle ) { + updatePopoverContent( + termId, + taxonomy, + termName, + taxonomyName, + postTitle + ) { if ( this.elements.popoverTitle ) { this.elements.popoverTitle.textContent = postTitle; } @@ -126,6 +140,10 @@ this.elements.taxonomyElement.textContent = taxonomy; } + if ( this.elements.taxonomyNameElement ) { + this.elements.taxonomyNameElement.textContent = taxonomyName; + } + if ( this.elements.termIdField ) { this.elements.termIdField.value = termId; } diff --git a/classes/suggested-tasks/providers/class-remove-terms-without-posts.php b/classes/suggested-tasks/providers/class-remove-terms-without-posts.php index 09aab0709..3d0ecfe98 100644 --- a/classes/suggested-tasks/providers/class-remove-terms-without-posts.php +++ b/classes/suggested-tasks/providers/class-remove-terms-without-posts.php @@ -341,6 +341,8 @@ public function add_task_actions( $data = [], $actions = [] ) { $task_details = $this->get_task_details( $task_data ); + $taxonomy = \get_taxonomy( $term->taxonomy ); + $actions[] = [ 'priority' => 10, 'html' => \sprintf( @@ -352,10 +354,11 @@ public function add_task_actions( $data = [], $actions = [] ) { \htmlspecialchars( \wp_json_encode( [ - 'post_title' => $task_details['post_title'], - 'target_term_id' => $task_data['target_term_id'], - 'target_taxonomy' => $task_data['target_taxonomy'], - 'target_term_name' => $task_data['target_term_name'], + 'post_title' => $task_details['post_title'], + 'target_term_id' => $task_data['target_term_id'], + 'target_taxonomy' => $task_data['target_taxonomy'], + 'target_taxonomy_name' => $taxonomy ? $taxonomy->label : '', + 'target_term_name' => $task_data['target_term_name'], ] ), ENT_QUOTES, @@ -393,14 +396,23 @@ public function print_popover_form_contents() {

        - + ', + '' + ); + ?>

        - +
        + +
        get_task_details( $task_data ); + $taxonomy = \get_taxonomy( $term->taxonomy ); + $actions[] = [ 'priority' => 10, 'html' => \sprintf( @@ -336,10 +338,11 @@ public function add_task_actions( $data = [], $actions = [] ) { \htmlspecialchars( \wp_json_encode( [ - 'post_title' => $task_details['post_title'], - 'target_term_id' => $task_data['target_term_id'], - 'target_taxonomy' => $task_data['target_taxonomy'], - 'target_term_name' => $task_data['target_term_name'], + 'post_title' => $task_details['post_title'], + 'target_term_id' => $task_data['target_term_id'], + 'target_taxonomy' => $task_data['target_taxonomy'], + 'target_taxonomy_name' => $taxonomy ? $taxonomy->label : '', + 'target_term_name' => $task_data['target_term_name'], ] ), ENT_QUOTES, @@ -377,7 +380,14 @@ public function print_popover_form_contents() {

        - + ', + '' + ); + ?>