Skip to content

Commit 06885a8

Browse files
authored
Implement generic contextual repository pattern for posts (#991)
* Add documentation for wp_mobile_cache contextual mappings Added comprehensive documentation for implementing database mappings for WordPress REST API contextual types in wp_mobile_cache. Changes: - Created CLAUDE.md with quick reference for common tasks - Created docs/IMPLEMENTING_MAPPINGS.md with detailed step-by-step guide - Documents the process for generating concrete types via cargo expand - Explains field analysis, mapping implementation, and migration creation - Provides helper function reference and common patterns * Implement view and embed context mappings for posts Reorganized post mappings to support multiple WordPress API contexts with separate implementations for edit, view, and embed. Changes: - Moved posts.rs to posts/ directory with separate files per context - Created posts/edit.rs (existing edit context mapping) - Created posts/view.rs (25 fields, no raw content or edit-only fields) - Created posts/embed.rs (9 fields, minimal data for embedding) - Created posts/mod.rs with shared helper for term relationship extraction - All contexts use extract_categories_and_tags() helper to avoid duplication - All 50 existing tests pass without modification * Refactor post repository to support multiple WordPress REST API contexts Consolidate mapping layer into repository and add generic context support for edit, view, and embed contexts. This eliminates unnecessary abstraction layers and provides a cleaner architecture. Architecture changes: - Create new context module with IsContext and PostContext traits - Add context marker types: EditContext, ViewContext, EmbedContext - Create db_types module for database type definitions separate from logic - Split db_types/posts into separate files per context (edit, view, embed) - Remove mappings/posts directory entirely Repository improvements: - Make PostRepository generic over PostContext trait: PostRepository<C> - Implement generic read operations via impl<C: PostContext> - Keep context-specific write operations in impl PostRepository<EditContext> - Move FromRowWithTerms trait into repository as private implementation detail - Implement FromRowWithTerms for all three contexts (Edit, View, Embed) - Add extract_categories_and_tags helper function Benefits: - Clean separation: db_types for structs, repository for logic - Reduced code scatter - related functionality in one place - Generic read operations work across all contexts - Type-safe context handling via trait bounds - Easier to navigate with split files per context Changes: - Add src/context.rs with context traits and marker types - Add src/db_types/ module with posts submodule split by context - Remove src/mappings/posts/ directory - Refactor src/repository/posts.rs to be generic over context - Update test fixtures to use PostRepository<EditContext> - Add Default impl and private_bounds allow attribute * Return Ok(None) instead of error for not-found queries in wp_mobile_cache Changed repository select methods to return `Result<Option<T>>` instead of `Result<T>`, treating "not found" as a valid outcome rather than an error condition. This is more idiomatic Rust and provides better clarity for callers. Uses rusqlite's built-in `OptionalExtension::optional()` method to cleanly convert `rusqlite::Result<T>` into `Result<Option<T>, SqliteDbError>`, automatically handling `QueryReturnedNoRows` as `Ok(None)` while preserving other errors. Changes: - Import `rusqlite::OptionalExtension` in repository/posts.rs - Update `select_by_rowid` to return `Result<Option<DbPost>>` - Update `select_by_post_id` to return `Result<Option<DbPost>>` - Refactor query error handling using `let-else` pattern for clarity - Update `delete_by_post_id` to handle new Option return type - Update all test assertions to work with Option values - Rename tests to reflect new behavior (returns_none vs returns_error) * Update IMPLEMENTING_MAPPINGS.md to reflect current architecture The documentation was outdated and referenced the old structure where mapping logic lived in `src/mappings/{entity}/`. Updated to reflect the current architecture where database operations are properly separated. Current architecture: - `src/db_types/`: Type-only definitions (column enums, wrapper structs) - `src/repository/`: All database interaction logic (FromRowWithTerms + upsert) - `src/mappings/helpers.rs`: Reusable conversion utilities This maintains proper separation of concerns where the repository pattern handles all database operations in one place, avoiding split responsibilities. Changes: - Update Step 4 to reference `db_types/` instead of `mappings/` - Add new Step 5 explaining FromRowWithTerms goes in repository - Update all file path references throughout document - Update checklist to reflect correct module locations - Update file organization diagram with accurate structure - Add architecture summary explaining the separation * Rename IMPLEMENTING_MAPPINGS.md to ADDING_NEW_ENTITIES.md The old name no longer accurately describes the document's purpose. The guide covers the complete process of adding database support for new WordPress entity types, not just "implementing mappings." Changes: - Rename docs/IMPLEMENTING_MAPPINGS.md to docs/ADDING_NEW_ENTITIES.md - Update self-reference in file organization diagram - Update references in CLAUDE.md with more descriptive text * Remove private FromRowWithTerms trait in favor of PostContext method Eliminated the private `FromRowWithTerms` trait by adding the `from_row_with_terms` method directly to the `PostContext` trait. This removes the need for `#[allow(private_bounds)]` and simplifies the architecture. Benefits: - No more private trait with unclear purpose - No compiler warning suppression needed - PostContext implementations are now complete in the repository module - Clearer architecture: context trait defines both types and behavior Changes: - Add `from_row_with_terms` method to `PostContext` trait in context.rs - Move `PostContext` implementations from context.rs to repository/posts.rs - Replace `impl FromRowWithTerms for DbPost` with `impl PostContext for Context` - Remove `where C::DbPost: FromRowWithTerms` bounds from repository methods - Update call sites from `C::DbPost::from_row_with_terms` to `C::from_row_with_terms` - Update return types from `Result<Self, ...>` to `Result<Self::DbPost, ...>` * Use lazy closure for term relationship loading to avoid unnecessary queries Changed `from_row_with_terms` to accept a closure instead of pre-fetched term relationships. This allows contexts to decide whether they need terms, avoiding unnecessary database queries for contexts like Embed that don't use them. Benefits: - EmbedContext no longer queries term_relationships table unnecessarily - Caller provides HOW to fetch, implementation decides IF to fetch - Proper separation of concerns and dependency injection - Maintains efficient batch loading for select_all (pre-fetch once, lazy access) Implementation: - Each context calls `fetch_terms()?` only if it needs categories/tags - EditContext and ViewContext: Call closure to get terms - EmbedContext: Never calls closure, avoiding the query entirely Changes: - Update PostContext trait method to accept FnOnce closure - Update repository methods to pass closures instead of pre-fetching - EditContext/ViewContext: Call fetch_terms() and use results - EmbedContext: Don't call fetch_terms(), add explanatory comment * Add database migrations for posts_view_context and posts_embed_context tables Created missing migrations for ViewContext and EmbedContext post tables to complete the contextual repository implementation. ViewContext table: - Includes most fields from EditContext - Excludes edit-only fields (password, permalink_template, generated_slug) - Excludes raw fields (guid_raw, title_raw, content_raw, content_block_version) - 29 columns total EmbedContext table: - Minimal fields for embedding posts in other content - Only includes: id, date, link, slug, post_type, title_rendered, author, excerpt fields, featured_media - 14 columns total Changes: - Add 0004-create-posts-view-context-table.sql migration - Add 0005-create-posts-embed-context-table.sql migration - Update MIGRATION_QUERIES array from 3 to 5 migrations - Includes proper indexes and foreign key constraints - Uses STRICT mode for type safety * Add integration tests with helper to verify column enum schema matching Added PRAGMA-based tests to catch mismatches between column enum definitions and actual database table schemas, with a reusable helper function to reduce test duplication. Implementation: - Add `get_table_column_names()` helper in test_fixtures.rs - Use helper to query actual column order from SQLite PRAGMA table_info - Verify each enum value maps to correct column name using `.as_index()` - Test the same code path production uses (ColumnIndex trait) - Verify total column count matches last enum value Benefits: - Catches column ordering bugs immediately in CI/CD - Reduces test duplication with shared helper function - Self-documenting: compares enum values against expected names - No runtime overhead: tests run during development only - Tests fail immediately if enums get out of sync with SQL All three context tests (Edit, View, Embed) now pass with real migrations. * Add upsert methods for ViewContext and EmbedContext with RETURNING optimization Implement write operations for view and embed contexts to complete the contextual repository pattern. Use SQLite's RETURNING clause to eliminate separate SELECT queries for rowid retrieval. Changes: - Add `upsert()` and `upsert_batch()` methods for ViewContext and EmbedContext - Refactor all three contexts (Edit/View/Embed) to use `RETURNING rowid` instead of separate SELECT statements - ViewContext syncs term relationships (categories and tags) - EmbedContext has no term relationships (minimal fields only) - Add test to verify bundled SQLite version supports RETURNING (3.50.2 >= 3.35.0) Performance improvements: - Eliminates 3 database round trips per upsert (one per context) - Safe for iOS and Android: rusqlite bundles SQLite 3.50.2 which includes RETURNING support * Remove unnecessary type re-exports from posts repository The re-exports created an alternative import path without adding semantic value. Types are already well-organized in db_types::posts module where consumers can import them directly. Keeping imports in a single canonical location improves code searchability. * Move PostContext trait to repository and update documentation Move entity-specific trait definitions to their repository modules for better organization. The context.rs module now contains only the generic IsContext trait and context marker types. Changes: - Move PostContext trait from context.rs to repository/posts.rs - Update context.rs to focus on generic infrastructure only - Rewrite ADDING_NEW_ENTITIES.md to be concise and accurate - Remove outdated references to CONTEXT_FIELD_ANALYSIS.md - Update trait method documentation to not assume all entities use term relationships - Add reminder to update platform test migration count assertions - Update Swift and Kotlin tests to expect 5 migrations (was 3) Documentation improvements: - Reduced from 487 lines to 86 lines - Focus on general process rather than exhaustive examples - Points to posts.rs as reference implementation - Clarifies that entity needs determine trait method signatures * Remove redundant wp_mobile_cache/CLAUDE.md The file contained outdated information referencing the old mappings/ structure and non-existent documentation files. The docs/ADDING_NEW_ENTITIES.md already serves as the canonical guide for implementing new entities. * Improve documentation example in get_table_column_names Update the example to demonstrate the correct usage pattern with column enum indices instead of hardcoded numeric indices. Changes: - Use `Rowid.as_index()` instead of `0` - Use `SiteId.as_index()` instead of `1` - Add import for `PostEditContextColumn` * Standardize error handling in wp_mobile_cache tests Replace unwrap().expect() pattern with expect().expect() for better error messages. The first expect() now handles Result errors with descriptive messages, while the second expect() handles Option types with context-specific messages. Changes: - Update posts.rs tests to use expect() with "Failed to select/read post..." messages - Update posts_constraint_tests.rs with descriptive Result error messages - Update posts_multi_site_tests.rs for consistency - Update posts_transaction_tests.rs for consistency * Extract SQLite version checking utilities for client use Add reusable functions for querying SQLite version and checking RETURNING support. Clients can now verify SQLite compatibility at runtime without duplicating logic. Changes: - Add `get_sqlite_version()` to query SQLite version via `QueryExecutor` - Add `does_sqlite_support_returning()` to check if version >= 3.35.0 - Refactor `test_bundled_sqlite_version_supports_returning` to use new utilities - Add unit test for version parsing with supported, unsupported, and invalid versions * Document minimum iOS 15 requirement for SQLite RETURNING support Add platform requirements note explaining that iOS 15 (SQLite 3.36.0) is the minimum supported version to ensure RETURNING clause compatibility. Changes: - Add platform requirements section in ADDING_NEW_ENTITIES.md - Link to YapDatabase wiki for SQLite version reference by OS
1 parent 0a7c437 commit 06885a8

File tree

19 files changed

+1389
-347
lines changed

19 files changed

+1389
-347
lines changed

native/kotlin/api/kotlin/src/integrationTest/kotlin/WordPressApiCacheTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class WordPressApiCacheTest {
1111

1212
@Test
1313
fun testThatMigrationsWork() = runTest {
14-
assertEquals(3, WordPressApiCache().performMigrations())
14+
assertEquals(5, WordPressApiCache().performMigrations())
1515
}
1616

1717
@Test

native/swift/Tests/wordpress-api-cache/WordPressApiCacheTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ actor Test {
1313

1414
@Test func testMigrationsWork() async throws {
1515
let migrationsPerformed = try await self.cache.performMigrations()
16-
#expect(migrationsPerformed == 3)
16+
#expect(migrationsPerformed == 5)
1717
}
1818

1919
#if !os(Linux)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Adding Database Support for New WordPress Entities
2+
3+
This guide explains how to add caching support for WordPress REST API entity types (posts, comments, users, etc.).
4+
5+
## Overview
6+
7+
WordPress REST API returns different fields based on the `context` parameter (`edit`, `view`, `embed`). Each context requires its own database table since field sets differ significantly.
8+
9+
**Architecture:**
10+
- `context.rs` - Generic `IsContext` trait and context marker types (EditContext, ViewContext, EmbedContext)
11+
- `db_types/{entity}/` - Column enums and wrapper structs (types only, no logic)
12+
- `repository/{entity}.rs` - Entity-specific trait definitions and all database operations
13+
14+
Use the existing `posts` implementation in `src/repository/posts.rs` as the primary reference.
15+
16+
## Discovering Context Fields
17+
18+
The `wp_api` crate uses procedural macros to generate context-specific types. To see what fields are actually available:
19+
20+
```bash
21+
# Generate expanded code for an entity
22+
cargo expand -p wp_api posts > /tmp/generated_posts.rs
23+
# or
24+
cargo expand -p wp_api comments > /tmp/generated_comments.rs
25+
```
26+
27+
Open the generated file and search for the context-specific types (e.g., `AnyPostWithEditContext`, `AnyPostWithViewContext`, `AnyPostWithEmbedContext`). Compare fields across contexts to understand what differs.
28+
29+
**Important**: Don't assume patterns - field availability varies by endpoint. Always verify against the expanded types.
30+
31+
## Implementation Steps
32+
33+
When adding a new entity type (e.g., implementing cache support for comments):
34+
35+
1. **Create type definitions** in `src/db_types/comments/`:
36+
- `mod.rs` - Re-exports
37+
- `edit.rs`, `view.rs`, `embed.rs` - One file per context
38+
- Each file contains: column enum (matching SQL table order) + database wrapper struct
39+
40+
2. **Define entity-specific trait and implement database logic** in `src/repository/comments.rs`:
41+
- Define `CommentContext` trait extending `IsContext` with associated types and row mapping method
42+
- The method signature depends on your entity's needs (e.g., posts use lazy closures for term loading)
43+
- Implement trait for each context (EditContext, ViewContext, EmbedContext)
44+
- Create generic `CommentRepository<C: CommentContext>`
45+
- Implement upsert methods for contexts that need write operations
46+
47+
3. **Create migrations** for each context table:
48+
- `migrations/NNNN-create-comments-edit-context-table.sql`
49+
- `migrations/NNNN-create-comments-view-context-table.sql`
50+
- `migrations/NNNN-create-comments-embed-context-table.sql`
51+
- Add to `MIGRATION_QUERIES` array in `lib.rs`
52+
- Update migration count assertions in platform test files:
53+
- `native/swift/Tests/wordpress-api-cache/WordPressApiCacheTests.swift`
54+
- `native/kotlin/api/kotlin/src/integrationTest/kotlin/WordPressApiCacheTest.kt`
55+
56+
4. **Add module exports** in `src/db_types/mod.rs`:
57+
```rust
58+
pub mod comments;
59+
```
60+
61+
5. **Write tests** in the repository file covering round-trip persistence and enum variants
62+
63+
## Key Design Decisions
64+
65+
**Column enum ordering**: Column indexes in the enum must match the exact order in SQL `CREATE TABLE` statements and all `SELECT *` queries. Add PRAGMA-based integration tests to verify this (see `test_post_edit_context_column_enum_matches_schema` in `repository/posts.rs` for reference).
66+
67+
**Lazy data loading**: If your entity requires optional related data (e.g., posts use term relationships for categories/tags), use `FnOnce()` closures in the trait method. This allows contexts that don't need the data to avoid unnecessary database queries by simply not calling the closure. See `PostContext::from_row_with_terms` for an example.
68+
69+
**Repository pattern**: All database operations belong in `repository/` - this includes both SQL execution AND row-to-type mapping logic. The `db_types/` module contains only type definitions.
70+
71+
**RETURNING optimization**: Use SQLite's `RETURNING rowid` clause in upsert statements to eliminate separate SELECT queries. Our bundled SQLite version (3.50.2) fully supports this.
72+
73+
**Platform requirements**: The minimum supported iOS version for this library is iOS 15, which bundles SQLite 3.36.0. This ensures RETURNING clause support (added in SQLite 3.35.0) across all target platforms. See [SQLite versions bundled with OS](https://github.com/yapstudios/YapDatabase/wiki/SQLite-version-(bundled-with-OS)) for reference.
74+
75+
## Reference Implementation
76+
77+
See `src/repository/posts.rs` for a complete working example including:
78+
- Context trait implementations with lazy closure pattern
79+
- Generic repository with context-specific methods
80+
- PRAGMA tests for column schema verification
81+
- Comprehensive test coverage
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
CREATE TABLE `posts_view_context` (
2+
-- Internal DB field (auto-incrementing)
3+
`rowid` INTEGER PRIMARY KEY AUTOINCREMENT,
4+
5+
-- Site identifier (foreign key to sites table)
6+
`db_site_id` INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
7+
8+
-- Top-level non-nullable fields
9+
`id` INTEGER NOT NULL,
10+
`date` TEXT NOT NULL,
11+
`date_gmt` TEXT NOT NULL,
12+
`link` TEXT NOT NULL,
13+
`modified` TEXT NOT NULL,
14+
`modified_gmt` TEXT NOT NULL,
15+
`slug` TEXT NOT NULL,
16+
`status` TEXT NOT NULL,
17+
`post_type` TEXT NOT NULL,
18+
`template` TEXT NOT NULL,
19+
20+
-- Top-level optional fields
21+
`author` INTEGER,
22+
`featured_media` INTEGER,
23+
`sticky` INTEGER,
24+
`parent` INTEGER,
25+
`menu_order` INTEGER,
26+
27+
-- Optional enums (stored as TEXT)
28+
`comment_status` TEXT,
29+
`ping_status` TEXT,
30+
`format` TEXT,
31+
32+
-- Complex optional fields (JSON)
33+
`meta` TEXT,
34+
35+
-- Nested: guid (only rendered field in view context)
36+
`guid_rendered` TEXT NOT NULL,
37+
38+
-- Nested: title (only rendered field in view context)
39+
`title_rendered` TEXT NOT NULL,
40+
41+
-- Nested: content (only rendered and protected fields in view context)
42+
`content_rendered` TEXT NOT NULL,
43+
`content_protected` INTEGER,
44+
45+
-- Nested: excerpt (entire struct is optional)
46+
`excerpt_raw` TEXT,
47+
`excerpt_rendered` TEXT,
48+
`excerpt_protected` INTEGER,
49+
50+
-- Client-side cache metadata: when this post was last fetched from the WordPress API
51+
`last_fetched_at` TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
52+
53+
FOREIGN KEY (db_site_id) REFERENCES sites(id) ON DELETE CASCADE
54+
) STRICT;
55+
56+
CREATE UNIQUE INDEX idx_posts_view_context_unique_db_site_id_and_id ON posts_view_context(db_site_id, id);
57+
CREATE INDEX idx_posts_view_context_db_site_id ON posts_view_context(db_site_id);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
CREATE TABLE `posts_embed_context` (
2+
-- Internal DB field (auto-incrementing)
3+
`rowid` INTEGER PRIMARY KEY AUTOINCREMENT,
4+
5+
-- Site identifier (foreign key to sites table)
6+
`db_site_id` INTEGER NOT NULL REFERENCES sites(id) ON DELETE CASCADE,
7+
8+
-- Top-level non-nullable fields (minimal set for embed context)
9+
`id` INTEGER NOT NULL,
10+
`date` TEXT NOT NULL,
11+
`link` TEXT NOT NULL,
12+
`slug` TEXT NOT NULL,
13+
`post_type` TEXT NOT NULL,
14+
15+
-- Nested: title (only rendered field in embed context)
16+
`title_rendered` TEXT NOT NULL,
17+
18+
-- Top-level optional fields
19+
`author` INTEGER,
20+
21+
-- Nested: excerpt (entire struct is optional)
22+
`excerpt_raw` TEXT,
23+
`excerpt_rendered` TEXT,
24+
`excerpt_protected` INTEGER,
25+
26+
-- Featured media
27+
`featured_media` INTEGER,
28+
29+
-- Client-side cache metadata: when this post was last fetched from the WordPress API
30+
`last_fetched_at` TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
31+
32+
FOREIGN KEY (db_site_id) REFERENCES sites(id) ON DELETE CASCADE
33+
) STRICT;
34+
35+
CREATE UNIQUE INDEX idx_posts_embed_context_unique_db_site_id_and_id ON posts_embed_context(db_site_id, id);
36+
CREATE INDEX idx_posts_embed_context_db_site_id ON posts_embed_context(db_site_id);

wp_mobile_cache/src/context.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/// Base trait for WordPress REST API context types.
2+
///
3+
/// This trait is entity-agnostic and only handles table naming and context identification.
4+
/// Entity-specific traits (e.g., PostContext) are defined in their respective repository modules.
5+
pub trait IsContext: 'static + Copy {
6+
/// The context suffix used in table names.
7+
///
8+
/// # Example
9+
/// ```
10+
/// // EditContext::context_suffix() => "edit"
11+
/// // ViewContext::context_suffix() => "view"
12+
/// // EmbedContext::context_suffix() => "embed"
13+
/// ```
14+
fn context_suffix() -> &'static str;
15+
16+
/// The WpContext enum variant for this context.
17+
fn wp_context() -> wp_api::WpContext;
18+
19+
/// Generate the full table name for a given entity type prefix.
20+
///
21+
/// # Example
22+
/// ```
23+
/// // EditContext::table_name("posts") => "posts_edit_context"
24+
/// // EditContext::table_name("comments") => "comments_edit_context"
25+
/// ```
26+
fn table_name(prefix: &str) -> String {
27+
format!("{}_{}_context", prefix, Self::context_suffix())
28+
}
29+
}
30+
31+
/// Marker type for Edit context
32+
#[derive(Debug, Clone, Copy)]
33+
pub struct EditContext;
34+
35+
/// Marker type for View context
36+
#[derive(Debug, Clone, Copy)]
37+
pub struct ViewContext;
38+
39+
/// Marker type for Embed context
40+
#[derive(Debug, Clone, Copy)]
41+
pub struct EmbedContext;
42+
43+
// Implement base IsContext trait for each marker type
44+
impl IsContext for EditContext {
45+
fn context_suffix() -> &'static str {
46+
"edit"
47+
}
48+
49+
fn wp_context() -> wp_api::WpContext {
50+
wp_api::WpContext::Edit
51+
}
52+
}
53+
54+
impl IsContext for ViewContext {
55+
fn context_suffix() -> &'static str {
56+
"view"
57+
}
58+
59+
fn wp_context() -> wp_api::WpContext {
60+
wp_api::WpContext::View
61+
}
62+
}
63+
64+
impl IsContext for EmbedContext {
65+
fn context_suffix() -> &'static str {
66+
"embed"
67+
}
68+
69+
fn wp_context() -> wp_api::WpContext {
70+
wp_api::WpContext::Embed
71+
}
72+
}
73+
74+
#[cfg(test)]
75+
mod tests {
76+
use super::*;
77+
78+
#[test]
79+
fn test_table_name_generation() {
80+
assert_eq!(EditContext::table_name("posts"), "posts_edit_context");
81+
assert_eq!(ViewContext::table_name("posts"), "posts_view_context");
82+
assert_eq!(EmbedContext::table_name("posts"), "posts_embed_context");
83+
84+
assert_eq!(EditContext::table_name("comments"), "comments_edit_context");
85+
assert_eq!(ViewContext::table_name("comments"), "comments_view_context");
86+
}
87+
88+
#[test]
89+
fn test_context_suffix() {
90+
assert_eq!(EditContext::context_suffix(), "edit");
91+
assert_eq!(ViewContext::context_suffix(), "view");
92+
assert_eq!(EmbedContext::context_suffix(), "embed");
93+
}
94+
95+
#[test]
96+
fn test_wp_context() {
97+
assert_eq!(EditContext::wp_context(), wp_api::WpContext::Edit);
98+
assert_eq!(ViewContext::wp_context(), wp_api::WpContext::View);
99+
assert_eq!(EmbedContext::wp_context(), wp_api::WpContext::Embed);
100+
}
101+
}

wp_mobile_cache/src/db_types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod posts;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::{DbSite, RowId, mappings::ColumnIndex};
2+
use wp_api::posts::AnyPostWithEditContext;
3+
4+
/// Column indexes for posts_edit_context table.
5+
/// These must match the order of columns in the CREATE TABLE statement.
6+
#[repr(usize)]
7+
#[derive(Debug, Clone, Copy)]
8+
pub(crate) enum PostEditContextColumn {
9+
Rowid = 0,
10+
SiteId = 1,
11+
Id = 2,
12+
Date = 3,
13+
DateGmt = 4,
14+
Link = 5,
15+
Modified = 6,
16+
ModifiedGmt = 7,
17+
Slug = 8,
18+
Status = 9,
19+
PostType = 10,
20+
Password = 11,
21+
Template = 12,
22+
PermalinkTemplate = 13,
23+
GeneratedSlug = 14,
24+
Author = 15,
25+
FeaturedMedia = 16,
26+
Sticky = 17,
27+
Parent = 18,
28+
MenuOrder = 19,
29+
CommentStatus = 20,
30+
PingStatus = 21,
31+
Format = 22,
32+
Meta = 23,
33+
GuidRaw = 24,
34+
GuidRendered = 25,
35+
TitleRaw = 26,
36+
TitleRendered = 27,
37+
ContentRaw = 28,
38+
ContentRendered = 29,
39+
ContentProtected = 30,
40+
ContentBlockVersion = 31,
41+
ExcerptRaw = 32,
42+
ExcerptRendered = 33,
43+
ExcerptProtected = 34,
44+
LastFetchedAt = 35,
45+
}
46+
47+
impl ColumnIndex for PostEditContextColumn {
48+
fn as_index(&self) -> usize {
49+
*self as usize
50+
}
51+
}
52+
53+
pub struct DbAnyPostWithEditContext {
54+
pub row_id: RowId,
55+
pub site: DbSite,
56+
pub post: AnyPostWithEditContext,
57+
pub last_fetched_at: String,
58+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use crate::{DbSite, RowId, mappings::ColumnIndex};
2+
use wp_api::posts::AnyPostWithEmbedContext;
3+
4+
/// Column indexes for posts_embed_context table.
5+
/// These must match the order of columns in the CREATE TABLE statement.
6+
#[repr(usize)]
7+
#[derive(Debug, Clone, Copy)]
8+
pub(crate) enum PostEmbedContextColumn {
9+
Rowid = 0,
10+
SiteId = 1,
11+
Id = 2,
12+
Date = 3,
13+
Link = 4,
14+
Slug = 5,
15+
PostType = 6,
16+
TitleRendered = 7,
17+
Author = 8,
18+
ExcerptRaw = 9,
19+
ExcerptRendered = 10,
20+
ExcerptProtected = 11,
21+
FeaturedMedia = 12,
22+
LastFetchedAt = 13,
23+
}
24+
25+
impl ColumnIndex for PostEmbedContextColumn {
26+
fn as_index(&self) -> usize {
27+
*self as usize
28+
}
29+
}
30+
31+
pub struct DbAnyPostWithEmbedContext {
32+
pub row_id: RowId,
33+
pub site: DbSite,
34+
pub post: AnyPostWithEmbedContext,
35+
pub last_fetched_at: String,
36+
}

0 commit comments

Comments
 (0)