PhoenixKit. Modules. Publishing. Web. Controller. Listing
(PhoenixKitPublishing v0.4.5)
Copy Markdown
View Source
Group listing functionality for the publishing controller.
Handles rendering post listings with:
- Language filtering and fallback
- Pagination
- Translation link building for listings
Summary
Functions
The group's published posts for the requested language, title/excerpt-resolved
and sorted newest-first — the shared source for the RSS feed and the post
page's prev/next navigation. Deliberately independent of the group's
listing_sort: feeds and chronological neighbors always mean "newest first".
Fetches group configuration by slug.
Filter posts to only include those that have matching language content. Handles both exact matches and base code matches (e.g., "en" matches "en-US"). Translation visibility is based on existence only — status comes from the post level.
Strict version - only matches exact language, no fallback to base code.
Filters posts to only include published ones. Excludes timestamp-mode posts with a future post_date.
Find a matching language in available languages. Handles exact matches and base code matching.
Get the actual language that the fallback matched. Used to redirect to the correct URL when requested language has no content.
Gets the page number from params.
Gets the posts per page setting.
The chronological neighbors of a post within its group + language, as
%{newer:, older:, date_counts:} — either neighbor nil at the chronology's
edge (or when the post isn't in the published set, e.g. a draft preview).
date_counts covers the WHOLE published set, so a timestamp neighbor's URL
correctly includes its time segment when the date has same-day siblings.
Paginates a list of posts.
Renders the group index page with resolved posts.
Renders a group listing page.
Renders the group listing as SEARCH RESULTS for query. Falls back to the
normal listing when the group's search_enabled setting is off — a ?q=
on a search-disabled group is ignored, not an error. The :ok shape
matches render_group_index/3 plus :search_query, with the
Featured/Latest bands suppressed and a single results page (capped at 50
matches, newest first).
Renders a category/tag archive: the listing shape (render_group_index/3
fields) with the term's posts, the bands suppressed, and a :term_filter
map (%{type:, label:, count:}) for the heading. Single results page,
newest first, capped like search.
Resolves posts for the requested language, handling exact match vs fallback.
chronological_posts/3 narrowed to a term scope: nil (whole group),
{:category, slug} (the category AND its descendants — WordPress archive
rule), or {:tag, tag} (case-insensitive tag match). Returns
{:ok, posts, label} where label is the category's translated name (nil
for the whole group, the raw tag for tags), or {:error, :not_found} for
an unknown category / a tag no published post carries.
Search matches for a group's public listing: a DB substring pass (title +
body of active PUBLISHED versions, candidate languages, ILIKE-escaped)
intersected with the chronological cache maps — so results carry the same
resolved titles/URLs/order as the listing. Returns {posts, date_counts},
the counts computed over the WHOLE published set so a matched timestamp
post's URL keeps its time segment when non-matched same-day siblings exist.
Functions
The group's published posts for the requested language, title/excerpt-resolved
and sorted newest-first — the shared source for the RSS feed and the post
page's prev/next navigation. Deliberately independent of the group's
listing_sort: feeds and chronological neighbors always mean "newest first".
Fetches group configuration by slug.
Filter posts to only include those that have matching language content. Handles both exact matches and base code matches (e.g., "en" matches "en-US"). Translation visibility is based on existence only — status comes from the post level.
Strict version - only matches exact language, no fallback to base code.
Filters posts to only include published ones. Excludes timestamp-mode posts with a future post_date.
Find a matching language in available languages. Handles exact matches and base code matching.
Get the actual language that the fallback matched. Used to redirect to the correct URL when requested language has no content.
Gets the page number from params.
Gets the posts per page setting.
The chronological neighbors of a post within its group + language, as
%{newer:, older:, date_counts:} — either neighbor nil at the chronology's
edge (or when the post isn't in the published set, e.g. a draft preview).
date_counts covers the WHOLE published set, so a timestamp neighbor's URL
correctly includes its time segment when the date has same-day siblings.
Paginates a list of posts.
Renders the group index page with resolved posts.
Renders a group listing page.
Renders the group listing as SEARCH RESULTS for query. Falls back to the
normal listing when the group's search_enabled setting is off — a ?q=
on a search-disabled group is ignored, not an error. The :ok shape
matches render_group_index/3 plus :search_query, with the
Featured/Latest bands suppressed and a single results page (capped at 50
matches, newest first).
Renders a category/tag archive: the listing shape (render_group_index/3
fields) with the term's posts, the bands suppressed, and a :term_filter
map (%{type:, label:, count:}) for the heading. Single results page,
newest first, capped like search.
Resolves posts for the requested language, handling exact match vs fallback.
chronological_posts/3 narrowed to a term scope: nil (whole group),
{:category, slug} (the category AND its descendants — WordPress archive
rule), or {:tag, tag} (case-insensitive tag match). Returns
{:ok, posts, label} where label is the category's translated name (nil
for the whole group, the raw tag for tags), or {:error, :not_found} for
an unknown category / a tag no published post carries.
Search matches for a group's public listing: a DB substring pass (title +
body of active PUBLISHED versions, candidate languages, ILIKE-escaped)
intersected with the chronological cache maps — so results carry the same
resolved titles/URLs/order as the listing. Returns {posts, date_counts},
the counts computed over the WHOLE published set so a matched timestamp
post's URL keeps its time segment when non-matched same-day siblings exist.