WordPress как на ладони

ЧПУ для трех таксономий и типа записи одновременно

Очередная заметка с кодом который бесполезен для 99% пользователей WordPress. Но для 1% это будет находкой, пожалуй. Речь о ЧПУ, решение сложной задачи. Объяснений что и как в этой заметке нет, потому что это как объяснять анекдот - либо ты понимаешь, либо нет...

Тот кто ко мне обратился с этой задачей, прежде попробовал несколько популярных плагинов, которые справиться с задачей не смогли: Gd custom tools (платный), Custom Post Type Permalinks (бесплатный). Увидев, что нужно сделать, я не удивился - сложно...

Задача

Создать тип записи и три таксы для него:

  • realty — Тип записи: объявления.
  • country — Многоуровневая таксономия: страна > город (Испания > Валенсия).
  • type_deal — Одноуровневая таксономия. Содержит только 2 термина: sale и rent (продажа, аренда).
  • type_realty — Многоуровневая таксономия: тип недвижимости (дома).

Создать произвольную структуру ссылок (ЧПУ) для такс и записи.

Для таксономий сделать ссылки вида:

  • dom/ estate / %country% /

  • dom/ estate / %country% / %type_deal% /

  • dom/ estate / %country% / %type_deal% / %type_realty% /

Для записи (объявлений):

  • dom/ estate / %country% / %type_deal% / %type_realty% / id-%post_id% /

Суть, сделать ЧПУ таксономий и записи полностью похожими. Чтобы можно было вручную убирать из URL последние элементы и попадать на уровень выше.

Примеры того что должно получиться в URL

Для всех трех таксономий:

  • dom/estate/spain/ - Недвижимость в Испании

  • dom/estate/spain/sale/ - Купить недвижимость в Испании

  • dom/estate/spain/sale/houses/ - Купить дом в Испании

  • dom/estate/spain/valensiya/sale/houses/ - Купить дом в Испании > Валенсия

  • dom/estate/spain/valensiya/sale-rent/ - Продажа и аренда всей недвижимости в Валенсии. Может выглядеть как dom/estate/spain/valensiya/

  • dom/estate/spain/valensiya/sale-rent/kommercheskaya/magazin/ - Продажа и аренда магазинов в Валенсии

Для каждой ссылки таксономии должна работать пагинация .../page/2/, .../page/3/

Для записи:

Все также как и у термина, только в конце еще ID записи:

  • dom/estate/spain/valensiya/sale/houses/id-123/. 123 - ID записи

Решение

Создаем файл в теме lib/register-ads-post-tax.php и подключаем его в functions.php темы:

require_once TEMPLATEPATH .'/lib/register-ads-post-tax.php';

Код файла:

<?php

## регистрация типов записей и таксономий
add_action('init', 'estate_type_register');
function estate_type_register(){

	// post_type realty
	register_post_type('realty', array(
		'description'         => 'Объявления о продаже недвижимости за рубежом.',
		'labels' => array(
			'name'               => 'Объявления',
			'singular_name'      => 'Объявление',
			'add_new'            => 'Добавить новое',
			'add_new_item'       => 'Добавить объявление',
			'edit_item'          => 'Изменить объявление',
			'new_item'           => 'Новое объявление',
			'view_item'          => 'Посмотреть объявления',
			'search_items'       => 'Поиск объявлений',
			'not_found'          => 'Не найдено ни одного объявления',
			'not_found_in_trash' => 'Объявлений в корзине не найдено',
			'parent_item_colon'  => 'Parent Объявление:',
			'all_items'          => 'Все объявления',
			'menu_name'          => 'Объявления'
		),
		'taxonomies'          => array( 'country', 'type_realty', 'type_deal' ),
		'public'              => true,
		'query_var'           => true,
		'rewrite'             => false,
		//'rewrite'             => true,
		//'rewrite'             => array( 'slug'=>'estate/%country%/%post_id%', 'with_front'=>false, 'feeds'=>false, 'pages'=>false, 'feed'=>false, 'paged'=>false ),
		'show_in_menu'        => true,
		'has_archive'         => false,
		'supports'            => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'custom-fields', 'revisions' ),
		'show_ui'             => true,
		'show_in_nav_menus'   => false,
	));

	## Изменяет ссылку на термины таксономий - 'type_deal' и 'type_realty', которая получается функцией get_term_link()
	## К какой стране относится берется из URL текущей страницы
	add_filter('term_link', 'deal_realty_tax_link_fix', 10, 3);
	function deal_realty_tax_link_fix( $link, $term, $taxonomy ){
		if( ! in_array( $taxonomy, array('type_deal','type_realty') ) ) return $link;

		$uri = $_SERVER['REQUEST_URI'];

		if( $taxonomy == 'type_deal' ){
			$link = preg_replace('~^(.*?/)(?:'. implode('|', __type_deal_elements()) .')/.*~', '\1', $uri ) . $term->slug;
		}

		if( $taxonomy == 'type_realty' ){
			$link = preg_replace('~^(.*?/(?:'. implode('|', __type_deal_elements()) .')/).*~', '\1', $uri ) . __build_tax_uri( $term );
		}

		return esc_url( user_trailingslashit( home_url($link) ) );
	}

	// фокусы со структурой ссылок
	if(1){
		//add_action('wp', 'xxxxxxx'); // debug
		function xxxxxxx($wp){
			print_r( get_queried_object() );
			print_r( $wp );
			print_r( $GLOBALS['wp_rewrite'] );
			exit;
		}

		// регистрируем структуру через add_permastruct, чтобы работала структура ЧПУ для типа записи
		add_permastruct('realty', 'estate/%country%/%type_deal%/%type_realty%/id-%post_id%', array(
			'with_front'  => 0,
			'paged'       => 0,
			'feed'        => 0,
			'walk_dirs'   => 0,
		));

		/*
		add_filter( 'query_vars', function( $vars ){
			$vars[] = 'type_deal';
			$vars[] = 'type_realty';
			return $vars;
		} );
		*/

		// поправим параметры запроса - удалим 'country' и добавим 'post_type=realty', потому что '?p=208' не работает, а '?p=208&post_type=realty' работает
		//$this->query_vars = apply_filters( 'request', $this->query_vars );
		add_action('request', 'remove_unwanted_query_vars' );
		function remove_unwanted_query_vars( $vars ){

			if( !empty($vars['country']) ){
				$_country = explode('/', $vars['country']);
				$vars['country'] = end( $_country ); // последний элемент
			}

			if( !empty($vars['type_realty']) ){
				$_type_realty = explode('/', $vars['type_realty']);
				$vars['type_realty'] = end( $_type_realty ); // последний элемент
			}

			// запрос типа записи 'realty' - параметры: country, type_realty, type_deal
			if( isset($vars['p'], $vars['type_realty']) && $vars['post_type'] === 'realty' ){
				$deal = __type_deal_elements();

				if( $vars['type_deal'] == end($deal)/*'sale-rent'*/ )
					unset( $vars['type_deal'] );
			}

			return $vars;
		}

		// добавим правила перезаписи
		//add_rewrite_rule('^estate/.+?/(?:sale|rent|sale-rent)/.+?/([0-9]+)/?', 'index.php?p=$matches[1]&post_type=realty', 'top' );

		// удалим все созданные правила перезаписи и создам новые...
		// $rules = apply_filters( $permastructname . '_rewrite_rules', $rules );
		// do_action_ref_array( 'generate_rewrite_rules', array( &$this ) );
		add_filter('realty'.'_rewrite_rules', 'delete_realty_rewrite_rules' );
		function delete_realty_rewrite_rules( $rules ){
			/* array(
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/?$] => index.php?attachment=$matches[1]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/embed/?$] => index.php?attachment=$matches[1]&embed=true
				[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)/embed/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&embed=true
				[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)/trackback/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&tb=1
				[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)(?:/([0-9]+))?/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&page=$matches[5]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/?$] => index.php?attachment=$matches[1]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
				[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/embed/?$] => index.php?attachment=$matches[1]&embed=true
			) */

			// должен быть до правил стран
			$rules = array(
				'estate/(.+?)/('. implode('|', __type_deal_elements() ) /*sale|rent|sale-rent*/ .')/(.+?)/id-([0-9]+)/?$' => 'index.php?post_type=realty&p=$matches[4]&country=$matches[1]&type_deal=$matches[2]&type_realty=$matches[3]',
			);
			return $rules;
		}

		## добавим правила перезаписи для 'country', 'type_deal', 'type_realty'
		add_filter('country'.'_rewrite_rules', 'add_more_country_rewrite_rules' );
		function add_more_country_rewrite_rules( $rules ){
			/*Array(
				[estate/(.+?)/page/?([0-9]{1,})/?$] => index.php?country=$matches[1]&paged=$matches[2]
				[estate/(.+?)/?$] => index.php?country=$matches[1]
			)*/

			// должен быть после правил типа запии 'realty'
			$_first_part = 'estate/(.+?)/('. implode('|', __type_deal_elements() ) /*sale|rent|sale-rent*/ .')';
			$_pade_part = 'page/?([0-9]{1,})';
			$more_riles = array(
				"$_first_part/(.+?)/$_pade_part/?$" => 'index.php?country=$matches[1]&type_deal=$matches[2]&type_realty=$matches[3]&paged=$matches[4]',
				"$_first_part/$_pade_part/?$"       => 'index.php?country=$matches[1]&type_deal=$matches[2]&paged=$matches[3]',
				"$_first_part/(.+?)/?$"             => 'index.php?country=$matches[1]&type_deal=$matches[2]&type_realty=$matches[3]',
				"$_first_part/?$"                   => 'index.php?country=$matches[1]&type_deal=$matches[2]',
			);

			$rules = array_merge( $more_riles, $rules );

			//die( print_r($rules) );
			return $rules;
		}

		// array( sale, rent, sale-rent )
		function __type_deal_elements(){
			$deal_terms = get_terms(array( 'taxonomy'=>'type_deal','hide_empty'=>0, 'fields'=>'id=>slug' ));
			$deal_terms[] = implode('-', $deal_terms); // sale-rent
			return $deal_terms;
		}

		/*
		add_action('generate_rewrite_rules', 'delete_ads_rewrite_rules' );
		function delete_ads_rewrite_rules( $that ){

			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/?$] => index.php?attachment=$matches[1]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/attachment/([^/]+)/embed/?$] => index.php?attachment=$matches[1]&embed=true
			[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)/embed/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&embed=true
			[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)/trackback/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&tb=1
			[estate/(.+?)/%type_deal%/%type_realty%/([0-9]+)(?:/([0-9]+))?/?$] => index.php?country=$matches[1]&%type_deal%$matches[2]&%type_realty%$matches[3]&p=$matches[4]&page=$matches[5]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/?$] => index.php?attachment=$matches[1]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
			[estate/.+?/%type_deal%/%type_realty%/[0-9]+/([^/]+)/embed/?$] => index.php?attachment=$matches[1]&embed=true

			foreach( $that->extra_rules_top as $rule => $_ ) if( preg_match('~^estate/.+type_deal~', $rule) ) unset($that->extra_rules_top[$rule]);
			foreach( $that->rules           as $rule => $_ ) if( preg_match('~^estate/.+type_deal~', $rule) ) unset($that->rules[$rule]);
		}
		*/

		// добавим post_type в параметры запроса, потому что просто '?p=208' почему-то не работает, а работает '?p=208&post_type=realty'
		//do_action_ref_array( 'parse_request', array( &$this ) );
		/*
		add_action('parse_request', function($wp){
			if( strpos($wp->matched_query, 'foo_') ) $wp->query_vars['post_type'] = 'realty';
		} );

		// дополнительный тег перезаписи, чтобы не учитывать
		add_rewrite_tag('%fake_country%', '(.+?)', '&adsfoovar_='); // adsfoovar_ - несуществующий параметр запроса, он будет удален... он не нужен...

		// заменим %realty% (%post_name%) на ID
		//global $wp_rewrite;
		//$wp_rewrite->extra_permastructs['realty'] = str_replace('%realty%', '%post_id%.html', $wp_rewrite->extra_permastructs['realty']);

		// Удалим слэш на конце, если нужно. Если слэш есть в структуре ЧПУ, то он будет добавляться и к постоянным страницам.
		//add_filter('user_trailingslashit', 'no_ads_trailslash', 170, 2);
		function no_ads_trailslash( $string, $type ){
			global $wp_rewrite;

			if( $type == 'realty' && $wp_rewrite->use_trailing_slashes && $wp_rewrite->using_permalinks() )
				return untrailingslashit($string);

		   return $string;
		}
		*/

		## Отфильтруем ЧПУ произвольного типа
		add_filter('post_type_link', 'realty_permalink', 1, 2);
		function realty_permalink( $permalink, $post ){
			if( false === strpos($permalink, '%country%') ) return $permalink;

			//global $wp_rewrite;
			//$perm = $wp_rewrite->get_extra_permastruct('realty');

			// Получаем элементы таксы 'country'
			$country_path = __build_tax_uri( get_the_terms( $post, 'country') ); // много уровней - asd/asd

			// type_realty_path
			$type_realty_path = __build_tax_uri( get_the_terms( $post, 'type_realty') ); // много уровней - asd/asd

			$type_deal_path = __build_tax_uri( get_the_terms( $post, 'type_deal') ); // один уровень - asd

			return strtr( $permalink, array(
				'%type_deal%'   => $type_deal_path,
				'%type_realty%' => $type_realty_path,
				'%country%'     => $country_path,
				'%post_id%'     => $post->ID,
			) );
		}

		## Получает цепочку из ярлыков указанного термина - вврехи пока у термина не будет родителей - 'parent/child/child'
		function __build_tax_uri( $terms ){
			if( is_wp_error($terms) || empty($terms) || ! ( is_object(reset($terms)) || is_object($terms) ) )
				return 'no_terms'; // элемента таксы нет, а должен быть...

			$term = is_object(reset($terms)) ? reset($terms) : $terms;
			$path = array( $term->slug );
			while( $term->parent ){
				$term = get_term( $term->parent );
				$path[] = $term->slug;
			}

			return implode('/', array_reverse($path) );
		}

		## 404 страница если в URL указаны неправильные названия таксономий.
		## По факту, WP затем 301 редиректит на правильный URL...
		add_filter('pre_handle_404', 'realty_404_test' );
		function realty_404_test( $false ){
			if( ! get_queried_object() ) return $false; // ничего не делает...

			$_404 = false;

			// запись объявления
			if( is_singular('realty') ){
				$post = get_queried_object();

				// type_deal
				if( ! $_404 && ( $term_name = get_query_var('type_deal') ) && ! has_term( explode('-', $term_name), 'type_deal', $post ) )
					$_404 = 1;

				// type_realty
				if( ! $_404 && ( $term_name = get_query_var('type_realty') ) && ! has_term( $term_name, 'type_realty', $post ) )
					$_404 = 1;

				// country
				if( ! $_404 && ( $term_name = get_query_var('country') ) && ! has_term( $term_name, 'country', $post ) )
					$_404 = 1;

			}

			// для такс
			if( is_tax(['type_deal','type_realty','country']) ){
				// type_deal
				if( ! $_404 && ( $term_name = get_query_var('type_deal') ) && ! get_term_by('slug', $term_name, 'type_deal') )
					$_404 = 1;

				// type_realty
				if( ! $_404 && ( $term_name = get_query_var('type_realty') ) && ! get_term_by('slug', $term_name, 'type_realty') )
					$_404 = 1;

				// country
				if( ! $_404 && ( $term_name = get_query_var('country') ) && ! get_term_by('slug', $term_name, 'country') )
					$_404 = 1;

			}

			if( $_404 ){
				global $wp_query;

				$wp_query->set_404();
				status_header( 404 );
				nocache_headers();

				return 1; // обрываем следующие проверки
			}

			return $false; // ничего не делает...
		}

	}

	## Такса - страна город регион
	register_taxonomy('country', array('realty'), array(
		'labels' => array(
			'name'                       => 'Страны',
			'singular_name'              => 'Страна',
			'search_items'               => 'Search Страны',
			'popular_items'              => 'Popular Страны',
			'all_items'                  => 'All Страны',
			'parent_item'                => 'Parent Страна',
			'parent_item_colon'          => 'Parent Страна:',
			'edit_item'                  => 'Edit Страна',
			'view_item'                  => 'View Страна',
			'update_item'                => 'Update Страна',
			'add_new_item'               => 'Add New Страна',
			'new_item_name'              => 'New Страна Name',
			'separate_items_with_commas' => 'Separate Страны with commas',
			'add_or_remove_items'        => 'Add or remove Страны',
			'choose_from_most_used'      => 'Choose from the most used Страны',
			'not_found'                  => 'No Страны found.',
			'menu_name'                  => 'Страны'
		),
		'hierarchical'       => true,
		'rewrite'            => array('slug'=>'estate', 'hierarchical'=>true, 'with_front'=>0, 'feed'=>0 ),
		'query_var'          => true,
		'public'             => true,
		'show_ui'            => true,
		'show_tagcloud'      => true,
		'show_admin_column'  => false,
		'show_in_nav_menus'  => true,
	));

	## Такса - тип недвижимости
	register_taxonomy( 'type_realty', array('realty'), array(
		'labels' => array(
			'name'                       => 'Тип недвижимости',
			'singular_name'              => 'Тип недвижимости',
			'search_items'               => 'Search Тип недвижимости',
			'popular_items'              => 'Popular Тип недвижимости',
			'all_items'                  => 'All Тип недвижимости',
			'parent_item'                => 'Parent Тип недвижимости',
			'parent_item_colon'          => 'Parent Тип недвижимости:',
			'edit_item'                  => 'Edit Тип недвижимости',
			'view_item'                  => 'View Тип недвижимости',
			'update_item'                => 'Update Тип недвижимости',
			'add_new_item'               => 'Add New Тип недвижимости',
			'new_item_name'              => 'New Тип недвижимости Name',
			'separate_items_with_commas' => 'Separate Тип недвижимости with commas',
			'add_or_remove_items'        => 'Add or remove Тип недвижимости',
			'choose_from_most_used'      => 'Choose from the most used Тип недвижимости',
			'not_found'                  => 'No Тип недвижимости found.',
			'menu_name'                  => 'Тип недвижимости'
		),
		'public'             => false,
		'rewrite'            => false,
		'hierarchical'       => true,
		'query_var'          => true, // query_var, чтобы запрос на термин работал...
		'publicly_queryable' => true, // query_var, чтобы запрос на термин работал...
		'show_ui'            => true,
		'show_in_quick_edit' => true,
		'show_tagcloud'      => false,
		'show_admin_column'  => false,
		'show_in_nav_menus'  => false,
	));

	## Такса - тип сделки  -  два типа - 'sale' и 'rent'
	register_taxonomy('type_deal', array('realty'), array(
		'labels' => array(
			'name'                       => 'Тип сделки',
			'singular_name'              => 'Тип сделки',
			'search_items'               => 'Search Тип сделки',
			'popular_items'              => 'Popular Тип сделки',
			'all_items'                  => 'All Тип сделки',
			'parent_item'                => 'Parent Тип сделки',
			'parent_item_colon'          => 'Parent Тип сделки:',
			'edit_item'                  => 'Edit Тип сделки',
			'view_item'                  => 'View Тип сделки',
			'update_item'                => 'Update Тип сделки',
			'add_new_item'               => 'Add New Тип сделки',
			'new_item_name'              => 'New Тип сделки Name',
			'separate_items_with_commas' => 'Separate Тип сделки with commas',
			'add_or_remove_items'        => 'Add or remove Тип сделки',
			'choose_from_most_used'      => 'Choose from the most used Тип сделки',
			'not_found'                  => 'No Тип сделки found.',
			'menu_name'                  => 'Тип сделки'
		),
		'public'             => false,
		'hierarchical'       => true, // для удобности выбора
		'query_var'          => true, // query_var, чтобы запрос на термин работал...
		'publicly_queryable' => true, // query_var, чтобы запрос на термин работал...
		'rewrite'            => false,
		'show_ui'            => true,
		'show_in_quick_edit' => true,
		'show_tagcloud'      => false,
		'show_in_nav_menus'  => false,
		'show_admin_column'  => false,
	));

}

##  отменим показ выбранного термина наверху в checkbox списке терминов
add_filter( 'wp_terms_checklist_args', 'set_checked_ontop_default', 10 );
function set_checked_ontop_default( $args ){
	// изменим параметр по умолчанию на false
	if( ! isset($args['checked_ontop']) ) $args['checked_ontop'] = false;

	return $args;
}

## Меняем страницу отдельной страны
add_filter('template_include', 'top_country_tpl_file');
function top_country_tpl_file( $template ) {

	// термин страницы верхнего уровня
	if( is_tax('country') ){
		if( ! get_query_var('type_realty') && ! get_query_var('type_deal') && ($term = get_queried_object()) && ! $term->parent ){
			$tpl_file = get_stylesheet_directory() . '/taxonomy-country-toplevel.php';
			if( file_exists($tpl_file) ) $template = $tpl_file;
		}
	}

	return $template;
}

// дополнительные хуки для станицы создания объявления
// изменение блока метабокса
if( is_admin() ){

	// стили в админке связанные с типом поста quest
	add_action('admin_print_footer_scripts', 'country_hook_admin_footer_scripts', 99);
	function country_hook_admin_footer_scripts(){
		$sc = get_current_screen();
		if( $sc->base != 'post' || ! in_array($sc->post_type, ['realty']) )
			return;
		?>
		<style>
			.postbox div.tabs-panel{ max-height:700px; border:0; }
			.category-tabs{ display:none; }
			#countrydiv .inside{ margin:0; padding:0; }
			#countrydiv #country-adder{ padding: 0 1em; }
			#country-all ul.children{ display:none; }
		</style>

		<script>
		jQuery(document).ready(function($){

			var $main = $('#country-all'),
				$checklist = $main.find('input[type="checkbox"]');

			$checklist.prop('type','radio');

			// стрелки ▾ ▸
			$main.find('label').each(function(){
				var $li = $(this).closest('li')
				if( $li.find('> .children').length )
					$(this).append('<span class="has_ch" style="opacity:.5;">▸</span>');
			});

			// развернуть/свернуть
			$main.on('click', 'input', function(){
				var $li = $(this).closest('li'),
					$child = $li.find('> .children');

				if( $child.length ){
					if( $child.is(':visible') ){
						$child.slideUp(200);
						$child.prev().find('.has_ch').text('▸');
					}
					else {
						$child.slideDown(200);
						$child.prev().find('.has_ch').text('▾');
					}
				}
			});

			// покажем выбранный внутренний
			var $checked = $checklist.filter(':checked')
			if( $checked.length )
				$checked.parents('ul.children').show()

		});
		</script>
		<?php
	}

}

Объяснять код не буду, долго, сложно, смысла особо нет, потому лень, извините...

24 комментария
Полезные 1 Все
    Войти