register tax to poststypes considering inheritance of tax metadata #111

This commit is contained in:
Leo Germani 2018-08-17 17:00:02 -03:00
parent de854bc036
commit 37586925ce
7 changed files with 424 additions and 22 deletions

View File

@ -78,22 +78,13 @@ class Taxonomy extends Entity {
],
);
$tax_cpts = [];
if (is_array($this->get_collections())){
foreach ($this->get_collections() as $tax_col){
$tax_cpts[] = $tax_col->get_db_identifier();
}
}
if (taxonomy_exists($this->get_db_identifier())){
unregister_taxonomy($this->get_db_identifier());
}
register_taxonomy(
$this->get_db_identifier(),
$tax_cpts,
null,
$args
);

View File

@ -162,12 +162,16 @@ class Items extends Repository {
$collection->register_collection_item_post_type();
}
// register taxonomies
// register taxonomies
if ( is_array( $taxonomies ) && sizeof( $taxonomies ) > 0 ) {
foreach ( $taxonomies as $taxonomy ) {
$taxonomy->tainacan_register_taxonomy();
}
}
// register taxonomies to collections considering metadata inheritance
$Tainacan_Taxonomies->register_taxonomies_for_all_collections();
}
public function insert( $item ) {

View File

@ -1095,7 +1095,7 @@ class Metadata extends Repository {
}
if ( $new_tax != $this->current_taxonomy ) {
$collection = $metadatum->get_collection();
$collection = $metadatum->get_collection_id();
if ( ! empty( $this->current_taxonomy ) && $collection ) {
do_action( 'tainacan-taxonomy-removed-from-collection', $this->current_taxonomy, $collection );
@ -1115,7 +1115,7 @@ class Metadata extends Repository {
if ( $metadata_type->get_primitive_type() == 'term' ) {
$removed_tax = $metadata_type->get_option( 'taxonomy_id' );
$collection = $metadatum->get_collection();
$collection = $metadatum->get_collection_id();
if ( ! empty( $removed_tax ) && $collection ) {
do_action( 'tainacan-taxonomy-removed-from-collection', $removed_tax, $collection );

View File

@ -900,6 +900,45 @@ abstract class Repository {
return $diffs;
}
/**
* Get IDs for all children, grand children till the depth parameter is reached
* @param int|\Tainacan\Entities\Entity $id The Entity ID or object
* @param bool|int $depth The maximum depth to llok for descendants. default is false = no limit
* @return array Array of IDs
*/
public function get_descendants_ids($id, $depth = false) {
$object = $id;
if (is_integer($id)) {
$object = $this->fetch($id);
}
if ( ! $object instanceof \Tainacan\Entities\Entity) {
return [];
}
global $wpdb;
$go_deeper = false === $depth || (is_integer($depth) && $depth > 1);
$new_depth = is_integer($depth) ? $depth - 1 : $depth;
$children = $wpdb->get_col( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_parent = %d AND post_type = %s", $object->get_id(), $object->get_post_type() ) );
if ($go_deeper && sizeof($children) > 0) {
$gchildren = [];
foreach ($children as $child) {
$_gchildren = $this->get_descendants_ids((int) $child, $new_depth);
if (!empty($_gchildren)) {
$gchildren = array_merge($gchildren, $_gchildren);
}
}
$children = array_merge($children, $gchildren);
}
return $children;
}
}
?>

View File

@ -181,6 +181,46 @@ class Taxonomies extends Repository {
return $this->fetch_output( $wp_query, $output );
}
}
/**
* fetch taxonomies by collection, considering inheritance
*
* @param Entities\Collection $collection
* @param array $args WP_Query args plus disabled_metadata
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
* @return array Entities\Metadatum
* @throws \Exception
*/
public function fetch_by_collection( Entities\Collection $collection, $args = [], $output = null ) {
$collection_id = $collection->get_id();
$Tainacan_Metadata = Metadata::get_instance();
// get all taxonomy metadata in this collection
$taxonomy_metas = $Tainacan_Metadata->fetch_by_collection($collection, ['metadata_type' => 'Tainacan\Metadata_Types\Taxonomy'], 'OBJECT');
$tax_ids = [];
foreach ( $taxonomy_metas as $taxonomy_meta ) {
$options = $taxonomy_meta->get_metadata_type_options();
if (isset($options['taxonomy_id'])) {
$tax_ids[] = $options['taxonomy_id'];
}
}
if (empty($tax_ids)) {
$tax_ids[] = 'please-return-nothing';
}
$newargs = [
'post__in' => $tax_ids
];
$args = array_merge($args, $newargs);
return $this->fetch($args, $output);
}
public function update( $object, $new_values = null ) {
return $this->insert( $object );
@ -235,26 +275,68 @@ class Taxonomies extends Repository {
return $trashed;
}
public function added_collection( $taxonomy_id, $collection ) {
public function added_collection( $taxonomy_id, $collection_id ) {
$id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) ) {
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id );
$tax->add_collection_id( $collection->get_id() );
$tax->add_collection_id( $collection_id );
if ( $tax->validate() ) {
$this->insert( $tax );
}
}
$this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id);
}
public function removed_collection( $taxonomy_id, $collection ) {
public function removed_collection( $taxonomy_id, $collection_id ) {
$id = $taxonomy_id;
if ( ! empty( $id ) && is_numeric( $id ) ) {
if ( ! empty( $id ) && is_numeric( $id ) && is_numeric($collection_id) ) {
$tax = $this->fetch( (int) $id );
$tax->remove_collection_id( $collection->get_id() );
$tax->remove_collection_id( $collection_id );
if ( $tax->validate() ) {
$this->insert( $tax );
}
}
$this->update_taxonomy_registry_for_collection($taxonomy_id, $collection_id);
}
public function update_taxonomy_registry_for_collection($taxonomy_id, $collection_id) {
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
// if repository level metadatum, update all collections
if ( $collection_id = $Tainacan_Metadata->get_default_metadata_attribute() ) {
$this->register_taxonomies_for_all_collections();
} else {
// get all children, grand children, etc.
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$children_ids = $Tainacan_Collections->get_descendants_ids($collection_id);
// register taxonomy for collection
$tax_slug = Entities\Taxonomy::$db_identifier_prefix . $taxonomy_id;
foreach ($children_ids as $child_id) {
$collection_slug = Entities\Collection::$db_identifier_prefix . $child_id . Entities\Collection::$db_identifier_sufix;
register_taxonomy_for_object_type( $tax_slug, $collection_slug );
}
}
}
public function register_taxonomies_for_all_collections() {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
// TODO: This can be a problem in large repositories.
$collections = $Tainacan_Collections->fetch( ['nopaging' => true], 'OBJECT' );
if ( ! is_array( $collections ) ) {
return;
}
// register taxonomies to other collections considering metadata inheritance
foreach ( $collections as $collection ) {
$taxonomies = $this->fetch_by_collection($collection, ['nopaging' => true], 'OBJECT');
foreach ( $taxonomies as $taxonomy ) {
register_taxonomy_for_object_type( $taxonomy->get_db_identifier(), $collection->get_db_identifier() );
}
}
}

View File

@ -142,6 +142,7 @@ class TaxonomyMetadatumTypes extends TAINACAN_UnitTestCase {
'collection',
array(
'name' => 'test',
'status' => 'publish',
),
true
);
@ -150,6 +151,7 @@ class TaxonomyMetadatumTypes extends TAINACAN_UnitTestCase {
'taxonomy',
array(
'name' => 'tax_test',
'status' => 'publish',
),
true
);
@ -158,10 +160,22 @@ class TaxonomyMetadatumTypes extends TAINACAN_UnitTestCase {
'taxonomy',
array(
'name' => 'tax_test2',
'status' => 'publish',
),
true
);
$tax3 = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test3',
'status' => 'publish',
),
true
);
$this->assertNotContains($tax->get_db_identifier(), get_object_taxonomies($collection->get_db_identifier()), 'Collection must be added to taxonomy when metadatum is created');
$metadatum = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
@ -177,10 +191,14 @@ class TaxonomyMetadatumTypes extends TAINACAN_UnitTestCase {
),
true
);
$this->assertContains($tax->get_db_identifier(), get_object_taxonomies($collection->get_db_identifier()), 'Collection must be added to taxonomy when metadatum is created');
$checkTax = $Tainacan_Taxonomies->fetch($tax->get_id());
$this->assertContains($collection->get_id(), $checkTax->get_collections_ids(), 'Collection must be added to taxonomy when metadatum is created');
$metadatum->set_metadata_type_options([
'taxonomy_id' => $tax2->get_id(),
'allow_new_terms' => false
@ -201,11 +219,193 @@ class TaxonomyMetadatumTypes extends TAINACAN_UnitTestCase {
$this->assertNotContains($collection->get_id(), $checkTax2->get_collections_ids(), 'Collection must be removed from taxonomy when metadatum is deleted');
$metadatum_repo = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'meta_repo',
'description' => 'description',
'collection_id' => 'default',
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'status' => 'publish',
'metadata_type_options' => [
'taxonomy_id' => $tax3->get_id(),
'allow_new_terms' => false
]
),
true
);
$this->assertContains($tax3->get_db_identifier(), get_object_taxonomies($collection->get_db_identifier()), 'Taxonommy used by repository level metadatum must be assigned to all collections post types');
}
/**
* @group fetch_by_collection
*/
function test_fetch_by_collection() {
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'status' => 'publish',
),
true
);
$collection2 = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'status' => 'publish',
),
true
);
$collection2_c = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2->get_id(),
'status' => 'publish',
),
true
);
$collection2_gc = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2_c->get_id(),
'status' => 'publish',
),
true
);
$tax = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test',
'status' => 'publish',
),
true
);
$tax2 = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test2',
'status' => 'publish',
),
true
);
$tax3 = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test3',
'status' => 'publish',
),
true
);
$tax4 = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test4',
'status' => 'publish',
),
true
);
// metadata 1 in repo level for every one
$metadatum_repo = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'meta_repo',
'description' => 'description',
'collection_id' => 'default',
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'status' => 'publish',
'metadata_type_options' => [
'taxonomy_id' => $tax->get_id(),
'allow_new_terms' => false
]
),
true
);
// meta 2 in collection 1 just for it
$metadatum2 = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'meta_repo',
'description' => 'description',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'status' => 'publish',
'metadata_type_options' => [
'taxonomy_id' => $tax2->get_id(),
'allow_new_terms' => false
]
),
true
);
// meta 3 in collection 2 for it and chidlren and grand children
$metadatum3 = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'meta_repo',
'description' => 'description',
'collection' => $collection2,
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'status' => 'publish',
'metadata_type_options' => [
'taxonomy_id' => $tax3->get_id(),
'allow_new_terms' => false
]
),
true
);
// meta 4 in collection 2c only for children and grand children
$metadatum4 = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'meta_repo',
'description' => 'description',
'collection' => $collection2_c,
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'status' => 'publish',
'metadata_type_options' => [
'taxonomy_id' => $tax4->get_id(),
'allow_new_terms' => false
]
),
true
);
$taxonomies_1 = $Tainacan_Taxonomies->fetch_by_collection($collection, [], 'OBJECT');
$this->assertEquals(2, sizeof($taxonomies_1));
$taxonomies_2 = $Tainacan_Taxonomies->fetch_by_collection($collection2, [], 'OBJECT');
$this->assertEquals(2, sizeof($taxonomies_2));
$taxonomies_3 = $Tainacan_Taxonomies->fetch_by_collection($collection2_c, [], 'OBJECT');
$this->assertEquals(3, sizeof($taxonomies_3));
$taxonomies_4 = $Tainacan_Taxonomies->fetch_by_collection($collection2_gc, [], 'OBJECT');
$this->assertEquals(3, sizeof($taxonomies_4));
}
function test_values_and_html() {
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();

View File

@ -43,8 +43,94 @@ class TestUtilities extends TAINACAN_UnitTestCase {
$this->assertEquals('', tainacan_get_initials($string));
}
function test_get_descendants_ids() {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'status' => 'publish',
),
true
);
$collection2 = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'status' => 'publish',
),
true
);
$collection2_c = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2->get_id(),
'status' => 'publish',
),
true
);
$collection2_gc = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2_c->get_id(),
'status' => 'publish',
),
true
);
$collection2_gc2 = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2_c->get_id(),
'status' => 'publish',
),
true
);
$collection2_ggc = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
'parent' => $collection2_gc->get_id(),
'status' => 'publish',
),
true
);
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$test = $Tainacan_Collections->get_descendants_ids($collection2);
$this->assertEquals(4, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2_c);
$this->assertEquals(3, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2_gc);
$this->assertEquals(1, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2_ggc);
$this->assertEquals(0, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection);
$this->assertEquals(0, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2, 2);
$this->assertEquals(3, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2, 1);
$this->assertEquals(1, sizeof($test));
$test = $Tainacan_Collections->get_descendants_ids($collection2_c, 1);
$this->assertEquals(2, sizeof($test));
}
}