Here is a quick solution, that may guide you to desired result.
$years = get_terms( array(
'taxonomy' => 'product-year',
'hide_empty' => true,
) );
$cats = get_terms( array(
'taxonomy' => 'product-cat',
'hide_empty' => true,
) );
if ( ! empty( $years ) && ! is_wp_error( $years ) ){
foreach ( $years as $year ) {
echo '<strong>'.$year->name.'</strong>';
if ( ! empty( $cats ) && ! is_wp_error( $cats ) ){
foreach ( $cats as $cat ) {
echo '<strong>'.$cat->name.'</strong>';
$args = array(
'post_type' => 'Products',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'product-year',
'field' => 'term_id',
'terms' => array( $year->term_id ),
),
array(
'taxonomy' => 'product-cat',
'field' => 'term_id',
'terms' => array( $cat->term_id ),
),
),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
echo '<table>';
while ( $query->have_posts() ) {
$query->the_post();
$countries = get_the_terms( get_the_ID(), 'product-country' );
if ( $countries && ! is_wp_error( $countries ) ) :
$countries_links = array();
foreach ( $countries as $country ) {
$countries_links[] = $country->name;
}
$countries_names = join( ", ", $countries_links );
}
echo '<tr><td>' . get_the_title( ) . '</td>'.'<td>' . $countries_names . '</td></tr>' ;
}
echo '</table>';
// Restore original Post Data
wp_reset_postdata();
}
}
}
}
}
Please take care of any typo if any.