class-wc-breadcrumb.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <?php
  2. /**
  3. * WC_Breadcrumb class.
  4. *
  5. * @package WooCommerce/Classes
  6. * @version 2.3.0
  7. */
  8. defined( 'ABSPATH' ) || exit;
  9. /**
  10. * Breadcrumb class.
  11. */
  12. class WC_Breadcrumb {
  13. /**
  14. * Breadcrumb trail.
  15. *
  16. * @var array
  17. */
  18. private $crumbs = array();
  19. /**
  20. * Add a crumb so we don't get lost.
  21. *
  22. * @param string $name Name.
  23. * @param string $link Link.
  24. */
  25. public function add_crumb( $name, $link = '' ) {
  26. $this->crumbs[] = array(
  27. strip_tags( $name ),
  28. $link,
  29. );
  30. }
  31. /**
  32. * Reset crumbs.
  33. */
  34. public function reset() {
  35. $this->crumbs = array();
  36. }
  37. /**
  38. * Get the breadcrumb.
  39. *
  40. * @return array
  41. */
  42. public function get_breadcrumb() {
  43. return apply_filters( 'woocommerce_get_breadcrumb', $this->crumbs, $this );
  44. }
  45. /**
  46. * Generate breadcrumb trail.
  47. *
  48. * @return array of breadcrumbs
  49. */
  50. public function generate() {
  51. $conditionals = array(
  52. 'is_home',
  53. 'is_404',
  54. 'is_attachment',
  55. 'is_single',
  56. 'is_product_category',
  57. 'is_product_tag',
  58. 'is_shop',
  59. 'is_page',
  60. 'is_post_type_archive',
  61. 'is_category',
  62. 'is_tag',
  63. 'is_author',
  64. 'is_date',
  65. 'is_tax',
  66. );
  67. if ( ( ! is_front_page() && ! ( is_post_type_archive() && intval( get_option( 'page_on_front' ) ) === wc_get_page_id( 'shop' ) ) ) || is_paged() ) {
  68. foreach ( $conditionals as $conditional ) {
  69. if ( call_user_func( $conditional ) ) {
  70. call_user_func( array( $this, 'add_crumbs_' . substr( $conditional, 3 ) ) );
  71. break;
  72. }
  73. }
  74. $this->search_trail();
  75. $this->paged_trail();
  76. return $this->get_breadcrumb();
  77. }
  78. return array();
  79. }
  80. /**
  81. * Prepend the shop page to shop breadcrumbs.
  82. */
  83. private function prepend_shop_page() {
  84. $permalinks = wc_get_permalink_structure();
  85. $shop_page_id = wc_get_page_id( 'shop' );
  86. $shop_page = get_post( $shop_page_id );
  87. // If permalinks contain the shop page in the URI prepend the breadcrumb with shop.
  88. if ( $shop_page_id && $shop_page && isset( $permalinks['product_base'] ) && strstr( $permalinks['product_base'], '/' . $shop_page->post_name ) && intval( get_option( 'page_on_front' ) ) !== $shop_page_id ) {
  89. $this->add_crumb( get_the_title( $shop_page ), get_permalink( $shop_page ) );
  90. }
  91. }
  92. /**
  93. * Is home trail..
  94. */
  95. private function add_crumbs_home() {
  96. $this->add_crumb( single_post_title( '', false ) );
  97. }
  98. /**
  99. * 404 trail.
  100. */
  101. private function add_crumbs_404() {
  102. $this->add_crumb( __( 'Error 404', 'woocommerce' ) );
  103. }
  104. /**
  105. * Attachment trail.
  106. */
  107. private function add_crumbs_attachment() {
  108. global $post;
  109. $this->add_crumbs_single( $post->post_parent, get_permalink( $post->post_parent ) );
  110. $this->add_crumb( get_the_title(), get_permalink() );
  111. }
  112. /**
  113. * Single post trail.
  114. *
  115. * @param int $post_id Post ID.
  116. * @param string $permalink Post permalink.
  117. */
  118. private function add_crumbs_single( $post_id = 0, $permalink = '' ) {
  119. if ( ! $post_id ) {
  120. global $post;
  121. } else {
  122. $post = get_post( $post_id ); // WPCS: override ok.
  123. }
  124. if ( 'product' === get_post_type( $post ) ) {
  125. $this->prepend_shop_page();
  126. $terms = wc_get_product_terms(
  127. $post->ID, 'product_cat', apply_filters(
  128. 'woocommerce_breadcrumb_product_terms_args', array(
  129. 'orderby' => 'parent',
  130. 'order' => 'DESC',
  131. )
  132. )
  133. );
  134. if ( $terms ) {
  135. $main_term = apply_filters( 'woocommerce_breadcrumb_main_term', $terms[0], $terms );
  136. $this->term_ancestors( $main_term->term_id, 'product_cat' );
  137. $this->add_crumb( $main_term->name, get_term_link( $main_term ) );
  138. }
  139. } elseif ( 'post' !== get_post_type( $post ) ) {
  140. $post_type = get_post_type_object( get_post_type( $post ) );
  141. if ( ! empty( $post_type->has_archive ) ) {
  142. $this->add_crumb( $post_type->labels->singular_name, get_post_type_archive_link( get_post_type( $post ) ) );
  143. }
  144. } else {
  145. $cat = current( get_the_category( $post ) );
  146. if ( $cat ) {
  147. $this->term_ancestors( $cat->term_id, 'category' );
  148. $this->add_crumb( $cat->name, get_term_link( $cat ) );
  149. }
  150. }
  151. $this->add_crumb( get_the_title( $post ), $permalink );
  152. }
  153. /**
  154. * Page trail.
  155. */
  156. private function add_crumbs_page() {
  157. global $post;
  158. if ( $post->post_parent ) {
  159. $parent_crumbs = array();
  160. $parent_id = $post->post_parent;
  161. while ( $parent_id ) {
  162. $page = get_post( $parent_id );
  163. $parent_id = $page->post_parent;
  164. $parent_crumbs[] = array( get_the_title( $page->ID ), get_permalink( $page->ID ) );
  165. }
  166. $parent_crumbs = array_reverse( $parent_crumbs );
  167. foreach ( $parent_crumbs as $crumb ) {
  168. $this->add_crumb( $crumb[0], $crumb[1] );
  169. }
  170. }
  171. $this->add_crumb( get_the_title(), get_permalink() );
  172. $this->endpoint_trail();
  173. }
  174. /**
  175. * Product category trail.
  176. */
  177. private function add_crumbs_product_category() {
  178. $current_term = $GLOBALS['wp_query']->get_queried_object();
  179. $this->prepend_shop_page();
  180. $this->term_ancestors( $current_term->term_id, 'product_cat' );
  181. $this->add_crumb( $current_term->name );
  182. }
  183. /**
  184. * Product tag trail.
  185. */
  186. private function add_crumbs_product_tag() {
  187. $current_term = $GLOBALS['wp_query']->get_queried_object();
  188. $this->prepend_shop_page();
  189. /* translators: %s: product tag */
  190. $this->add_crumb( sprintf( __( 'Products tagged &ldquo;%s&rdquo;', 'woocommerce' ), $current_term->name ) );
  191. }
  192. /**
  193. * Shop breadcrumb.
  194. */
  195. private function add_crumbs_shop() {
  196. if ( intval( get_option( 'page_on_front' ) ) === wc_get_page_id( 'shop' ) ) {
  197. return;
  198. }
  199. $_name = wc_get_page_id( 'shop' ) ? get_the_title( wc_get_page_id( 'shop' ) ) : '';
  200. if ( ! $_name ) {
  201. $product_post_type = get_post_type_object( 'product' );
  202. $_name = $product_post_type->labels->singular_name;
  203. }
  204. $this->add_crumb( $_name, get_post_type_archive_link( 'product' ) );
  205. }
  206. /**
  207. * Post type archive trail.
  208. */
  209. private function add_crumbs_post_type_archive() {
  210. $post_type = get_post_type_object( get_post_type() );
  211. if ( $post_type ) {
  212. $this->add_crumb( $post_type->labels->singular_name, get_post_type_archive_link( get_post_type() ) );
  213. }
  214. }
  215. /**
  216. * Category trail.
  217. */
  218. private function add_crumbs_category() {
  219. $this_category = get_category( $GLOBALS['wp_query']->get_queried_object() );
  220. if ( 0 !== intval( $this_category->parent ) ) {
  221. $this->term_ancestors( $this_category->term_id, 'category' );
  222. }
  223. $this->add_crumb( single_cat_title( '', false ), get_category_link( $this_category->term_id ) );
  224. }
  225. /**
  226. * Tag trail.
  227. */
  228. private function add_crumbs_tag() {
  229. $queried_object = $GLOBALS['wp_query']->get_queried_object();
  230. /* translators: %s: tag name */
  231. $this->add_crumb( sprintf( __( 'Posts tagged &ldquo;%s&rdquo;', 'woocommerce' ), single_tag_title( '', false ) ), get_tag_link( $queried_object->term_id ) );
  232. }
  233. /**
  234. * Add crumbs for date based archives.
  235. */
  236. private function add_crumbs_date() {
  237. if ( is_year() || is_month() || is_day() ) {
  238. $this->add_crumb( get_the_time( 'Y' ), get_year_link( get_the_time( 'Y' ) ) );
  239. }
  240. if ( is_month() || is_day() ) {
  241. $this->add_crumb( get_the_time( 'F' ), get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ) );
  242. }
  243. if ( is_day() ) {
  244. $this->add_crumb( get_the_time( 'd' ) );
  245. }
  246. }
  247. /**
  248. * Add crumbs for taxonomies
  249. */
  250. private function add_crumbs_tax() {
  251. $this_term = $GLOBALS['wp_query']->get_queried_object();
  252. $taxonomy = get_taxonomy( $this_term->taxonomy );
  253. $this->add_crumb( $taxonomy->labels->name );
  254. if ( 0 !== intval( $this_term->parent ) ) {
  255. $this->term_ancestors( $this_term->term_id, $this_term->taxonomy );
  256. }
  257. $this->add_crumb( single_term_title( '', false ), get_term_link( $this_term->term_id, $this_term->taxonomy ) );
  258. }
  259. /**
  260. * Add a breadcrumb for author archives.
  261. */
  262. private function add_crumbs_author() {
  263. global $author;
  264. $userdata = get_userdata( $author );
  265. /* translators: %s: author name */
  266. $this->add_crumb( sprintf( __( 'Author: %s', 'woocommerce' ), $userdata->display_name ) );
  267. }
  268. /**
  269. * Add crumbs for a term.
  270. *
  271. * @param int $term_id Term ID.
  272. * @param string $taxonomy Taxonomy.
  273. */
  274. private function term_ancestors( $term_id, $taxonomy ) {
  275. $ancestors = get_ancestors( $term_id, $taxonomy );
  276. $ancestors = array_reverse( $ancestors );
  277. foreach ( $ancestors as $ancestor ) {
  278. $ancestor = get_term( $ancestor, $taxonomy );
  279. if ( ! is_wp_error( $ancestor ) && $ancestor ) {
  280. $this->add_crumb( $ancestor->name, get_term_link( $ancestor ) );
  281. }
  282. }
  283. }
  284. /**
  285. * Endpoints.
  286. */
  287. private function endpoint_trail() {
  288. $endpoint = is_wc_endpoint_url() ? WC()->query->get_current_endpoint() : '';
  289. $endpoint_title = $endpoint ? WC()->query->get_endpoint_title( $endpoint ) : '';
  290. if ( $endpoint_title ) {
  291. $this->add_crumb( $endpoint_title );
  292. }
  293. }
  294. /**
  295. * Add a breadcrumb for search results.
  296. */
  297. private function search_trail() {
  298. if ( is_search() ) {
  299. /* translators: %s: search term */
  300. $this->add_crumb( sprintf( __( 'Search results for &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() ), remove_query_arg( 'paged' ) );
  301. }
  302. }
  303. /**
  304. * Add a breadcrumb for pagination.
  305. */
  306. private function paged_trail() {
  307. if ( get_query_var( 'paged' ) ) {
  308. /* translators: %d: page number */
  309. $this->add_crumb( sprintf( __( 'Page %d', 'woocommerce' ), get_query_var( 'paged' ) ) );
  310. }
  311. }
  312. }