Skip to content

Commit 5caba6f

Browse files
authored
Merge branch 'develop' into ari/audit-2025-10
2 parents 17ec8fc + 1466073 commit 5caba6f

36 files changed

Lines changed: 1492 additions & 93 deletions

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
= 1.9.0 =
22

3+
In this release we've added an integration with the **All In One Seo** plugin so you’ll now see personalized suggestions based on your current SEO configuration.
4+
5+
Added these recommendations from Ravi:
6+
7+
* All In One SEO: [noindex the author archive](https://prpl.fyi/aioseo-author-archive)
8+
* All In One SEO: [noindex the date archive](https://prpl.fyi/aioseo-date-archive)
9+
* All In One SEO: [Remove post authors feeds](https://prpl.fyi/aioseo-crawl-optimization-feed-authors)
10+
* All In One SEO: [Remove comment feeds](https://prpl.fyi/aioseo-crawl-optimization-feed-comments)
11+
* All In One SEO: [disable the media pages](https://prpl.fyi/aioseo-media-pages)
12+
* All In One SEO: set your [organization](https://prpl.fyi/aioseo-organization-logo) or [person](https://prpl.fyi/aioseo-person-logo) logo
13+
314
Enhancements:
415

516
* Add "Show all Recommendations" button to the "Ravi's Recommendations" widget
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* global prplInteractiveTaskFormListener, progressPlanner */
2+
3+
/*
4+
* All in One SEO: noindex the author archive.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'aioseo-author-archive',
11+
popoverId: 'prpl-popover-aioseo-author-archive',
12+
callback: () => {
13+
fetch( progressPlanner.ajaxUrl, {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/x-www-form-urlencoded',
17+
},
18+
body: new URLSearchParams( {
19+
action: 'prpl_interactive_task_submit_aioseo-author-archive',
20+
nonce: progressPlanner.nonce,
21+
} ),
22+
} );
23+
},
24+
} );
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* global prplInteractiveTaskFormListener, progressPlanner */
2+
3+
/*
4+
* All in One SEO: disable author RSS feeds.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'aioseo-crawl-settings-feed-authors',
11+
popoverId: 'prpl-popover-aioseo-crawl-settings-feed-authors',
12+
callback: () => {
13+
fetch( progressPlanner.ajaxUrl, {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/x-www-form-urlencoded',
17+
},
18+
body: new URLSearchParams( {
19+
action: 'prpl_interactive_task_submit_aioseo-crawl-settings-feed-authors',
20+
nonce: progressPlanner.nonce,
21+
} ),
22+
} );
23+
},
24+
} );
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* global prplInteractiveTaskFormListener, progressPlanner */
2+
3+
/*
4+
* All in One SEO: disable global comment RSS feeds.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'aioseo-crawl-settings-feed-comments',
11+
popoverId: 'prpl-popover-aioseo-crawl-settings-feed-comments',
12+
callback: () => {
13+
fetch( progressPlanner.ajaxUrl, {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/x-www-form-urlencoded',
17+
},
18+
body: new URLSearchParams( {
19+
action: 'prpl_interactive_task_submit_aioseo-crawl-settings-feed-comments',
20+
nonce: progressPlanner.nonce,
21+
} ),
22+
} );
23+
},
24+
} );
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* global prplInteractiveTaskFormListener, progressPlanner */
2+
3+
/*
4+
* All in One SEO: noindex the date archive.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'aioseo-date-archive',
11+
popoverId: 'prpl-popover-aioseo-date-archive',
12+
callback: () => {
13+
fetch( progressPlanner.ajaxUrl, {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/x-www-form-urlencoded',
17+
},
18+
body: new URLSearchParams( {
19+
action: 'prpl_interactive_task_submit_aioseo-date-archive',
20+
nonce: progressPlanner.nonce,
21+
} ),
22+
} );
23+
},
24+
} );
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* global prplInteractiveTaskFormListener, progressPlanner */
2+
3+
/*
4+
* All in One SEO: redirect media pages.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'aioseo-media-pages',
11+
popoverId: 'prpl-popover-aioseo-media-pages',
12+
callback: () => {
13+
fetch( progressPlanner.ajaxUrl, {
14+
method: 'POST',
15+
headers: {
16+
'Content-Type': 'application/x-www-form-urlencoded',
17+
},
18+
body: new URLSearchParams( {
19+
action: 'prpl_interactive_task_submit_aioseo-media-pages',
20+
nonce: progressPlanner.nonce,
21+
} ),
22+
} );
23+
},
24+
} );

assets/js/web-components/prpl-badge-progress-bar.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ customElements.define(
1717
* Observed attributes, defined the attributes that will trigger the attributeChangedCallback.
1818
*/
1919
static get observedAttributes() {
20-
return [ 'data-badge-id', 'data-points', 'data-max-points' ];
20+
return [
21+
'data-badge-id',
22+
'data-points',
23+
'data-max-points',
24+
'data-branding-id',
25+
];
2126
}
2227

2328
/**
@@ -32,6 +37,9 @@ customElements.define(
3237
maxPoints: parseInt(
3338
this.getAttribute( 'data-max-points' ) || 10
3439
),
40+
brandingId: parseInt(
41+
this.getAttribute( 'data-branding-id' ) || 0
42+
),
3543
};
3644
}
3745

@@ -70,6 +78,10 @@ customElements.define(
7078
* Get the progress percent.
7179
*/
7280
get progressPercent() {
81+
// Prevent division by zero.
82+
if ( 0 === this.maxPoints ) {
83+
return 0;
84+
}
7385
return ( this.points / this.maxPoints ) * 100;
7486
}
7587

@@ -98,8 +110,14 @@ customElements.define(
98110
// Convert kebab-case to camelCase
99111
.replace( /-([a-z])/g, ( _, chr ) => chr.toUpperCase() );
100112

101-
// Update state.
102-
this.state[ camelCaseName ] = newVal;
113+
// Update state with proper type conversion.
114+
this.state[ camelCaseName ] = [
115+
'points',
116+
'maxPoints',
117+
'brandingId',
118+
].includes( camelCaseName )
119+
? parseInt( newVal || 0 )
120+
: newVal;
103121

104122
// Update progress.
105123
this.updateProgress();

classes/admin/class-page.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ public function enqueue_scripts() {
180180
$default_localization_data = [
181181
'name' => 'progressPlanner',
182182
'data' => [
183-
'onboardNonceURL' => \progress_planner()->get_utils__onboard()->get_remote_nonce_url(),
184-
'onboardAPIUrl' => \progress_planner()->get_utils__onboard()->get_remote_url(),
183+
'onboardNonceURL' => \progress_planner()->get_utils__onboard()->get_remote_url( 'get-nonce' ),
184+
'onboardAPIUrl' => \progress_planner()->get_utils__onboard()->get_remote_url( 'onboard' ),
185185
'ajaxUrl' => \admin_url( 'admin-ajax.php' ),
186186
'nonce' => \wp_create_nonce( 'progress_planner' ),
187187
],

classes/class-suggested-tasks-db.php

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,25 @@ public function add( $data ) {
5252
}
5353

5454
// Check if we have an existing task with the same title.
55-
$posts = $this->get_tasks_by(
55+
$posts = $this->get_tasks_by(
5656
[
5757
'post_status' => [ 'publish', 'trash', 'draft', 'future', 'pending' ], // 'any' doesn't include statuses which have 'exclude_from_search' set to true (trash and pending).
5858
'numberposts' => 1,
59-
'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
60-
[
61-
'key' => 'prpl_task_id',
62-
'value' => $data['task_id'],
63-
'compare' => '=',
64-
],
65-
],
59+
'name' => \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $data['task_id'] ),
60+
]
61+
);
62+
$posts_trashed = $this->get_tasks_by(
63+
[
64+
'post_status' => [ 'trash' ],
65+
'numberposts' => 1,
66+
'name' => \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $data['task_id'] ) . '__trashed',
6667
]
6768
);
6869

70+
if ( empty( $posts ) && ! empty( $posts_trashed ) ) {
71+
$posts = $posts_trashed;
72+
}
73+
6974
// If we have an existing task, skip.
7075
if ( ! empty( $posts ) ) {
7176
\delete_option( $lock_key );
@@ -83,6 +88,7 @@ public function add( $data ) {
8388
'post_title' => $data['post_title'],
8489
'post_content' => $data['description'] ?? '',
8590
'menu_order' => $data['order'] ?? 0,
91+
'post_name' => \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $data['task_id'] ),
8692
];
8793
switch ( $data['post_status'] ) {
8894
case 'pending':
@@ -313,12 +319,7 @@ public function get_tasks_by( $params ) {
313319
break;
314320

315321
case 'task_id':
316-
$args['meta_query'] = isset( $args['meta_query'] ) ? $args['meta_query'] : []; // phpcs:ignore WordPress.DB.SlowDBQuery
317-
$args['meta_query'][] = [
318-
'key' => 'prpl_task_id',
319-
'value' => $value,
320-
];
321-
322+
$args['name'] = \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $value );
322323
unset( $params[ $param ] );
323324
break;
324325

@@ -359,6 +360,23 @@ public function get( $args = [] ) {
359360
$results = $this->format_recommendations(
360361
\get_posts( $args )
361362
);
363+
if ( ! empty( $args['post_status'] )
364+
&& \in_array( 'trash', (array) $args['post_status'], true )
365+
&& isset( $args['name'] )
366+
) {
367+
$results_trashed = $this->format_recommendations(
368+
\get_posts(
369+
\wp_parse_args(
370+
$args,
371+
[
372+
'post_status' => [ 'trash' ],
373+
'name' => \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $args['name'] ) . '__trashed',
374+
]
375+
)
376+
)
377+
);
378+
$results = array_merge( $results, $results_trashed );
379+
}
362380

363381
\wp_cache_set( $cache_key, $results, static::GET_TASKS_CACHE_GROUP );
364382

classes/class-suggested-tasks.php

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ public function init(): void {
8080
$completed_tasks = $this->tasks_manager->evaluate_tasks();
8181

8282
foreach ( $completed_tasks as $task ) {
83-
if ( ! $task->task_id && $task->ID ) {
83+
if ( ! $task->post_name && $task->ID ) {
8484
continue;
8585
}
8686

8787
// Change the task status to pending.
8888
$task->celebrate();
8989

9090
// Insert an activity.
91-
$this->insert_activity( $task->task_id );
91+
$this->insert_activity( \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $task->post_name ) );
9292
}
9393
}
9494

@@ -156,7 +156,7 @@ public function on_automatic_updates_complete(): void {
156156
\progress_planner()->get_suggested_tasks_db()->update_recommendation( $pending_tasks[0]->ID, [ 'post_status' => 'trash' ] );
157157

158158
// Insert an activity.
159-
$this->insert_activity( $pending_tasks[0]->task_id );
159+
$this->insert_activity( \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $pending_tasks[0]->post_name ) );
160160
}
161161

162162
/**
@@ -324,13 +324,13 @@ public function suggested_task_action() {
324324
switch ( $action ) {
325325
case 'complete':
326326
// Insert an activity.
327-
$this->insert_activity( $task->task_id );
327+
$this->insert_activity( \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $task->post_name ) );
328328
$updated = true;
329329
break;
330330

331331
case 'pending': // User task was marked as pending.
332332
case 'delete':
333-
$this->delete_activity( $task->task_id );
333+
$this->delete_activity( \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $task->post_name ) );
334334
$updated = true;
335335
break;
336336
}
@@ -375,17 +375,12 @@ public function register_post_type() {
375375
);
376376

377377
$rest_meta_fields = [
378-
'prpl_task_id' => [
378+
'prpl_url' => [
379379
'type' => 'string',
380380
'single' => true,
381381
'show_in_rest' => true,
382382
],
383-
'prpl_url' => [
384-
'type' => 'string',
385-
'single' => true,
386-
'show_in_rest' => true,
387-
],
388-
'menu_order' => [
383+
'menu_order' => [
389384
'type' => 'number',
390385
'single' => true,
391386
'show_in_rest' => true,
@@ -506,6 +501,8 @@ public function rest_prepare_recommendation( $response, $post ) {
506501
$provider = \progress_planner()->get_suggested_tasks()->get_tasks_manager()->get_task_provider( $provider_term[0]->slug );
507502
}
508503

504+
$response->data['slug'] = \progress_planner()->get_suggested_tasks()->get_task_id_from_slug( $response->data['slug'] );
505+
509506
if ( $provider ) {
510507
$response->data['prpl_provider'] = $provider_term[0];
511508
// Link should be added during run time, since it is not added for users without required capability.
@@ -514,18 +511,18 @@ public function rest_prepare_recommendation( $response, $post ) {
514511
: '';
515512

516513
$response->data['prpl_popover_id'] = $provider->get_popover_id();
517-
518-
// This has to be the last item to be added because actions use data from previous items.
519-
$response->data['prpl_task_actions'] = $provider->get_task_actions( $response->data );
520-
$response->data['prpl_points'] = $provider->get_points();
514+
$response->data['prpl_points'] = $provider->get_points();
521515

522516
/*
523517
* Check if task was completed before - for example, comments were disabled and then re-enabled, and remove points if so.
524518
* Those are tasks which are completed by toggling an option, so non repetitive & not user tasks.
525519
*/
526-
if ( ! \has_term( 'user', 'prpl_recommendations_provider', $post->ID ) && ! $provider->is_repetitive() && $provider->task_has_activity( $response->data['meta']['prpl_task_id'] ) ) {
520+
if ( ! \has_term( 'user', 'prpl_recommendations_provider', $post->ID ) && ! $provider->is_repetitive() && $provider->task_has_activity( $response->data['slug'] ) ) {
527521
$response->data['prpl_points'] = 0;
528522
}
523+
524+
// This has to be the last item to be added because actions use data from previous items.
525+
$response->data['prpl_task_actions'] = $provider->get_task_actions( $response->data );
529526
}
530527

531528
// Category taxonomy removed - no longer adding prpl_category to response.
@@ -597,4 +594,14 @@ function ( $task ) use ( $args ) {
597594
*/
598595
return \apply_filters( 'progress_planner_suggested_tasks_in_rest_format', $tasks, $args );
599596
}
597+
598+
/**
599+
* Get the task ID from a slug.
600+
*
601+
* @param string $slug The slug.
602+
* @return string
603+
*/
604+
public function get_task_id_from_slug( $slug ) {
605+
return explode( '__trashed', $slug )[0];
606+
}
600607
}

0 commit comments

Comments
 (0)