diff --git a/.gitignore b/.gitignore
index 7506fef..4b44d2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/vendor
.phpunit.result.cache
coverage.xml
+/coverage
diff --git a/README.md b/README.md
index 782016a..b9443ba 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
## Requirements
-* PHP >=7.2
+* PHP >=8.1
* [Composer](https://getcomposer.org/)
-* [WordPress](https://wordpress.org) >=5.1
+* [WordPress](https://wordpress.org) >=6.3
## Installation
@@ -20,64 +20,123 @@ Run the following in your terminal to install PostTypes with [Composer](https://
$ composer require jjgrainger/posttypes
```
-PostTypes uses [PSR-4](https://www.php-fig.org/psr/psr-4/) autoloading and can be used with the Composer's autoloader. Below is a basic example of getting started, though your setup may be different depending on how you are using Composer.
-
-```php
-require __DIR__ . '/vendor/autoload.php';
-
-use PostTypes\PostType;
-
-$books = new PostType( 'book' );
-
-$books->register();
-```
-
-See Composer's [basic usage](https://getcomposer.org/doc/01-basic-usage.md#autoloading) guide for details on working with Composer and autoloading.
+PostTypes uses [PSR-4](https://www.php-fig.org/psr/psr-4/) autoloading and can be used with the Composer's autoloader. See Composer's [basic usage](https://getcomposer.org/doc/01-basic-usage.md#autoloading) guide for details on working with Composer and autoloading.
## Basic Usage
-Below is a basic example of setting up a simple book post type with a genre taxonomy. For more information, check out the [online documentation here](https://posttypes.jjgrainger.co.uk).
+#### Create a custom post type
+
+Custom post types are defined as classes that extend the base `PostType` class. At a minimum, the `name` method must be implemented to define the post type slug. All other methods are optional and allow you to configure labels, options, taxonomies, admin columns, filters, and more as needed.
```php
-// Require the Composer autoloader.
-require __DIR__ . '/vendor/autoload.php';
+ __( 'Book', 'text-domain' ),
+ 'singular_name' => __( 'Book', 'text-domain' ),
+ 'menu_name' => __( 'Books', 'text-domain' ),
+ 'all_items' => __( 'Books', 'text-domain' ),
+ 'add_new' => __( 'Add New', 'text-domain' ),
+ 'add_new_item' => __( 'Add New Book', 'text-domain' ),
+ 'edit_item' => __( 'Edit Book', 'text-domain' ),
+ 'new_item' => __( 'New Book', 'text-domain' ),
+ 'view_item' => __( 'View Book', 'text-domain' ),
+ 'search_items' => __( 'Search Books', 'text-domain' ),
+ 'not_found' => __( 'No Books found', 'text-domain' ),
+ 'not_found_in_trash' => __( 'No Books found in Trash', 'text-domain'),
+ 'parent_item_colon' => __( 'Parent Book', 'text-domain' ),
+ ];
+ }
+
+ /**
+ * Define Post Type feature supports.
+ */
+ public function supports(): array {
+ return [
+ 'title',
+ 'editor',
+ 'thumbnail',
+ 'custom-fields'
+ ];
+ }
+
+ /**
+ * Define Taxonomies associated with the Post Type.
+ */
+ public function taxonomies(): array {
+ return [
+ 'genre'
+ 'category',
+ ];
+ }
+
+ /**
+ * Set the menu icon for the Post Type.
+ */
+ public function icon(): string {
+ return 'dashicons-book';
+ }
+
+ /**
+ * Set the admin post table filters.
+ */
+ public function filters(): array {
+ return [
+ 'genre',
+ 'category'
+ ];
+ }
+
+ /**
+ * Define the columns for the admin post table.
+ */
+ public function columns(Columns $columns): Columns {
+ // Remove the author and date column.
+ $columns->remove( [ 'author', 'date' ] );
+
+ // Add a Rating column.
+ $columns->add( 'rating', __( 'Rating', 'post-types' ) );
+
+ // Populate the rating column.
+ $columns->populate( 'rating', function( $post_id ) {
+ echo get_post_meta( $post_id, 'rating', true );
+ } );
+
+ return $columns;
+ }
+}
+```
-// Attach the genre taxonomy (which is created below).
-$books->taxonomy( 'genre' );
+### Register a custom post type
-// Hide the date and author columns.
-$books->columns()->hide( [ 'date', 'author' ] );
+Once the custom post type class is created it can be registered to WordPress by instantiating and call the register method.
-// Set the Books menu icon.
-$books->icon( 'dashicons-book-alt' );
+```php
+// Instantiate the Books PostType class.
+$books = new Books;
-// Register the post type to WordPress.
+// Register the books PostType to WordPress.
$books->register();
-
-// Create a genre taxonomy.
-$genres = new Taxonomy( 'genre' );
-
-// Set options for the taxonomy.
-$genres->options( [
- 'hierarchical' => false,
-] );
-
-// Register the taxonomy to WordPress.
-$genres->register();
```
## Notes
* The full documentation can be found online at [posttypes.jjgrainger.co.uk](https://posttypes.jjgrainger.co.uk)
-* The class has no methods for making custom fields for post types, use [Advanced Custom Fields](https://advancedcustomfields.com)
-* The book's example used in the README.md can be found in [examples/books.php](examples/books.php)
* Licensed under the [MIT License](https://github.com/jjgrainger/PostTypes/blob/master/LICENSE)
* Maintained under the [Semantic Versioning Guide](https://semver.org)
diff --git a/docs/Getting-started.md b/docs/Getting-started.md
index 628a53e..532b2f8 100644
--- a/docs/Getting-started.md
+++ b/docs/Getting-started.md
@@ -2,9 +2,9 @@
## Requirements
-* PHP >=7.2
+* PHP >=8.1
* [Composer](https://getcomposer.org/)
-* [WordPress](https://wordpress.org) >=5.1
+* [WordPress](https://wordpress.org) >=6.3
## Installation
@@ -16,55 +16,116 @@ Run the following in your terminal to install PostTypes with [Composer](https://
$ composer require jjgrainger/posttypes
```
-PostTypes uses [PSR-4](https://www.php-fig.org/psr/psr-4/) autoloading and can be used with the Composer's autoloader. Below is a basic example of getting started, though your setup may be different depending on how you are using Composer.
-
-```php
-require __DIR__ . '/vendor/autoload.php';
-
-use PostTypes\PostType;
-
-$books = new PostType( 'book' );
-
-$books->register();
-```
-
-See Composer's [basic usage](https://getcomposer.org/doc/01-basic-usage.md#autoloading) guide for details on working with Composer and autoloading.
+PostTypes uses [PSR-4](https://www.php-fig.org/psr/psr-4/) autoloading and can be used with the Composer's autoloader. See Composer's [basic usage](https://getcomposer.org/doc/01-basic-usage.md#autoloading) guide for details on working with Composer and autoloading.
## Basic Usage
-Below is a basic example of setting up a simple book post type with a genre taxonomy.
+#### Create a custom post type
+
+Custom post types are defined as classes that extend the base `PostType` class. At a minimum, the `name` method must be implemented to define the post type slug. All other methods are optional and allow you to configure labels, options, taxonomies, admin columns, filters, and more as needed.
```php
-// Require the Composer autoloader.
-require __DIR__ . '/vendor/autoload.php';
+ __( 'Book', 'text-domain' ),
+ 'singular_name' => __( 'Book', 'text-domain' ),
+ 'menu_name' => __( 'Books', 'text-domain' ),
+ 'all_items' => __( 'Books', 'text-domain' ),
+ 'add_new' => __( 'Add New', 'text-domain' ),
+ 'add_new_item' => __( 'Add New Book', 'text-domain' ),
+ 'edit_item' => __( 'Edit Book', 'text-domain' ),
+ 'new_item' => __( 'New Book', 'text-domain' ),
+ 'view_item' => __( 'View Book', 'text-domain' ),
+ 'search_items' => __( 'Search Books', 'text-domain' ),
+ 'not_found' => __( 'No Books found', 'text-domain' ),
+ 'not_found_in_trash' => __( 'No Books found in Trash', 'text-domain'),
+ 'parent_item_colon' => __( 'Parent Book', 'text-domain' ),
+ ];
+ }
+
+ /**
+ * Define Post Type feature supports.
+ */
+ public function supports(): array {
+ return [
+ 'title',
+ 'editor',
+ 'thumbnail',
+ 'custom-fields'
+ ];
+ }
+
+ /**
+ * Define Taxonomies associated with the Post Type.
+ */
+ public function taxonomies(): array {
+ return [
+ 'genre'
+ 'category',
+ ];
+ }
+
+ /**
+ * Set the menu icon for the Post Type.
+ */
+ public function icon(): string {
+ return 'dashicons-book';
+ }
+
+ /**
+ * Set the admin post table filters.
+ */
+ public function filters(): array {
+ return [
+ 'genre',
+ 'category'
+ ];
+ }
+
+ /**
+ * Define the columns for the admin post table.
+ */
+ public function columns(Columns $columns): Columns {
+ // Remove the author and date column.
+ $columns->remove( [ 'author', 'date' ] );
+
+ // Add a Rating column.
+ $columns->add( 'rating', __( 'Rating', 'post-types' ) );
+
+ // Populate the rating column.
+ $columns->populate( 'rating', function( $post_id ) {
+ echo get_post_meta( $post_id, 'rating', true );
+ } );
+
+ return $columns;
+ }
+}
+```
-// Attach the genre taxonomy (which is created below).
-$books->taxonomy( 'genre' );
+### Register a custom post type
-// Hide the date and author columns.
-$books->columns()->hide( [ 'date', 'author' ] );
+Once the custom post type class is created it can be registered to WordPress by instantiating and call the register method.
-// Set the Books menu icon.
-$books->icon( 'dashicons-book-alt' );
+```php
+// Instantiate the Books PostType class.
+$books = new Books;
-// Register the post type to WordPress.
+// Register the books PostType to WordPress.
$books->register();
-
-// Create a genre taxonomy.
-$genres = new Taxonomy( 'genre' );
-
-// Set options for the taxonomy.
-$genres->options( [
- 'hierarchical' => false,
-] );
-
-// Register the taxonomy to WordPress.
-$genres->register();
```
diff --git a/docs/Notes.md b/docs/Notes.md
deleted file mode 100644
index 0eac9fb..0000000
--- a/docs/Notes.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Notes
-
-## Translations
-
-Since 2.0 the `translation()` method has been removed. You can translate any labels and names when you assign them to the PostType or Taxonomy. It was removed to provide more control to the developer while encouraging best practices around internationalizing plugins and themes set out by [WordPress](https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/).
-
-```php
-// Translating the post types plural and singular names.
-$books = new PostType( [
- 'name' => 'book',
- 'singular' => __( 'Book', 'YOUR_TEXTDOMAIN' ),
- 'plural' => __( 'Books', 'YOUR_TEXTDOMAIN' ),
- 'slug' => 'books',
-] );
-
-// Translating labels.
-$books->labels( [
- 'add_new_item' => __( 'Add new Book', 'YOUR_TEXTDOMAIN' ),
-] );
-```
-
-## Custom Fields
-
-The class has no methods for making custom fields for post types, use [Advanced Custom Fields](https://advancedcustomfields.com).
-
-## Examples
-
-The books example used in the README.md can be found in [examples/books.php](https://github.com/jjgrainger/posttypes/blob/master/examples/books.php).
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index 0ce1fb5..ae46bff 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -1,18 +1,24 @@
# Table of Contents
-* [PostTypes v2.2.1](../README.md)
+* [PostTypes v3.0](../README.md)
* [Getting Started](Getting-started.md)
* [PostTypes](post-types/README.md)
* [Create a Post Type](post-types/Create-a-post-type.md)
- * [Add Taxonomies](post-types/Add-taxonomies.md)
- * [Filters](post-types/Filters.md)
- * [Columns](post-types/Columns.md)
- * [Menu Icons](post-types/Menu-icons.md)
- * [Flush Rewrite Rules](post-types/Flush-rewrite-rules.md)
+ * [Defining Labels](post-types/Defining-labels.md)
+ * [Defining Options](post-types/Defining-options.md)
+ * [Defining taxonomies](post-types/Defining-taxonomies.md)
+ * [Defining feature supports](post-types/Defining-feature-supports.md)
+ * [Defining an icon](post-types/Defining-an-icon.md)
+ * [Defining filters](post-types/Defining-filters.md)
+ * [Modifying columns](post-types/Modifying-columns.md)
+ * [Creating columns](post-types/Creating-columns.md)
+ * [Defining hooks](post-types/Defining-hooks.md)
* [Taxonomies](taxonomies/README.md)
* [Create a Taxonomy](taxonomies/Create-a-taxonomy.md)
- * [Add to Post Type](taxonomies/Add-to-post-type.md)
- * [Columns](taxonomies/Columns.md)
-* [Notes](Notes.md)
+ * [Defining Labels](taxonomies/Defining-labels.md)
+ * [Defining Options](taxonomies/Defining-options.md)
+ * [Defining Post Types](taxonomies/Defining-post-types.md)
+ * [Modifying Columns](taxonomies/Modifying-columns.md)
+ * [Defining Hooks](taxonomies/Defining-hooks.md)
* [Contributing](../CONTRIBUTING.md)
* [Changelog](../Changelog.md)
diff --git a/docs/post-types/Add-taxonomies.md b/docs/post-types/Add-taxonomies.md
deleted file mode 100644
index 87a060f..0000000
--- a/docs/post-types/Add-taxonomies.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add Taxonomies
-
-You can add new and existing taxonomies to a post type by passing the taxonomy name to the `taxonomy()` method.
-
-```php
-// Create a book post type.
-$books = new PostType( 'book' );
-
-// Add the genre taxonomy to the book post type.
-$books->taxonomy( 'genre' );
-
-// Add the default category taxonomy.
-$books->taxonomy( 'category' );
-
-// Register the post type to WordPress.
-$books->register();
-```
-
-This method only attaches the taxonomy to the post type, to _create_ a taxonomy see the [documentation](../taxonomies/Create-a-taxonomy.md) on creating a new taxonomy.
-
-Taxonomies and post types can be created in any order.
diff --git a/docs/post-types/Columns.md b/docs/post-types/Columns.md
deleted file mode 100644
index 638dbd1..0000000
--- a/docs/post-types/Columns.md
+++ /dev/null
@@ -1,76 +0,0 @@
-# Columns
-
-To modify a post types admin columns use the `column()` manager. It has a variety of methods to help fine tune admin table columns.
-
-#### Add Columns
-
-To add columns to the admin edit screen pass an array of column slugs and labels to the `add()` method.
-
-```php
-// Add multiple columns and set their labels.
-$books->columns()->add( [
- 'rating' => __( 'Rating' ),
- 'price' => __( 'Price' ),
-] );
-```
-
-#### Hide Columns
-
-To hide columns pass the column slug to the `hide()` method. For multiple columns pass an array of column slugs.
-
-```php
-$books->columns()->hide( 'author' );
-
-$books->columns()->hide( [ 'author', 'date' ] );
-```
-
-#### Column Order
-
-To rearrange columns pass an array of column slugs and position to the `order()` method. Only columns you want to reorder need to be set, not all columns. Positions are based on a zero based index.
-
-```php
-$books->columns()->order( [
- 'rating' => 2,
- 'genre' => 4,
-] );
-```
-
-#### Set Columns
-
-To set all columns to display pass an array of the column slugs and labels to the `set()` method. This overrides any other configuration set by the methods above.
-
-```php
-$books->columns()->set( [
- 'cb' => '',
- 'title' => __( 'Title' ),
- 'genre' => __( 'Genres' ),
- 'rating' => __( 'Rating' ),
- 'date' => __( 'Date' ),
-] );
-```
-
-#### Populate Columns
-
-To populate any column use the `populate()` method, by passing the column slug and a callback function.
-
-```php
-$books->columns()->populate( 'rating', function ( $column, $post_id ) {
- echo get_post_meta( $post_id, 'rating', true ) . '/10';
-} );
-```
-
-#### Sortable Columns
-
-To define which custom columns are sortable use the `sortable()` method. This method accepts an array of column slugs and an array of sorting options.
-
-The first option is the `meta_key` to sort the columns by.
-
-The second option is how the items are ordered, either numerically (`true`) or alphabetically (`false`) by default.
-
-```php
-// Make both the price and rating columns sortable and ordered numerically.
-$books->columns()->sortable( [
- 'price' => [ 'price', true ],
- 'rating' => [ 'rating', true ],
-] );
-```
diff --git a/docs/post-types/Create-a-post-type.md b/docs/post-types/Create-a-post-type.md
index 97aa021..d843efe 100644
--- a/docs/post-types/Create-a-post-type.md
+++ b/docs/post-types/Create-a-post-type.md
@@ -1,119 +1,36 @@
# Create a Post Type
-You can use PostTypes to create a new post type, or work with an [existing post type](#work-with-existing-posttypes). PostTypes can be included in your theme or plugins.
-
-## Create a new Post Type
-
-To create a new post type pass the post types name to the class constructor. In order to apply changes to WordPress you must call the `register()` method.
+Post types can be made by creating a new class that extends the `PostType` abstract class. All PostType classes require you to implement the `name()` method. Below is an example of a simple Books PostType class to get started.
```php
use PostTypes\PostType;
-// Create a book post type.
-$books = new PostType( 'book' );
-
-// Register the post type to WordPress.
-$books->register();
-```
-
-{% hint style="info" %}
-The `register()` method hooks into WordPress and sets up the different actions and filters to create your custom post type. You do not need to add any of your PostTypes code in actions/filters. Doing so may lead to unexpected results.
-{% endhint %}
-
-### Set names
-
-The post type labels and slugs are automatically generated from the post type name, however, you can set these manually by passing an array of names to the class constructor.
-
-```php
-$names = [
- 'name' => 'book',
- 'singular' => 'Book',
- 'plural' => 'Books',
- 'slug' => 'books',
-];
-
-$books = new PostType( $names );
-
-$books->register();
+class Books extends PostType
+{
+ /**
+ * Returns the post type name to register to WordPress.
+ *
+ * @return string
+ */
+ public function name(): string
+ {
+ return 'book';
+ }
+}
```
-The following names are accepted.
-
-| Key | Description | Example |
-| --- | --- | --- |
-| `name` | is the post type name | *required*, singular, lowercase, underscores |
-| `singular` | is the singular label for the post type | e.g 'Book', 'Person' |
-| `plural` | is the plural label for the post type | e.g 'Books', 'People' |
-| `slug` | is the post type slug used in the permalinks | plural, lowercase, hyphens |
-
-The only required field is the post type's `name`, all others are optional.
+## Register PostType to WordPress
-### Set options
-
-Options for the post type are set by passing an array as the second argument in the class constructor.
+Once your PostType class is created the new post type can be registered to WordPress by instantiating the class and calling the `register()` method in your plugin or theme.
```php
-$options = [
- 'has_archive' => false,
-];
-
-$books = new PostType( 'book', $options );
-
-$books->register();
-```
-
-Alternatively, you can set options using the `options()` method.
-
-```php
-$books = new PostType( 'book' );
-
-$books->options( [
- 'has_archive' => false,
-] );
+// Instantiate the Books PostType class.
+$books = new Books;
+// Register the books PostType to WordPress.
$books->register();
```
-The options match the arguments passed to the `register_post_type()` WordPress function. All available options are on the [WordPress Codex](https://codex.wordpress.org/Function_Reference/register_post_type#Parameters)
-
-### Set labels
-
-You can set the labels for the post type by passing an array as the third argument in the class constructor.
-
-```php
-$labels = [
- 'add_new_item' => __( 'Add new Book' ),
-];
-
-$books = new PostType( 'book', $options, $labels );
-
-$books->register();
-```
-
-Alternatively, you can use the `labels()` method to set the labels for the post type.
-
-```php
-$books = new PostType( 'books' );
-
-$books->labels( [
- 'add_new_item' => __( 'Add new Book' ),
-] );
-
-$books->register();
-```
-
-All available labels are on the [WordPress Codex](https://codex.wordpress.org/Function_Reference/register_post_type#labels)
-
-## Work with existing Post Types
-
-To work with existing post types pass the post type name into the constructor. Be careful and avoid using global variables (e.g `$post`) which can lead to unwanted results.
-
-```php
-// Create a PostType object for an existing post type in WordPress.
-$blog = new PostType( 'post' );
-
-// Make changes to the post type...
-
-// You still need to register the changes to WordPress.
-$blog->register();
-```
+{% hint style="info" %}
+The `register()` method hooks into WordPress and sets all the actions and filters required to create your custom post type. You do not need to add any of your PostTypes code in actions/filters. Doing so may lead to unexpected results.
+{% endhint %}
diff --git a/docs/post-types/Creating-columns.md b/docs/post-types/Creating-columns.md
new file mode 100644
index 0000000..6561bba
--- /dev/null
+++ b/docs/post-types/Creating-columns.md
@@ -0,0 +1,88 @@
+# Custom Columns
+
+The `Column` class allows developers to create reusable, self-contained columns for the post listing table in the WordPress admin. These custom columns can display post meta, taxonomy values, or any custom data related to the post.
+
+Columns are defined by extending the abstract `PostTypes\Column` class and implementing the required `name()` method, along with any optional logic such as rendering, sorting, or changing the label.
+
+## Creating a Custom Column
+
+To create a custom column, extend the base `Column` class and implement the methods you need. Here's an example of a `PriceColumn` that pulls a `_price` meta field from the post and displays it in the admin list table:
+
+```php
+use PostTypes\Column;
+
+class PriceColumn extends Column
+{
+ /**
+ * Defines the column key used internally.
+ *
+ * @return string.
+ */
+ public function name(): string
+ {
+ return 'price';
+ }
+
+ /**
+ * Define the column label.
+ *
+ * @return string
+ */
+ public function label(): string
+ {
+ return __( 'Price', 'my-text-domain' );
+ }
+
+ /**
+ * Populate column callback.
+ *
+ * @return void
+ */
+ public function populate( int $post_id ): void
+ {
+ echo '$' . get_post_meta( $post_id, '_price', true );
+ }
+
+ /**
+ * Set the column can be sorted.
+ *
+ * @return boolean
+ */
+ public function isSortable(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Handle sorting the column by modifying the admin query.
+ *
+ * @param $query \WP_Query
+ * @return void
+ */
+ public function sort(\WP_Query $query): void
+ {
+ $query->set( 'meta_key', '_price' );
+ $query->set( 'orderby', 'meta_value_num' );
+ }
+}
+```
+
+## Adding the Column to a Post Type
+
+Once you’ve defined your custom column, you can add it to a PostType using the `$columns->column()` method inside your `PostType` class:
+
+```php
+use PostTypes\PostType;
+
+class Book extends PostType
+{
+ //...
+
+ public function columns( $columns ): void
+ {
+ $columns->column( new PriceColumn );
+
+ return $columns;
+ }
+}
+```
diff --git a/docs/post-types/Defining-an-icon.md b/docs/post-types/Defining-an-icon.md
new file mode 100644
index 0000000..f309206
--- /dev/null
+++ b/docs/post-types/Defining-an-icon.md
@@ -0,0 +1,26 @@
+# Menu Icons
+
+WordPress has [Dashicons](https://developer.wordpress.org/resource/dashicons/), an icon font you can use with your custom post types.
+
+To set the post type icon pass the dashicon icon slug in the `icon()` method.
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns the admin menu icon for the Books post type.
+ *
+ * @return array
+ */
+ public function icon(): string
+ {
+ return 'dashicons-book-alt';
+ }
+}
+```
+
+A list of available icons can be found on the [WordPress documentation](https://developer.wordpress.org/resource/dashicons/)
diff --git a/docs/post-types/Defining-feature-supports.md b/docs/post-types/Defining-feature-supports.md
new file mode 100644
index 0000000..7608660
--- /dev/null
+++ b/docs/post-types/Defining-feature-supports.md
@@ -0,0 +1,28 @@
+## Define feature supports
+
+You can define the features your post types supports using the `supports` method. This works similarly to the [`post_type_supports`](https://developer.wordpress.org/reference/functions/post_type_supports/) function in WordPress and returns an array of 'features'.
+
+The `title` and `editor` features are enabled by default, matching the WordPress defaults. A list of available features can be seen in the [WordPress documentation](https://developer.wordpress.org/reference/functions/post_type_supports/#more-information).
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns features the Books post type supports.
+ *
+ * @return array
+ */
+ public function supports(): array
+ {
+ return [
+ 'title',
+ 'editor',
+ 'custom-fields',
+ ];
+ }
+}
+```
diff --git a/docs/post-types/Defining-filters.md b/docs/post-types/Defining-filters.md
new file mode 100644
index 0000000..0db583d
--- /dev/null
+++ b/docs/post-types/Defining-filters.md
@@ -0,0 +1,28 @@
+# Defining filters
+
+Filters that appear for the post type listing admin screen can be defined using the `filters()` method.
+
+This should return an array of taxonomy slugs that are to be used as dropdown filters for the post type.
+
+An empty array is returned by default.
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns the filters for the Books post type.
+ *
+ * @return array
+ */
+ public function filters(): array
+ {
+ return [
+ 'category',
+ ];
+ }
+}
+```
diff --git a/docs/post-types/Defining-hooks.md b/docs/post-types/Defining-hooks.md
new file mode 100644
index 0000000..7f03b42
--- /dev/null
+++ b/docs/post-types/Defining-hooks.md
@@ -0,0 +1,38 @@
+# Defining hooks
+
+Additional hooks are supported with the `hooks()` method.
+
+Here you can register additional actions and filters to WordPress and allows you to keep logic associated with your post type in one class.
+
+```php
+use PostTypes\PostType;
+use WP_Post;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Adds additional hooks for the post type.
+ *
+ * @return array
+ */
+ public function hooks(): array
+ {
+ add_action( 'save_post_book', [ $this, 'onSave' ], 10, 3 );
+ }
+
+ /**
+ * Run additional logic when saving a Books post.
+ *
+ * @param int $post_id
+ * @param WP_Post $post
+ * @param bool $update
+ * @return void
+ */
+ public function onSave(int $post_id, WP_Post $post, bool $update)
+ {
+ // Run additional logic when a Books post type is saved...
+ }
+}
+```
diff --git a/docs/post-types/Defining-labels.md b/docs/post-types/Defining-labels.md
new file mode 100644
index 0000000..548135f
--- /dev/null
+++ b/docs/post-types/Defining-labels.md
@@ -0,0 +1,39 @@
+# Defining labels
+
+Labels for a PostType are defined in the `labels()` method and should return an array of labels.
+
+By default, an empty array is returned and the WordPress default labels are used.
+
+See [`get_post_type_labels()`](https://developer.wordpress.org/reference/functions/get_post_type_labels/) for a full list of supported labels.
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns the Books post type labels.
+ *
+ * @return array
+ */
+ public function labels(): array
+ {
+ return [
+ 'name' => __( 'Books', 'my-text-domain' ),
+ 'singular_name' => __( 'Book', 'my-text-domain' ),
+ 'menu_name' => __( 'Books', 'my-text-domain' ),
+ 'all_items' => __( 'Books', 'my-text-domain' ),
+ 'add_new' => __( 'Add New', 'my-text-domain' ),
+ 'add_new_item' => __( 'Add New Book', 'my-text-domain' ),
+ 'edit_item' => __( 'Edit Book', 'my-text-domain' ),
+ 'new_item' => __( 'New Book', 'my-text-domain' ),
+ 'view_item' => __( 'View Book', 'my-text-domain' ),
+ 'search_items' => __( 'Search Books', 'my-text-domain' ),
+ 'not_found' => __( 'No Books found', 'my-text-domain' ),
+ 'not_found_in_trash' => __( 'No Books found in Trash', 'my-text-domain' ),
+ ];
+ }
+}
+```
diff --git a/docs/post-types/Defining-options.md b/docs/post-types/Defining-options.md
new file mode 100644
index 0000000..ab9a2ba
--- /dev/null
+++ b/docs/post-types/Defining-options.md
@@ -0,0 +1,29 @@
+# Defining options
+
+Options for a PostType are defined in the `options()` method and should return an array of valid [WordPress post type options](https://developer.wordpress.org/reference/functions/register_post_type/#parameters).
+
+By default, an empty array is returned but these options are merged with a generated options array in [PostTypes](#) and whatever options are defined here will overwrite those defaults.
+
+See [`register_post_type()`](https://developer.wordpress.org/reference/functions/register_post_type/#parameters) for a full list of supported options.
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns the options for the Books post type.
+ *
+ * @return array
+ */
+ public function options(): array
+ {
+ return [
+ 'public' => true,
+ 'show_in_rest' => true,
+ ];
+ }
+}
+```
diff --git a/docs/post-types/Defining-taxonomies.md b/docs/post-types/Defining-taxonomies.md
new file mode 100644
index 0000000..fcf8da2
--- /dev/null
+++ b/docs/post-types/Defining-taxonomies.md
@@ -0,0 +1,31 @@
+# Defining Taxonomies
+
+Taxonomies for a PostType can be definied using the `taxonomies()` method. This method should return an array of taxonomy slugs to associate with the post type.
+
+An empty array is returned by default and no taxonomies are attached to the PostType.
+
+```php
+use PostTypes\PostType;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Returns taxonomies attached to the Books post type.
+ *
+ * @return array
+ */
+ public function taxonomies(): array
+ {
+ return [
+ 'category',
+ 'genre',
+ ];
+ }
+}
+```
+
+This method only attaches the taxonomy to the post type, to _create_ a taxonomy see the [documentation](../taxonomies/Create-a-taxonomy.md) on creating a new taxonomy.
+
+Taxonomies and post types can be created and registered in any order.
diff --git a/docs/post-types/Filters.md b/docs/post-types/Filters.md
deleted file mode 100644
index 9e4d96d..0000000
--- a/docs/post-types/Filters.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Filters
-
-You can set what dropdown filters appear on the post type admin edit screen by passing an array of taxonomy names to the `filters()` method.
-
-```php
-$books->filters( [ 'genre', 'category' ] );
-```
-
-The order the filters appear are set by the order of the items in the array.
-
-```php
-// Display the category dropdown first.
-$books->filters( [ 'category', 'genre' ] );
-```
-
-An empty array will remove all dropdown filters from the admin edit screen.
-
-```php
-// Don't display filters on the admin edit screen.
-$books->filters( [] );
-```
diff --git a/docs/post-types/Flush-rewrite-rules.md b/docs/post-types/Flush-rewrite-rules.md
deleted file mode 100644
index cfd0786..0000000
--- a/docs/post-types/Flush-rewrite-rules.md
+++ /dev/null
@@ -1,9 +0,0 @@
-
-# Flush Rewrite Rules
-
-You can programmatically recreate the sites rewrite rules with the `flush()` method.
-This is an expensive operation and should be used with caution, see [codex](https://codex.wordpress.org/Function_Reference/flush_rewrite_rules) for more.
-
-```php
-$books->flush();
-```
diff --git a/docs/post-types/Menu-icons.md b/docs/post-types/Menu-icons.md
deleted file mode 100644
index 6a8125e..0000000
--- a/docs/post-types/Menu-icons.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Menu Icons
-
-WordPress 3.8 has [Dashicons](https://developer.wordpress.org/resource/dashicons/), an icon font you can use with your custom post types.
-
-To set the post type icon pass the dashicon icon slug to the `icon()` method.
-
-```php
-$books->icon( 'dashicons-book-alt' );
-```
-A list of available icons can be found on the [WordPress codex](https://developer.wordpress.org/resource/dashicons/)
diff --git a/docs/post-types/Modifying-columns.md b/docs/post-types/Modifying-columns.md
new file mode 100644
index 0000000..362e300
--- /dev/null
+++ b/docs/post-types/Modifying-columns.md
@@ -0,0 +1,159 @@
+# Modifying columns
+
+To modify a post types admin columns use the `column()` method. This method accepts the `PostTypes\Columns` manager which has a variety of methods to help fine tune admin table columns.
+
+## Adding Columns
+
+To add columns to the admin edit screen pass an array of column slugs and labels to the `add()` method.
+
+```php
+use PostTypes\PostType;
+use PostTypes\Columns;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Set the PostTypes admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Add a new price column.
+ $columns->add( 'price', __( 'Price', 'my-text-domain' ) );
+
+ // Populate the price column with post meta.
+ $columns->populate( 'price', function( $post_id ) {
+ echo '$' . get_post_meta( $post_id, '_price', true );
+ } );
+
+ // Make the price column sortable.
+ $columns->sortable( 'price', function( WP_Query $query ) {
+ $query->set( 'orderby', 'meta_value_num' );
+ $query->set( 'meta_key', 'price' );
+ } );
+
+ return $columns;
+ }
+}
+```
+
+## Populate Columns
+
+To populate any column use the `populate()` method, by passing the column slug and a callback function.
+
+```php
+use PostTypes\PostType;
+use PostTypes\Columns;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Set the PostTypes admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ $columns->populate( 'rating', function( $post_id ) {
+ echo get_post_meta( $post_id, 'rating', true ) . '/10';
+ } );
+
+ return $columns;
+ }
+}
+```
+
+## Sortable Columns
+
+To define which custom columns are sortable use the `sortable()` method.
+
+```php
+use PostTypes\PostType;
+use PostTypes\Columns;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Set the PostTypes admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Make the rating column sortable.
+ $columns->sortable( 'rating', function( WP_Query $query ) {
+ $query->set( 'orderby', 'meta_value_num' );
+ $query->set( 'meta_key', 'rating' );
+ } );
+
+ return $columns;
+ }
+}
+```
+
+## Hide Columns
+
+To hide columns pass the column slug to the `hide()` method. For multiple columns pass an array of column slugs.
+
+```php
+use PostTypes\PostType;
+use PostTypes\Columns;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Set the PostTypes admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Hide the Author and Date columns
+ $columns->hide( [ 'author', 'date' ] );
+
+ return $columns;
+ }
+}
+```
+
+## Column Order
+
+To rearrange columns pass an array of column slugs and position to the `order()` method. Only olumns you want to reorder need to be set, not all columns.
+
+
+```php
+use PostTypes\PostType;
+use PostTypes\Columns;
+
+class Books extends PostType
+{
+ //...
+
+ /**
+ * Set the PostTypes admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Order the new Rating and Genre columns.
+ $columns->order( [
+ 'rating' => 2,
+ 'genre' => 4,
+ ] );
+
+ return $columns;
+ }
+}
+```
+
+
diff --git a/docs/post-types/README.md b/docs/post-types/README.md
index 380a23c..1b9c6f4 100644
--- a/docs/post-types/README.md
+++ b/docs/post-types/README.md
@@ -3,8 +3,12 @@
The following section contains information on creating and working with post types.
* [Create a Post Type](Create-a-post-type.md)
-* [Add Taxonomies](Add-taxonomies.md)
-* [Filters](Filters.md)
-* [Columns](Columns.md)
-* [Menu Icons](Menu-icons.md)
-* [Flush Rewrite Rules](Flush-rewrite-rules.md)
+* [Defining Labels](Defining-labels.md)
+* [Defining Options](Defining-options.md)
+* [Defining taxonomies](Defining-taxonomies.md)
+* [Defining feature supports](Defining-feature-supports.md)
+* [Defining an icon](Defining-an-icon.md)
+* [Defining filters](Defining-filters.md)
+* [Modifying columns](Modifying-columns.md)
+* [Creating columns](Creating-columns.md)
+* [Defining hooks](Defining-hooks.md)
diff --git a/docs/taxonomies/Add-to-post-type.md b/docs/taxonomies/Add-to-post-type.md
deleted file mode 100644
index 95fdd11..0000000
--- a/docs/taxonomies/Add-to-post-type.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## Add to post type
-
-You can add a taxonomy to any post type by passing the post type name to the `posttype()` method.
-
-```php
-// Create the genre taxonomy.
-$genres = new Taxonomy( 'genre' );
-
-// Attach to the book post type.
-$genres->posttype( 'books' );
-
-// Register changes to WordPress.
-$genres->register();
-```
-
-Alternatively, you can attach a taxonomy to a post type when creating a post type using its [`taxonomy()`](../post-types/Add-taxonomies.md) method.
diff --git a/docs/taxonomies/Columns.md b/docs/taxonomies/Columns.md
deleted file mode 100644
index c7bfa45..0000000
--- a/docs/taxonomies/Columns.md
+++ /dev/null
@@ -1,89 +0,0 @@
-## Columns
-
-You can now modify `Taxonomy` columns using the same methods as you would for a `PostType`. For example:
-
-```php
-use PostTypes\Taxonomy;
-
-// Create a taxonomy.
-$genres = new Taxonomy( 'genre' );
-
-// Add a column to the taxonomy admin table.
-$genres->columns()->add( [
- 'popularity' => __( 'Popularity' ),
-] );
-
-// Register the taxonomy to WordPress.
-$genres->register();
-```
-
-#### Add Columns
-
-To add columns to the admin edit screen pass an array of column slugs and labels to the `add()` method.
-
-```php
-// Add columns and set their labels.
-$genres->columns()->add( [
- 'popularity' => __( 'Popularity' ),
-] );
-```
-
-#### Hide Columns
-
-To hide columns pass the column slug to the `hide()` method. For multiple columns pass an array of column slugs.
-
-```php
-$genres->columns()->hide( 'description' );
-```
-
-#### Column Order
-
-To rearrange columns pass an array of column slugs and position to the `order()` method. Only columns you want to reorder need to be set, not all columns. Positions are based on a zero based index.
-
-```php
-$genres->columns()->order( [
- 'popularity' => 2,
-] );
-```
-
-#### Set Columns
-
-To set all columns to display pass an array of the column slugs and labels to the `set()` method. This overrides any other configuration set by the methods above.
-
-```php
-$genres->columns()->set( [
- 'cb' => '',
- 'name' => __( 'Name' ),
- 'description' => __( 'Description' ),
- 'slug' => __( 'Slug' ),
- 'popularity' => __( 'Popularity' ),
-] );
-```
-
-#### Populate Columns
-
-To populate any column use the `populate()` method, by passing the column slug and a callback function.
-
-Taxonomy columns work differently to post type columns. The callback receives 3 arguments, the columns content, the column name and the term ID. Also, the [hook used](https://developer.wordpress.org/reference/hooks/manage_this-screen-taxonomy_custom_column/) is a filter, so the column value must be returned.
-
-```php
-$genres->columns()->populate( 'popularity', function ( $content, $column, $term_id ) {
- return get_term_meta( $term_id, 'popularity', true );
-} );
-```
-
-#### Sortable Columns
-
-To define which custom columns are sortable use the `sortable()` method. This method accepts an array of column slugs and an array of sorting options.
-
-The first option is the term `meta_key` to sort the columns by.
-
-The second option is how the items are ordered, either numerically (`true`) or alphabetically (`false`) by default.
-
-```php
-// Make both the price and rating columns sortable and ordered numerically.
-$genres->columns()->sortable( [
- 'popularity' => [ 'popularity', true ],
-] );
-```
-
diff --git a/docs/taxonomies/Create-a-taxonomy.md b/docs/taxonomies/Create-a-taxonomy.md
index b5edfc3..107703a 100644
--- a/docs/taxonomies/Create-a-taxonomy.md
+++ b/docs/taxonomies/Create-a-taxonomy.md
@@ -9,105 +9,55 @@ To create a new taxonomy pass the taxonomy name to the class constructor. Labels
```php
use PostTypes\Taxonomy;
-// Create a new taxonomy
-$genres = new Taxonomy( 'genre' );
-
-// Register the taxonomy to WordPress
-$genres->register();
-```
-
-#### Set names
-
-You can define names by passing an array as the first argument. Only `name` is required.
-
-```php
-$names = [
- 'name' => 'genre',
- 'singular' => 'Genre',
- 'plural' => 'Genres',
- 'slug' => 'genres'
-];
-
-$genres = new Taxonomy( $names );
-
-$genres->register();
+class Genres extends Taxonomy
+{
+ /**
+ * Returns the taxonomy name to register to WordPress.
+ *
+ * @return string
+ */
+ public function name(): string
+ {
+ return 'genre';
+ }
+}
```
-The following names are accepted.
-
-| Key | Description | Example |
-| --- | --- | --- |
-| `name` | is the taxonomy name | *required*, singular, lowercase, underscores |
-| `singular` | is the singular label for the taxonomy | e.g 'Genre', 'Category' |
-| `plural` | is the plural label for the taxonomy | e.g 'Genres', 'Categories' |
-| `slug` | is the taxonomy slug used in the permalinks | plural, lowercase, hyphens |
-
-#### Add options
-
-You can further customise taxonomies by passing an array of options as the second argument in the constructor.
-
-```php
-$options = [
- 'hierarchical' => false,
-];
-
-$genres = new Taxonomy( 'genre', $options );
-
-$genres->register();
-```
+## Set the slug for the Taxonomy
-Alternatively, you can set options using the `options()` method.
+By default, the Taxonomy name is used as the slug for the taxonomy too. To change this use the `slug()` method to return a slug string.
```php
-$genres = new Taxonomy( 'genre' );
-
-$genres->options( [
- 'hierarchical' => false,
-] );
+use PostTypes\Taxonomy;
-$genres->register();
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Returns the taxonomy slug.
+ *
+ * @return string
+ */
+ public function slug(): string
+ {
+ return 'genres';
+ }
+}
```
-The options match the arguments passed to the `register_taxonomy()` WordPress function. All available options are on the [WordPress Codex](https://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments).
+## Register the Taxonomy to WordPress
-#### Add labels
-
-You can define the labels for a taxonomy by passing an array as the third argument in the class constructor.
+Once your Taxonomy class is created it can be registered to WordPress by instantiating the class and calling the `register()` method in your plugin or theme.
```php
-$labels = [
- 'add_new_item' => __( 'Add new Genre' ),
-];
-
-$genres = new Taxonomy( 'genres', $options, $labels );
+// Instantiate the Genres Taxonomy class.
+$genres = new Genres;
+// Register the Genres Taxonomy to WordPress.
$genres->register();
```
-Alternatively, you can use the `labels()` method to set the labels for the taxonomy.
-
-```php
-$genres = new Taxonomy( 'genre' );
-
-$genres->labels( [
- 'add_new_item' => __( 'Add new Genre' ),
-] );
-
-$genres->register();
-```
-
-All available labels are on the [WordPress Codex](https://codex.wordpress.org/Function_Reference/register_taxonomy)
-
-## Work with existing Taxonomies
-
-You can work with existing taxonomies by passing the taxonomy name to the Taxonoy constructor. Once you have made your changes you need to register them to WordPress using the `register()` method.
-
-```php
-// Create a new Taxonomy object for an existing taxonomy.
-$tags = new Taxonomy( 'post_tag' );
-
-// Modify the taxonomy...
-
-// Regsiter changes to WordPress.
-$tags->register();
-```
+{% hint style="info" %}
+The `register()` method hooks into WordPress and sets all the actions and filters required to create your taxonomy. You do not need to add any of your Taxonomy code in actions/filters. Doing so may lead to unexpected results.
+{% endhint %}
diff --git a/docs/taxonomies/Defining-hooks.md b/docs/taxonomies/Defining-hooks.md
new file mode 100644
index 0000000..bdfe5ee
--- /dev/null
+++ b/docs/taxonomies/Defining-hooks.md
@@ -0,0 +1,44 @@
+# Defining hooks
+
+Additional hooks are supported with the `hooks()` method.
+
+Here you can register additional actions and filters to WordPress and allows you to keep logic associated with your post type in one class.
+
+```php
+use PostTypes\Taxonomy;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Adds additional hooks for the post type.
+ *
+ * @return array
+ */
+ public function hooks(): array
+ {
+ add_action( 'saved_term', [ $this, 'onSave' ], 10, 5 );
+ }
+
+ /**
+ * Run additional logic when saving a term.
+ *
+ * @param int $term_id
+ * @param int $tt_id
+ * @param string $taxonomy
+ * @param bool $update
+ * @param array $args
+ * @return void
+ */
+ public function onSave(int $term_id, int $tt_id, string $taxonomy, bool $update, array $args)
+ {
+ // Check what taxonomy term we are working with...
+ if ( $taxonomy !== $this->name() ) {
+ return;
+ }
+
+ // Run additional logic when a term is saved...
+ }
+}
+```
diff --git a/docs/taxonomies/Defining-labels.md b/docs/taxonomies/Defining-labels.md
new file mode 100644
index 0000000..e0f3bbc
--- /dev/null
+++ b/docs/taxonomies/Defining-labels.md
@@ -0,0 +1,33 @@
+# Defining labels
+
+Labels for a Taxonomy are defined in the `labels()` method and should return an array of labels.
+
+By default, an empty array is returned and the WordPress default labels are used.
+
+See [`get_taxonomy_labels()`](https://developer.wordpress.org/reference/functions/get_taxonomy_labels/) for a full list of supported labels.
+
+```php
+use PostTypes\Taxonomy;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Returns the Genres labels.
+ *
+ * @return array
+ */
+ public function labels(): array
+ {
+ return [
+ 'name' => __( 'Genres', 'my-text-domain' ),
+ 'singular_name' => __( 'Genre', 'my-text-domain' ),
+ 'search_items' => __( 'Search Genres', 'my-text-domain' ),
+ 'all_items' => __( 'Genres', 'my-text-domain' ),
+ 'edit_item' => __( 'Edit Genre', 'my-text-domain' ),
+ 'view_item' => __( 'View Genre', 'my-text-domain' ),
+ ];
+ }
+}
+```
diff --git a/docs/taxonomies/Defining-options.md b/docs/taxonomies/Defining-options.md
new file mode 100644
index 0000000..f8f6c2e
--- /dev/null
+++ b/docs/taxonomies/Defining-options.md
@@ -0,0 +1,29 @@
+# Defining options
+
+Options for a Taxonomy are defined in the `options()` method and should return an array of valid [WordPress taxonomy options](https://developer.wordpress.org/reference/functions/register_taxonomy/#parameters).
+
+By default, an empty array is returned.
+
+See [`register_taxonomy()`](https://developer.wordpress.org/reference/functions/register_taxonomy/#parameters) for a full list of supported options.
+
+```php
+use PostTypes\Taxonomy;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Returns the options for the Genres taxonomy.
+ *
+ * @return array
+ */
+ public function options(): array
+ {
+ return [
+ 'public' => true,
+ 'hierarchical' => true,
+ ];
+ }
+}
+```
diff --git a/docs/taxonomies/Defining-post-types.md b/docs/taxonomies/Defining-post-types.md
new file mode 100644
index 0000000..95eef00
--- /dev/null
+++ b/docs/taxonomies/Defining-post-types.md
@@ -0,0 +1,31 @@
+# Defining Post Types
+
+Post types for a Taxonomy can be definied using the `posttypes()` method. This method should return an array of post type names to associate with the taxonomy.
+
+An empty array is returned by default and no post types are attached to the Taxonomy.
+
+```php
+use PostTypes\Taxonomy;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Returns post types attached to the Genres taxonomy.
+ *
+ * @return array
+ */
+ public function posttypes(): array
+ {
+ return [
+ 'post',
+ 'books',
+ ];
+ }
+}
+```
+
+This method only attaches the post type to the taxonomy, to _create_ a post type see the [documentation](../post-types/Create-a-post-type.md) on creating a new post type.
+
+Taxonomies and post types can be created and registered in any order.
diff --git a/docs/taxonomies/Modifying-columns.md b/docs/taxonomies/Modifying-columns.md
new file mode 100644
index 0000000..0a5d1a3
--- /dev/null
+++ b/docs/taxonomies/Modifying-columns.md
@@ -0,0 +1,160 @@
+# Modifying columns
+
+To modify a taxonomies admin columns use the `column()` method. This method accepts the `PostTypes\Columns` manager which has a variety of methods to help fine tune admin table columns.
+
+## Adding Columns
+
+To add columns to the admin list table pass an array of column slugs and labels to the `add()` method.
+
+```php
+use PostTypes\Taxonomy;
+use PostTypes\Columns;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Set the Taxonomy admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Add a new Popularity column.
+ $columns->add( 'popularity', __( 'Popularity', 'my-text-domain' ) );
+
+ // Populate the popularity column with term meta.
+ $columns->populate( 'popularity', function( $term_id ) {
+ echo '$' . get_term_meta( $term_id, '_popularity', true );
+ } );
+
+ // Make the popularity column sortable.
+ $columns->sortable( 'popularity', function( WP_Term_Query $query ) {
+ $query->query_vars['orderby'] = 'meta_value_num';
+ $query->query_vars['meta_key'] = 'popularity';
+ } );
+
+ return $columns;
+ }
+}
+```
+
+## Populate Columns
+
+To populate any column use the `populate()` method, by passing the column slug and a callback function.
+
+```php
+use PostTypes\Taxonomy;
+use PostTypes\Columns;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Set the Taxonomy admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ $columns->populate( 'popularity', function( $term_id ) {
+ echo '$' . get_term_meta( $term_id, '_popularity', true );
+ } );
+
+
+ return $columns;
+ }
+}
+```
+
+## Sortable Columns
+
+To define which custom columns are sortable use the `sortable()` method.
+
+```php
+use PostTypes\Taxonomy;
+use PostTypes\Columns;
+use WP_Term_Query;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Set the Taxonomy admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Make the popularity column sortable.
+ $columns->sortable( 'popularity', function( WP_Term_Query $query ) {
+ $query->query_vars['orderby'] = 'meta_value_num';
+ $query->query_vars['meta_key'] = 'popularity';
+ } );
+
+ return $columns;
+ }
+}
+```
+
+## Hide Columns
+
+To hide columns pass the column slug to the `hide()` method. For multiple columns pass an array of column slugs.
+
+```php
+use PostTypes\Taxonomy;
+use PostTypes\Columns;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Set the Taxonomy admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Hide the Description column.
+ $columns->hide( [ 'description' ] );
+
+ return $columns;
+ }
+}
+```
+
+## Column Order
+
+To rearrange columns pass an array of column slugs and position to the `order()` method. Only olumns you want to reorder need to be set, not all columns.
+
+
+```php
+use PostTypes\Taxonomy;
+use PostTypes\Columns;
+
+class Genres extends Taxonomy
+{
+ //...
+
+ /**
+ * Set the Taxonomy admin columns.
+ *
+ * @return array
+ */
+ public function columns( Columns $column ): Columns
+ {
+ // Order the new Popularity column.
+ $columns->order( [
+ 'popularity' => 2,
+ ] );
+
+ return $columns;
+ }
+}
+```
+
+
diff --git a/docs/taxonomies/README.md b/docs/taxonomies/README.md
index af22a96..042032a 100644
--- a/docs/taxonomies/README.md
+++ b/docs/taxonomies/README.md
@@ -3,5 +3,8 @@
The following section contains information on creating and working with taxonomies.
* [Create a Taxonomy](Create-a-taxonomy.md)
-* [Add to Post Type](Add-to-post-type.md)
-* [Columns](Columns.md)
+* [Defining Labels](Defining-labels.md)
+* [Defining Options](Defining-options.md)
+* [Defining Post Types](Defining-post-types.md)
+* [Modifying Columns](Modifying-columns.md)
+* [Defining Hooks](Defining-hooks.md)
diff --git a/examples/Genres.php b/examples/Genres.php
new file mode 100644
index 0000000..5086a7a
--- /dev/null
+++ b/examples/Genres.php
@@ -0,0 +1,66 @@
+remove(['posts']);
+
+ $columns->add(
+ 'popularity',
+ __( 'Popularity', 'post-types' ),
+ function( $term_id ) {
+ echo get_term_meta( $term_id, 'popularity', true );
+ }
+ );
+
+ $columns->order( [
+ 'popularity' => 2,
+ ] );
+
+ $columns->sortable( 'popularity', function( $query ) {
+ $query->query_vars['orderby'] = 'meta_value';
+ $query->query_vars['meta_key'] = 'popularity';
+ } );
+
+ return $columns;
+ }
+
+ public function labels(): array {
+ return [
+ 'name' => __( 'Genres', 'post-types' ),
+ 'singular_name' => __( 'Genre', 'post-types' ),
+ 'menu_name' => __( 'Genres', 'post-types' ),
+ 'all_items' => __( 'All Genres', 'post-types' ),
+ 'edit_item' => __( 'Edit Genre', 'post-types' ),
+ 'view_item' => __( 'View Genre', 'post-types' ),
+ 'update_item' => __( 'Update Genre', 'post-types' ),
+ 'add_new_item' => __( 'Add New Genre', 'post-types' ),
+ 'new_item_name' => __( 'New Genre', 'post-types' ),
+ 'parent_item' => __( 'Parent Genres', 'post-types' ),
+ 'parent_item_colon' => __( 'Parent Genres: ', 'post-types' ),
+ 'search_items' => __( 'Search Genres', 'post-types' ),
+ 'popular_items' => __( 'Popular Genres', 'post-types' ),
+ 'separate_items_with_commas' => __( 'Seperate Genres with commas', 'post-types' ),
+ 'add_or_remove_items' => __( 'Add or remove Genres', 'post-types' ),
+ 'choose_from_most_used' => __( 'Choose from most used Genres', 'post-types' ),
+ 'not_found' => __( 'No Genres found', 'post-types' ),
+ ];
+ }
+}
diff --git a/examples/Price.php b/examples/Price.php
new file mode 100644
index 0000000..6246a79
--- /dev/null
+++ b/examples/Price.php
@@ -0,0 +1,31 @@
+set('orderby', 'meta_value_num');
+ $query->set('meta_key', 'price');
+ }
+}
diff --git a/examples/books.php b/examples/books.php
index 8451431..a3c5e32 100644
--- a/examples/books.php
+++ b/examples/books.php
@@ -1,59 +1,93 @@
__( 'Book', 'post-types' ),
+ 'singular_name' => __( 'Book', 'post-types' ),
+ 'menu_name' => __( 'Books', 'post-types' ),
+ 'all_items' => __( 'Books', 'post-types' ),
+ 'add_new' => __( 'Add New', 'post-types' ),
+ 'add_new_item' => __( 'Add New Book', 'post-types' ),
+ 'edit_item' => __( 'Edit Book', 'post-types' ),
+ 'new_item' => __( 'New Book', 'post-types' ),
+ 'view_item' => __( 'View Book', 'post-types' ),
+ 'search_items' => __( 'Search Books', 'post-types' ),
+ 'not_found' => __( 'No Books found', 'post-types' ),
+ 'not_found_in_trash' => __( 'No Books found in Trash', 'post-types'),
+ 'parent_item_colon' => __( 'Parent Book', 'post-types' ),
+ ];
+ }
-// Create a books Post Type
-$books = new PostType( 'book' );
+ public function taxonomies(): array {
+ return [
+ 'post_tag',
+ 'genre',
+ ];
+ }
-// Add the Genre Taxonomy
-$books->taxonomy( 'genre' );
+ public function supports(): array {
+ return [
+ 'title',
+ 'editor',
+ 'author',
+ 'custom-fields',
+ ];
+ }
-// Hide the date and author columns
-$books->columns()->hide( [ 'date', 'author' ] );
+ public function options(): array {
+ return [
+ 'show_in_rest' => false,
+ ];
+ }
-// add a price and rating column
-$books->columns()->add( [
- 'rating' => __( 'Rating' ),
- 'price' => __( 'Price' )
-] );
+ public function icon(): string {
+ return 'dashicons-book';
+ }
-// Populate the custom column
-$books->columns()->populate( 'rating', function( $column, $post_id ) {
- echo get_post_meta( $post_id, 'rating' ) . '/10';
-} );
+ public function filters(): array {
+ return [
+ 'genre',
+ 'post_tag',
+ ];
+ }
-// Populate the custom column
-$books->columns()->populate( 'price', function( $column, $post_id ) {
- echo '£' . get_post_meta( $post_id, 'price' );
-} );
+ public function columns( Columns $columns ): Columns {
-// Set sortable columns
-$books->columns()->sortable( [
- 'price' => [ 'price', true ],
- 'rating' => [ 'rating', true ]
-] );
+ $columns->remove( [ 'author', 'date' ] );
-// Set the Books menu icon
-$books->icon( 'dashicons-book-alt' );
+ $columns->column( new Price );
-// Register the PostType to WordPress
-$books->register();
+ $columns->add( 'rating', __( 'Rating', 'post-types' ) );
-// Create the genre Taxonomy
-$genres = new Taxonomy( 'genre' );
+ $columns->populate( 'rating', function( $post_id ) {
+ echo get_post_meta( $post_id, 'rating', true );
+ } );
-// Add a popularity column to the genre taxonomy
-$genres->columns()->add( [
- 'popularity' => 'Popularity'
-] );
+ $columns->sortable( 'rating', function( $query ) {
+ $query->set('orderby', 'meta_value_num');
+ $query->set('meta_key', 'rating');
+ } );
-// Populate the new column
-$genres->columns()->populate( 'popularity', function( $content, $column, $term_id ) {
- return get_term_meta( $term_id, 'popularity', true );
-} );
+ $columns->order( [
+ 'price' => 4,
+ 'rating' => 5,
+ 'taxonomy-genre' => 2,
+ 'tags' => 3,
+ ] );
-// Register the taxonomy to WordPress
-$genres->register();
+ return $columns;
+ }
+}
diff --git a/src/Column.php b/src/Column.php
new file mode 100644
index 0000000..857c7b0
--- /dev/null
+++ b/src/Column.php
@@ -0,0 +1,67 @@
+name()));
+ }
+
+ /**
+ * Populate the column.
+ *
+ * @param integer $objectId
+ * @return void
+ */
+ public function populate(int $objectId): void
+ {
+ return;
+ }
+
+ /**
+ * Set the column order.
+ *
+ * @return integer|null
+ */
+ public function order(): ?int
+ {
+ return null;
+ }
+
+ /**
+ * Handle sorting the column.
+ *
+ * @param \WP_Query|\WP_Term_Query $query
+ * @return void
+ */
+ public function sort($query)
+ {
+ return;
+ }
+
+ /**
+ * Can the column be sorted.
+ *
+ * @return boolean
+ */
+ public function isSortable(): bool
+ {
+ return false;
+ }
+}
diff --git a/src/Columns.php b/src/Columns.php
index 14ac23d..cdd7be5 100644
--- a/src/Columns.php
+++ b/src/Columns.php
@@ -2,239 +2,210 @@
namespace PostTypes;
-/**
- * Columns
- *
- * Used to help manage a post types columns in the admin table
- *
- * @link https://github.com/jjgrainger/PostTypes/
- * @author jjgrainger
- * @link https://jjgrainger.co.uk
- * @version 2.2.1
- * @license https://opensource.org/licenses/mit-license.html MIT License
- */
+use PostTypes\Contracts\ColumnContract;
+
class Columns
{
/**
- * Holds an array of all the defined columns.
- *
- * @var array
- */
- public $items = [];
-
- /**
- * An array of columns to add.
+ * Columns to add.
*
* @var array
*/
public $add = [];
/**
- * An array of columns to hide.
+ * Column populate callbacks.
*
* @var array
*/
- public $hide = [];
+ public $populate = [];
/**
- * An array of columns to reposition.
+ * Columns to remove.
*
* @var array
*/
- public $positions = [];
+ public $remove = [];
/**
- * An array of custom populate callbacks.
+ * Columns order.
*
* @var array
*/
- public $populate = [];
+ public $order = [];
/**
- * An array of columns that are sortable.
+ * Sortable columns and sort callbacks.
*
* @var array
*/
public $sortable = [];
/**
- * Set the all columns
- * @param array $columns an array of all the columns to replace
+ * Add a column object.
+ *
+ * @param ColumnContract $column
+ * @return void
*/
- public function set($columns)
+ public function column(ColumnContract $column)
{
- $this->items = $columns;
- }
+ $this->add($column->name(), $column->label());
- /**
- * Add a new column
- * @param string $column the slug of the column
- * @param string $label the label for the column
- */
- public function add($columns, $label = null)
- {
+ $this->populate($column->name(), [$column, 'populate']);
- if (!is_array($columns)) {
- $columns = [$columns => $label];
+ if (!is_null($column->order())) {
+ $this->order[$column->name()] = $column->order();
}
- foreach ($columns as $column => $label) {
- if (is_null($label)) {
- $label = str_replace(['_', '-'], ' ', ucfirst($column));
- }
-
- $this->add[$column] = $label;
+ if ($column->isSortable()) {
+ $this->sortable($column->name(), [$column, 'sort']);
}
-
- return $this;
}
/**
- * Add a column to hide
- * @param string $column the slug of the column to hdie
+ * Add a column.
+ *
+ * @param string $key
+ * @param string $label
+ * @param callable|null $callback
+ * @return void
*/
- public function hide($columns)
+ public function add(string $key, string $label, callable $callback = null)
{
- if (!is_array($columns)) {
- $columns = [$columns];
- }
+ $this->add[$key] = $label;
- foreach ($columns as $column) {
- $this->hide[] = $column;
+ if (is_callable($callback)) {
+ $this->populate($key, $callback);
}
-
- return $this;
}
/**
- * Set a custom callback to populate a column
- * @param string $column the column slug
- * @param mixed $callback callback function
+ * Set column populate callback.
+ *
+ * @param string $key
+ * @param callable $callback
+ * @return void
*/
- public function populate($column, $callback)
+ public function populate(string $key, callable $callback)
{
- $this->populate[$column] = $callback;
-
- return $this;
+ $this->populate[$key] = $callback;
}
/**
- * Define the postion for a columns
- * @param string $columns an array of columns
+ * Remove columns.
+ *
+ * @param array $keys
+ * @return void
*/
- public function order($columns)
+ public function remove(array $keys)
{
- foreach ($columns as $column => $position) {
- $this->positions[$column] = $position;
- }
-
- return $this;
+ $this->remove = array_merge($this->remove, $keys);
}
/**
- * Set columns that are sortable
- * @param string $column the slug of the column
- * @param string $meta_value the meta_value to orderby
- * @param boolean $is_num whether to order by string/number
+ * Set columns order
+ *
+ * @param array $order
+ * @return void
*/
- public function sortable($sortable)
+ public function order(array $order)
{
- foreach ($sortable as $column => $options) {
- $this->sortable[$column] = $options;
- }
-
- return $this;
+ $this->order = array_merge($this->order, $order);
}
/**
- * Check if an orderby field is a custom sort option.
- * @param string $orderby the orderby value from query params
+ * Set sortable columns and sort callback.
+ *
+ * @param string $key
+ * @param callable $callback
+ * @return void
*/
- public function isSortable($orderby)
+ public function sortable(string $key, callable $callback)
{
- if (is_string($orderby) && array_key_exists($orderby, $this->sortable)) {
- return true;
- }
-
- foreach ($this->sortable as $column => $options) {
- if (is_string($options) && $options === $orderby) {
- return true;
- }
- if (is_array($options) && isset($options[0]) && $options[0] === $orderby) {
- return true;
- }
- }
-
- return false;
+ $this->sortable[$key] = $callback;
}
/**
- * Get meta key for an orderby.
- * @param string $orderby the orderby value from query params
+ * Apply columns.
+ *
+ * @param array $columns
+ * @return void
*/
- public function sortableMeta($orderby)
+ public function applyColumns(array $columns)
{
- if (array_key_exists($orderby, $this->sortable)) {
- return $this->sortable[$orderby];
+ if (!empty($this->add)) {
+ $columns = array_merge($columns, $this->add);
}
- foreach ($this->sortable as $column => $options) {
- if (is_string($options) && $options === $orderby) {
- return $options;
- }
- if (is_array($options) && isset($options[0]) && $options[0] === $orderby) {
- return $options;
+ if (!empty($this->remove)) {
+ $columns = array_diff_key($columns, array_flip($this->remove));
+ }
+
+ if (!empty($this->order)) {
+ $order = $this->order;
+
+ // Sort the order array.
+ asort($order);
+
+ // Flip order so the index is the position.
+ $order = array_flip($order);
+
+ // Create the current order array.
+ $current = array_keys($columns);
+
+ // Loop over the order.
+ foreach ($order as $index => $key) {
+ array_splice($current, $index, 0, $key);
}
+
+ $new = array_flip(array_unique($current));
+
+ $columns = array_merge($new, $columns);
}
- return '';
+ return $columns;
}
/**
- * Modify the columns for the object
- * @param array $columns WordPress default columns
- * @return array The modified columns
+ * Populate a column.
+ *
+ * @param string $column
+ * @param array $params
+ * @return void
*/
- public function modifyColumns($columns)
+ public function populateColumn(string $column, array $params)
{
- // if user defined set columns, return those
- if (!empty($this->items)) {
- return $this->items;
+ if (isset($this->populate[$column]) && is_callable($this->populate[$column])) {
+ call_user_func_array($this->populate[$column], $params);
}
+ }
- // add additional columns
- if (!empty($this->add)) {
- foreach ($this->add as $key => $label) {
- $columns[$key] = $label;
- }
+ /**
+ * Set sortable columns
+ *
+ * @param array $columns
+ * @return array
+ */
+ public function setSortable(array $columns): array
+ {
+ foreach (array_keys($this->sortable) as $key) {
+ $columns[$key] = $key;
}
- // unset hidden columns
- if (!empty($this->hide)) {
- foreach ($this->hide as $key) {
- unset($columns[$key]);
- }
- }
+ return $columns;
+ }
- // if user has made added custom columns
- if (!empty($this->positions)) {
- foreach ($this->positions as $key => $position) {
- // find index of the element in the array
- $index = array_search($key, array_keys($columns));
- // retrieve the element in the array of columns
- $item = array_slice($columns, $index, 1);
- // remove item from the array
- unset($columns[$key]);
-
- // split columns array into two at the desired position
- $start = array_slice($columns, 0, $position, true);
- $end = array_slice($columns, $position, count($columns) - 1, true);
-
- // insert column into position
- $columns = $start + $item + $end;
- }
+ /**
+ * Sort a column.
+ *
+ * @param string $column
+ * @param \WP_Query|\WP_Term_Query $query
+ * @return void
+ */
+ public function sortColumn(string $column, $query)
+ {
+ if (isset($this->sortable[$column]) && is_callable($this->sortable[$column])) {
+ call_user_func_array($this->sortable[$column], [$query]);
}
-
- return $columns;
}
}
diff --git a/src/Contracts/ColumnContract.php b/src/Contracts/ColumnContract.php
new file mode 100644
index 0000000..45c955e
--- /dev/null
+++ b/src/Contracts/ColumnContract.php
@@ -0,0 +1,50 @@
+names($names);
-
- // assign custom options to the PostType
- $this->options($options);
-
- // assign labels to the PostType
- $this->labels($labels);
+ return $this->name();
}
/**
- * Set the names for the PostType
- * @param mixed $names A string for the name, or an array of names
- * @return $this
+ * Post type labels.
+ *
+ * @return array
*/
- public function names($names)
+ public function labels(): array
{
- // only the post type name is passed
- if (is_string($names)) {
- $names = ['name' => $names];
- }
-
- // set the names array
- $this->names = $names;
-
- // create names for the PostType
- $this->createNames();
-
- return $this;
+ return [];
}
/**
- * Set the options for the PostType
- * @param array $options An array of options for the PostType
- * @return $this
+ * Post type options.
+ *
+ * @return array
*/
- public function options(array $options)
+ public function options(): array
{
- $this->options = $options;
-
- return $this;
+ return [];
}
/**
- * Set the labels for the PostType
- * @param array $labels An array of labels for the PostType
- * @return $this
+ * Post type taxonomies.
+ *
+ * @return array
*/
- public function labels(array $labels)
+ public function taxonomies(): array
{
- $this->labels = $labels;
-
- return $this;
+ return [];
}
/**
- * Add a Taxonomy to the PostType
- * @param mixed $taxonomies The Taxonomy name(s) to add
- * @return $this
- */
- public function taxonomy($taxonomies)
- {
- $taxonomies = is_string($taxonomies) ? [$taxonomies] : $taxonomies;
-
- foreach ($taxonomies as $taxonomy) {
- $this->taxonomies[] = $taxonomy;
- }
-
- return $this;
- }
-
- /**
- * Add filters to the PostType
- * @param array $filters An array of Taxonomy filters
- * @return $this
+ * Post type supports.
+ *
+ * @return array
*/
- public function filters(array $filters)
+ public function supports(): array
{
- $this->filters = $filters;
-
- return $this;
+ return [
+ 'title',
+ 'editor',
+ ];
}
/**
- * Set the menu icon for the PostType
- * @param string $icon A dashicon class for the menu icon
- * @return $this
+ * Post type icon.
+ *
+ * @return string|null
*/
- public function icon($icon)
+ public function icon(): ?string
{
- $this->icon = $icon;
-
- return $this;
+ return null;
}
/**
- * Flush rewrite rules
- * @link https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
- * @param boolean $hard
- * @return void
+ * Post type filters.
+ *
+ * @return array
*/
- public function flush($hard = true)
+ public function filters(): array
{
- flush_rewrite_rules($hard);
+ return [];
}
/**
- * Get the Column Manager for the PostType
+ * Post type columns.
+ *
+ * @param Columns $columns
* @return Columns
*/
- public function columns()
+ public function columns(Columns $columns): Columns
{
- if (!isset($this->columns)) {
- $this->columns = new Columns;
- }
-
- return $this->columns;
+ return $columns;
}
/**
- * Register the PostType to WordPress
+ * Post type additional hooks.
+ *
* @return void
*/
- public function register()
+ public function hooks(): void
{
- (new PostTypeRegistrar($this))->register();
+ return;
}
/**
- * Create the required names for the PostType
+ * Register the post type.
+ *
* @return void
*/
- public function createNames()
- {
- // names required for the PostType
- $required = [
- 'name',
- 'singular',
- 'plural',
- 'slug',
- ];
-
- foreach ($required as $key) {
- // if the name is set, assign it
- if (isset($this->names[$key])) {
- $this->$key = $this->names[$key];
- continue;
- }
-
- // if the key is not set and is singular or plural
- if (in_array($key, ['singular', 'plural'])) {
- // create a human friendly name
- $name = ucwords(strtolower(str_replace(['-', '_'], ' ', $this->names['name'])));
- }
-
- if ($key === 'slug') {
- // create a slug friendly name
- $name = strtolower(str_replace([' ', '_'], '-', $this->names['name']));
- }
-
- // if is plural or slug, append an 's'
- if (in_array($key, ['plural', 'slug'])) {
- if (substr($name, strlen($name) - 1, 1) == "y") {
- $name = substr($name, 0, strlen($name) - 1) . "ies";
- } else {
- $name .= 's';
- }
- }
-
- // asign the name to the PostType property
- $this->$key = $name;
- }
- }
-
- /**
- * Create options for PostType
- * @return array Options to pass to register_post_type
- */
- public function createOptions()
- {
- // default options
- $options = [
- 'public' => true,
- 'rewrite' => [
- 'slug' => $this->slug
- ]
- ];
-
- // replace defaults with the options passed
- $options = array_replace_recursive($options, $this->options);
-
- // create and set labels
- if (!isset($options['labels'])) {
- $options['labels'] = $this->createLabels();
- }
-
- // set the menu icon
- if (!isset($options['menu_icon']) && isset($this->icon)) {
- $options['menu_icon'] = $this->icon;
- }
-
- return $options;
- }
-
- /**
- * Create the labels for the PostType
- * @return array
- */
- public function createLabels()
- {
- // default labels
- $labels = [
- 'name' => $this->plural,
- 'singular_name' => $this->singular,
- 'menu_name' => $this->plural,
- 'all_items' => $this->plural,
- 'add_new' => "Add New",
- 'add_new_item' => "Add New {$this->singular}",
- 'edit_item' => "Edit {$this->singular}",
- 'new_item' => "New {$this->singular}",
- 'view_item' => "View {$this->singular}",
- 'search_items' => "Search {$this->plural}",
- 'not_found' => "No {$this->plural} found",
- 'not_found_in_trash' => "No {$this->plural} found in Trash",
- 'parent_item_colon' => "Parent {$this->singular}:",
- ];
-
- return array_replace_recursive($labels, $this->labels);
- }
-
- /**
- * Calculate the filters for the PostType
- * @return array
- */
- public function getFilters()
+ public function register(): void
{
- // default filters are empty
- $filters = [];
-
- // if custom filters have been set, use them
- if (!is_null($this->filters)) {
- return $this->filters;
- }
-
- // if no custom filters have been set, and there are
- // Taxonomies assigned to the PostType
- if (is_null($this->filters) && !empty($this->taxonomies)) {
- // create filters for each taxonomy assigned to the PostType
- return $this->taxonomies;
- }
-
- return $filters;
+ (new PostTypeRegistrar($this))->register();
}
}
diff --git a/src/Registrars/PostTypeRegistrar.php b/src/Registrars/PostTypeRegistrar.php
index 898e41f..6923693 100644
--- a/src/Registrars/PostTypeRegistrar.php
+++ b/src/Registrars/PostTypeRegistrar.php
@@ -2,220 +2,215 @@
namespace PostTypes\Registrars;
-use PostTypes\PostType;
+use PostTypes\Contracts\PostTypeContract;
+use PostTypes\Columns;
class PostTypeRegistrar
{
- protected $posttype;
+ /**
+ * PostType to register.
+ *
+ * @var PostTypeContract
+ */
+ private $posttype;
+
+ /**
+ * The PostType columns.
+ *
+ * @var Columns
+ */
+ private $columns;
- public function __construct(PostType $posttype)
+ /**
+ * Constructor.
+ *
+ * @param PostTypeContract $posttype
+ */
+ public function __construct(PostTypeContract $posttype)
{
$this->posttype = $posttype;
}
+ /**
+ * Register the PostType to WordPress.
+ *
+ * @return void
+ */
public function register()
{
- // Get the PostType name.
- $name = $this->posttype->name;
+ $name = $this->posttype->name();
- // Register the PostType
- if (!post_type_exists($name)) {
- add_action('init', [$this, 'registerPostType'], 10);
- } else {
- add_filter('register_post_type_args', [$this, 'modifyPostType'], 10, 2);
- }
-
- // register Taxonomies to the PostType
- add_action('init', [$this, 'registerTaxonomies'], 10);
+ // Initialize the post type.
+ add_action('init', [$this, 'createColumns'], 10, 0);
+ add_action('init', [$this, 'initialize'], 10, 0);
- // modify filters on the admin edit screen
- add_action('restrict_manage_posts', [$this, 'modifyFilters'], 10, 1);
+ // Handle PostType filters.
+ add_action('restrict_manage_posts', [$this, 'modifyFilters'], 10, 2);
- if (isset($this->posttype->columns)) {
- // modify the admin edit columns.
- add_filter('manage_' . $name . '_posts_columns', [$this, 'modifyColumns'], 10, 1);
+ // Handle PostType columns.
+ add_filter('manage_' . $name . '_posts_columns', [$this, 'modifyColumns'], 10, 1);
+ add_filter('manage_' . $name . '_posts_custom_column', [$this, 'populateColumns'], 10, 2);
+ add_filter('manage_edit-' . $name . '_sortable_columns', [$this, 'setSortableColumns'], 10, 1);
+ add_action('pre_get_posts', [$this, 'sortSortableColumns'], 10, 1);
- // populate custom columns
- add_filter('manage_' . $name . '_posts_custom_column', [$this, 'populateColumns'], 10, 2);
-
- // run filter to make columns sortable.
- add_filter('manage_edit-' . $name . '_sortable_columns', [$this, 'setSortableColumns'], 10, 1);
+ // Register custom hooks.
+ $this->posttype->hooks();
+ }
- // run action that sorts columns on request.
- add_action('pre_get_posts', [$this, 'sortSortableColumns'], 10, 1);
- }
+ /**
+ * Create Columns.
+ *
+ * @return void
+ */
+ public function createColumns()
+ {
+ $this->columns = $this->posttype->columns(new Columns());
}
/**
- * Register the PostType
+ * Register Post Type.
+ *
* @return void
*/
- public function registerPostType()
+ public function initialize()
{
- // create options for the PostType
- $options = $this->posttype->createOptions();
+ // Modify the existing PostType if it exists.
+ if (post_type_exists($this->posttype->name())) {
+ add_filter('register_post_type_args', [$this, 'modifyPostType'], 10, 2);
- // check that the post type doesn't already exist
- if (!post_type_exists($this->posttype->name)) {
- // register the post type
- register_post_type($this->posttype->name, $options);
+ return;
}
+
+ // Register the new PostType to WordPress.
+ register_post_type($this->posttype->name(), $this->generateOptions());
}
/**
- * Modify the existing Post Type.
+ * Modify the existing PostType.
*
+ * @param array $args
+ * @param string $posttype
* @return array
*/
public function modifyPostType(array $args, string $posttype)
{
- if ($posttype !== $this->posttype->name) {
+ if ($posttype !== $this->posttype->name()) {
return $args;
}
- // create options for the PostType
- $options = $this->posttype->createOptions();
-
- return array_replace_recursive($args, $options);
+ return array_replace_recursive($args, $this->generateOptions());
}
/**
- * Register Taxonomies to the PostType
- * @return void
+ * Generate the options for the PostType.
+ *
+ * @return array
*/
- public function registerTaxonomies()
+ public function generateOptions()
{
- if (empty($this->posttype->taxonomies)) {
- return;
- }
-
- foreach ($this->posttype->taxonomies as $taxonomy) {
- register_taxonomy_for_object_type($taxonomy, $this->posttype->name);
- }
+ $defaults = [
+ 'public' => true,
+ 'show_in_rest' => true,
+ 'labels' => $this->posttype->labels(),
+ 'taxonomies' => $this->posttype->taxonomies(),
+ 'supports' => $this->posttype->supports(),
+ 'menu_icon' => $this->posttype->icon(),
+ 'rewrite' => [
+ 'slug' => $this->posttype->slug(),
+ ],
+ ];
+
+ return array_replace_recursive($defaults, $this->posttype->options());
}
/**
- * Modify and display filters on the admin edit screen
- * @param string $posttype The current screen post type
+ * Modify the PostType filters.
+ *
+ * @param string $posttype
* @return void
*/
public function modifyFilters($posttype)
{
- // first check we are working with the this PostType
- if ($posttype === $this->posttype->name) {
- // calculate what filters to add
- $filters = $this->posttype->getFilters();
-
- foreach ($filters as $taxonomy) {
- // if the taxonomy doesn't exist, ignore it
- if (!taxonomy_exists($taxonomy)) {
- continue;
- }
-
- // If the taxonomy is not registered to the post type, continue.
- if (!is_object_in_taxonomy($this->posttype->name, $taxonomy)) {
- continue;
- }
-
- // get the taxonomy object
- $tax = get_taxonomy($taxonomy);
-
- // start the html for the filter dropdown
- $selected = null;
-
- if (isset($_GET[$taxonomy])) {
- $selected = sanitize_title($_GET[$taxonomy]);
- }
-
- $dropdown_args = [
- 'name' => $taxonomy,
- 'value_field' => 'slug',
- 'taxonomy' => $tax->name,
- 'show_option_all' => $tax->labels->all_items,
- 'hierarchical' => $tax->hierarchical,
- 'selected' => $selected,
- 'orderby' => 'name',
- 'hide_empty' => 0,
- 'show_count' => 0,
- ];
-
- // Output screen reader label.
- sprintf(
- '',
- $taxonomy,
- $tax->labels->filter_by_item
- );
-
- // Output dropdown for taxonomy.
- wp_dropdown_categories($dropdown_args);
+ if ($posttype !== $this->posttype->name()) {
+ return;
+ }
+
+ foreach ($this->posttype->filters() as $taxonomy) {
+ if (!is_object_in_taxonomy($posttype, $taxonomy)) {
+ continue;
}
+
+ $query_var = get_taxonomy($taxonomy)->query_var;
+ $selected = isset($_GET[$query_var]) ? $_GET[$query_var] : '';
+
+ $options = [
+ 'name' => $query_var, //$taxonomy,
+ 'value_field' => 'slug',
+ 'taxonomy' => $taxonomy,
+ 'show_option_all' => get_taxonomy($taxonomy)->labels->all_items,
+ 'hierarchical' => get_taxonomy($taxonomy)->hierarchical,
+ 'hide_empty' => 0,
+ 'show_count' => 0,
+ 'orderby' => 'name',
+ 'selected' => $selected, //isset($_GET[$taxonomy]) ? $_GET[$taxonomy] : '',
+ ];
+
+ echo '';
+
+ wp_dropdown_categories($options);
}
}
/**
- * Modify the columns for the PostType
- * @param array $columns Default WordPress columns
- * @return array The modified columns
+ * Modify the PostType columns.
+ *
+ * @param array $columns
+ * @return array
*/
- public function modifyColumns($columns)
+ public function modifyColumns(array $columns)
{
- return $this->posttype->columns->modifyColumns($columns);
+ return $this->columns->applyColumns($columns);
}
+
/**
- * Populate custom columns for the PostType
- * @param string $column The column slug
- * @param int $post_id The post ID
+ * Populate the PostType columns.
+ *
+ * @param string $column
+ * @param int $post_id
+ * @return void
*/
public function populateColumns($column, $post_id)
{
- if (isset($this->posttype->columns->populate[$column])) {
- call_user_func_array($this->posttype->columns()->populate[$column], [$column, $post_id]);
- }
+ $this->columns->populateColumn($column, [$post_id]);
}
/**
- * Make custom columns sortable
- * @param array $columns Default WordPress sortable columns
+ * Set the PostTypes sortable columns.
+ *
+ * @param array $columns
+ * @return array
*/
public function setSortableColumns($columns)
{
- if (!empty($this->posttype->columns()->sortable)) {
- $columns = array_merge($columns, $this->posttype->columns()->sortable);
- }
-
- return $columns;
+ return $this->columns->setSortable($columns);
}
/**
- * Set query to sort custom columns
- * @param WP_Query $query
+ * Sort PostType columns.
+ *
+ * @param \WP_Query $query
+ * @return void
*/
public function sortSortableColumns($query)
{
- // don't modify the query if we're not in the post type admin
- if (!is_admin() || $query->get('post_type') !== $this->posttype->name) {
+ if (!is_admin() || !$query->is_main_query()) {
return;
}
- $orderby = $query->get('orderby');
-
- // if the sorting a custom column
- if ($this->posttype->columns()->isSortable($orderby)) {
- // get the custom column options
- $meta = $this->posttype->columns()->sortableMeta($orderby);
+ $column = $query->get('orderby');
- // determine type of ordering
- if (is_string($meta) or !$meta[1]) {
- $meta_key = $meta;
- $meta_value = 'meta_value';
- } else {
- $meta_key = $meta[0];
- $meta_value = 'meta_value_num';
- }
-
- // set the custom order
- $query->set('meta_key', $meta_key);
- $query->set('orderby', $meta_value);
- }
+ $this->columns->sortColumn($column, $query);
}
}
diff --git a/src/Registrars/TaxonomyRegistrar.php b/src/Registrars/TaxonomyRegistrar.php
index d6da048..1548c06 100644
--- a/src/Registrars/TaxonomyRegistrar.php
+++ b/src/Registrars/TaxonomyRegistrar.php
@@ -2,144 +2,160 @@
namespace PostTypes\Registrars;
-use PostTypes\Taxonomy;
+use PostTypes\Contracts\TaxonomyContract;
+use PostTypes\Columns;
class TaxonomyRegistrar
{
- protected $taxonomy;
+ /**
+ * Taxonomy to register.
+ *
+ * @var TaxonomyContract
+ */
+ private $taxonomy;
+
+ /**
+ * Taxonomy Columns.
+ *
+ * @var Columns
+ */
+ private $columns;
- public function __construct(Taxonomy $taxonomy)
+ /**
+ * Constructor.
+ *
+ * @param TaxonomyContract $taxonomy
+ */
+ public function __construct(TaxonomyContract $taxonomy)
{
$this->taxonomy = $taxonomy;
}
+ /**
+ * Register the Taxonomy to WordPress.
+ *
+ * @return void
+ */
public function register()
{
- // Get the Taxonomy name.
- $name = $this->taxonomy->name;
+ $name = $this->taxonomy->name();
- // Register the taxonomy, set priority to 9 so taxonomies are registered before PostTypes
add_action('init', [$this, 'registerTaxonomy'], 9);
+ add_action('init', [$this, 'registerTaxonomyToPostTypes'], 10);
+ add_action('init', [$this, 'createcolumns'], 10);
- // Assign taxonomy to post type objects
- add_action('init', [$this, 'registerTaxonomyToObjects'], 10);
-
- if (isset($this->taxonomy->columns)) {
- // Modify the columns for the Taxonomy
- add_filter("manage_edit-' . $name . '_columns", [$this, 'modifyColumns']);
-
- // populate the columns for the Taxonomy
- add_filter('manage_' . $name . '_custom_column', [$this, 'populateColumns'], 10, 3);
+ // Handle Taxonomy columns.
+ add_filter('manage_edit-' . $name . '_columns', [$this, 'modifyColumns'], 10, 1);
+ add_filter('manage_' . $name . '_custom_column', [$this, 'populateColumns'], 10, 3);
+ add_filter('manage_edit-' . $name . '_sortable_columns', [$this, 'setSortableColumns'], 10, 1);
+ add_action('parse_term_query', [$this, 'sortSortableColumns'], 10, 1);
- // set custom sortable columns
- add_filter('manage_edit-' . $name . '_sortable_columns', [$this, 'setSortableColumns']);
+ // Register custom hooks.
+ $this->taxonomy->hooks();
+ }
- // run action that sorts columns on request
- add_action('parse_term_query', [$this, 'sortSortableColumns']);
- }
+ /**
+ * Create Columns.
+ *
+ * @return void
+ */
+ public function createColumns()
+ {
+ $this->columns = $this->taxonomy->columns(new Columns());
}
/**
- * Register the Taxonomy to WordPress
+ * Register the Taxonomy.
+ *
* @return void
*/
public function registerTaxonomy()
{
- // Get the existing taxonomy options if it exists.
- $options = (taxonomy_exists($this->taxonomy->name)) ? (array) get_taxonomy($this->taxonomy->name) : [];
-
- // create options for the Taxonomy.
- $options = array_replace_recursive($options, $this->taxonomy->createOptions());
+ register_taxonomy($this->taxonomy->name(), null, $this->generateOptions());
+ }
- // register the Taxonomy with WordPress.
- register_taxonomy($this->taxonomy->name, null, $options);
+ /**
+ * Generate Taxonomy options.
+ *
+ * @return array
+ */
+ public function generateOptions()
+ {
+ $defaults = [
+ 'public' => true,
+ 'show_in_rest' => true,
+ 'hierarchical' => true,
+ 'show_admin_column' => true,
+ 'labels' => $this->taxonomy->labels(),
+ 'rewrite' => [
+ 'slug' => $this->taxonomy->slug(),
+ ],
+ ];
+
+ return array_replace_recursive($defaults, $this->taxonomy->options());
}
/**
- * Register the Taxonomy to PostTypes
+ * Register Taxonomy to post types.
+ *
* @return void
*/
- public function registerTaxonomyToObjects()
+ public function registerTaxonomyToPostTypes()
{
- // register Taxonomy to each of the PostTypes assigned
- if (empty($this->taxonomy->posttypes)) {
- return;
- }
-
- foreach ($this->taxonomy->posttypes as $posttype) {
- register_taxonomy_for_object_type($this->taxonomy->name, $posttype);
+ foreach ($this->taxonomy->posttypes() as $posttype) {
+ register_taxonomy_for_object_type($this->taxonomy->name(), $posttype);
}
}
/**
- * Modify the columns for the Taxonomy
- * @param array $columns The WordPress default columns
+ * Modify the Taxonomy columns.
+ *
+ * @param array $columns
* @return array
*/
- public function modifyColumns($columns)
+ public function modifyColumns(array $columns)
{
- return $this->taxonomy->columns->modifyColumns($columns);
+ return $this->columns->applyColumns($columns);
}
/**
- * Populate custom columns for the Taxonomy
- * @param string $content
- * @param string $column
- * @param int $term_id
+ * Populate Taxonomy column.
+ *
+ * @param string $content
+ * @param string $column
+ * @param int $term_id
+ * @return void
*/
public function populateColumns($content, $column, $term_id)
{
- if (isset($this->taxonomy->columns->populate[$column])) {
- $content = call_user_func_array(
- $this->taxonomy->columns()->populate[$column],
- [$content, $column, $term_id]
- );
- }
-
- return $content;
+ $this->columns->populateColumn($column, [$term_id, $content]);
}
/**
- * Make custom columns sortable
- * @param array $columns Default WordPress sortable columns
+ * Set the Taxonomy sortable columns.
+ *
+ * @param array $columns
+ * @return array
*/
public function setSortableColumns($columns)
{
- if (!empty($this->taxonomy->columns()->sortable)) {
- $columns = array_merge($columns, $this->taxonomy->columns()->sortable);
- }
-
- return $columns;
+ return $this->columns->setSortable($columns);
}
/**
- * Set query to sort custom columns
- * @param WP_Term_Query $query
+ * Sort Taxonomy column.
+ *
+ * @param \WP_Term_Query $query
+ * @return void
*/
public function sortSortableColumns($query)
{
- // don't modify the query if we're not in the post type admin
- if (!is_admin() || !in_array($this->taxonomy->name, $query->query_vars['taxonomy'] ?? [])) {
+ if (!is_admin() || !in_array($this->taxonomy->name(), $query->query_vars['taxonomy'])) {
return;
}
- // check the orderby is a custom ordering
- if (isset($_GET['orderby']) && array_key_exists($_GET['orderby'], $this->taxonomy->columns()->sortable)) {
- // get the custom sorting options
- $meta = $this->taxonomy->columns()->sortable[$_GET['orderby']];
-
- // check ordering is not numeric
- if (is_string($meta)) {
- $meta_key = $meta;
- $orderby = 'meta_value';
- } else {
- $meta_key = $meta[0];
- $orderby = 'meta_value_num';
- }
-
- // set the sort order
- $query->query_vars['orderby'] = $orderby;
- $query->query_vars['meta_key'] = $meta_key;
- }
+ $column = $query->query_vars['orderby'];
+
+ $this->columns->sortColumn($column, $query);
}
}
diff --git a/src/Taxonomy.php b/src/Taxonomy.php
index a0acde5..1fdd318 100644
--- a/src/Taxonomy.php
+++ b/src/Taxonomy.php
@@ -3,263 +3,86 @@
namespace PostTypes;
use PostTypes\Columns;
+use PostTypes\Contracts\TaxonomyContract;
use PostTypes\Registrars\TaxonomyRegistrar;
-/**
- * Taxonomy
- *
- * Create WordPress Taxonomies easily
- *
- * @link https://github.com/jjgrainger/PostTypes/
- * @author jjgrainger
- * @link https://jjgrainger.co.uk
- * @version 2.2.1
- * @license https://opensource.org/licenses/mit-license.html MIT License
- */
-class Taxonomy
+abstract class Taxonomy implements TaxonomyContract
{
/**
- * The names passed to the Taxonomy
- * @var mixed
+ * Taxonomy name.
+ *
+ * @return string
*/
- public $names;
+ abstract public function name(): string;
/**
- * The Taxonomy name
- * @var string
+ * Taxonomy slug.
+ *
+ * @return string
*/
- public $name;
-
- /**
- * The singular label for the Taxonomy
- * @var string
- */
- public $singular;
-
- /**
- * The plural label for the Taxonomy
- * @var string
- */
- public $plural;
-
- /**
- * The Taxonomy slug
- * @var string
- */
- public $slug;
-
- /**
- * Custom options for the Taxonomy
- * @var array
- */
- public $options;
-
- /**
- * Custom labels for the Taxonomy
- * @var array
- */
- public $labels;
-
- /**
- * PostTypes to register the Taxonomy to
- * @var array
- */
- public $posttypes = [];
-
- /**
- * The column manager for the Taxonomy
- * @var mixed
- */
- public $columns;
-
- /**
- * Create a Taxonomy
- * @param mixed $names The name(s) for the Taxonomy
- */
- public function __construct($names, $options = [], $labels = [])
+ public function slug(): string
{
- $this->names($names);
-
- $this->options($options);
-
- $this->labels($labels);
- }
-
- /**
- * Set the names for the Taxonomy
- * @param mixed $names The name(s) for the Taxonomy
- * @return $this
- */
- public function names($names)
- {
- if (is_string($names)) {
- $names = ['name' => $names];
- }
-
- $this->names = $names;
-
- // create names for the Taxonomy
- $this->createNames();
-
- return $this;
+ return $this->name();
}
/**
- * Set options for the Taxonomy
- * @param array $options
- * @return $this
+ * Taxonomy labels.
+ *
+ * @return array
*/
- public function options(array $options = [])
+ public function labels(): array
{
- $this->options = $options;
-
- return $this;
+ return [];
}
/**
- * Set the Taxonomy labels
- * @param array $labels
- * @return $this
+ * Taxonomy options.
+ *
+ * @return array
*/
- public function labels(array $labels = [])
+ public function options(): array
{
- $this->labels = $labels;
-
- return $this;
+ return [];
}
/**
- * Assign a PostType to register the Taxonomy to
- * @param mixed $posttypes
- * @return $this
+ * Taxonomy post types.
+ *
+ * @return array
*/
- public function posttype($posttypes)
+ public function posttypes(): array
{
- $posttypes = is_string($posttypes) ? [$posttypes] : $posttypes;
-
- foreach ($posttypes as $posttype) {
- $this->posttypes[] = $posttype;
- }
-
- return $this;
+ return [];
}
/**
- * Get the Column Manager for the Taxonomy
+ * Taxonomy columns.
+ *
+ * @param Columns $columns
* @return Columns
*/
- public function columns()
+ public function columns(Columns $columns): Columns
{
- if (!isset($this->columns)) {
- $this->columns = new Columns;
- }
-
- return $this->columns;
+ return $columns;
}
/**
- * Register the Taxonomy to WordPress
+ * Taxonomy hooks.
+ *
* @return void
*/
- public function register()
+ public function hooks(): void
{
- (new TaxonomyRegistrar($this))->register();
+ return;
}
/**
- * Create names for the Taxonomy
+ * Register the taxonomy.
+ *
* @return void
*/
- public function createNames()
- {
- $required = [
- 'name',
- 'singular',
- 'plural',
- 'slug',
- ];
-
- foreach ($required as $key) {
- // if the name is set, assign it
- if (isset($this->names[$key])) {
- $this->$key = $this->names[$key];
- continue;
- }
-
- // if the key is not set and is singular or plural
- if (in_array($key, ['singular', 'plural'])) {
- // create a human friendly name
- $name = ucwords(strtolower(str_replace(['-', '_'], ' ', $this->names['name'])));
- }
-
- if ($key === 'slug') {
- // create a slug friendly name
- $name = strtolower(str_replace([' ', '_'], '-', $this->names['name']));
- }
-
- // if is plural or slug, append an 's'
- if (in_array($key, ['plural', 'slug'])) {
- $name .= 's';
- }
-
- // asign the name to the PostType property
- $this->$key = $name;
- }
- }
-
- /**
- * Create options for Taxonomy
- * @return array Options to pass to register_taxonomy
- */
- public function createOptions()
- {
- // default options
- $options = [
- 'hierarchical' => true,
- 'show_admin_column' => true,
- 'rewrite' => [
- 'slug' => $this->slug,
- ],
- ];
-
- // replace defaults with the options passed
- $options = array_replace_recursive($options, $this->options);
-
- // create and set labels
- if (!isset($options['labels'])) {
- $options['labels'] = $this->createLabels();
- }
-
- return $options;
- }
-
- /**
- * Create labels for the Taxonomy
- * @return array
- */
- public function createLabels()
+ public function register(): void
{
- // default labels
- $labels = [
- 'name' => $this->plural,
- 'singular_name' => $this->singular,
- 'menu_name' => $this->plural,
- 'all_items' => "All {$this->plural}",
- 'edit_item' => "Edit {$this->singular}",
- 'view_item' => "View {$this->singular}",
- 'update_item' => "Update {$this->singular}",
- 'add_new_item' => "Add New {$this->singular}",
- 'new_item_name' => "New {$this->singular} Name",
- 'parent_item' => "Parent {$this->plural}",
- 'parent_item_colon' => "Parent {$this->plural}:",
- 'search_items' => "Search {$this->plural}",
- 'popular_items' => "Popular {$this->plural}",
- 'separate_items_with_commas' => "Seperate {$this->plural} with commas",
- 'add_or_remove_items' => "Add or remove {$this->plural}",
- 'choose_from_most_used' => "Choose from most used {$this->plural}",
- 'not_found' => "No {$this->plural} found",
- ];
-
- return array_replace($labels, $this->labels);
+ (new TaxonomyRegistrar($this))->register();
}
}
diff --git a/tests/ColumnTest.php b/tests/ColumnTest.php
new file mode 100644
index 0000000..4bafa1a
--- /dev/null
+++ b/tests/ColumnTest.php
@@ -0,0 +1,23 @@
+getMockForAbstractClass(Column::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('price'));
+
+ $this->assertEquals('price', $stub->name());
+ $this->assertEquals('Price', $stub->label());
+ $this->assertEquals(null, $stub->populate(1));
+ $this->assertEquals(null, $stub->order());
+ $this->assertEquals(null, $stub->sort(true));
+ $this->assertEquals(false, $stub->isSortable());
+ }
+}
diff --git a/tests/ColumnsTest.php b/tests/ColumnsTest.php
index ce2b217..7500015 100644
--- a/tests/ColumnsTest.php
+++ b/tests/ColumnsTest.php
@@ -1,262 +1,219 @@
columns = new Columns;
- }
+ $columns = new Columns;
- /** @test */
- public function canCreateColumns()
- {
- $this->assertInstanceOf(Columns::class, $this->columns);
+ $columns->add('column', 'Test Column');
+
+ $this->assertArrayHasKey('column', $columns->add);
+ $this->assertSame('Test Column', $columns->add['column']);
}
- /** @test */
- public function canSetColumns()
+ public function test_can_add_column_with_column_class()
{
- $columns = [
- 'title' => 'Title',
- 'date' => 'Date',
- ];
+ $stub = $this->getMockForAbstractClass(Column::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
- $this->columns->set($columns);
+ $columns = new Columns;
+ $columns->column($stub);
- $this->assertEquals($this->columns->items, $columns);
+ $this->assertArrayHasKey('column', $columns->add);
+ $this->assertSame('Column', $columns->add['column']);
+
+ $this->assertArrayHasKey('column', $columns->populate);
+ $this->assertIsCallable($columns->populate['column']);
}
- /** @test */
- public function canAddColumnsWithArray()
+ public function test_can_add_column_with_populate_callback()
{
- $columns = [
- 'genre' => 'Genre',
- ];
+ $columns = new Columns;
- $this->columns->add($columns);
+ $columns->add('column', 'Test Column', function() {});
- $this->assertEquals($this->columns->add, $columns);
+ $this->assertArrayHasKey('column', $columns->populate);
+ $this->assertIsCallable($columns->populate['column']);
}
- /** @test */
- public function canAddColumnsWithArgs()
+ public function test_can_set_column_populate_callback()
{
- $this->columns->add('genre', 'Genre');
-
- // Auto generated label1
- $this->columns->add('price');
+ $columns = new Columns;
- $expected = [
- 'genre' => 'Genre',
- 'price' => 'Price',
- ];
+ $columns->populate('column', function() {});
- $this->assertEquals($this->columns->add, $expected);
+ $this->assertArrayHasKey('column', $columns->populate);
+ $this->assertIsCallable($columns->populate['column']);
}
- /** @test */
- public function canHideColumns()
+ public function test_can_set_remove_column()
{
- $columns = [
- 'date'
- ];
+ $columns = new Columns;
- $this->columns->hide($columns);
+ $columns->remove(['column']);
- $this->assertEquals($this->columns->hide, $columns);
+ $this->assertEquals(['column'], $columns->remove);
}
- /** @test */
- public function canPopulateColumns()
+ public function test_can_set_remove_columns_with_multiple_calls()
{
- $callable = function($column, $post_id) {
- echo $post_id;
- };
+ $columns = new Columns;
- $this->columns->populate('post_id', $callable);
+ $columns->remove(['column']);
+ $columns->remove(['column_2']);
- $this->assertEquals($this->columns->populate['post_id'], $callable);
+ $this->assertEquals(['column', 'column_2'], $columns->remove);
}
- /** @test */
- public function canOrderColumns()
+ public function test_can_set_order_columns()
{
- $columns = [
- 'date' => 3,
- 'genre' => 2
- ];
+ $columns = new Columns;
- $this->columns->order($columns);
+ $columns->order([
+ 'column' => 1,
+ ]);
- $this->assertEquals($this->columns->positions, $columns);
+ $this->assertEquals(['column' => 1], $columns->order);
}
- /** @test */
- public function canSortColumns()
+ public function test_can_set_order_columns_with_multiple_calls()
{
- $columns = [
- 'rating' => ['_rating', true]
- ];
+ $columns = new Columns;
- $this->columns->sortable($columns);
+ $columns->order(['column' => 1]);
+ $columns->order(['column_2' => 3]);
- $this->assertEquals($this->columns->sortable, $columns);
+ $this->assertEquals(['column' => 1, 'column_2' => 3], $columns->order);
}
- /** @test */
- public function usesSetColumnsOverDefaults()
+ public function test_can_order_column_with_column_class()
{
- $defaults = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'comments' => 'Comments',
- 'date' => 'Date'
- ];
+ $columns = new Columns;
- $columns = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'date' => 'Date'
- ];
+ $stub = $this->createMock(Column::class);
- $this->columns->set($columns);
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
- $output = $this->columns->modifyColumns($defaults);
+ $stub->expects($this->any())
+ ->method('order')
+ ->will($this->returnValue(1));
- $this->assertEquals($output, $columns);
- }
- /** @test */
- public function addsColumnsToDefaults()
- {
- $columns = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'comments' => 'Comments',
- 'date' => 'Date'
- ];
+ $columns->column($stub);
- $this->columns->add(['genre' => 'Genres']);
+ $this->assertEquals(['column' => 1], $columns->order);
+ }
- $output = $this->columns->modifyColumns($columns);
+ public function test_can_set_sortable_column()
+ {
+ $columns = new Columns;
- $columns['genre'] = 'Genres';
+ $columns->sortable('column', function() {});
- $this->assertEquals($output, $columns);
+ $this->assertArrayHasKey('column', $columns->sortable);
+ $this->assertIsCallable($columns->sortable['column']);
}
- /** @test */
- public function hideColumnsFromDefaults()
+ public function test_can_apply_columns()
{
- $columns = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'comments' => 'Comments',
- 'date' => 'Date'
- ];
-
- $this->columns->hide('comments');
+ $columns = new Columns;
- $output = $this->columns->modifyColumns($columns);
+ $columns->add('column_5', 'Column 5');
- unset($columns['comments']);
+ $columns->remove(['column_2']);
- $this->assertEquals($output, $columns);
- }
+ $columns->order([
+ 'column_3' => 0,
+ ]);
- /** @test */
- public function setOrderOfDefaultColumns()
- {
- $columns = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'comments' => 'Comments',
- 'date' => 'Date'
+ $original = [
+ 'column_1' => 'Column 1',
+ 'column_2' => 'Column 2',
+ 'column_3' => 'Column 3',
+ 'column_4' => 'Column 4',
];
- $this->columns->order([
- 'date' => 1,
- 'title' => 3
- ]);
-
- $output = $this->columns->modifyColumns($columns);
+ $modified = $columns->applyColumns($original);
$expected = [
- 'date' => 'Date',
- 'author' => 'Author',
- 'title' => 'Title',
- 'comments' => 'Comments',
+ 'column_3' => 'Column 3',
+ 'column_1' => 'Column 1',
+ 'column_4' => 'Column 4',
+ 'column_5' => 'Column 5',
];
- $this->assertEquals($output, $expected);
+ $this->assertSame($expected, $modified);
}
- /** @test */
- public function canModifyColumns()
+ public function test_can_populate_column()
{
- $defaults = [
- 'title' => 'Title',
- 'author' => 'Author',
- 'comments' => 'Comments',
- 'date' => 'Date'
- ];
-
- $expected = [
- 'title' => 'Title',
- 'genre' => 'Genre',
- 'author' => 'Author',
- 'date' => 'Date'
- ];
+ $columns = new Columns;
- $this->columns->hide('comments');
+ $stub = $this->createMock(Column::class);
- $this->columns->add(['genre' => 'Genre']);
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
- $this->columns->order([
- 'genre' => 2,
- ]);
+ $stub->expects($this->once())
+ ->method('populate')
+ ->with($this->greaterThan(0));
- $output = $this->columns->modifyColumns($defaults);
+ $columns->column($stub);
- $this->assertEquals($output, $expected);
+ $columns->populateColumn('column', [1]);
}
- /** @test */
- public function canIdentifySortableColumns()
+ public function test_can_add_sortable_columns_to_sortable_list()
{
- $columns = [
- 'rating' => ['_rating', true],
- 'price' => '_price',
- 'sortable' => ['sortable'],
+ $columns = new Columns;
+
+ $columns->sortable('column', function() {});
+
+ $sortable = [
+ 'title' => 'title',
];
- $this->columns->sortable($columns);
+ $sortable = $columns->setSortable($sortable);
+
+ $expected = [
+ 'title' => 'title',
+ 'column' => 'column',
+ ];
- $this->assertTrue($this->columns->isSortable('_rating'));
- $this->assertTrue($this->columns->isSortable('_price'));
- $this->assertTrue($this->columns->isSortable('sortable'));
- $this->assertFalse($this->columns->isSortable('not_a_column'));
+ $this->assertSame($expected, $sortable);
}
- /** @test */
- public function returnsCorrectSortableMetaKey()
+ public function test_can_sort_column()
{
- $columns = [
- 'rating' => ['_rating', true],
- 'price' => '_price',
- 'column' => ['sortable'],
- ];
+ $columns = new Columns;
+
+ $stub = $this->createMock(Column::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
+
+ $stub->expects($this->once())
+ ->method('isSortable')
+ ->will($this->returnValue(true));
+
+ $stub->expects($this->once())
+ ->method('sort')
+ ->with($this->greaterThan(0));
- $this->columns->sortable($columns);
+ $columns->column($stub);
- $this->assertEquals($this->columns->sortableMeta('rating'), ['_rating', true]);
- $this->assertEquals($this->columns->sortableMeta('_price'), '_price');
- $this->assertEquals($this->columns->sortableMeta('sortable'), ['sortable']);
- $this->assertEquals($this->columns->sortableMeta('not_a_column'), '');
+ $columns->sortColumn('column', 1);
}
}
diff --git a/tests/PostTypeTest.php b/tests/PostTypeTest.php
index 2e3bd91..c0bbd4d 100644
--- a/tests/PostTypeTest.php
+++ b/tests/PostTypeTest.php
@@ -2,302 +2,24 @@
use PHPUnit\Framework\TestCase;
use PostTypes\PostType;
-use PostTypes\Columns;
class PostTypeTest extends TestCase
{
- protected $books;
-
- protected function setUp(): void
- {
- // setup basic PostType
- $this->books = new PostType('book');
- }
-
- /** @test */
- public function canCreatePostType()
- {
- $this->assertInstanceOf(PostType::class, $this->books);
- }
-
- /** @test */
- public function hasNameOnInstantiation()
- {
- $this->assertEquals($this->books->names['name'], 'book');
- }
-
- /** @test */
- public function hasNamesOnInstantiation()
- {
- $names = [
- 'name' => 'book',
- 'singular' => 'Book',
- 'plural' => 'Books',
- 'slug' => 'books'
- ];
-
- $books = new PostType($names);
-
- $this->assertEquals($books->names, $names);
- }
-
- /** @test */
- public function hasOptionsOnInstantiation()
- {
- $this->assertEquals($this->books->options, []);
- }
-
- /** @test */
- public function hasCustomOptionsOnInstantiation()
- {
- $options = [
- 'public' => true
- ];
-
- $books = new PostType('books', $options);
-
- $this->assertEquals($books->options, $options);
- }
-
- /** @test */
- public function hasLabelsOnInstantiation()
- {
- $this->assertEquals($this->books->labels, []);
- }
-
- /** @test */
- public function hasCustomLabelsOnInstantiation()
- {
- $labels = [
- 'name' => 'Books',
- 'add_new' => 'Add New Book'
- ];
-
- $books = new PostType('books', [], $labels);
-
- $this->assertEquals($books->labels, $labels);
- }
-
- /** @test */
- public function taxonomiesEmptyOnInstantiation()
- {
- $this->assertEquals($this->books->taxonomies, []);
- }
-
- /** @test */
- public function hasCustomTaxonomiesWhenPassed()
- {
- $books = $this->books;
-
- $books->taxonomy('genre');
-
- $this->assertEquals($books->taxonomies, ['genre']);
- }
-
- /** @test */
- public function canAddMultipleTaxonomies()
- {
- $books = $this->books;
-
- $books->taxonomy(['genre', 'publisher']);
-
- $this->assertEquals($books->taxonomies, ['genre', 'publisher']);
- }
-
- /** @test */
- public function filtersNullOnInstantiation()
- {
- $this->assertNull($this->books->filters);
- }
-
- /** @test */
- public function hasFiltersWhenAdded()
- {
- $books = $this->books;
-
- $books->filters(['genre']);
-
- $this->assertEquals($books->filters, ['genre']);
- }
-
- /** @test */
- public function iconNullOnInstantiation()
- {
- $this->assertNull($this->books->icon);
- }
-
- /** @test */
- public function hasIconWhenSet()
- {
- $books = $this->books;
-
- $books->icon('dashicon-book-alt');
-
- $this->assertEquals($books->icon, 'dashicon-book-alt');
- }
-
- /** @test */
- public function columnsIsNullOnInstantiation()
- {
- $this->assertEquals($this->books->columns, null);
- }
-
- /** @test */
- public function columnsReturnsInstanceOfColumns()
- {
- $this->assertInstanceOf(Columns::class, $this->books->columns());
- }
-
- /** @test */
- public function namesCreatedFromName()
- {
- $this->books->createNames();
-
- $this->assertEquals($this->books->name, 'book');
- $this->assertEquals($this->books->singular, 'Book');
- $this->assertEquals($this->books->plural, 'Books');
- $this->assertEquals($this->books->slug, 'books');
- }
-
- /** @test */
- public function smartNamesCreatedFromName()
- {
- $story = new PostType('story');
-
- $this->assertEquals($story->name, 'story');
- $this->assertEquals($story->singular, 'Story');
- $this->assertEquals($story->plural, 'Stories');
- $this->assertEquals($story->slug, 'stories');
- }
-
- /** @test */
- public function passedNamesAreUsed()
- {
- $names = [
- 'name' => 'book',
- 'singular' => 'Single Book',
- 'plural' => 'Multiple Books',
- 'slug' => 'slug_books',
- ];
-
- $this->books->names($names);
-
- $this->books->createNames();
-
- $this->assertEquals($this->books->name, 'book');
- $this->assertEquals($this->books->singular, 'Single Book');
- $this->assertEquals($this->books->plural, 'Multiple Books');
- $this->assertEquals($this->books->slug, 'slug_books');
- }
-
- /** @test */
- public function defaultOptionsUsedIfNotSet()
- {
- // generated options
- $options = $this->books->createOptions();
-
- // expected options
- $defaults = [
- 'public' => true,
- 'labels' => $this->books->createLabels(),
- 'rewrite' => [
- 'slug' => $this->books->slug
- ]
- ];
-
- $this->assertEquals($options, $defaults);
- }
-
- /** @test */
- public function optionsGeneratedCorrectly()
- {
- // Set custom options
- $this->books->options([
- 'public' => false,
- ]);
-
- // Set option with helper method
- $this->books->icon('dashicon-book-alt');
-
- // generated options
- $options = $this->books->createOptions();
-
- // expected options
- $expected = [
- 'public' => false,
- 'labels' => $this->books->createLabels(),
- 'menu_icon' => $this->books->icon,
- 'rewrite' => [
- 'slug' => $this->books->slug
- ]
- ];
-
- $this->assertEquals($options, $expected);
- }
-
- /** @test */
- public function defaultLabelsAreGenerated()
- {
- $labels = $this->books->createLabels();
-
- $defaults = [
- 'name' => $this->books->plural,
- 'singular_name' => $this->books->singular,
- 'menu_name' => $this->books->plural,
- 'all_items' => $this->books->plural,
- 'add_new' => "Add New",
- 'add_new_item' => "Add New {$this->books->singular}",
- 'edit_item' => "Edit {$this->books->singular}",
- 'new_item' => "New {$this->books->singular}",
- 'view_item' => "View {$this->books->singular}",
- 'search_items' => "Search {$this->books->plural}",
- 'not_found' => "No {$this->books->plural} found",
- 'not_found_in_trash' => "No {$this->books->plural} found in Trash",
- 'parent_item_colon' => "Parent {$this->books->singular}:",
- ];
-
- $this->assertEquals($labels, $defaults);
- }
-
- /** @test */
- public function filtersAreEmptyIfNotSetAndNoTaxonomies()
- {
- $filters = $this->books->getFilters();
-
- $this->assertEquals($filters, []);
- }
-
- /** @test */
- public function filtersAreSameAsTaxonomyIfNotSet()
- {
- $this->books->taxonomy('genre');
-
- $filters = $this->books->getFilters();
-
- $this->assertEquals($filters, ['genre']);
- }
-
- /** @test */
- public function filtersAreWhatAssignedIfPassed()
- {
- $this->books->filters(['genre', 'published']);
-
- $this->books->taxonomy('genre');
-
- $filters = $this->books->getFilters();
-
- $this->assertEquals($filters, ['genre', 'published']);
- }
-
- /** @test */
- public function filtersAreEmptyIfSetWithEmptyArray()
- {
- $this->books->filters([]);
-
- $this->books->taxonomy('genre');
-
- $filters = $this->books->getFilters();
-
- $this->assertEquals($filters, []);
+ public function test_post_type_returns_defaults()
+ {
+ $stub = $this->getMockForAbstractClass(PostType::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $this->assertEquals('book', $stub->slug());
+ $this->assertEquals([], $stub->labels());
+ $this->assertEquals([], $stub->options());
+ $this->assertEquals([], $stub->taxonomies());
+ $this->assertEquals(['title', 'editor'], $stub->supports());
+ $this->assertEquals(null, $stub->icon());
+ $this->assertEquals([], $stub->filters());
+ $this->assertEquals(null, $stub->hooks());
}
}
diff --git a/tests/Registrars/PostTypeRegistrarTest.php b/tests/Registrars/PostTypeRegistrarTest.php
index e6a64bd..eb480e2 100644
--- a/tests/Registrars/PostTypeRegistrarTest.php
+++ b/tests/Registrars/PostTypeRegistrarTest.php
@@ -1,24 +1,173 @@
getMockForAbstractClass(PostType::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $registrar = new PostTypeRegistrar($stub);
+
+ $this->assertInstanceOf(PostTypeRegistrar::class, $registrar);
+ }
+
+ public function test_will_modify_post_type()
+ {
+ $stub = $this->getMockForAbstractClass(PostType::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $registrar = new PostTypeRegistrar($stub);
+
+ $args = [
'public' => false,
- ]);
+ ];
+
+ $options = $registrar->modifyPostType($args, 'book');
+
+ $expected = [
+ 'public' => true,
+ 'show_in_rest' => true,
+ 'labels' => [],
+ 'taxonomies' => [],
+ 'supports' => ['title', 'editor'],
+ 'menu_icon' => null,
+ 'rewrite' => [
+ 'slug' => 'book',
+ ],
+ ];
+
+ $this->assertEquals($expected, $options);
+ }
+
+ public function test_will_not_modify_post_type_if_name_does_not_match()
+ {
+ $stub = $this->getMockForAbstractClass(PostType::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $registrar = new PostTypeRegistrar($stub);
+
+ $args = [
+ 'public' => false,
+ ];
+
+ $options = $registrar->modifyPostType($args, 'post');
+
+ $this->assertEquals($args, $options);
+ }
+
+ public function test_can_modify_columns()
+ {
+ $defaults = [
+ 'cb' => '',
+ 'title' => 'Title',
+ 'author' => 'Author',
+ ];
+
+ $columns = new Columns;
+ $columns->add('date', 'Date', function() {});
+
+ $stub = $this->getMockBuilder(PostType::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
+
+ $registrar = new PostTypeRegistrar($stub);
+ $registrar->createColumns();
+ $output = $registrar->modifyColumns($defaults);
+
+ $expected = [
+ 'cb' => '',
+ 'title' => 'Title',
+ 'author' => 'Author',
+ 'date' => 'Date',
+ ];
+
+ $this->assertEquals($expected, $output);
+ }
+
+ public function test_can_populate_column()
+ {
+ $columns = new Columns;
+
+ $stub = $this->createMock(Column::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
+
+ $stub->expects($this->once())
+ ->method('populate')
+ ->will($this->returnValue(true));
+
+ $columns->column($stub);
+
+ $stub = $this->getMockBuilder(PostType::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
+
+ $registrar = new PostTypeRegistrar($stub);
+ $registrar->createColumns();
+ $registrar->populateColumns('column', 1);
+ }
+
+ public function test_can_set_sortable_columns()
+ {
+ $columns = new Columns;
+ $columns->sortable('column', function() {});
+
+ $sortable = [
+ 'title' => 'title',
+ ];
+
+ $stub = $this->getMockBuilder(PostType::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('book'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
- $registrar = new PostTypeRegistrar($posttype);
+ $registrar = new PostTypeRegistrar($stub);
+ $registrar->createColumns();
+ $output = $registrar->setSortableColumns($sortable);
- $options = $registrar->modifyPostType([
- 'public' => true,
- ], 'post');
+ $expected = [
+ 'title' => 'title',
+ 'column' => 'column',
+ ];
- $this->assertEquals(false, $options['public']);
+ $this->assertEquals($expected, $output);
}
}
diff --git a/tests/Registrars/TaxonomyRegistrarTest.php b/tests/Registrars/TaxonomyRegistrarTest.php
index 3a2494b..15e62a9 100644
--- a/tests/Registrars/TaxonomyRegistrarTest.php
+++ b/tests/Registrars/TaxonomyRegistrarTest.php
@@ -1,17 +1,160 @@
getMockForAbstractClass(Taxonomy::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
+
+ $registrar = new TaxonomyRegistrar($stub);
$this->assertInstanceOf(TaxonomyRegistrar::class, $registrar);
}
+
+ public function test_can_generate_options_with_overrides()
+ {
+ $stub = $this->getMockBuilder(Taxonomy::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
+
+ $stub->expects($this->any())
+ ->method('slug')
+ ->will($this->returnValue('genre'));
+
+
+ $stub->expects($this->once())
+ ->method('options')
+ ->will($this->returnValue([
+ 'public' => false,
+ ]));
+
+
+ $registrar = new TaxonomyRegistrar($stub);
+
+ $options = $registrar->generateOptions();
+
+ $expected = [
+ 'public' => false,
+ 'show_in_rest' => true,
+ 'hierarchical' => true,
+ 'show_admin_column' => true,
+ 'labels' => [],
+ 'rewrite' => [
+ 'slug' => 'genre',
+ ],
+ ];
+
+ $this->assertEquals($expected, $options);
+ }
+
+ public function test_can_modify_columns()
+ {
+ $defaults = [
+ 'cb' => '',
+ 'name' => 'Name',
+ ];
+
+ $columns = new Columns;
+ $columns->add('popularity', 'Popularity', function() {});
+
+ $stub = $this->getMockBuilder(Taxonomy::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
+
+ $registrar = new TaxonomyRegistrar($stub);
+ $registrar->createColumns();
+ $output = $registrar->modifyColumns($defaults);
+
+ $expected = [
+ 'cb' => '',
+ 'name' => 'Name',
+ 'popularity' => 'Popularity',
+ ];
+
+ $this->assertEquals($expected, $output);
+ }
+
+ public function test_can_populate_column()
+ {
+ $columns = new Columns;
+
+ $stub = $this->createMock(Column::class);
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('column'));
+
+ $stub->expects($this->once())
+ ->method('populate')
+ ->will($this->returnValue(true));
+
+ $columns->column($stub);
+
+ $stub = $this->getMockBuilder(Taxonomy::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
+
+ $registrar = new TaxonomyRegistrar($stub);
+ $registrar->createColumns();
+ $registrar->populateColumns('', 'column', 1);
+ }
+
+ public function test_can_set_sortable_columns()
+ {
+ $columns = new Columns;
+ $columns->sortable('column', function() {});
+
+ $sortable = [
+ 'title' => 'title',
+ ];
+
+ $stub = $this->getMockBuilder(Taxonomy::class)
+ ->getMock();
+
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
+
+ $stub->expects($this->once())
+ ->method('columns')
+ ->will($this->returnValue($columns));
+
+ $registrar = new TaxonomyRegistrar($stub);
+ $registrar->createColumns();
+ $output = $registrar->setSortableColumns($sortable);
+
+ $expected = [
+ 'title' => 'title',
+ 'column' => 'column',
+ ];
+
+ $this->assertEquals($expected, $output);
+ }
}
diff --git a/tests/TaxonomyTest.php b/tests/TaxonomyTest.php
index 2883c19..a8049ec 100644
--- a/tests/TaxonomyTest.php
+++ b/tests/TaxonomyTest.php
@@ -2,166 +2,21 @@
use PHPUnit\Framework\TestCase;
use PostTypes\Taxonomy;
-use PostTypes\Columns;
class TaxonomyTest extends TestCase
{
- protected $genres;
-
- protected function setUp(): void
- {
- $this->genres = new Taxonomy('genre');
- }
-
- /** @test */
- public function canCreateTaxonomy()
- {
- $this->assertInstanceOf(Taxonomy::class, $this->genres);
- }
-
- /** @test */
- public function hasNameOnInstantiation()
- {
- $this->assertEquals('genre', $this->genres->names['name']);
- }
-
- /** @test */
- public function hasNamesOnInstantiation()
- {
- $names = [
- 'name' => 'genre',
- 'singular' => 'Genre',
- 'plural' => 'Genres',
- 'slug' => 'genres'
- ];
-
- $genres = new Taxonomy($names);
-
- $this->assertEquals($genres->names, $names);
- }
-
- /** @test */
- public function hasOptionsOnInstantiation()
- {
- $this->assertEquals($this->genres->options, []);
- }
-
- /** @test */
- public function hasCustomOptionsOnInstantiation()
- {
- $options = [
- 'public' => true,
- ];
-
- $genres = new Taxonomy('genre', $options);
-
- $this->assertEquals($genres->options, $options);
- }
-
- /** @test */
- public function hasLabelsOnInstatiation()
- {
- $this->assertEquals($this->genres->labels, []);
- }
-
- /** @test */
- public function hasCustomLabelsOnInstantiation()
- {
- $labels = [
- 'name' => 'Genres',
- 'add_new' => 'Add New Genre'
- ];
-
- $genres = new Taxonomy('genre', [], $labels);
-
- $this->assertEquals($genres->labels, $labels);
- }
-
- /** @test */
- public function posttypesEmptyOnInstantiation()
- {
- $this->assertEquals($this->genres->posttypes, []);
- }
-
- /** @test */
- public function hasCustomPosttypesWhenAssigned()
- {
- $genres = new Taxonomy('genre');
-
- $genres->posttype('books');
-
- $this->assertEquals($genres->posttypes, ['books']);
- }
-
- /** @test */
- public function canAddMultiplePostTypes()
- {
- $genres = new Taxonomy('genre');
-
- $genres->posttype(['books', 'films']);
-
- $this->assertEquals($genres->posttypes, ['books', 'films']);
- }
-
- /** @test */
- public function namesCreatedFromName()
- {
- $this->genres->createNames();
-
- $this->assertEquals($this->genres->name, 'genre');
- $this->assertEquals($this->genres->singular, 'Genre');
- $this->assertEquals($this->genres->plural, 'Genres');
- $this->assertEquals($this->genres->slug, 'genres');
- }
-
- /** @test */
- public function passedNamesAreUsed()
+ public function test_taxonomy_returns_defaults()
{
- $names = [
- 'name' => 'genre',
- 'singular' => 'Single Genre',
- 'plural' => 'Multiple Genres',
- 'slug' => 'slug-genres',
- ];
-
- $this->genres->names($names);
+ $stub = $this->getMockForAbstractClass(Taxonomy::class);
- $this->genres->createNames();
-
- $this->assertEquals($this->genres->name, 'genre');
- $this->assertEquals($this->genres->singular, 'Single Genre');
- $this->assertEquals($this->genres->plural, 'Multiple Genres');
- $this->assertEquals($this->genres->slug, 'slug-genres');
- }
-
- /** @test */
- public function defaultOptionsUsedIfNotSet()
- {
- // generated options
- $options = $this->genres->createOptions();
+ $stub->expects($this->any())
+ ->method('name')
+ ->will($this->returnValue('genre'));
- // expected options
- $defaults = [
- 'hierarchical' => true,
- 'show_admin_column' => true,
- 'labels' => $this->genres->createLabels(),
- 'rewrite' => [
- 'slug' => $this->genres->slug,
- ],
- ];
-
- $this->assertEquals($options, $defaults);
- }
-
- /** @test */
- public function columnsIsNullOnInstantiation()
- {
- $this->assertEquals($this->genres->columns, null);
- }
-
- /** @test */
- public function columnsReturnsInstanceOfColumns()
- {
- $this->assertInstanceOf(Columns::class, $this->genres->columns());
+ $this->assertEquals('genre', $stub->slug());
+ $this->assertEquals([], $stub->labels());
+ $this->assertEquals([], $stub->options());
+ $this->assertEquals([], $stub->posttypes());
+ $this->assertEquals(null, $stub->hooks());
}
}