Skip to content

Conversation

@ljonesfl
Copy link
Member

@ljonesfl ljonesfl commented Jan 16, 2026

Note

Introduces scheduling and improves publishing/slug UX and validation end-to-end.

  • UI: Adds scheduled status, shows published_at for published/scheduled, enforces date on submit, and auto-generates slug from title with manual override; slug no longer required and constrained by [a-z0-9-]+.
  • DTOs: Extend create/update request schemas with optional published_at (datetime-local pattern) and enum now includes scheduled.
  • Services: Creator/Updater set published_at rules—require for scheduled, accept provided value, auto-set for published when missing; adds safe datetime parsing with clear errors.
  • Tests: New unit tests covering scheduled-post requirements, invalid dates, auto-set behavior, and preserving published_at when reverting to draft.

Written by Cursor Bugbot for commit 68e4e6d. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • "Scheduled" post status and a Published Date/Time field (shown for Published/Scheduled).
    • Auto-generate slug from title with manual-edit support; slug pattern and helper text updated.
    • Server accepts an optional published date and uses it when present; published date auto-set for Published posts if omitted.
  • Bug Fixes / Validation

    • Prevent saving a post as Scheduled without a published date; initialize published-date visibility on load; client-side and server-side validation added.
  • Tests

    • Added unit tests for scheduled-post validation, published-date parsing, preservation, and related scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds scheduled-post support: UI updates (slug pattern/auto-generation, new Scheduled status, Published Date/Time field with client-side validation), DTOs accept optional published_at, services validate/parse published_at and enforce rules for SCHEDULED/PUBLISHED, and unit tests cover new behaviors.

Changes

Cohort / File(s) Change summary
Admin views
resources/views/admin/posts/create.php, resources/views/admin/posts/edit.php
Added slug pattern and auto-generation from title; helper text updated; added "Scheduled" status; introduced published_at UI (published-at-wrapper, #published_at) with show/hide logic and client-side validation. edit.php contains duplicated client-side logic.
DTOs
src/Cms/Dtos/posts/create-post-request.yaml, src/Cms/Dtos/posts/update-post-request.yaml
Added optional published_at string field with pattern enforcing YYYY-MM-DDTHH:MM or empty.
Post services
src/Cms/Services/Post/Creator.php, src/Cms/Services/Post/Updater.php
Extract published_at; added parseDateTime helper; validate/parse published_at; require published date for SCHEDULED status; set PublishedAt from provided value or now when appropriate; throw InvalidArgumentException on invalid/missing scheduled date.
Unit tests
tests/Unit/Cms/Services/Post/CreatorTest.php, tests/Unit/Cms/Services/Post/UpdaterTest.php
Updated DTO builders to accept publishedAt; added tests for scheduled-post validation, successful scheduling with published date, invalid date formats, and preservation of publishedAt across status changes.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Browser
participant AdminUI as "Admin UI (create/edit)"
participant Server as "Controller"
participant Service as "Post Service\n(Creator/Updater)"
participant DB as "Database"

Browser->>AdminUI: enter title/slug/status/published_at
AdminUI-->>Browser: auto-generate slug; show/hide published_at; client-side validate scheduled date
AdminUI->>Server: submit form (includes published_at)
Server->>Service: pass DTO (includes published_at)
Service->>Service: validate status; parseDateTime(published_at) if present; enforce scheduled date
alt valid
Service->>DB: persist post with PublishedAt
DB-->>Service: ok
Service-->>Server: success
Server-->>Browser: redirect/confirm
else invalid/missing for scheduled
Service-->>Server: throw InvalidArgumentException
Server-->>Browser: show error
end

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

"I nibble at slugs and dates with glee,
A scheduled hop from draft to be,
Title to slug, time set just right,
I stamp the clock and tuck it tight.
🐇✨"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title mentions two main features: editing post published dates and auto-updating post slug. Both are present in the changeset—published_at handling is added across UI, DTOs, and services, and slug auto-generation logic is implemented in the view files. However, there is a typo ('pubished' instead of 'published') that reduces clarity.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ Complexity Δ
cms 73.90% <100.00%> (+0.09%) 2142.00 <4.00> (+14.00)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ Complexity Δ
src/Cms/Services/Post/Creator.php 100.00% <100.00%> (ø) 12.00 <2.00> (+7.00)
src/Cms/Services/Post/Updater.php 100.00% <100.00%> (ø) 14.00 <2.00> (+7.00)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@resources/views/admin/posts/create.php`:
- Around line 248-255: The current change handler only hides/shows the
published-at UI but does not clear or disable the underlying input, causing
stale published_at to be submitted; update the handler tied to
document.getElementById('status') so that when the status is 'published' or
'scheduled' it sets the published-at input (e.g., the element inside
'published-at-wrapper', such as id 'published-at' or name 'published_at') to
enabled and when hidden it clears its value (set to empty) and sets
disabled=true to prevent submission; also invoke the same logic once on page
load (or on DOMContentLoaded) to sync the initial visibility/state.

In `@resources/views/admin/posts/edit.php`:
- Around line 47-51: Add client-side validation to ensure a published date/time
is provided when the post status is set to "scheduled": hook into the post form
submit handler (element id 'post-form'), read the status field (id 'status') and
the published date input (id 'published_at'), and prevent submit with an inline
error (or alert) if status === 'scheduled' and published_at is empty; also
update the helper text near the published_at input (or the display logic in
'published-at-wrapper') to clearly state that scheduled posts require a future
publish date/time.
🧹 Nitpick comments (2)
src/Cms/Services/Post/Updater.php (1)

59-85: Guard published_at updates by status to avoid drafts carrying a publish timestamp.

Right now any non-empty published_at is applied regardless of status. If a user toggles from scheduled/published back to draft (or an API sends published_at with draft), drafts can still get a publish date. Consider applying published_at only for published/scheduled statuses (and ignore/clear otherwise). Please mirror the guard in src/Cms/Services/Post/Creator.php for parity.

♻️ Suggested adjustment
-		// Business rule: set published date
-		if( $publishedAt && trim( $publishedAt ) !== '' )
-		{
-			// Use provided published date
-			$post->setPublishedAt( new \DateTimeImmutable( $publishedAt ) );
-		}
-		elseif( $status === ContentStatus::PUBLISHED->value && !$post->getPublishedAt() )
-		{
-			// Auto-set to now for published posts when not provided and not already set
-			$post->setPublishedAt( new \DateTimeImmutable() );
-		}
+		// Business rule: set published date (only for published/scheduled)
+		if( in_array( $status, [ ContentStatus::PUBLISHED->value, ContentStatus::SCHEDULED->value ], true ) )
+		{
+			if( $publishedAt && trim( $publishedAt ) !== '' )
+			{
+				// Use provided published date
+				$post->setPublishedAt( new \DateTimeImmutable( $publishedAt ) );
+			}
+			elseif( $status === ContentStatus::PUBLISHED->value && !$post->getPublishedAt() )
+			{
+				// Auto-set to now for published posts when not provided and not already set
+				$post->setPublishedAt( new \DateTimeImmutable() );
+			}
+		}
resources/views/admin/posts/edit.php (1)

20-21: Slug pattern allows leading/trailing hyphens.

The pattern [a-z0-9-]+ permits slugs like --test--, while the auto-generation code strips leading/trailing hyphens. Consider a stricter pattern if you want consistency:

^[a-z0-9]+(-[a-z0-9]+)*$

Otherwise, the changes look good—removing required to enable auto-generation and the helper text update are clear.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1ce088 and f5b519d.

📒 Files selected for processing (6)
  • resources/views/admin/posts/create.php
  • resources/views/admin/posts/edit.php
  • src/Cms/Dtos/posts/create-post-request.yaml
  • src/Cms/Dtos/posts/update-post-request.yaml
  • src/Cms/Services/Post/Creator.php
  • src/Cms/Services/Post/Updater.php
🧰 Additional context used
🧬 Code graph analysis (3)
src/Cms/Services/Post/Updater.php (2)
src/Cms/Models/Post.php (2)
  • setPublishedAt (300-304)
  • getPublishedAt (292-295)
src/Cms/Models/Page.php (2)
  • setPublishedAt (306-310)
  • getPublishedAt (298-301)
src/Cms/Services/Post/Creator.php (2)
src/Cms/Models/Post.php (1)
  • setPublishedAt (300-304)
src/Cms/Models/Page.php (1)
  • setPublishedAt (306-310)
resources/views/admin/posts/edit.php (3)
src/Cms/Models/Tag.php (1)
  • getSlug (72-75)
src/Cms/Models/Post.php (3)
  • getSlug (96-99)
  • getStatus (251-254)
  • getPublishedAt (292-295)
src/Cms/Models/Category.php (1)
  • getSlug (73-76)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: build-test (sqlite)
  • GitHub Check: build-test (postgres)
  • GitHub Check: build-test (mysql)
🔇 Additional comments (8)
src/Cms/Dtos/posts/create-post-request.yaml (1)

38-46: DTO update looks consistent with the update flow.

Optional published_at and the scheduled status align cleanly with the update DTO.

src/Cms/Services/Post/Creator.php (1)

59-81: LGTM — published_at handling matches the update flow.

Explicit dates are respected and the auto-set behavior for published posts is preserved.

resources/views/admin/posts/create.php (3)

19-20: Slug input validation/help text looks good.

Clear guidance and a tight pattern for URL-safe slugs.


42-50: Scheduled status option + Published Date/Time field integrate cleanly.

The UI now aligns with the new status and publish date workflow.


228-245: Auto-slug generation logic is clear and user-friendly.

The auto-generated vs. manual edit tracking is straightforward.

src/Cms/Dtos/posts/update-post-request.yaml (1)

38-46: No action required—scheduled status is fully implemented.

All concerns have been verified: ContentStatus enum includes SCHEDULED, the schedule() method in Publisher enforces that scheduled posts must have a future published_at date, repository methods support querying scheduled posts, and downstream services properly handle the new status. The implementation is complete and correct.

resources/views/admin/posts/edit.php (2)

43-43: LGTM!

The new "Scheduled" status option follows the same pattern as existing options and integrates well with the published_at visibility logic.


254-281: LGTM!

The JavaScript logic is well-implemented:

  • Auto-generation respects existing slugs on page load (since dataset.autoGenerated is undefined)
  • Clearing the slug re-enables auto-generation on subsequent title changes
  • The published-at visibility toggle correctly matches the server-side initial display condition

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

@ljonesfl ljonesfl closed this Jan 19, 2026
@ljonesfl ljonesfl deleted the feature/post-updates branch January 19, 2026 04:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants