Skip to content

Instantly share code, notes, and snippets.

@benpearson
Last active January 9, 2025 06:52
Show Gist options
  • Select an option

  • Save benpearson/8f65e6565e35ebafe146fab0e99e42f8 to your computer and use it in GitHub Desktop.

Select an option

Save benpearson/8f65e6565e35ebafe146fab0e99e42f8 to your computer and use it in GitHub Desktop.
Dynamically create taxonomy terms for date units eg. `month and year`
<?php
abstract class DT_DateUnitTaxonomy
{
private $post_type;
private $taxonomy;
private $acf;
/**
* @param $post_type Post type to assign the month terms to
* @param $taxonomy Registered custom taxonomy to use for months
*/
public function __construct(string $post_type, string $taxonomy, bool $acf = false)
{
$this->post_type = $post_type;
$this->taxonomy = $taxonomy;
$this->acf = $acf;
}
public function init()
{
$this->update_term_on_post_update();
}
protected function update_term_on_post_update()
{
if ($this->acf) {
// Use ACF hook
add_action('acf/save_post', function ($post_id) {
// Check a post from the relevant post type has been updated
if (get_post_type($post_id) !== $this->post_type) {
return;
}
$saved_post = get_post($post_id);
if (!$saved_post) {
return;
}
$this->update_term_for_post($saved_post);
});
} else {
// Use core hook
add_action('post_updated', function (int $post_id, WP_Post $after, WP_Post $before) {
// Check a post from the relevant post type has been updated
if (get_post_type($post_id) !== $this->post_type) {
return;
}
$this->update_term_for_post($after);
}, 10, 3);
/**
* WP All Import hook
*
* @param $post_id int The ID of the item (post/user/taxonomy) saved or updated.
* @param $xml_node SimpleXMLElement The libxml resource of the current XML element.
* @param $is_update bool
*/
add_action( 'pmxi_saved_post', function ($post_id, $xml_node, $is_update ) {
// Check a post from the relevant post type has been updated
if (get_post_type($post_id) !== $this->post_type) {
return;
}
if (!$after) {
$after = get_post($post_id);
}
$this->update_term_for_post($after);
}, 10, 3 );
}
}
/**
* Make sure post has the correct month-year term assigned to it.
*/
protected function update_term_for_post(WP_Post $post)
{
$this->remove_all_terms_from_post($post); // TODO Could be more efficient? Currently removing all terms, even the correct one in some cases.
$term_title = $this->get_term_title($post);
if (!$term_title) {
return false;
}
$term_slug = $this->get_term_slug($term_title);
if (!$term_slug) {
return false;
}
// Check if correct term already exists
$term = $this->get_term_by_slug($term_slug);
// If term exists
if (isset($term->term_id) && $term->term_id) {
$this->add_term_to_post($post, $term->term_id);
} else {
// Create term and add to the post
$term_data = $this->create_term_from_post($post, $term_title, $term_slug);
if (isset($term_data['term_id']) && $term_data['term_id']) {
$this->add_term_to_post($post, $term_data['term_id']);
}
}
}
protected function remove_all_terms_from_post(WP_Post $post)
{
if (!$post) {
return false;
}
$post_terms = get_the_terms($post, $this->taxonomy);
if (!$post_terms) {
return false;
}
$post_term_ids = wp_list_pluck($post_terms, 'term_id');
if (!$post_term_ids) {
return false;
}
wp_remove_object_terms($post->ID, $post_term_ids, $this->taxonomy);
}
/**
* Get the term object by slug, otherwise return false
*/
protected function get_term_by_slug(string $term_slug)
{
if (!$term_slug) {
return false;
}
$term = get_term_by('slug', $term_slug, $this->taxonomy, OBJECT);
return ($term instanceof WP_Term)
? $term
: false;
}
protected function add_term_to_post(WP_Post $post, int $term_id)
{
if (!$post || !$term_id) {
return false;
}
wp_add_object_terms($post->ID, $term_id, $this->taxonomy);
}
/**
* Create a term based on the publish date of a post.
* Return an array of data for the new term, false otherwise.
*/
protected function create_term_from_post(WP_Post $post, string $term_title, string $term_slug)
{
if (!$term_title || !$term_slug) {
return false;
}
return wp_insert_term($term_title, $this->taxonomy, ['slug' => $term_slug]); // Add a term to the database
}
/**
* Get a term slug from the post's publish date
*/
protected function get_term_slug(string $term_title)
{
return ($term_title) ? sanitize_title($term_title) : false;
}
/**
* Get a term title from the post's publish date
*/
abstract protected function get_term_title(WP_Post $post);
}
<?php
class DT_MonthTaxonomy extends DT_DateUnitTaxonomy
{
/**
* Get a term title from the post's publish date in the format 'August 1977'
*/
protected function get_term_title(WP_Post $post)
{
$unix_timestamp = strtotime($post->post_date);
$month = date("F", $unix_timestamp);
$year = date("Y", $unix_timestamp);
return "{$month} {$year}";
}
}
<?php
class DT_QuarterTaxonomy extends DT_DateUnitTaxonomy
{
/**
* Get a term title from the date ACF in the format 'August 1977'
*/
protected function get_term_title(WP_Post $post)
{
if (!$post) {
return false;
}
$acf_date = get_field('event_date', $post->ID); // IMPORTANT ACF return format must be m/d/Y (11/25/2022)
if (!$acf_date) {
return false;
}
$unix_timestamp = strtotime($acf_date);
$datetime = new DateTime($acf_date);
$year = date("Y", $unix_timestamp);
$quater_2_start = new DateTime("{$year}-4-1");
$quater_3_start = new DateTime("{$year}-7-1");
$quater_4_start = new DateTime("{$year}-10-1");
if ($datetime < $quater_2_start) {
$months = 'January to March';
} elseif ($datetime < $quater_3_start) {
$months = 'April to June';
} elseif ($datetime < $quater_4_start) {
$months = 'July to September';
} else {
$months = 'October to December';
}
return "{$months} {$year}";
}
}
/**
* Automated date taxonomies
*/
//if (class_exists('MonthTaxonomy')) {
// $month_taxonomy = new MonthTaxonomy('post', DT_PREFIX . 'month');
// $month_taxonomy->init();
//}
//if (class_exists('QuarterTaxonomy')) {
// $quarter_taxonomy = new QuarterTaxonomy(DT_PREFIX . 'event', DT_PREFIX . 'quarter', true); // ACF date field
// $quarter_taxonomy->init();
//}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment