From e69f003de7333ca9b657d8caf2d1818ab8140c37 Mon Sep 17 00:00:00 2001 From: Leo Germani Date: Sat, 3 Mar 2018 21:22:15 -0300 Subject: [PATCH] starting Category field type --- src/classes/entities/class-tainacan-field.php | 2 +- .../category/class-tainacan-category.php | 111 +++++++++++++++++ .../field-type/class-tainacan-field-type.php | 52 +++++++- .../class-tainacan-item-metadata.php | 60 ++++++--- .../class-tainacan-repository.php | 11 +- src/classes/tainacan-creator.php | 1 + tests/test-category-field-types.php | 116 ++++++++++++++++++ tests/test-fields.php | 2 +- 8 files changed, 330 insertions(+), 25 deletions(-) create mode 100644 src/classes/field-types/category/class-tainacan-category.php create mode 100644 tests/test-category-field-types.php diff --git a/src/classes/entities/class-tainacan-field.php b/src/classes/entities/class-tainacan-field.php index ec878a832..5650489cf 100644 --- a/src/classes/entities/class-tainacan-field.php +++ b/src/classes/entities/class-tainacan-field.php @@ -377,7 +377,7 @@ class Field extends Entity { return true; if (!is_array($is_valid)) - throw new Exception("Return of validate_options field type method should be an Array in case of error"); + throw new \Exception("Return of validate_options field type method should be an Array in case of error"); foreach ($is_valid as $field => $message) { $this->add_error($field, $message); diff --git a/src/classes/field-types/category/class-tainacan-category.php b/src/classes/field-types/category/class-tainacan-category.php new file mode 100644 index 000000000..b32e818e0 --- /dev/null +++ b/src/classes/field-types/category/class-tainacan-category.php @@ -0,0 +1,111 @@ +set_default_options([ + 'allow_new_terms' => false + ]); + + // TODO: Set component depending on options. If multiple is checkbox. if single, select. etc. + $this->component = 'tainacan-category'; + } + + /** + * @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata + * @return string + */ + + public function render( $itemMetadata ){ + $options = ( isset( $this->options['options'] ) ) ? $this->options['options'] : ''; + return 'get_value() ).'\' + name="'.$itemMetadata->get_field()->get_name().'">'; + } + + /** + * generate the fields for this field type + */ + public function form(){ + global $Tainacan_Taxonomies; + $taxonomies = $Tainacan_Taxonomies->fetch([], 'OBJECT') + + // TODO: form incomplete and not tested + + ?> + + +
+ + + + + + + get_item(); + $field = $item_metadata->get_field(); + + if ( !in_array($item->get_status(), apply_filters('tainacan-status-require-validation', ['publish','future','private'])) ) + return true; + + $valid = true; + + if (false === $this->get_option('allow_new_terms')) { + $terms = $item_metadata->get_value(); + if (!is_array($terms)) + $terms = array($terms); + + foreach ($terms as $term) { + if (is_object($term) && $term instanceof \WP_Term) { + $term = $term->term_id; + } + + if (!term_exists($term)) { + $valid = false; + break; + } + } + + } + + return $valid; + + } + +} \ No newline at end of file diff --git a/src/classes/field-types/field-type/class-tainacan-field-type.php b/src/classes/field-types/field-type/class-tainacan-field-type.php index 4dd79e23b..7de8bda39 100644 --- a/src/classes/field-types/field-type/class-tainacan-field-type.php +++ b/src/classes/field-types/field-type/class-tainacan-field-type.php @@ -9,8 +9,32 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' ); */ abstract class Field_Type { + + /** + * Indicates the type of variable that this field type handles. + * + * This is used to relate Field types and filter types, so we know which filter types + * will be available to be used for each field based on its Field Type + * + * For instance, the Filter Type "input text" may be used to search in any field that has + * a Field Type with a string primitive type. + * + * @var string + */ private $primitive_type; - public $options; + + /** + * Array of options spececific to this field type. Stored in field_type_options property of the Field object + * @var Array + */ + public $options = []; + + /** + * The default values for the field type options array + * @var Array + */ + public $default_options = []; + public $errors; /** @@ -70,6 +94,32 @@ abstract class Field_Type { public function set_options( $options ){ $this->options = ( is_array( $options ) ) ? $options : unserialize( $options ); } + + public function set_default_options(Array $options) { + $this->default_options = $options; + } + + /** + * Gets the options for this field types, including default values for options + * that were not set yet. + * @return Array Fielt type options + */ + public function get_options() { + return array_merge($this->default_options, $this->options); + } + + /** + * Gets one option from the options array. + * + * Checks if option exist or if it have a default value. Otherwise return an empty string + * + * @param string $key the desired option + * @return mixed the option value, the default value or an empty string + */ + public function get_option($key) { + $options = $this->get_options(); + return isset($options[$key]) ? $options[$key] : ''; + } /** * generate the fields for this field type diff --git a/src/classes/repositories/class-tainacan-item-metadata.php b/src/classes/repositories/class-tainacan-item-metadata.php index e7105f69d..b7990062b 100644 --- a/src/classes/repositories/class-tainacan-item-metadata.php +++ b/src/classes/repositories/class-tainacan-item-metadata.php @@ -11,26 +11,29 @@ class Item_Metadata extends Repository { public function insert($item_metadata) { $unique = !$item_metadata->is_multiple(); + + $field_type = $item_metadata->get_field()->get_field_type_object(); + if ($field_type->core) { + $this->save_core_field_value($item_metadata); + } elseif ($field_type->get_primitive_type() == 'term') { + $this->save_terms_field_value($item_metadata); + } else { + if ($unique) { + update_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $item_metadata->get_value() ) ); + } else { + delete_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id()); + + if (is_array($item_metadata->get_value())){ + $values = $item_metadata->get_value(); - if ($unique) { - $field_type = $item_metadata->get_field()->get_field_type_object(); - if ($field_type->core) { - $this->save_core_field_value($item_metadata); - } else { - update_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $item_metadata->get_value() ) ); - } - - } else { - delete_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id()); - - if (is_array($item_metadata->get_value())){ - $values = $item_metadata->get_value(); - - foreach ($values as $value){ - add_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $value )); - } - } - } + foreach ($values as $value){ + add_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $value )); + } + } + } + } + + do_action('tainacan-insert', $item_metadata); do_action('tainacan-insert-Item_Metadata_Entity', $item_metadata); @@ -60,6 +63,14 @@ class Item_Metadata extends Repository { } } } + + public function save_terms_field_value($item_metadata) { + $field_type = $item_metadata->get_field()->get_field_type_object(); + if ($field_type->get_primitive_type() == 'term') { + $new_terms = $item_metadata->get_value(); + wp_set_object_terms($item_metadata->get_item()->get_id(), $new_terms, $field_type->get_option('taxonomy_id')); + } + } /** * Fetch Item Field objects related to an Item @@ -110,7 +121,16 @@ class Item_Metadata extends Repository { $get_method = 'get_' . $field_type->related_mapped_prop; return $item->$get_method(); - + + } elseif ($field_type->get_primitive_type() == 'term') { + + $terms = wp_get_object_terms($item_metadata->get_item()->get_id(), $field_type->get_option('taxonomy_id')); + + if ($unique) + $terms = reset($terms); + + return $terms; + } else { return get_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), $unique); } diff --git a/src/classes/repositories/class-tainacan-repository.php b/src/classes/repositories/class-tainacan-repository.php index ded2f90fc..a37a6fc64 100644 --- a/src/classes/repositories/class-tainacan-repository.php +++ b/src/classes/repositories/class-tainacan-repository.php @@ -118,7 +118,7 @@ abstract class Repository { return false; if ($map[$prop]['map'] == 'meta') { - update_post_meta($obj->get_id(), $prop, wp_slash( $obj->get_mapped_property($prop) )); + update_post_meta($obj->get_id(), $prop, $this->maybe_add_slashes( $obj->get_mapped_property($prop) )); } elseif($map[$prop]['map'] == 'meta_multi') { $values = $obj->get_mapped_property($prop); @@ -126,11 +126,18 @@ abstract class Repository { if (is_array($values)){ foreach ($values as $value){ - add_post_meta($obj->get_id(), $prop, wp_slash( $value )); + add_post_meta($obj->get_id(), $prop, $this->maybe_add_slashes( $value )); } } } } + + function maybe_add_slashes($value) { + if (is_string($value) && strpos($value, '\\') !== false) { + return wp_slash($value); + } + return $value; + } /** * Prepare the output for the fetch() methods. diff --git a/src/classes/tainacan-creator.php b/src/classes/tainacan-creator.php index 24407120e..24e4b480e 100644 --- a/src/classes/tainacan-creator.php +++ b/src/classes/tainacan-creator.php @@ -88,6 +88,7 @@ $Tainacan_Fields->register_field_type('Tainacan\Field_Types\Numeric'); $Tainacan_Fields->register_field_type('Tainacan\Field_Types\Selectbox'); $Tainacan_Fields->register_field_type('Tainacan\Field_Types\Relationship'); $Tainacan_Fields->register_field_type('Tainacan\Field_Types\Radio'); +$Tainacan_Fields->register_field_type('Tainacan\Field_Types\Category'); global $Tainacan_Filters; $Tainacan_Filters = new \Tainacan\Repositories\Filters(); diff --git a/tests/test-category-field-types.php b/tests/test-category-field-types.php new file mode 100644 index 000000000..d8a7332d3 --- /dev/null +++ b/tests/test-category-field-types.php @@ -0,0 +1,116 @@ +tainacan_entity_factory->create_entity( + 'collection', + array( + 'name' => 'test', + ), + true + ); + + $tax = $this->tainacan_entity_factory->create_entity( + 'taxonomy', + array( + 'name' => 'tax_test', + 'collections' => [$collection], + ), + true + ); + + $field = $this->tainacan_entity_factory->create_entity( + 'field', + array( + 'name' => 'metadado', + 'description' => 'title', + 'collection' => $collection, + 'field_type' => 'Tainacan\Field_Types\Category', + 'field_type_options' => [ + 'taxonomy_id' => $tax->get_db_identifier(), + 'allow_new_terms' => false + ] + ), + true + ); + + $field2 = $this->tainacan_entity_factory->create_entity( + 'field', + array( + 'name' => 'metadado_desc', + 'description' => 'description', + 'collection' => $collection, + 'field_type' => 'Tainacan\Field_Types\Category' + ), + true + ); + + + $i = $this->tainacan_entity_factory->create_entity( + 'item', + array( + 'title' => 'item test', + 'description' => 'adasdasdsa', + 'collection' => $collection, + 'status' => 'publish', + ), + true + ); + + /** TODO test existing term + $term = new \Tainacan\Entities\Term(); + $term->set_name('Red'); + $term->validate(); + $term = $Tainacan_Terms->insert($term); + + $item_metadata = new \Tainacan\Entities\Item_Metadata_Entity($i, $field); + $item_metadata->set_value('Red'); + + $this->assertTrue($item_metadata->validate(), 'item metadata should validate because it is an existing term'); + + $Tainacan_Item_Metadata->insert($item_metadata); + **/ + $item_metadata = new \Tainacan\Entities\Item_Metadata_Entity($i, $field); + $item_metadata->set_value('love'); + + $this->assertFalse($item_metadata->validate(), 'item metadata should not validate because it does not allow new terms'); + + // Lets change it + $options = $field->get_field_type_options(); + $options['allow_new_terms'] = true; + $field->set_field_type_options($options); + $field->validate(); + $field = $Tainacan_Fields->insert($field); + + $item_metadata->set_field($field); + + $this->assertTrue($item_metadata->validate(), 'item metada should validate because it now allows new terms'); + + $Tainacan_Item_Metadata->insert($item_metadata); + + $checkItem = $Tainacan_Items->fetch($i->get_id()); + + $check_item_metadata = new \Tainacan\Entities\Item_Metadata_Entity($checkItem, $field); + + $this->assertEquals('WP_Term', get_class($check_item_metadata->get_value())); + } + +} \ No newline at end of file diff --git a/tests/test-fields.php b/tests/test-fields.php index 85511eda7..ec185c0ca 100644 --- a/tests/test-fields.php +++ b/tests/test-fields.php @@ -194,7 +194,7 @@ class Fields extends TAINACAN_UnitTestCase { */ function test_metadata_field_type(){ global $Tainacan_Fields; - $this->assertEquals( 7, sizeof( $Tainacan_Fields->fetch_field_types() ) ); + $this->assertEquals( 8, sizeof( $Tainacan_Fields->fetch_field_types() ) ); }