diff --git a/src/classes/repositories/class-tainacan-metadata.php b/src/classes/repositories/class-tainacan-metadata.php index 569bc1448..f14c310ef 100644 --- a/src/classes/repositories/class-tainacan-metadata.php +++ b/src/classes/repositories/class-tainacan-metadata.php @@ -1014,19 +1014,78 @@ class Metadata extends Repository { if ( $metadatum_type === 'Tainacan\Metadata_Types\Taxonomy' ) { if ($items_query) { - $base_query = $wpdb->prepare("FROM $wpdb->term_relationships tr - INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id - INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id - WHERE - tt.parent = %d AND - tr.object_id IN ($items_query) AND - tt.taxonomy = %s - $search_q + + // $base_query = $wpdb->prepare("FROM $wpdb->term_relationships tr + // INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id + // INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id + // WHERE + // tt.parent = %d AND + // tr.object_id IN ($items_query) AND + // tt.taxonomy = %s + // $search_q + // ORDER BY t.name ASC + // ", + // $args['parent_id'], + // $taxonomy_slug + // ); + + //$search_query = "AND (tt.parent <> %d OR t.name LIKE '%master%')"; + + + $base_query = $wpdb->prepare(" + SELECT DISTINCT t.term_id, t.name, tt.parent, coalesce(tr.term_taxonomy_id, 0) as have_items + FROM + $wpdb->terms t INNER JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id + LEFT JOIN $wpdb->term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id AND tr.object_id IN ($items_query) + WHERE tt.taxonomy = %s ORDER BY t.name ASC - ", - $args['parent_id'], - $taxonomy_slug + ", + $taxonomy_slug ); + + $all_hierarchy = $wpdb->get_results($base_query); + + $results = $this->_process_terms_tree($all_hierarchy, $args['parent_id']); + $total = count($results); + + // $results = []; + // + // function children_has_items($term_id, $hierarchy) { + // + // $has_items = false; + // + // foreach ( $hierarchy as $h ) { + // + // if ( $term_in_hierarchy->parent != $term_id ) { + // continue; + // } + // + // if ( $h->have_items > 0 ) { + // return true; + // } else { + // return children_has_items($h->term_id, $hierarchy); + // } + // + // } + // + // return false; + // + // } + // var_dump($all_hierarchy); + // foreach ($all_hierarchy as $term_in_hierarchy) { + // if ( $term_in_hierarchy->parent != $args['parent_id'] ) { + // continue; + // } + // + // if ( $term_in_hierarchy->have_items > 0 || children_has_items($term_in_hierarchy->term_id, $all_hierarchy) ) { + // $results[] = $term_in_hierarchy; + // } + // + // } + + + + } else { $base_query = $wpdb->prepare("FROM $wpdb->term_taxonomy tt INNER JOIN $wpdb->terms t ON tt.term_id = t.term_id @@ -1039,14 +1098,18 @@ class Metadata extends Repository { $args['parent_id'], $taxonomy_slug ); + + $query = "SELECT DISTINCT t.name, t.term_id, tt.term_taxonomy_id, tt.parent $base_query $pagination"; + + $total_query = "SELECT COUNT(DISTINCT tt.term_taxonomy_id) $base_query"; + $total = $wpdb->get_var($total_query); + + $results = $wpdb->get_results($query); + } - $query = "SELECT DISTINCT t.name, t.term_id, tt.term_taxonomy_id, tt.parent $base_query $pagination"; - $total_query = "SELECT COUNT(DISTINCT tt.term_taxonomy_id) $base_query"; - - $results = $wpdb->get_results($query); // add selected to the result if ( !empty($args['include']) ) { @@ -1071,7 +1134,7 @@ class Metadata extends Repository { } } - $total = $wpdb->get_var($total_query); + $number = is_integer($args['number']) && $args['number'] >=1 ? $args['number'] : $total; if( $number < 1){ $pages = 1; @@ -1197,6 +1260,75 @@ class Metadata extends Repository { ]; } + + public function _process_terms_tree($tree, $search_parent) { + + $h_map = []; + $results = []; + foreach ( $tree as $h ) { + + //echo "Processing $h->term_id\n"; + //var_dump($h); + //echo "Já ta mapeado?\n"; + //var_dump(( isset($h_map[$h->term_id]) && $h_map[$h->term_id]->have_items > 0 )); + + if ( $h->have_items > 0 || ( isset($h_map[$h->term_id]) && $h_map[$h->term_id]->have_items > 0 ) ) { + + //echo "have_items\n"; + + $h->have_items = 1; + $h_map[$h->term_id] = $h; + + + + if ($h->parent == $search_parent) { + //echo "Add to results\n"; + $results[] = $h; + } + + $_parent = $h->parent; + + if ( $h->parent > 0 && !isset($h_map[$_parent]) ) { + //echo "Setting parent with have items 1\n"; + //echo "Parent ID = $_parent\n"; + $h_map[$_parent] = (object)['have_items' => 1]; + } + + while( isset($h_map[$_parent]) && $h_map[$_parent]->have_items != 1 ) { + + //echo "Looping\n"; + + $h_map[$_parent]->have_items = 1; + + if ( isset($h_map[$_parent]->parent) ) { + //echo "Parent exists: $_parent\n"; + if ($h_map[$_parent]->parent == $search_parent) { + //echo "Add to results: {$h_map[$_parent]->term_id}\n"; + $results[] = $h_map[$_parent]; + } + $_parent = $h_map[$_parent]->parent; + } else { + //echo "Parent not exists\n"; + $_parent = 0; + } + + } + + } else { + //echo "Not have items\n"; + $h_map[$h->term_id] = $h; + if ( $h->parent > 0 && !isset($h_map[$h->parent]) ) { + //echo "Parent added: $h->parent\n"; + $h_map[$h->parent] = (object)['have_items' => $h->have_items]; + } + + } + + } + + return $results; + + } /** * Stores the value of the taxonomy_id option to use on update_taxonomy_metadatum method. diff --git a/tests/test-facets.php b/tests/test-facets.php index 48dc96834..a20ed8b39 100644 --- a/tests/test-facets.php +++ b/tests/test-facets.php @@ -52,6 +52,19 @@ class Facets extends TAINACAN_UnitApiTestCase { $this->taxonomy = $taxonomy; + $taxonomy2 = $this->tainacan_entity_factory->create_entity( + 'taxonomy', + array( + 'name' => 'genero2', + 'description' => 'tipos de musica2', + 'allow_insert' => 'yes', + 'status' => 'publish' + ), + true + ); + + $this->taxonomy = $taxonomy; + $term_1 = $this->tainacan_entity_factory->create_entity( 'term', array( @@ -113,6 +126,104 @@ class Facets extends TAINACAN_UnitApiTestCase { true ); + $term2_root = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Root' + ), + true + ); + $term2_root2 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Root2' + ), + true + ); + $term2_root_c1 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Children', + 'parent' => $term2_root->get_id() + ), + true + ); + $term2_root_c2 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Children2', + 'parent' => $term2_root->get_id() + ), + true + ); + $term2_root_gc1 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'GChildren', + 'parent' => $term2_root_c2->get_id() + ), + true + ); + $term2_root_gc2 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'GChildren2', + 'parent' => $term2_root_c2->get_id() + ), + true + ); + $term2_root2_c1 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Children', + 'parent' => $term2_root2->get_id() + ), + true + ); + $term2_root2_c2 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'Children2', + 'parent' => $term2_root2->get_id() + ), + true + ); + $term2_root2_gc1 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'GChildren', + 'parent' => $term2_root2_c2->get_id() + ), + true + ); + $term2_root2_gc2 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'GChildren2', + 'parent' => $term2_root2_c2->get_id() + ), + true + ); + $term2_root2_ggc1 = $this->tainacan_entity_factory->create_entity( + 'term', + array( + 'taxonomy' => $taxonomy2->get_db_identifier(), + 'name' => 'GGChildren1', + 'parent' => $term2_root2_gc2->get_id() + ), + true + ); + $meta_1_tax = $this->tainacan_entity_factory->create_entity( 'metadatum', array( @@ -150,6 +261,24 @@ class Facets extends TAINACAN_UnitApiTestCase { $this->meta_2_tax = $meta_2_tax; + $meta_3_tax = $this->tainacan_entity_factory->create_entity( + 'metadatum', + array( + 'name' => 'test taxonomy', + 'status' => 'publish', + 'collection' => $collection2, + 'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy', + 'metadata_type_options' => [ + 'allow_new_terms' => true, + 'taxonomy_id' => $taxonomy2->get_id() + ], + 'multiple' => 'yes' + ), + true + ); + + $this->meta_3_tax = $meta_3_tax; + $metadatum_text = $this->tainacan_entity_factory->create_entity( 'metadatum', array( @@ -239,8 +368,16 @@ class Facets extends TAINACAN_UnitApiTestCase { $this->tainacan_item_metadata_factory->create_item_metadata($item, $meta_2_tax, [$term_2_c->get_id()]); } - - + // hierarchical taxonomy + if ($i <= 10) { + $this->tainacan_item_metadata_factory->create_item_metadata($item, $meta_3_tax, [$term2_root_c1->get_id()]); + } elseif($i <= 20) { + $this->tainacan_item_metadata_factory->create_item_metadata($item, $meta_3_tax, [$term2_root2_c1->get_id()]); + } elseif($i <= 30) { + $this->tainacan_item_metadata_factory->create_item_metadata($item, $meta_3_tax, [$term2_root2_gc2->get_id()]); + } elseif($i <= 40) { + $this->tainacan_item_metadata_factory->create_item_metadata($item, $meta_3_tax, [$term2_root2_ggc1->get_id()]); + } } $this->repository = \Tainacan\Repositories\Metadata::get_instance(); @@ -647,7 +784,16 @@ class Facets extends TAINACAN_UnitApiTestCase { // test count items normal // test default taxonomy + $values = $this->repository->fetch_all_metadatum_values( $this->meta_3_tax->get_id()); + $values = $this->get_values($values); + $this->assertEquals(2, sizeof($values)); + // test default taxonomy without filter + $values = $this->repository->fetch_all_metadatum_values( $this->meta_3_tax->get_id(), [ + 'items_filter' => false + ]); + $values = $this->get_values($values); + $this->assertEquals(2, sizeof($values)); // test search taxonomy // test search taxonomy with filter // test search taxonomy without filter @@ -660,6 +806,168 @@ class Facets extends TAINACAN_UnitApiTestCase { + } + + /** + * @group term_tree + */ + public function test_process_term_tree() { + + $data = [ + (object) [ + 'term_id' => 1, + 'name' => 'Root', + 'parent' => 0, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 2, + 'name' => 'Child 1', + 'parent' => 1, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 3, + 'name' => 'G Child 1', + 'parent' => 2, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 4, + 'name' => 'G G Child', + 'parent' => 3, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 5, + 'name' => 'G G Child 2', + 'parent' => 3, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 6, + 'name' => 'G G G Child', + 'parent' => 4, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 7, + 'name' => 'G G G Child 2', + 'parent' => 5, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 8, + 'name' => '2 Root', + 'parent' => 0, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 9, + 'name' => '2 Child', + 'parent' => 8, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 10, + 'name' => '2 Child 2', + 'parent' => 8, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 11, + 'name' => '2 G Child', + 'parent' => 10, + 'have_items' => 0 + ], + (object) [ + 'term_id' => 12, + 'name' => '2 G Child 2', + 'parent' => 10, + 'have_items' => 0 + ] + ]; + + $data_b = $data; + + + $MetaRepo = \Tainacan\Repositories\Metadata::get_instance(); + + + // items on 5 and 12 + $data[4]->have_items = 1; + $data[11]->have_items = 1; + $i = 0; + while ($i<100) { + $i++; + + shuffle($data); + + $results = $MetaRepo->_process_terms_tree($data, 0); + + $this->assertEquals(2, count($results)); + $ids = array_map(function($el) {return $el->term_id; }, $results); + $this->assertContains(1, $ids); + $this->assertContains(8, $ids); + + + $results = $MetaRepo->_process_terms_tree($data, 3); + + $this->assertEquals(1, count($results)); + $ids = array_map(function($el) {return $el->term_id; }, $results); + $this->assertContains(5, $ids); + + $results = $MetaRepo->_process_terms_tree($data, 5); + $this->assertEquals(0, count($results)); + + $results = $MetaRepo->_process_terms_tree($data, 10); + $this->assertEquals(1, count($results)); + $this->assertEquals(12, $results[0]->term_id); + + } + + // items on 6, 7 and 8 + $data = $data_b; + $data[4]->have_items = 0; + $data[11]->have_items = 0; + $data[7]->have_items = 1; + $data[6]->have_items = 1; + $data[5]->have_items = 1; + + $i = 0; + while ($i<100) { + $i++; + + shuffle($data); + + $results = $MetaRepo->_process_terms_tree($data, 0); + + $this->assertEquals(2, count($results)); + $ids = array_map(function($el) {return $el->term_id; }, $results); + $this->assertContains(1, $ids); + $this->assertContains(8, $ids); + + + $results = $MetaRepo->_process_terms_tree($data, 3); + $this->assertEquals(2, count($results)); + $ids = array_map(function($el) {return $el->term_id; }, $results); + $this->assertContains(5, $ids); + $this->assertContains(4, $ids); + + $results = $MetaRepo->_process_terms_tree($data, 5); + $this->assertEquals(1, count($results)); + $ids = array_map(function($el) {return $el->term_id; }, $results); + $this->assertContains(7, $ids); + + $results = $MetaRepo->_process_terms_tree($data, 10); + $this->assertEquals(0, count($results)); + + $results = $MetaRepo->_process_terms_tree($data, 6); + $this->assertEquals(0, count($results)); + + } + + }