PhoenixKit.Modules.Publishing.Storage (phoenix_kit v1.7.43)

Copy Markdown View Source

Filesystem storage helpers for publishing posts.

Content is stored under:

priv/publishing/<group>/<YYYY-MM-DD>/<HH:MM>/<language>.phk

Where <language> is determined by the site's content language setting. Files use the .phk (PhoenixKit) format, which supports XML-style component markup for building pages with swappable design variants.

Submodules

This module delegates to specialized submodules for better organization:

  • Storage.Paths - Path management and resolution
  • Storage.Languages - Language operations and i18n
  • Storage.Slugs - Slug validation and generation
  • Storage.Versions - Version management
  • Storage.Deletion - Trash and delete operations
  • Storage.Helpers - Shared utilities

Summary

Types

A post with metadata and content.

Functions

Adds a new language file to an existing post (timestamp mode).

Checks if the content or title has changed.

Counts the number of posts on a specific date for a blog. Used to determine if time should be included in URLs.

Creates a new version of a post by copying from the source version.

Creates a new post (timestamp mode), returning its metadata and content.

Creates a slug-mode post, returning metadata and paths for the primary language.

Creates a new version of a post from a specified source version or blank.

Lists posts for the given blog (timestamp mode). Accepts optional preferred_language to show titles in user's language.

Lists slug-mode posts for the given blog.

Lists all time folders (posts) for a specific date in a blog. Returns a list of time strings in HH:MM format, sorted.

Migrates a single post from legacy structure to versioned structure.

Moves an entire publishing group to the trash folder.

Publishes a version, atomically archiving all other versions.

Reads a post for a specific language (timestamp mode).

Renames a publishing group directory on disk when the slug changes.

Sets the status of a specific translation (language file) in a version.

Deprecated: Use publish_version/3 instead.

Checks whether a new version should be created based on changes. Currently always returns false - users create new versions explicitly.

Checks if only the status is being changed (no content or title changes). Status-only changes don't require a new version.

Updates a post's metadata/content (timestamp mode).

Updates slug-mode posts in place (no slug change).

Types

post()

@type post() :: %{
  group: String.t() | nil,
  slug: String.t() | nil,
  date: Date.t() | nil,
  time: Time.t() | nil,
  path: String.t(),
  full_path: String.t(),
  metadata: map(),
  content: String.t(),
  language: String.t(),
  available_languages: [String.t()],
  language_statuses: %{required(String.t()) => String.t() | nil},
  mode: :slug | :timestamp | nil,
  version: integer() | nil,
  available_versions: [integer()],
  version_statuses: %{required(integer()) => String.t()},
  version_dates: %{required(integer()) => String.t() | nil},
  is_legacy_structure: boolean()
}

A post with metadata and content.

The language_statuses field is preloaded when fetching posts via list_posts/2 or read_post/2 to avoid redundant file reads. It maps language codes to their publication status (e.g., %{"en" => "published", "es" => "draft"}).

Version fields:

  • version: Current version number (1, 2, 3...)
  • available_versions: List of all version numbers for this post
  • version_statuses: Map of version => status for quick lookup

Functions

absolute_path(relative_path)

See PhoenixKit.Modules.Publishing.Storage.Paths.absolute_path/1.

add_language_to_post(group_slug, post_path, language_code)

@spec add_language_to_post(String.t(), String.t(), String.t()) ::
  {:ok, post()} | {:error, any()}

Adds a new language file to an existing post (timestamp mode).

add_language_to_post_slug_mode(group_slug, post_slug, language_code, version \\ nil)

@spec add_language_to_post_slug_mode(
  String.t(),
  String.t(),
  String.t(),
  integer() | nil
) ::
  {:ok, post()} | {:error, any()}

Adds a new language file to a slug-mode post.

check_primary_language_status(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Languages.check_primary_language_status/2.

cleanup_empty_legacy_root()

See PhoenixKit.Modules.Publishing.Storage.Paths.cleanup_empty_legacy_root/0.

clear_url_slug_from_post(group_slug, post_slug, url_slug)

See PhoenixKit.Modules.Publishing.Storage.Slugs.clear_url_slug_from_post/3.

content_changed?(post, params)

@spec content_changed?(post(), map()) :: boolean()

Checks if the content or title has changed.

count_posts_on_date(group_slug, date)

@spec count_posts_on_date(String.t(), Date.t() | String.t()) :: non_neg_integer()

Counts the number of posts on a specific date for a blog. Used to determine if time should be included in URLs.

create_new_version(group_slug, source_post, params \\ %{}, audit_meta \\ %{})

@spec create_new_version(String.t(), post(), map(), map() | keyword()) ::
  {:ok, post()} | {:error, any()}

Creates a new version of a post by copying from the source version.

create_post(group_slug, audit_meta \\ %{})

@spec create_post(String.t(), map() | keyword()) :: {:ok, post()} | {:error, any()}

Creates a new post (timestamp mode), returning its metadata and content.

create_post_slug_mode(group_slug, title \\ nil, preferred_slug \\ nil, audit_meta \\ %{})

@spec create_post_slug_mode(
  String.t(),
  String.t() | nil,
  String.t() | nil,
  map() | keyword()
) ::
  {:ok, post()} | {:error, any()}

Creates a slug-mode post, returning metadata and paths for the primary language.

create_version_from(group_slug, post_slug, source_version, params \\ %{}, audit_meta \\ %{})

@spec create_version_from(String.t(), String.t(), integer() | nil, map(), map()) ::
  {:ok, post()} | {:error, any()}

Creates a new version of a post from a specified source version or blank.

delete_language(group_slug, post_id, language, version \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Deletion.delete_language/4.

delete_version(group_slug, post_id, version)

See PhoenixKit.Modules.Publishing.Storage.Deletion.delete_version/3.

detect_available_languages(dir_path, primary \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Languages.detect_available_languages/2.

detect_post_structure(post_path)

See PhoenixKit.Modules.Publishing.Storage.Versions.detect_post_structure/1.

enabled_language_codes()

See PhoenixKit.Modules.Publishing.Storage.Languages.enabled_language_codes/0.

ensure_group_root(group_slug)

See PhoenixKit.Modules.Publishing.Storage.Paths.ensure_group_root/1.

generate_unique_slug(group_slug, title, preferred \\ nil, opts \\ [])

See PhoenixKit.Modules.Publishing.Storage.Slugs.generate_unique_slug/4.

get_display_code(language_code, enabled_languages)

See PhoenixKit.Modules.Publishing.Storage.Languages.get_display_code/2.

get_language_info(language_code)

See PhoenixKit.Modules.Publishing.Storage.Languages.get_language_info/1.

get_latest_published_version(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_latest_published_version/2.

get_latest_version(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_latest_version/2.

get_post_primary_language(group_slug, post_slug, version \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Languages.get_post_primary_language/3.

get_primary_language()

See PhoenixKit.Modules.Publishing.Storage.Languages.get_primary_language/0.

get_published_version(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_published_version/2.

get_version_date(group_slug, post_slug, version, language)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_version_date/4.

get_version_metadata(group_slug, post_slug, version, language)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_version_metadata/4.

get_version_status(group_slug, post_slug, version, language)

See PhoenixKit.Modules.Publishing.Storage.Versions.get_version_status/4.

group_path(group_slug)

See PhoenixKit.Modules.Publishing.Storage.Paths.group_path/1.

has_legacy_groups?()

See PhoenixKit.Modules.Publishing.Storage.Paths.has_legacy_groups?/0.

language_enabled?(language_code, enabled_languages)

See PhoenixKit.Modules.Publishing.Storage.Languages.language_enabled?/2.

language_filename()

See PhoenixKit.Modules.Publishing.Storage.Languages.language_filename/0.

language_filename(language_code)

See PhoenixKit.Modules.Publishing.Storage.Languages.language_filename/1.

legacy_group?(group_slug)

See PhoenixKit.Modules.Publishing.Storage.Paths.legacy_group?/1.

legacy_root_path()

See PhoenixKit.Modules.Publishing.Storage.Paths.legacy_root_path/0.

list_posts(group_slug, preferred_language \\ nil)

@spec list_posts(String.t(), String.t() | nil) :: [post()]

Lists posts for the given blog (timestamp mode). Accepts optional preferred_language to show titles in user's language.

list_posts_slug_mode(group_slug, preferred_language \\ nil)

@spec list_posts_slug_mode(String.t(), String.t() | nil) :: [post()]

Lists slug-mode posts for the given blog.

list_times_on_date(group_slug, date)

@spec list_times_on_date(String.t(), Date.t() | String.t()) :: [String.t()]

Lists all time folders (posts) for a specific date in a blog. Returns a list of time strings in HH:MM format, sorted.

list_versions(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Versions.list_versions/2.

load_language_statuses(post_dir, available_languages)

See PhoenixKit.Modules.Publishing.Storage.Languages.load_language_statuses/2.

load_version_dates(group_slug, post_slug, versions, primary \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Versions.load_version_dates/4.

load_version_statuses(group_slug, post_slug, versions, primary \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Versions.load_version_statuses/4.

migrate_group(group_slug)

See PhoenixKit.Modules.Publishing.Storage.Paths.migrate_group/1.

migrate_post_to_versioned(post, language \\ nil)

@spec migrate_post_to_versioned(post(), String.t() | nil) ::
  {:ok, post()} | {:error, any()}

Migrates a single post from legacy structure to versioned structure.

move_group_to_trash(group_slug)

@spec move_group_to_trash(String.t()) :: {:ok, String.t()} | {:error, term()}

Moves an entire publishing group to the trash folder.

move_post_to_new_slug(group_slug, post, new_slug, params, audit_meta \\ %{})

@spec move_post_to_new_slug(String.t(), post(), String.t(), map(), map() | keyword()) ::
  {:ok, post()} | {:error, any()}

Moves a slug-mode post to a new slug.

new_root_path()

See PhoenixKit.Modules.Publishing.Storage.Paths.new_root_path/0.

order_languages_for_display(available, enabled, primary \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Languages.order_languages_for_display/3.

parse_version_number(name)

See PhoenixKit.Modules.Publishing.Storage.Versions.parse_version_number/1.

propagate_status_to_translations(post_dir, primary_language, new_status)

See PhoenixKit.Modules.Publishing.Storage.Languages.propagate_status_to_translations/3.

publish_version(group_slug, post_slug, version_to_publish)

@spec publish_version(String.t(), String.t(), integer()) :: :ok | {:error, any()}

Publishes a version, atomically archiving all other versions.

read_post(group_slug, relative_path)

@spec read_post(String.t(), String.t()) :: {:ok, post()} | {:error, any()}

Reads a post for a specific language (timestamp mode).

read_post_slug_mode(group_slug, post_slug, language \\ nil, version \\ nil)

@spec read_post_slug_mode(String.t(), String.t(), String.t() | nil, integer() | nil) ::
  {:ok, post()} | {:error, any()}

Reads a slug-mode post.

rename_group_directory(old_slug, new_slug)

@spec rename_group_directory(String.t(), String.t()) :: :ok | {:error, term()}

Renames a publishing group directory on disk when the slug changes.

root_path()

See PhoenixKit.Modules.Publishing.Storage.Paths.root_path/0.

set_translation_status(group_slug, post_slug, version, language, status)

@spec set_translation_status(
  String.t(),
  String.t(),
  integer(),
  String.t(),
  String.t()
) ::
  :ok | {:error, any()}

Sets the status of a specific translation (language file) in a version.

set_version_live(group_slug, post_slug, version)

This function is deprecated. Use publish_version/3 instead.
@spec set_version_live(String.t(), String.t(), integer()) :: :ok | {:error, any()}

Deprecated: Use publish_version/3 instead.

should_create_new_version?(post, params, editing_language)

@spec should_create_new_version?(post(), map(), String.t()) :: boolean()

Checks whether a new version should be created based on changes. Currently always returns false - users create new versions explicitly.

slug_exists?(group_slug, post_slug)

See PhoenixKit.Modules.Publishing.Storage.Slugs.slug_exists?/2.

status_change_only?(post, params)

@spec status_change_only?(post(), map()) :: boolean()

Checks if only the status is being changed (no content or title changes). Status-only changes don't require a new version.

trash_language(group_slug, relative_path)

See PhoenixKit.Modules.Publishing.Storage.Deletion.trash_language/2.

trash_post(group_slug, post_identifier)

See PhoenixKit.Modules.Publishing.Storage.Deletion.trash_post/2.

update_post(group_slug, post, params, audit_meta \\ %{})

@spec update_post(String.t(), post(), map(), map() | keyword()) ::
  {:ok, post()} | {:error, any()}

Updates a post's metadata/content (timestamp mode).

update_post_primary_language(group_slug, post_slug, new_primary)

See PhoenixKit.Modules.Publishing.Storage.Languages.update_post_primary_language/3.

update_post_slug_in_place(group_slug, post, params, audit_meta \\ %{})

@spec update_post_slug_in_place(String.t(), post(), map(), map() | keyword()) ::
  {:ok, post()} | {:error, any()}

Updates slug-mode posts in place (no slug change).

update_post_slug_mode(group_slug, post, params, audit_meta \\ %{})

@spec update_post_slug_mode(String.t(), post(), map(), map() | keyword()) ::
  {:ok, post()} | {:error, any()}

Updates slug-mode posts.

valid_slug?(slug)

See PhoenixKit.Modules.Publishing.Storage.Slugs.valid_slug?/1.

validate_slug(slug)

See PhoenixKit.Modules.Publishing.Storage.Slugs.validate_slug/1.

validate_url_slug(group_slug, url_slug, language, exclude \\ nil)

See PhoenixKit.Modules.Publishing.Storage.Slugs.validate_url_slug/4.

version_dir?(name)

See PhoenixKit.Modules.Publishing.Storage.Versions.version_dir?/1.

version_path(group_slug, post_slug, version)

See PhoenixKit.Modules.Publishing.Storage.Versions.version_path/3.

write_root_path()

See PhoenixKit.Modules.Publishing.Storage.Paths.write_root_path/0.