arraypress / wp-post-utils
A lean WordPress library for working with posts and post operations
dev-main
2025-07-13 14:19 UTC
Requires
- php: >=7.4
This package is auto-updated.
Last update: 2025-09-02 14:54:38 UTC
README
A lightweight WordPress library for working with posts and post operations. Provides clean APIs for post retrieval, content management, meta operations, and bulk actions with value/label formatting perfect for forms and admin interfaces.
Features
- 🎯 Clean API: WordPress-style snake_case methods with consistent interfaces
- 🔍 Built-in Search: Post search with value/label formatting for forms
- 📋 Form-Ready Options: Perfect value/label arrays for selects and admin interfaces
- 🔗 Term Management: Easy term assignment and relationship management
- 📊 Meta Operations: Simple post meta handling with type safety
- 🎨 Flexible Identifiers: Use IDs, slugs, titles, or objects interchangeably
- ⚡ Bulk Operations: Efficient bulk status changes, deletions, and updates
- ➕ Post Creation: Create single or multiple posts with flexible options
Requirements
- PHP 7.4 or later
- WordPress 5.0 or later
Installation
composer require arraypress/wp-post-utils
Basic Usage
Working with Single Posts
use ArrayPress\PostUtils\Post; // Get post by ID $post = Post::get( 123 ); // Get post by identifier (ID, slug, or title) $post = Post::get_by_identifier( 'hello-world' ); $post = Post::get_by_slug( 'hello-world' ); $post = Post::get_by_title( 'Hello World' ); // Check if post exists if ( Post::exists( 123 ) ) { // Post exists } // Create a new post $post = Post::create( 'My New Post', 'This is the content' ); // Create post with additional data $post = Post::create( 'My New Post', 'Content here', [ 'post_type' => 'page', 'post_status' => 'draft', 'post_author' => 5, 'meta_input' => [ 'custom_field' => 'value' ] ] ); // Create post only if it doesn't exist $post = Post::create_if_not_exists( 'Unique Title', 'Content' ); // Get post content and meta $title = Post::get_title( 123 ); $content = Post::get_content( 123 ); $excerpt = Post::get_excerpt( 123 ); $url = Post::get_url( 123 ); $slug = Post::get_slug( 123 ); $type = Post::get_type( 123 ); // Get author information $author_id = Post::get_author_id( 123 ); $author = Post::get_author( 123 ); // Returns WP_User object // Get post meta $meta_value = Post::get_meta( 123, 'custom_field' ); $meta_with_default = Post::get_meta_with_default( 123, 'priority', 'normal' ); // Check post status and conditions if ( Post::is_published( 123 ) ) { // Post is published } if ( Post::is_draft( 123 ) ) { // Post is draft } if ( Post::is_scheduled( 123 ) ) { // Post is scheduled } if ( Post::is_type( 123, 'page' ) ) { // Post is a page } if ( Post::is_type( 123, [ 'post', 'custom_post' ] ) ) { // Post is either a post or custom_post } if ( Post::has_thumbnail( 123 ) ) { $thumbnail = Post::get_thumbnail_url( 123 ); } if ( Post::has_content( 123 ) ) { // Post has content } if ( Post::has_excerpt( 123 ) ) { // Post has manual excerpt } if ( Post::is_sticky( 123 ) ) { // Post is sticky } if ( Post::allows_comments( 123 ) ) { $comment_count = Post::get_comment_count( 123 ); } // Content analysis $words = Post::count_words( 123 ); $reading_time = Post::get_reading_time( 123 ); // minutes $age_days = Post::get_age( 123 ); // Post management Post::update_status( 123, 'draft' ); Post::trash( 123 ); Post::delete( 123, true ); // force delete // Dates $date = Post::get_date( 123, 'Y-m-d' ); $modified = Post::get_modified_date( 123 );
Working with Multiple Posts
<?php use ArrayPress\PostUtils\Posts; // Get multiple posts $posts = Posts::get( [ 1, 2, 3 ] ); $posts = Posts::get( [ 1, 2, 3 ], 'page' ); // Specific post type // Create multiple posts $result = Posts::create( [ [ 'post_title' => 'First Post', 'post_content' => 'Content for first post', 'post_type' => 'post' ], [ 'post_title' => 'Second Post', 'post_content' => 'Content for second post', 'post_type' => 'page' ] ] ); // Create posts with shared defaults $result = Posts::create( [ [ 'post_title' => 'Post One', 'post_content' => 'Content one' ], [ 'post_title' => 'Post Two', 'post_content' => 'Content two' ] ], [ 'post_type' => 'custom_post', 'post_status' => 'draft', 'post_author' => 5 ] ); // Create posts only if they don't exist $result = Posts::create_if_not_exists( [ [ 'post_title' => 'About Us', 'post_type' => 'page' ], [ 'post_title' => 'Contact', 'post_type' => 'page' ] ] ); // Check results if ( ! empty( $result['created'] ) ) { foreach ( $result['created'] as $post ) { echo "Created post: " . $post->post_title . "\n"; } } if ( ! empty( $result['existing'] ) ) { foreach ( $result['existing'] as $post ) { echo "Post already exists: " . $post->post_title . "\n"; } } if ( ! empty( $result['errors'] ) ) { foreach ( $result['errors'] as $error ) { echo "Error: " . $error . "\n"; } } // Get posts by identifiers $post_ids = Posts::get_by_identifiers( [ 'hello-world', 'about-us' ] ); $post_objects = Posts::get_by_identifiers( [ 'hello-world', 'about-us' ], 'any', true ); // Search posts and get options $options = Posts::search_options( 'technology' ); // Returns: [['value' => 1, 'label' => 'Tech Article'], ...] // Get all posts as options $all_options = Posts::get_options( 'post' ); // Returns: [1 => 'Hello World', 2 => 'About Us', ...] // Get posts by author or date range $author_posts = Posts::get_by_author( 5 ); $recent_posts = Posts::get_recent( 10 ); $range_posts = Posts::get_by_date_range( '2024-01-01', '2024-12-31' );
Post Creation Examples
// Plugin activation - create default pages function create_default_pages() { $default_pages = [ [ 'post_title' => 'Privacy Policy', 'post_content' => 'Your privacy policy content here.', 'post_type' => 'page', 'post_status' => 'publish' ], [ 'post_title' => 'Terms of Service', 'post_content' => 'Your terms of service content here.', 'post_type' => 'page', 'post_status' => 'publish' ] ]; $result = Posts::create_if_not_exists( $default_pages ); // Log creation results error_log( sprintf( 'Created %d pages, %d already existed', count( $result['created'] ), count( $result['existing'] ) ) ); } // Import posts from external data function import_posts_from_data( $posts_data ) { $posts = []; foreach ( $posts_data as $data ) { $posts[] = [ 'post_title' => $data['title'], 'post_content' => $data['content'], 'post_type' => $data['type'] ?? 'post', 'post_status' => $data['status'] ?? 'publish', 'meta_input' => $data['meta'] ?? [] ]; } return Posts::create( $posts, [ 'post_author' => get_current_user_id() ] ); } // Create test content for development function create_test_content() { $test_posts = [ 'Sample Blog Post' => 'This is a sample blog post for testing.', 'About Page' => 'This is the about page content.', 'Contact Page' => 'Contact us at info@example.com' ]; $posts_data = []; foreach ( $test_posts as $title => $content ) { $posts_data[] = [ 'post_title' => $title, 'post_content' => $content, 'post_type' => str_contains( $title, 'Page' ) ? 'page' : 'post' ]; } return Posts::create_if_not_exists( $posts_data ); }
Meta Operations
// Get meta with default $value = Post::get_meta_with_default( 123, 'priority', 'normal' ); // Update meta only if changed Post::update_meta_if_changed( 123, 'status', 'updated' ); // Delete meta Post::delete_meta( 123, 'old_field' );
Bulk Operations
// Change status for multiple posts $results = Posts::change_status( [ 1, 2, 3 ], 'draft' ); // Trash multiple posts $results = Posts::trash( [ 1, 2, 3 ] ); // Delete permanently $results = Posts::delete( [ 1, 2, 3 ], true ); // Change author $results = Posts::change_author( [ 1, 2, 3 ], 5 ); // Check results foreach ( $results as $post_id => $success ) { if ( $success ) { echo "Successfully updated post {$post_id}\n"; } else { echo "Failed to update post {$post_id}\n"; } }
Hierarchy Operations
// Parent-child relationships $parent_id = Post::get_parent_id( 123 ); $children = Post::get_children( 123 ); if ( Post::is_child_of( 123, 456 ) ) { // Post 123 is child of 456 } // Get children with custom args $child_pages = Post::get_children( 123, [ 'post_status' => [ 'publish', 'private' ], 'orderby' => 'title', 'order' => 'ASC' ] );
Search Functionality
// Basic search $results = Posts::search( 'wordpress' ); // Search with specific post types $results = Posts::search( 'wordpress', [ 'post', 'page' ] ); // Search with additional arguments $results = Posts::search( 'technology', [ 'post' ], [ 'posts_per_page' => 10, 'meta_key' => 'featured', 'meta_value' => '1' ] ); // Get search results as options for forms $options = Posts::search_options( 'admin' );
API Reference
Post Class (Single Posts)
Core Retrieval:
get( int $post_id ): ?WP_Post
get_by_identifier( $identifier, $post_type = 'any', $post_status = 'publish' ): ?WP_Post
get_by_slug( string $slug, $post_type = 'post' ): ?WP_Post
get_by_title( string $title, $post_type = 'post' ): ?WP_Post
get_by_meta( string $meta_key, $meta_value, $post_type = 'post' ): ?WP_Post
exists( int $post_id ): bool
Creation:
create( string $title, string $content = '', array $args = [] ): ?WP_Post
create_if_not_exists( string $title, string $content = '', array $args = [] ): ?WP_Post
Content & Basic Info:
get_title( int $post_id, bool $raw = false ): string
get_content( int $post_id, bool $raw = false ): string
get_excerpt( int $post_id, bool $raw = false ): string
get_url( int $post_id ): string|false
get_slug( int $post_id ): ?string
get_type( int $post_id ): string|false
get_field( int $post_id, string $field )
get_thumbnail_url( int $post_id ): string|false
Author:
get_author_id( int $post_id ): ?int
get_author( int $post_id ): ?WP_User
Content Analysis:
count_words( int $post_id ): int
get_reading_time( int $post_id, int $words_per_minute = 200 ): int
Meta Operations:
get_meta( int $post_id, string $key, bool $single = true )
get_meta_with_default( int $post_id, string $meta_key, $default )
update_meta_if_changed( int $post_id, string $meta_key, $meta_value ): bool
delete_meta( int $post_id, string $meta_key ): bool
Status & Conditionals:
get_status( int $post_id ): string|false
is_published( int $post_id ): bool
is_draft( int $post_id ): bool
is_private( int $post_id ): bool
is_scheduled( int $post_id ): bool
is_sticky( int $post_id ): bool
is_type( int $post_id, string|array $post_type ): bool
has_content( int $post_id ): bool
has_excerpt( int $post_id ): bool
has_password( int $post_id ): bool
has_thumbnail( int $post_id ): bool
allows_comments( int $post_id ): bool
Dates & Analysis:
get_date( int $post_id, string $format = 'Y-m-d H:i:s' ): string|false
get_modified_date( int $post_id, string $format = 'Y-m-d H:i:s' ): string|false
get_age( int $post_id, bool $use_modified_date = false ): int|false
get_comment_count( int $post_id ): int
Hierarchy:
get_parent_id( int $post_id ): int
is_child_of( int $post_id, int $parent_id ): bool
get_children( int $post_id, array $args = [] ): array
Actions:
update_status( int $post_id, string $new_status ): bool
trash( int $post_id ): bool
delete( int $post_id, bool $force = false ): bool
Posts Class (Multiple Posts)
Core Retrieval:
get( array $post_ids, $post_type = 'any', array $args = [] ): array
get_by_identifiers( array $identifiers, $post_type = 'any', bool $return_objects = false ): array
get_by_author( int $author_id, array $args = [] ): array
get_recent( int $number = 5, array $args = [] ): array
get_by_date_range( string $start_date, string $end_date, array $args = [] ): array
Creation:
create( array $posts, array $defaults = [] ): array
create_if_not_exists( array $posts, array $defaults = [] ): array
Search & Options:
search( string $search, array $post_types = ['post'], array $args = [] ): array
search_options( string $search, array $post_types = ['post'], array $args = [] ): array
get_options( $post_type = 'post', array $args = [] ): array
Bulk Actions:
change_status( array $post_ids, string $new_status ): array
change_author( array $post_ids, int $new_author ): array
trash( array $post_ids ): array
delete( array $post_ids, bool $force = false ): array
Key Features
- Value/Label Format: Perfect for forms and selects
- Search Functionality: Built-in post search with formatting
- Post Creation: Create single or multiple posts with validation
- Bulk Operations: Efficient multi-post management
- Meta Handling: Simple and safe meta operations
- Flexible Identifiers: Use IDs, slugs, titles, or objects interchangeably
- Content Analysis: Word counts, reading time, age calculations
- Hierarchy Support: Parent-child relationship management
- Type Checking: Flexible post type validation with single or multiple types
Requirements
- PHP 7.4+
- WordPress 5.0+
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the GPL-2.0-or-later License.