ideasonpurpose / wp-data-model
Base package for building data models for WordPress sites
Requires
- doctrine/inflector: 2.0.8
- ideasonpurpose/wp-admin-separators: 1.0.8
Requires (Dev)
- ideasonpurpose/wp-test-stubs: dev-main
- kint-php/kint: ^5
- phpunit/phpunit: ^10.2
- dev-master
- v0.7.6
- v0.7.5
- v0.7.4
- v0.7.3
- v0.7.2
- v0.7.1
- v0.7.0
- v0.6.0
- v0.5.3
- v0.5.2
- v0.5.1
- v0.5.0
- 0.4.3
- 0.4.2
- 0.4.1
- 0.4.0
- 0.3.0
- 0.2.7
- 0.2.6
- 0.2.5
- 0.2.4
- 0.2.3
- 0.2.2
- 0.2.1
- 0.2.0
- v0.1.2
- dev-dependabot/npm_and_yarn/minimist-1.2.8
- dev-dependabot/npm_and_yarn/json5-2.2.3
- dev-dependabot/npm_and_yarn/ansi-regex-4.1.1
- dev-dependabot/npm_and_yarn/node-fetch-2.6.7
- dev-dependabot/npm_and_yarn/tmpl-1.0.5
- dev-dependabot/npm_and_yarn/path-parse-1.0.7
This package is auto-updated.
Last update: 2024-11-12 18:10:31 UTC
README
Version 0.7.6
Base package for building data model plugins for WordPress sites at Ideas On Purpose.
Example data-model Plugin
To start a new data-model plugin, copy the example directory. Create new CPTs and Taxonomies in the lib subdirectory, then instantiate those from main.php. Connect Taxonomies to Post Types with a taxonomyMap
and rename built-in Post Types and Taxonomies with static calls to WP\Rename
.
Create Custom Post Types and Taxonomies
New Custom Post_Types are created as PHP classes which extend IdeasOnPurpose\WP\CPT
, new Taxonomies extend IdeasOnPurpose\WP\Taxonomy
. All new classes should include a props
method which defines $this->args
.
Taxonomy Maps and post_type assignment
The main.php file connects post_types to taxonomies using an array-map where each key is a single taxonomy and each value is an array of post_types to attach to. An example looks like this:
// main.php $this->taxonomyMap = [ "category" => ["post", "policy", "help"], "audience" => ["post", "help", "event"], "fellowship" => ["event"], ];
Separators
Call new WP\Admin\Separators(22, 26)
with a list of indexes to insert separators into the menu. Matching indexes will insert the separator after the CPT, so the following code will show Events with a separator directly below it:
new CPT\Article(23); new WP\Admin\Separators(23);
Admin CSS
New Post_Types and Taxonomies can add specific CSS Rules to the WordPress admin by defining a $css
property.
Generating Labels
A default set of labels can be generated from WP\DataModel::postTypeLabels()
and WP\DataModel::taxonomyLabels()
. These are often used to populate the labels
value of the $args
property when defining a new Post_Type or Taxonomy.
Arguments are:
$labelBase
String The base name of the label. This will be inflected and case-corrected to match WordPress defaults.$inflect
[Boolean], defaulttrue
A boolean switch to enable singular/plural inflection of$labelBase
.$overrides
[Array], default:[]
An array of labels which will override the generated defaults post_type and taxonomy labels.
WordPress Compatibility
WordPress reports a tested
value describing the latest version the plugin was developed and tested on. This value is auto-generated before the package.json version script runs. Tested values are collected from the WordPress Stable-Check API and stored in assets/tested.json.
Renaming Built-in Post Types and Taxonomies
Built-in post_types and taxonomies can be easily renamed. The DataModel object adds a static function to the WP namespace which can be called like this:
WP\Rename::post("topic"); // rename Posts to Topics WP\Rename::category("colors"); // Rename Categories to Colors WP\Rename::tag("flavors", ["popular_items" => "Most delicious flavors"]); // Rename Tags to Flavors with an override label
DataModel will normalize singular and plural terms and capitalization to match WordPress best practices. For non-standard uses, supply override labels.
tag
is an alias for post_tag
, both can be used.
Renaming only affects the labels of built in Types and Taxonomies, internal query_vars are unchanged.
Why a static call?
Renaming via a static call was a deliberate choice. Unlike creating a new CPT or Taxonomy, renaming does not create anything new, so a new
invocation wouldn't make sense, even though it would parallel existing syntax.
Calling new CPT
or new Taxonomy
makes sense because those commands create something new. For renaming, the command acts on something which already exists, so the invocation syntax would be inconsistent with the performed action.
The syntax for renaming can often be achieved in a single line whereas creating new CPTs or Taxonomies usually requires defining additional actions and filters.
Composer Updates
The Docker Compose Composer service will mount and use local auth credentials if they exist in ~/.composer/auth.json. If those credentials don't exist and Composer hits an API rate limit, pasting a token will create a new auth.json file in the mount which with persist on the host system.
Nav-Menu Visibility
The plugin will automatically set all custom Taxonomies and CPTs to be visible by default in the WordPress Nav-Menu Admin for new user accounts. Previously, users had to remember to open Screen Options and enable each component of the data model.
If you'd like to reset nav-menu visibility for all existing user accounts, run this to clear previous entries from the user_meta table.
DELETE FROM `wp_usermeta` WHERE `meta_key` = "metaboxhidden_nav-menus";
Automatic plugin updates and AWS
Whenever a new version is pushed, a GitHub Action runs which compiles and packages the project, then pushes the versioned asset to one of our AWS S3 buckets. A lambda microservice handles queries from the plugin and enables native WordPress plugin updates for new versions.
AWS Lambda
The aws directory contains the lambda function which handles update requests from the WordPress Admin Plugins page for each installed plugin.
Lambda function updates must be manually triggered by calling npm run lambda:deploy
.
Changelog, Description and Banners
Assets should be stored in the project and be uploaded to a directory matching the plugin basename
The README.md and CHANGELOG.md files will be used to populate details in the WordPress plugin admin interface. The Changelog is auto-generated.
Notes
- The wp-update-handler lambda function lives in AWS region
us-east-2
. - AWS lambda functions run on node v14, run
nvm use 14
beforenpm install
to ensure package compatibility. - AWS Credentials should be created from IAM > Users > Security Credentials for user iop-cams. Duplicate .env.sample and update the values in that file
- AWS API-Gateway now references the lambda using
$LATEST
instead of a published version to make deploying updates simpler. The Lambda Function setting is found in the API Gateway Resource's POST - Integration Request options - Use this link to switch to the correct organization account role: AWS Login
GitHub Actions
The publish-to-aws GitHub Action (part of the example plugin) will build the plugin and push the artifact to our S3 updates bucket. Each project will need to define two GitHub Secrets for accessing AWS, these names are found in the env
section at the top of the example/.github/workflows/publish-to-aws.yml file:
env: S3_URI: s3://ideasonpurpose-wp-updates AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Testing plugin updates
Our WordPress Updates AWS endpoint can be tested by sending a POST request with a raw JSON body which looks something like this:
{ "version": "0.0.1", "slug": "example-data-model", "plugin": "example-data-model/main.php" }
Default Post_Type and Taxonomy Labels
Default labels can be extracted from WordPress by dumping the global $wp_post_types[$type]->labels
and $wp_taxonomies[$taxonomy]->labels
objects. WordPress defines labels as an Array, but stores them as an object. Posts and Pages overlap cleanly, Tags and Categories include special-cases for hierarchical display.
// Default Page labels [ "name" => "Pages", "singular_name" => "Page", "add_new" => "Add New", "add_new_item" => "Add New Page", "edit_item" => "Edit Page", "new_item" => "New Page", "view_item" => "View Page", "view_items" => "View Pages", "search_items" => "Search Pages", "not_found" => "No pages found.", "not_found_in_trash" => "No pages found in Trash.", "parent_item_colon" => "Parent Page:", "all_items" => "All Pages", "archives" => "Page Archives", "attributes" => "Page Attributes", "insert_into_item" => "Insert into page", "uploaded_to_this_item" => "Uploaded to this page", "featured_image" => "Featured image", "set_featured_image" => "Set featured image", "remove_featured_image" => "Remove featured image", "use_featured_image" => "Use as featured image", "filter_items_list" => "Filter pages list", "filter_by_date" => "Filter by date", "items_list_navigation" => "Pages list navigation", "items_list" => "Pages list", "item_published" => "Page published.", "item_published_privately" => "Page published privately.", "item_reverted_to_draft" => "Page reverted to draft.", "item_scheduled" => "Page scheduled.", "item_updated" => "Page updated.", "menu_name" => "Pages", "name_admin_bar" => "Page", ];
// Default Category labels [ "name" => "Categories", "singular_name" => "Category", "search_items" => "Search Categories", "popular_items" => null, "all_items" => "All Categories", "parent_item" => "Parent Category", "parent_item_colon" => "Parent Category:", "edit_item" => "Edit Category", "view_item" => "View Category", "update_item" => "Update Category", "add_new_item" => "Add New Category", "new_item_name" => "New Category Name", "separate_items_with_commas" => null, "add_or_remove_items" => null, "choose_from_most_used" => null, "not_found" => "No categories found.", "no_terms" => "No categories", "filter_by_item" => "Filter by category", "items_list_navigation" => "Categories list navigation", "items_list" => "Categories list", "most_used" => "Most Used", "back_to_items" => "← Go to Categories", "menu_name" => "Categories", "name_admin_bar" => "category", ];
// Default Tag (post_tag) labels [ "name" => "Tags", "singular_name" => "Tag", "search_items" => "Search Tags", "popular_items" => "Popular Tags", "all_items" => "All Tags", "parent_item" => null, "parent_item_colon" => null, "edit_item" => "Edit Tag", "view_item" => "View Tag", "update_item" => "Update Tag", "add_new_item" => "Add New Tag", "new_item_name" => "New Tag Name", "separate_items_with_commas" => "Separate tags with commas", "add_or_remove_items" => "Add or remove tags", "choose_from_most_used" => "Choose from the most used tags", "not_found" => "No tags found.", "no_terms" => "No tags", "filter_by_item" => null, "items_list_navigation" => "Tags list navigation", "items_list" => "Tags list", "most_used" => "Most Used", "back_to_items" => "← Go to Tags", "menu_name" => "Tags", "name_admin_bar" => "post_tag", ];
Brought to you by IOP
This project is actively developed and used in production at Ideas On Purpose.