Here’s how you do it… It’s quite extensive. I have no idea if this is the best way or not, – but this is how I solved it. There might be a couple of errors in the code. But it works for me.
This is a quite specific wish for a functionality. Another way to go about it would be to just make the category.php
-page do the same thing (since it basically does the same thing.
Generate a list of the pages that should be emitted from getting a category created
function generate_the_excluded_array() {
global $excluded_pages;
$excluded_pages = array(); // Add all pages with the search-template
$search_pages = get_pages(array(
'meta_key' => '_wp_page_template',
'meta_value' => 'page-search.php'
));
$excluded_pages[] = get_option( 'page_on_front' ); // Add home page
foreach($search_pages as $page){
// Add all pages that has the search-page-template activated
$excluded_pages[] = $page->ID;
}
}
add_action( 'after_setup_theme', 'generate_the_excluded_array' );
Upon save, – then get a list of all pages and iterate through them
function custom_set_category_on_cpt() {
global $page_category_mapping;
global $excluded_pages;
$local_excluded_pages = implode(', ', $excluded_pages );
$pages_args = array(
'sort_order' => 'asc',
'sort_column' => 'post_title',
'hierarchical' => 1,
'exclude' => $local_excluded_pages,
'include' => '',
'meta_key' => '',
'meta_value' => '',
'authors' => '',
'child_of' => 0,
'parent' => 0,
'exclude_tree' => '',
'number' => '',
'offset' => 0,
'post_type' => 'page',
'post_status' => 'publish'
);
$pages = get_pages( $pages_args );
foreach( $pages as $page ){
custom_create_category_and_check_for_page_children( $page, 0 );
}
purge_categories(); // A function for deleting categories that don't have a corresponding page.
}
add_action( 'save_post', 'custom_set_category_on_cpt' );
A function for purging the categories
function purge_categories( $page_category_mapping_) {
global $page_category_mapping;
$category_args = array(
'hide_empty' => 0,
'exclude' => array(1),
);
$categories = get_categories( $category_args );
foreach($categories as $category){
$category_args = array(
'name' => $category->name,
'hide_empty' => false,
'parent' => $category->category_parent
);
$category_array = get_terms( 'category', $category_args );
$page_ID_with_corresponding_name="";
foreach ( $page_category_mapping as $key => $val ) {
if( $category_array[0]->term_id === $val[ 'category_ID' ] ){
$page_ID_with_corresponding_name = $key;
}
}
if( empty( $page_ID_with_corresponding_name ) ) {
wp_delete_category( $category_array[0]->term_id );
}
}
}
A function for determining if a page has children or not
function custom_page_has_children( $post_ID ) {
$children = get_pages( array( 'child_of' => $post_ID ) );
if( count( $children ) == 0 ) {
return false;
} else {
return true;
}
}
A (recursive) function for creating the category and check if that page has any children
function custom_create_category_and_check_for_page_children( $page, $page_parent ){
custom_create_category_for_page( $page );
if( custom_page_has_children( $page->ID ) ){
$list_childpages_arg = array(
'sort_order' => 'asc',
'sort_column' => 'post_title',
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'meta_key' => '',
'meta_value' => '',
'authors' => '',
'child_of' => 0,
'parent' => $page->ID,
'exclude_tree' => '',
'number' => '',
'offset' => 0,
'post_type' => 'page',
'post_status' => 'publish',
);
$childpages = get_pages( $list_childpages_arg);
foreach( $childpages as $childpage ){
custome_create_category_and_check_for_page_children( $childpage, $page->ID );
custom_create_category_for_page( $childpage );
}
}
}
And this function has this as a part of it:
function custom_create_category_for_page( $page ){
global $page_category_mapping;
if( $page->post_parent == 0 ){
$categorys_parents_ID = 0;
} else {
$categorys_parents_ID = $page_category_mapping[ $page->post_parent ]['category_ID'];
}
$category_args = array(
'name' => $page->post_title,
'hide_empty' => false,
'parent' => $categorys_parents_ID
);
$category_array = get_terms( 'category', $category_args );
$category_ID = $category_array[0]->term_id;
if( empty( $category_array) ) {
$category_ID = wp_create_category( $page->post_title, $categorys_parents_ID );
}
if ( ! array_key_exists( $page->ID, $page_category_mapping ) ){
$page_category_mapping[ $page->ID ] = array(
'category_ID' => $category_ID,
'category_parent_ID' => $categorys_parents_ID
);
}
}
Creating a page-to-category-mapping, to be utilized other places
function build_page_category_mapping() {
global $excluded_pages;
$local_excluded_pages = implode(', ', $excluded_pages );
// Initializing empty array
$page_category_mapping = array();
$pages_args = array(
'sort_order' => 'asc',
'sort_column' => 'post_title',
'hierarchical' => 1,
'exclude' => $local_excluded_pages,
'include' => '',
'meta_key' => '',
'meta_value' => '',
'authors' => '',
'child_of' => 0,
'parent' => - 1,
'exclude_tree' => '',
'number' => '',
'offset' => 0,
'post_type' => 'page',
'post_status' => 'publish'
);
$all_pages = get_pages( $pages_args );
foreach ( $all_pages as $page ) {
$page_ancestors_array = get_ancestors( $page->ID, 'page', 'post_type' );
$page_depth = count( $page_ancestors_array );
// GOOD FOR DEBUGGING
// echo '<br /><br /><br /><br /><br />';
// echo $page->post_title . ' is the post title<br />';
// echo 'Depth: ' . $page_depth . '<br />';
if ( $page_depth == 0 ) {
$page_parent_ID = 0;
$page_parent_name = null;
$categorys_parents_ID = 0;
} elseif ( $page_depth == 1 ){
$page_parent_ID = $page_ancestors_array[0];
$page_parent_name = get_post( $page_parent_ID )->post_title;
$parent_category_args = array(
'name' => $page_parent_name,
'hide_empty' => false,
'parent' => 0
);
$categorys_parents= get_terms( 'category', $parent_category_args );
$categorys_parents_ID = $categorys_parents[0]->term_id;
} else {
// Depth > 1
$page_ancestors_array = array_reverse( $page_ancestors_array );
// Two variables to determine how deep in the tree 'we've gotten'.
$pages_temp_topmost = -1;
$pages_temp_nextonedown = -1;
$page_parent_name="";
$i = 0; // Iteration counter
$find_the_right_category_array = array(); // Array for the output (category ancestry).
foreach ( $page_ancestors_array as $ancestor ) {
if( $pages_temp_topmost === -1 && $pages_temp_nextonedown === -1 ){
$pages_temp_topmost = $ancestor;
$ancestor_category_args = array(
'name' => get_post( $ancestor )->post_title,
'hide_empty' => false,
'parent' => 0
);
$ancestor_category_array = get_terms( 'category', $ancestor_category_args );
if( count( $ancestor_category_array ) == 1){
$find_the_right_category_array[ $i ] = $ancestor_category_array[0];
} else {
throw new Exception("Exception code: 1 - This shouldn't be possible, - but several categories was found with that parent and name");
}
} elseif ( $pages_temp_topmost != -1 && $pages_temp_nextonedown === -1 ) {
$pages_temp_nextonedown = $ancestor;
$temp_var = (int) ($i - 1);
$ancestor_category_args = array(
'name' => get_post( $ancestor )->post_title,
'hide_empty' => false,
'parent' => $find_the_right_category_array[ $temp_var ]->term_id
);
$ancestor_category_array = get_terms( 'category', $ancestor_category_args );
if( count( $ancestor_category_array ) == 1){
$find_the_right_category_array[ $i ] = $ancestor_category_array[0];
} else {
throw new Exception("Exception code: 2 - This shouldn't be possible, - but several categories was found with that parent and name");
}
} else {
$temp_var = (int) ($i - 1);
$ancestor_category_args = array(
'name' => get_post( $ancestor )->post_title,
'hide_empty' => false,
'parent' => $find_the_right_category_array[ $temp_var ]->term_id
);
$ancestor_category_array = get_terms( 'category', $ancestor_category_args );
if( count( $ancestor_category_array ) == 1){
$find_the_right_category_array[ $i ] = $ancestor_category_array[0];
} else {
throw new Exception("Exception code: 3 - This shouldn't be possible, - but several categories was found with that parent and name");
}
}
$i += 1;
}
end($find_the_right_category_array);
$key = key( $find_the_right_category_array );
$categorys_parents_ID = $find_the_right_category_array[ $key ]->term_id;
}
$category_args = array(
'name' => $page->post_title,
'hide_empty' => false,
'parent' => $categorys_parents_ID
);
$category_array = get_terms( 'category', $category_args );
// Since that can only return one category, then we can do the following:
$category_ID = $category_array[0]->term_id;
// GOOD FOR DEBUGGING
// echo '<pre>';
// echo 'Page: ' . $page->ID . ' - with the name: ' . $page->post_title . ' <br />';
// echo 'Pages parent ' . $page_parent_ID . ' - with the name: ' . $page_parent_name . ' <br />';
// echo 'Category: ' . $category_ID . ' - with the name: ' . $page->post_title . ' <br />';
// echo 'Categorys parent: ' . $categorys_parents_ID;
// echo '</pre>';
if ( ! array_key_exists( $page->ID, $page_category_mapping ) ){
$page_category_mapping[ $page->ID ] = array(
'category_ID' => $category_ID,
'category_parent_ID' => $categorys_parents_ID
);
}
}
return $page_category_mapping;
}
add_action( 'init', 'build_page_category_mapping' );
// This might be redundant, but I'm not sure.
global $page_category_mapping;
$page_category_mapping = build_page_category_mapping();
I know this is a huge mess… But it was the best (only) way I could make it happen.