summaryrefslogtreecommitdiff
path: root/src/PostType.php
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2024-06-07 21:48:12 +0200
committerDaniel Weipert <git@mail.dweipert.de>2024-06-07 21:48:12 +0200
commit3a837ef6bb8445ba8e944741d6f00f763c12e714 (patch)
treef00919fd1a5546e212399d2083d7a65750c93eb0 /src/PostType.php
initial commitHEADv1.0.0main
Diffstat (limited to 'src/PostType.php')
-rw-r--r--src/PostType.php535
1 files changed, 535 insertions, 0 deletions
diff --git a/src/PostType.php b/src/PostType.php
new file mode 100644
index 0000000..97edc02
--- /dev/null
+++ b/src/PostType.php
@@ -0,0 +1,535 @@
+<?php
+
+namespace PostTypes;
+
+use PostTypes\Columns;
+
+/**
+ * PostType
+ */
+class PostType
+{
+ /**
+ * The names passed to the PostType
+ * @var array
+ */
+ public $names;
+
+ /**
+ * The name for the PostType
+ * @var string
+ */
+ public $name;
+
+ /**
+ * The singular for the PostType
+ * @var string
+ */
+ public $singular;
+
+ /**
+ * The plural name for the PostType
+ * @var string
+ */
+ public $plural;
+
+ /**
+ * The slug for the PostType
+ * @var string
+ */
+ public $slug;
+
+ /**
+ * Options for the PostType
+ * @var array
+ */
+ public $options;
+
+ /**
+ * Labels for the PostType
+ * @var array
+ */
+ public $labels;
+
+ /**
+ * Taxonomies for the PostType
+ * @var array
+ */
+ public $taxonomies = [];
+
+ /**
+ * Filters for the PostType
+ * @var mixed
+ */
+ public $filters;
+
+ /**
+ * The menu icon for the PostType
+ * @var string
+ */
+ public $icon;
+
+ /**
+ * The column manager for the PostType
+ * @var mixed
+ */
+ public $columns;
+
+ /**
+ * Create a PostType
+ * @param mixed $names A string for the name, or an array of names
+ * @param array $options An array of options for the PostType
+ */
+ public function __construct($names, $options = [], $labels = [])
+ {
+ // assign names to the PostType
+ $this->names($names);
+
+ // assign custom options to the PostType
+ $this->options($options);
+
+ // assign labels to the PostType
+ $this->labels($labels);
+ }
+
+ /**
+ * Set the names for the PostType
+ * @param mixed $names A string for the name, or an array of names
+ * @return $this
+ */
+ public function names($names)
+ {
+ // 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;
+ }
+
+ /**
+ * Set the options for the PostType
+ * @param array $options An array of options for the PostType
+ * @return $this
+ */
+ public function options(array $options)
+ {
+ $this->options = $options;
+
+ return $this;
+ }
+
+ /**
+ * Set the labels for the PostType
+ * @param array $labels An array of labels for the PostType
+ * @return $this
+ */
+ public function labels(array $labels)
+ {
+ $this->labels = $labels;
+
+ return $this;
+ }
+
+ /**
+ * 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
+ */
+ public function filters(array $filters)
+ {
+ $this->filters = $filters;
+
+ return $this;
+ }
+
+ /**
+ * Set the menu icon for the PostType
+ * @param string $icon A dashicon class for the menu icon
+ * @return $this
+ */
+ public function icon($icon)
+ {
+ $this->icon = $icon;
+
+ return $this;
+ }
+
+ /**
+ * Flush rewrite rules
+ * @link https://codex.wordpress.org/Function_Reference/flush_rewrite_rules
+ * @param boolean $hard
+ * @return void
+ */
+ public function flush($hard = true)
+ {
+ flush_rewrite_rules($hard);
+ }
+
+ /**
+ * Get the Column Manager for the PostType
+ * @return PostTypes\Columns
+ */
+ public function columns()
+ {
+ if (!isset($this->columns)) {
+ $this->columns = new Columns;
+ }
+
+ return $this->columns;
+ }
+
+ /**
+ * Register the PostType to WordPress
+ * @return void
+ */
+ public function register()
+ {
+ // register the PostType
+ if (!post_type_exists($this->name)) {
+ add_action('init', [$this, 'registerPostType']);
+ } else {
+ add_filter('register_post_type_args', [$this, 'modifyPostType'], 10, 2);
+ }
+
+ // register Taxonomies to the PostType
+ add_action('init', [$this, 'registerTaxonomies']);
+
+ // modify filters on the admin edit screen
+ add_action('restrict_manage_posts', [$this, 'modifyFilters']);
+
+ if (isset($this->columns)) {
+ // modify the admin edit columns.
+ add_filter("manage_{$this->name}_posts_columns", [$this, 'modifyColumns'], 10, 1);
+
+ // populate custom columns
+ add_filter("manage_{$this->name}_posts_custom_column", [$this, 'populateColumns'], 10, 2);
+
+ // run filter to make columns sortable.
+ add_filter('manage_edit-'.$this->name.'_sortable_columns', [$this, 'setSortableColumns']);
+
+ // run action that sorts columns on request.
+ add_action('pre_get_posts', [$this, 'sortSortableColumns']);
+ }
+ }
+
+ /**
+ * Register the PostType
+ * @return void
+ */
+ public function registerPostType()
+ {
+ // create options for the PostType
+ $options = $this->createOptions();
+
+ // check that the post type doesn't already exist
+ if (!post_type_exists($this->name)) {
+ // register the post type
+ register_post_type($this->name, $options);
+ }
+ }
+
+ /**
+ * Modify the existing Post Type.
+ *
+ * @return array
+ */
+ public function modifyPostType(array $args, string $posttype)
+ {
+ if ($posttype !== $this->name) {
+ return $args;
+ }
+
+ // create options for the PostType
+ $options = $this->createOptions();
+
+ $args = array_replace_recursive($args, $options);
+
+ return $args;
+ }
+
+ /**
+ * Create the required names for the PostType
+ * @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' => "Erstellen",
+ 'add_new_item' => "{$this->singular} erstellen",
+ 'edit_item' => "{$this->singular} bearbeiten",
+ 'new_item' => "{$this->singular} erstellen",
+ 'view_item' => "{$this->singular} anschauen",
+ 'search_items' => "{$this->plural} suchen",
+ 'not_found' => "Kein {$this->plural} gefunden",
+ 'not_found_in_trash' => "Es wurden keine {$this->plural} im Papierkorb gefunden.",
+ 'parent_item_colon' => "Eltern-{$this->singular}:",
+ ];
+
+ return array_replace_recursive($labels, $this->labels);
+ }
+
+ /**
+ * Register Taxonomies to the PostType
+ * @return void
+ */
+ public function registerTaxonomies()
+ {
+ if (!empty($this->taxonomies)) {
+ foreach ($this->taxonomies as $taxonomy) {
+ register_taxonomy_for_object_type($taxonomy, $this->name);
+ }
+ }
+ }
+
+ /**
+ * Modify and display filters on the admin edit screen
+ * @param string $posttype The current screen post type
+ * @return void
+ */
+ public function modifyFilters($posttype)
+ {
+ // first check we are working with the this PostType
+ if ($posttype === $this->name) {
+ // calculate what filters to add
+ $filters = $this->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->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.
+ echo '<label class="screen-reader-text" for="cat">' . $tax->labels->filter_by_item . '</label>';
+
+ // Output dropdown for taxonomy.
+ wp_dropdown_categories($dropdown_args);
+ }
+ }
+ }
+
+ /**
+ * Calculate the filters for the PostType
+ * @return array
+ */
+ public function getFilters()
+ {
+ // 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;
+ }
+
+ /**
+ * Modify the columns for the PostType
+ * @param array $columns Default WordPress columns
+ * @return array The modified columns
+ */
+ public function modifyColumns($columns)
+ {
+ $columns = $this->columns->modifyColumns($columns);
+
+ return $columns;
+ }
+
+ /**
+ * Populate custom columns for the PostType
+ * @param string $column The column slug
+ * @param int $post_id The post ID
+ */
+ public function populateColumns($column, $post_id)
+ {
+ if (isset($this->columns->populate[$column])) {
+ call_user_func_array($this->columns()->populate[$column], [$column, $post_id]);
+ }
+ }
+
+ /**
+ * Make custom columns sortable
+ * @param array $columns Default WordPress sortable columns
+ */
+ public function setSortableColumns($columns)
+ {
+ if (!empty($this->columns()->sortable)) {
+ $columns = array_merge($columns, $this->columns()->sortable);
+ }
+
+ return $columns;
+ }
+
+ /**
+ * Set query to sort custom columns
+ * @param WP_Query $query
+ */
+ 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->name) {
+ return;
+ }
+
+ $orderby = $query->get('orderby');
+
+ // if the sorting a custom column
+ if ($this->columns()->isSortable($orderby)) {
+ // get the custom column options
+ $meta = $this->columns()->sortableMeta($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);
+ }
+ }
+}