basic structure of compound field type

This commit is contained in:
Leo Germani 2018-03-27 00:53:51 -03:00
parent 4b74bec2f6
commit d9bcc0381d
8 changed files with 376 additions and 10 deletions

View File

@ -0,0 +1,4 @@
* post_meta of deleted fields
* post_meta of deleted instaces of a multiple compound Field. post_meta of a field that is child of a compound field, but which the ID does not appear in any array of a compound field meta_value

View File

@ -16,10 +16,26 @@ class Item_Metadata_Entity extends Entity {
*/
protected $repository = 'Item_Metadata';
function __construct(Item $item, Field $field) {
/**
*
* @param Item $item Item Entity
* @param Field $field Field Entity
* @param int $meta_id ID for a specific meta row
*/
function __construct(Item $item, Field $field, $meta_id = null, $parent_meta_id = null) {
$this->set_item($item);
$this->set_field($field);
if (!is_null($meta_id) && is_int($meta_id)) {
$this->set_meta_id($meta_id);
}
if (!is_null($parent_meta_id) && is_int($parent_meta_id)) {
$this->set_parent_meta_id($parent_meta_id);
}
}
public function __toString(){
@ -64,6 +80,39 @@ class Item_Metadata_Entity extends Entity {
$this->field = $field;
}
/**
* Set the specific meta ID for this metadata.
*
* When this value is set, get_value() will use it to fetch the value from
* the post_meta table, instead of considering the item and field IDs
*
* @param int $meta_id the ID of a specifica post_meta row
*/
function set_meta_id($meta_id) {
if (is_int($meta_id)) {
$this->meta_id = $meta_id;
return true;
// TODO: Should we check here to see if this meta_id is really from this field and item?
}
return false;
}
/**
* Set parent_meta_id. Used when a item_metadata is inside a compound Field
*
* When you have a multiple compound field, this indicates of which instace of the value this item_metadata is attached to
*
* @param [type] $parent_meta_id [description]
*/
function set_parent_meta_id($parent_meta_id) {
if (is_int($parent_meta_id)) {
$this->parent_meta_id = $parent_meta_id;
return true;
// TODO: Should we check here to see if this meta_id is really from this field and item?
}
return false;
}
/**
* Return the item
*
@ -82,6 +131,24 @@ class Item_Metadata_Entity extends Entity {
return $this->field;
}
/**
* Return the meta_id
*
* @return Field
*/
function get_meta_id() {
return isset($this->meta_id) ? $this->meta_id : null;
}
/**
* Return the meta_id
*
* @return Field
*/
function get_parent_meta_id() {
return isset($this->parent_meta_id) ? $this->parent_meta_id : 0;
}
/**
* Return the field value
*
@ -157,10 +224,6 @@ class Item_Metadata_Entity extends Entity {
foreach($value as $val) {
if (!empty($val))
$one_filled = true;
// TODO: call fieldtype validation
// if (invalid) $valid = false;
}
if ($this->is_required() && !$one_filled) {

View File

@ -310,6 +310,11 @@ class Item extends Entity {
continue;
}
// skip validation for Compound Fields
if ( $itemMetadata->get_field()->get_field_type() == 'Tainacan\Field_Types\Compound' ) {
continue;
}
if ( ! $itemMetadata->validate() ) {
$errors = $itemMetadata->get_errors();
$this->add_error( $itemMetadata->get_field()->get_name(), $errors );

View File

@ -0,0 +1,41 @@
<?php
namespace Tainacan\Field_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanFieldType
*/
class Compound extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
$this->set_primitive_type('compound');
$this->set_component('tainacan-compound');
}
/**
* @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata
* @return string
*/
public function render( $itemMetadata ){
return '<tainacan-text
id="tainacan-text-' . $itemMetadata->get_item()->WP_Post->post_name . '"
field_id ="'.$itemMetadata->get_field()->get_id().'"
item_id="'.$itemMetadata->get_item()->get_id().'"
value=\''.json_encode( $itemMetadata->get_value() ).'\'
name="'.$itemMetadata->get_field()->get_name().'"></tainacan-text>';
}
/**
* generate the fields for this field type
*/
public function form(){
}
}

View File

@ -68,7 +68,7 @@ class Fields extends Repository {
//'validation' => v::numeric(),
],
'parent' => [
'map' => 'parent',
'map' => 'post_parent',
'title' => __('Parent', 'tainacan'),
'type' => 'integer',
'description'=> __('Parent field', 'tainacan'),
@ -252,6 +252,9 @@ class Fields extends Repository {
* @param $class_name string | object The class name or the instance
*/
public function register_field_type( $class_name ){
// TODO: we shoud not allow registration of field types of retricted core field types (e.g. compound, term) by plugins
if( is_object( $class_name ) ){
$class_name = get_class( $class_name );
}

View File

@ -35,9 +35,30 @@ class Item_Metadata extends Repository {
$this->save_core_field_value($item_metadata);
} elseif ($field_type->get_primitive_type() == 'term') {
$this->save_terms_field_value($item_metadata);
} elseif ($field_type->get_primitive_type() == 'compound') {
// do nothing. Compound values are updated when its child fields are updated
return $item_metadata;
} else {
if ($unique) {
update_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $item_metadata->get_value() ) );
if (is_int($item_metadata->get_meta_id())) {
update_metadata_by_mid( 'post', $item_metadata->get_meta_id(), wp_slash( $item_metadata->get_value() ) );
} else {
// update_post_meta returns meta ID on addition and true on update
$added_meta_id = update_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), wp_slash( $item_metadata->get_value() ) );
}
// handle fields inside Compound fields when adding a new meta value
//var_dump($item_metadata->get_field()->get_parent());
//var_dump($item_metadata->get_parent_meta_id());
//var_dump($item_metadata->get_value());
//die;
if ( ( $item_metadata->get_field()->get_parent() > 0 || $item_metadata->get_parent_meta_id() > 0 ) && is_int($added_meta_id)) {
$added_compound = $this->add_compound_value($item_metadata, $added_meta_id);
}
} else {
delete_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id());
@ -56,7 +77,18 @@ class Item_Metadata extends Repository {
do_action('tainacan-insert', $item_metadata);
do_action('tainacan-insert-Item_Metadata_Entity', $item_metadata);
return new Entities\Item_Metadata_Entity($item_metadata->get_item(), $item_metadata->get_field());
$new_entity = new Entities\Item_Metadata_Entity($item_metadata->get_item(), $item_metadata->get_field());
if (isset($added_compound) && is_int($added_compound)) {
$new_entity->set_parent_meta_id($added_compound);
}
if (isset($added_meta_id) && is_int($added_meta_id)) {
$new_entity->set_meta_id($added_meta_id);
}
return $new_entity;
}
/**
@ -95,6 +127,34 @@ class Item_Metadata extends Repository {
}
}
/**
*
* @return null|ind the meta id of the created compound metadata
*/
public function add_compound_value(Entities\Item_Metadata_Entity $item_metadata, $meta_id) {
$current_value = get_metadata_by_mid( 'post', $item_metadata->get_parent_meta_id() );
if (is_object($current_value))
$current_value = $current_value->meta_value;
//var_dump($current_value); die;
if ( !is_array($current_value) )
$current_value = [];
if ( !in_array( $meta_id, $current_value ) ) {
$current_value[] = $meta_id;
}
if ( $item_metadata->get_parent_meta_id() > 0 ) {
update_metadata_by_mid( 'post', $item_metadata->get_parent_meta_id(), $current_value );
} elseif ( $item_metadata->get_field()->get_parent() > 0 ) {
return add_post_meta( $item_metadata->get_item()->get_id(), $item_metadata->get_field()->get_parent(), $current_value );
}
}
/**
* Fetch Item Field objects related to an Item
*
@ -165,12 +225,73 @@ class Item_Metadata extends Repository {
return $terms;
} elseif ($field_type->get_primitive_type() == 'compound') {
global $wpdb;
$rows = $wpdb->get_results(
$wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $item_metadata->get_item()->get_id(), $item_metadata->field->get_id()),
ARRAY_A );
$return_value = [];
if (is_array($rows)) {
foreach ($rows as $row) {
$value = $this->extract_compound_value(maybe_unserialize($row['meta_value']), $item_metadata->get_item(), $row['meta_id']);
if ( $unique ) {
$return_value = $value;
break;
} else {
$return_value[] = $value;
}
}
}
return $return_value;
} else {
if (is_int($item_metadata->get_meta_id())) {
$value = get_metadata_by_mid( 'post', $item_metadata->get_meta_id() );
if ( is_object($value) && isset( $value->meta_value) ) {
return $value->meta_value;
}
} else {
return get_post_meta($item_metadata->item->get_id(), $item_metadata->field->get_id(), $unique);
}
}
}
/**
* Transforms the array saved as meta_value with the IDs of post_meta saved as a value for compound fields
* and converts it into an array of Item Metadatada Entitites
*
* @param array $ids The array of post_meta ids
* @param Entities\Item $item The item this post_meta is related to
* @param int $compund_meta_id the meta_id of the parent compound metadata
* @return array An array of Item_Metadata_Entity objects
*/
private function extract_compound_value(array $ids, Entities\Item $item, $compund_meta_id) {
$return_value = [];
if (is_array($ids)) {
foreach ($ids as $id) {
$post_meta_object = get_metadata_by_mid( 'post', $id );
if ( is_object($post_meta_object) ) {
$field = new Entities\Field($post_meta_object->meta_key);
$return_value[] = new Entities\Item_Metadata_Entity( $item, $field, $id, $compund_meta_id );
}
}
}
return $return_value;
}
public function register_post_type() { }
public function get_map() { return []; }

View File

@ -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\Category');
$Tainacan_Fields->register_field_type('Tainacan\Field_Types\Compound');
$Tainacan_Filters = \Tainacan\Repositories\Filters::getInstance();

View File

@ -0,0 +1,128 @@
<?php
namespace Tainacan\Tests;
/**
* Class TestCollections
*
* @package Test_Tainacan
*/
use Tainacan\Entities;
/**
* Sample test case.
*/
class CompoundFieldTypes extends TAINACAN_UnitTestCase {
function test_compound_field_types() {
$Tainacan_Fields = \Tainacan\Repositories\Fields::getInstance();
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::getInstance();
$Tainacan_Items = \Tainacan\Repositories\Items::getInstance();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test',
),
true
);
$field = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'meta',
'description' => 'description',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Compound',
'status' => 'publish',
),
true
);
$field_child1 = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'meta2',
'description' => 'description',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish',
'parent' => $field->get_id(),
),
true
);
$field_child2 = $this->tainacan_entity_factory->create_entity(
'field',
array(
'name' => 'meta3',
'description' => 'description',
'collection' => $collection,
'field_type' => 'Tainacan\Field_Types\Text',
'status' => 'publish',
'parent' => $field->get_id(),
),
true
);
$i = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'item test',
'description' => 'adasdasdsa',
'collection' => $collection,
'status' => 'publish',
),
true
);
$item_metadata1 = new \Tainacan\Entities\Item_Metadata_Entity($i, $field_child1);
$item_metadata1->set_value('Red');
$item_metadata1->validate();
$item_metadata1 = $Tainacan_Item_Metadata->insert($item_metadata1);
$item_metadata = new \Tainacan\Entities\Item_Metadata_Entity($i, $field_child2, null, $item_metadata1->get_parent_meta_id());
$item_metadata->set_value('Blue');
$item_metadata->validate();
$item_metadata = $Tainacan_Item_Metadata->insert($item_metadata);
$compoundItem = new \Tainacan\Entities\Item_Metadata_Entity($i, $field);
global $wpdb;
var_dump($wpdb->get_results("SELECT * FROM $wpdb->postmeta WHERE post_id = {$i->get_id()}"));
//var_dump($wpdb->get_results("SELECT * FROM $wpdb->posts WHERE parent = {$field->get_id()}"));
$compoundValue = $compoundItem->get_value();
$this->assertTrue( is_array($compoundValue), 'value of a compound should return array' );
$this->assertEquals( 2, sizeof($compoundValue), 'value should have 2 item metadata' );
$this->assertTrue( $compoundValue[0] instanceof \Tainacan\Entities\Item_Metadata_Entity , 'First element of value should be an item metadata entity' );
$this->assertTrue( $compoundValue[1] instanceof \Tainacan\Entities\Item_Metadata_Entity , 'Second element of value should be an item metadata entity' );
//var_dump($compoundValue);
$metas = [];
foreach ($compoundValue as $val) {
$metas[$val->get_field()->get_id()] = $val->get_value();
}
$this->assertEquals( 'Red', $metas[$field_child1->get_id()] , 'First element of value should have "Red" value' );
$this->assertEquals( 'Blue', $metas[$field_child2->get_id()] , 'Second element of value should have "Blue" value' );
//var_dump($compoundValue[0]->get_field()->get_id());
//var_dump($field_child2->get_id());
//var_dump($field_child1->get_id());
//var_dump($field->get_id());
}
}