New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix draft lessons getting published when Course is updated #7582
Conversation
Because for the actual publish call sent by default by Gutenberg, is_admin is false. So it will never catch the actual publish call
Test the previous changes of this PR with WordPress Playground. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## trunk #7582 +/- ##
==========================================
Coverage 51.76% 51.77%
- Complexity 11323 11401 +78
==========================================
Files 641 650 +9
Lines 48185 48549 +364
Branches 470 470
==========================================
+ Hits 24943 25135 +192
- Misses 22861 23033 +172
Partials 381 381
... and 42 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
Thanks for the write-up!
I don't get why it worked in the original PR then, if the lessons weren't even created at that point? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this, but step 4 (Lessons should get published) didn't work. My lessons are still in Draft. On trunk
branch they are published.
tests/unit-tests/admin/test-class-sensei-course-pre-publish-panel.php
Outdated
Show resolved
Hide resolved
|
||
if ( $is_main_publish_call ) { | ||
// This is the first call made, it's not the structure saving call, so the added/updated lessons are not yet saved at this point. | ||
// So we set the flag to publish lessons on the next call, which is made after the structure is saved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this comment a bit confusing. You reference a "next call" here, saying that this next call will be made after the structure is saved. But in the previous sentence, you said that this call is also not the structure saving call, so it's unclear from these comments when the call to save the structure actually happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The saving process is a bit complex :p So I was struggling a bit a capture it in small comments. Basically, when we click on Publish, GB makes a call with the markup. We are referring to it as the Publish call, this is the first call.
If you check the code here -
editor.isSavingPost() && ! editor.isAutosavingPost(); |
dispatch( storeName ).startPostSave(); |
After the structure is also saved, we trigger another GB call (not a structure saving call, a same call as the first Publish call, but the difference is by this time, the Course is already published)
yield* actions.savePost(); |
And this last call is the one I am referring to in the comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the logic, but I still think the comment needs to be improved a bit to eliminate confusion for the next person. 🙂 Perhaps you could add a numbered list of the calls that are made somewhere in this function to "set the stage" so to speak, indicating which ones are always called and which ones may be called? I think it's more important for the comment to be clear than to be succinct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only when you are adding new unsaved lessons and clicking on the Publish button. But let's say you have created a Course, added a bunch of Lessons and clicked on "Save Draft". Later you come back to this course, edit something or maybe not, and then click on Publish, in that case the lessons will already be created, because they got created the last time you clicked on "Save Draft" |
Test the previous changes of this PR with WordPress Playground. |
Thanks for finding this case! Actually it's due to another behavior I've noticed now. If you add the lessons fast after creating the Course, they got added as "Draft", but if you do it slower, they get added as "Unsaved". The issue was when in unsaved state, metabox saving call (auto generated by GB) also triggered the FastScreen.Recording.2024-04-08.at.10.03.47.PM.movSlowScreen.Recording.2024-04-08.at.10.04.56.PM.mov |
Test the previous changes of this PR with WordPress Playground. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test the previous changes of this PR with WordPress Playground. |
Thanks @donnapep ! I've updated the comments here 2ac96e8 . Please LMK if it looks better now. Thank you! |
Resolves #7555
Proposed Changes
Even though the lessons were supposed to get published only at the time of the Course getting published, they were getting published on all updates of course.
If we look at the code, it's attached to the
publish_course
hook, so it should get called ONLY when the Course is getting published, right?Well, no! If we look at the documentation of the hook, in the bottom, it says -
So it was getting called everytime for a published Course, and lessons were getting published.
But luckily, there's an
old_status
param, which shows which status this post is transitioning from. So it should be just as simple as just checking if the Course is getting Published from an old status of!== 'publish'
right?Well, no! To understand the reason, you need to know how we save our Course structure from GB editor. When you create a Course, add a bunch of lessons and click on Publish, or when you edit the Course outline block, and click on Update in an existing course, first a call is initiated by GB to save the Course markup (it doesn't save the lessons, modules, or the course structure), parallelly, another call is initiated to save the Metabox values. Once these two are completed, Sensei sends an API call with the payload of the Course structure in JSON, this is when the Lessons get created/updated. After that, an (or multiple) update calls are made to sync the frontend and backend Course structure.
So, even if we try to publish the lessons at the time of the transition of the Course, it won't work, because, the lessons do not even exist at the time of the Course getting published! (The first GB call).
So we can do it in the later call right? Yap, but how do you differentiate it from a normal Update call? To do that, we've set a flag that's set at the time of the transition, and gets cleared after the subsequent call. Is that all?
Well, no! because if we attach the hook inside the
is_admin()
check, it will not get attached for the first GB call, so inside the hook, we won't even know that it's transitioning to Publish. Why does a GB call from the editor made inside Admin panel is gettingis_admin()
to returnfalse
you ask? I don't know, haven't looked into it yet (planning to do later after publishing this PR).A couple of things I've noticed:
If lessons are already in draft (not unsaved, draft) in a draft course, then clicking on publish doesn't immediately update the UI of the lessons remove the
draft
tag from below them. But it's not newly introduced, it was existing, I haven't fixed it here.And it's technically possible to still publish a lesson in a subsequent update if you follow a special sequence (but you kinda have to intentionally try it). So I haven't covered that case. For general testing and use case flows, it should be enough.
Testing Instructions
Pre-Merge Checklist