Merge branch 'feature/facets_ES' into develop

This commit is contained in:
vnmedeiros 2019-04-16 16:40:03 -03:00
commit 65c6cd9ad7
47 changed files with 1666 additions and 553 deletions

View File

@ -198,6 +198,7 @@ class Admin {
'exposer_type_param' => \Tainacan\Exposers_Handler::TYPE_PARAM,
'repository_name' => get_bloginfo('name'),
'api_max_items_per_page' => $TAINACAN_API_MAX_ITEMS_PER_PAGE,
'wp_elasticpress' => class_exists('EP_API'),
];
$maps = [

View File

@ -86,7 +86,7 @@
<b-field
:addons="false"
v-if="editForm.filter_type_object && editForm.filter_type_object.component.includes('checkbox')">
v-if="editForm.filter_type_object && editForm.filter_type_object.use_max_options">
<label class="label is-inline-block">
{{ $i18n.get('label_max_options_to_show') }}
<help-button

View File

@ -25,16 +25,15 @@
animated
@input="fetchSelectedLabels()"
v-model="activeTab">
<b-tab-item :label="$i18n.get('label_all_terms')">
<b-tab-item :label="isTaxonomy ? $i18n.get('label_all_terms') : $i18n.get('label_all_metadatum_values')">
<div
v-if="!isSearching && !isTaxonomy"
class="modal-card-body tainacan-checkbox-list-container">
<a
v-if="checkboxListOffset"
v-if="isUsingElasticSearch ? lastTermOnFisrtPage != checkboxListOffset : checkboxListOffset"
role="button"
class="tainacan-checkbox-list-page-changer"
@click="beforePage">
@click="previousPage">
<span class="icon">
<i class="tainacan-icon tainacan-icon-previous"/>
</span>
@ -88,9 +87,9 @@
<b-field
role="li"
:addons="false"
v-if="finderColumn.length"
v-if="finderColumn.children.length"
class="tainacan-li-checkbox-modal"
v-for="(option, index) in finderColumn"
v-for="(option, index) in finderColumn.children"
:id="`${key}.${index}-tainacan-li-checkbox-model`"
:ref="`${key}.${index}-tainacan-li-checkbox-model`"
:key="index">
@ -130,9 +129,9 @@
</span>
</a>
</b-field>
<li v-if="finderColumn.length">
<li v-if="finderColumn.children.length">
<div
v-if="finderColumn.length < totalRemaining[key].remaining"
v-if="totalRemaining[key].remaining === true || (finderColumn.length < totalRemaining[key].remaining)"
@click="getMoreOptions(finderColumn, key)"
class="tainacan-show-more">
<span class="icon">
@ -170,7 +169,7 @@
</b-tab-item>
<b-tab-item
:label="$i18n.get('label_selected_terms')">
:label="isTaxonomy ? $i18n.get('label_selected_terms') : $i18n.get('label_selected_metadatum_values')">
<div class="modal-card-body tainacan-tags-container">
<b-field
@ -185,7 +184,7 @@
attached
closable
@close="selected instanceof Array ? selected.splice(index, 1) : selected = ''">
{{ isTaxonomy ? selectedTagsName[term] : term }}
{{ (isTaxonomy || metadatum_type === 'Tainacan\\Metadata_Types\\Relationship') ? selectedTagsName[term] : term }}
</b-tag>
</div>
</b-field>
@ -296,7 +295,7 @@
isCheckbox: {
type: Boolean,
default: true,
},
}
},
data() {
return {
@ -322,6 +321,9 @@
activeTab: 0,
selectedTagsName: {},
isSelectedTermsLoading: false,
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false,
previousLastTerms: [],
lastTermOnFisrtPage: null
}
},
updated(){
@ -340,16 +342,13 @@
},
methods: {
fetchSelectedLabels() {
this.isSelectedTermsLoading = true;
let selected = this.selected instanceof Array ? this.selected : [this.selected];
if (this.taxonomy_id && selected.length) {
for (const term of selected) {
if(!this.isSelectedTermsLoading){
this.isSelectedTermsLoading = true;
}
axios.get(`/taxonomy/${this.taxonomy_id}/terms/${term}`)
.then((res) => {
@ -361,8 +360,21 @@
this.isSelectedTermsLoading = false;
});
}
} else {
} else if (this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' && selected.length) {
this.isSelectedTermsLoading = true;
for (const item of selected) {
axios.get('/items/' + item + '?fetch_only=title')
.then((res) => {
this.saveSelectedTagName(res.data.id, res.data.title);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
}
},
saveSelectedTagName(value, label){
@ -376,20 +388,34 @@
}
return label;
},
beforePage(){
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
previousPage() {
this.noMorePage = 0;
if(this.checkboxListOffset < 0){
this.checkboxListOffset = 0;
}
this.isCheckboxListLoading = true;
if (this.isUsingElasticSearch) {
this.previousLastTerms.pop();
if (this.previousLastTerms.length > 0) {
this.getOptions(this.previousLastTerms.pop());
this.previousLastTerms.push(this.checkboxListOffset);
} else {
this.getOptions(0);
}
} else {
this.checkboxListOffset -= this.maxNumOptionsCheckboxList;
if (this.checkboxListOffset < 0)
this.checkboxListOffset = 0;
this.getOptions(this.checkboxListOffset);
}
},
nextPage() {
if(!this.noMorePage) {
if (this.isUsingElasticSearch)
this.previousLastTerms.push(this.checkboxListOffset);
if (!this.noMorePage && !this.isUsingElasticSearch) {
// LIMIT 0, 20 / LIMIT 19, 20 / LIMIT 39, 20 / LIMIT 59, 20
if (this.checkboxListOffset === this.maxNumOptionsCheckboxList){
this.checkboxListOffset += this.maxNumOptionsCheckboxList - 1;
@ -409,32 +435,29 @@
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
if ( this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, this.optionName, this.isRepositoryLevel, [], offset, this.maxNumOptionsCheckboxList, true);
promise.request
.then(() => {
this.isCheckboxListLoading = false;
this.isSearchingLoading = false;
})
.catch(error => {
this.$console.log(error);
})
} else {
if ( this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' )
promise = this.getValuesRelationship( this.optionName, this.isRepositoryLevel, [], offset, this.maxNumOptionsCheckboxList, true);
else
promise = this.getValuesPlainText( this.metadatum_id, this.optionName, this.isRepositoryLevel, [], offset, this.maxNumOptionsCheckboxList, true);
promise.request
.then(() => {
.then((data) => {
this.isCheckboxListLoading = false;
this.isSearchingLoading = false;
if (this.isUsingElasticSearch) {
this.checkboxListOffset = data.last_term;
if (!this.lastTermOnFisrtPage || this.lastTermOnFisrtPage == this.checkboxListOffset) {
this.lastTermOnFisrtPage = this.checkboxListOffset;
this.previousLastTerms.push(0);
}
}
})
.catch(error => {
this.$console.log(error);
})
}
// Search Request Token for cancelling
this.getOptionsValuesCancel = promise.source;
@ -463,7 +486,7 @@
axios.get(route)
.then((res) => {
this.searchResults = res.data;
this.searchResults = res.data.values;
this.isSearchingLoading = false;
}).catch((error) => {
this.$console.log(error);
@ -528,11 +551,11 @@
}
},
createColumn(res, column) {
let children = res.data;
let children = res.data.values;
this.totalRemaining = Object.assign({}, this.totalRemaining, {
[`${column == undefined ? 0 : column+1}`]: {
remaining: res.headers['x-wp-total'],
remaining: this.isUsingElasticSearch ? (children.length > 0 ? res.data.last_term == children[children.length - 1].value : false) : res.headers['x-wp-total'],
}
});
@ -540,7 +563,7 @@
if (children.length > 0) {
for (let f in this.finderColumns) {
if (this.finderColumns[f][0].value == children[0].value) {
if (this.finderColumns[f].children[0].value == children[0].value) {
first = f;
break;
}
@ -548,15 +571,16 @@
}
if (first != undefined) {
this.finderColumns.splice(first, 1, children);
this.finderColumns.splice(first, 1, { children: children, lastTerm: res.data.last_term });
} else {
this.finderColumns.push(children);
this.finderColumns.push({ children: children, lastTerm: res.data.last_term });
}
},
appendMore(options, key) {
appendMore(options, key, lastTerm) {
for (let option of options) {
this.finderColumns[key].push(option)
this.finderColumns[key].children.push(option);
}
this.finderColumns[key].lastTerm = lastTerm;
},
getOptionChildren(option, key, index) {
let query_items = { 'current_query': this.query };
@ -567,9 +591,8 @@
let parent = 0;
if (option) {
if (option)
parent = option.value;
}
let query = `?order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=0&` + qs.stringify(query_items);
@ -599,9 +622,10 @@
},
getMoreOptions(finderColumn, key) {
if (finderColumn.length > 0) {
let parent = finderColumn[0].parent;
let offset = finderColumn.length;
if (finderColumn.children && finderColumn.children.length > 0) {
let parent = finderColumn.children[0].parent;
let offset = finderColumn.children.length;
let query_items = { 'current_query': this.query };
let query = `?order=asc&parent=${parent}&number=${this.maxNumOptionsCheckboxFinderColumns}&offset=${offset}&` + qs.stringify(query_items);
@ -609,6 +633,9 @@
if (!this.isFilter)
query += '&hideempty=0';
if (finderColumn.lastTerm)
query += '&last_term=' + finderColumn.lastTerm
this.isColumnLoading = true;
let route = `/collection/${this.collection_id}/facets/${this.metadatum_id}${query}`;
@ -619,7 +646,13 @@
axios.get(route)
.then(res => {
this.appendMore(res.data, key);
this.appendMore(res.data.values, key, res.data.last_term);
this.totalRemaining = Object.assign({}, this.totalRemaining, {
[`${key}`]: {
remaining: this.isUsingElasticSearch ? (res.data.values.length > 0 ? (res.data.last_term == res.data.values[res.data.values.length - 1].value) : false) : res.headers['x-wp-total'],
}
});
this.isColumnLoading = false;
})

View File

@ -193,7 +193,6 @@
:open="collapsed"
:is-repository-level="isRepositoryLevel"/>
</template>
</div>
</template>

View File

@ -1455,7 +1455,6 @@
},
mounted() {
this.prepareFilters();
this.prepareMetadata();
this.localDisplayedMetadata = JSON.parse(JSON.stringify(this.displayedMetadata));

View File

@ -118,6 +118,9 @@
padding: 1.25rem;
}
.autocomplete {
.dropdown-menu {
width: 100%;
}
.dropdown-item {
white-space: initial !important;
}

View File

@ -338,6 +338,8 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_show_metadata' => __( 'Show metadata', 'tainacan' ),
'label_all_terms' => __( 'All terms', 'tainacan' ),
'label_selected_terms' => __( 'Selected terms', 'tainacan' ),
'label_all_metadatum_values' => __( 'All metadatum values', 'tainacan' ),
'label_selected_metadatum_values' => __( 'Selected metadatum values', 'tainacan' ),
'label_editing_item_number' => __( 'Editing item n.', 'tainacan' ),
'label_sequence_editing_item' => __( 'Sequence editing: Item', 'tainacan' ),
'label_%s_files_remaining' => __( '%s files remaining.', 'tainacan' ),

View File

@ -68,6 +68,7 @@ class REST_Facets_Controller extends REST_Controller {
$number = null;
$_search = null;
$collection_id = ( isset($request['collection_id']) ) ? $request['collection_id'] : null;
$last_term = ( isset($request['last_term']) ) ? $request['last_term'] : '';
$query_args = defined('TAINACAN_FACETS_DISABLE_FILTER_ITEMS') && true === TAINACAN_FACETS_DISABLE_FILTER_ITEMS ? [] : $request['current_query'];
$query_args = $this->prepare_filters($query_args);
@ -123,15 +124,21 @@ class REST_Facets_Controller extends REST_Controller {
'items_filter' => $query_args,
'include' => $include,
'parent_id' => $parent_id,
'count_items' => defined('TAINACAN_FACETS_DISABLE_COUNT_ITEMS') && true === TAINACAN_FACETS_DISABLE_COUNT_ITEMS ? false : true
'count_items' => defined('TAINACAN_FACETS_DISABLE_COUNT_ITEMS') && true === TAINACAN_FACETS_DISABLE_COUNT_ITEMS ? false : true,
'last_term' => $last_term
];
$response = $this->metadatum_repository->fetch_all_metadatum_values( $metadatum_id, $args );
$all_values = $this->metadatum_repository->fetch_all_metadatum_values( $metadatum_id, $args );
$rest_response = new \WP_REST_Response($response['values'], 200);
$response = [
'values' => $all_values['values'],
'last_term' => $all_values['last_term']
];
$rest_response->header('X-WP-Total', $response['total']);
$rest_response->header('X-WP-TotalPages', $response['pages']);
$rest_response = new \WP_REST_Response($response, 200);
$rest_response->header('X-WP-Total', isset($all_values['total']) ? $all_values['total'] : 0 );
$rest_response->header('X-WP-TotalPages', isset($all_values['pages']) ? $all_values['pages'] : 0 );
return $rest_response;

View File

@ -275,13 +275,18 @@ class REST_Items_Controller extends REST_Controller {
}
}
$response = [];
$response['items'] = [];
$response['template'] = '';
$query_start = microtime(true);
$items = $this->items_repository->fetch($args, $collection_id, 'WP_Query');
$query_end = microtime(true);
// Filter right after the ->fetch() method. Elastic Search integration relies on this on its 'last_aggregations' hook
$response['filters'] = apply_filters('tainacan-api-items-filters-response', [], $request);
$response = [];
$query_end = microtime(true);
$return_template = false;
@ -324,7 +329,7 @@ class REST_Items_Controller extends REST_Controller {
include $view_mode['template'];
$response = ob_get_clean();
$response['template'] = ob_get_clean();
} else {
@ -336,7 +341,7 @@ class REST_Items_Controller extends REST_Controller {
$prepared_item = $this->prepare_item_for_response($item, $request);
array_push($response, $prepared_item);
array_push($response['items'], $prepared_item);
}
wp_reset_postdata();
@ -344,6 +349,8 @@ class REST_Items_Controller extends REST_Controller {
}
$response = apply_filters('tainacan-api-items-response', $response, $request);
$total_items = $items->found_posts;
$max_pages = ceil($total_items / (int) $items->query_vars['posts_per_page']);

View File

@ -11,22 +11,104 @@
namespace Tainacan;
class Elastic_Press {
public $last_aggregations;
public $facets;
function __construct($ajax_query=false) {
private $aggregation_type = 'items';
private static $instance = null;
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
protected function __construct($ajax_query=false) {
add_action('init', [$this, 'init']);
}
function init() {
if (!class_exists('EP_API')) {
return; // ElasticPress not active
}
$this->last_aggregations = [];
//activates the inclusion of the complete hierarchy of terms.
add_filter('ep_sync_terms_allow_hierarchy', '__return_true');
add_filter('tainacan_fetch_args', [$this, 'filter_args'], 10, 2);
add_action('ep_retrieve_aggregations', function ( array $aggregations, $scope, $args ) {
$this->last_aggregations = $this->format_aggregations($aggregations);
}, 10, 3);
add_filter('tainacan-api-items-filters-response', function($filters) { return $this->last_aggregations; });
add_filter('tainacan-fetch-all-metadatum-values', [$this, 'fetch_all_metadatum_values'], 10, 3);
add_filter( 'ep_config_mapping', [$this, 'elasticpress_config_mapping'], 10, 1 );
add_filter( 'ep_post_sync_args', [$this, 'ep_post_sync_args'], 10, 2 );
// add_action('ep_add_query_log', function($query) { //using to DEBUG
// error_log("DEGUG:");
// error_log($query["args"]["body"]);
// });
}
function elasticpress_config_mapping( $mapping ) {
$name_field = 'relationship_label';
$array_dynamic_templates = $mapping["mappings"]["post"]["dynamic_templates"];
foreach ($array_dynamic_templates as $key => $dynamic_templates) {
if ( isset($dynamic_templates['template_meta_types'] )) {
$mapping["mappings"]["post"]["dynamic_templates"][$key]['template_meta_types']["mapping"]["properties"][$name_field] = ['type' => 'keyword'];
// $mapping["mappings"]["post"]["dynamic_templates"][$key]['template_meta_types']["mapping"]["properties"][$name_field] =
// ['type' => 'nested',
// 'properties' => [
// 'label' => ['type' => 'text']
// //,'description' => ['type'=>'text']
// ]
// ];
}
}
return $mapping;
}
function ep_post_sync_args( $post_args, $post_id ) {
$name_field = 'relationship_label';
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$item = $Tainacan_Items->fetch($post_id);
if ($item instanceof Entities\Item) {
$ids_meta = array_keys ($post_args['meta']);
\array_filter(function($n) {
if (is_numeric($n)) return intval($n);
}, $ids_meta);
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance();
$metadatas = $Tainacan_Item_Metadata->fetch($item, 'OBJECT', [ 'post__in' => $ids_meta, 'order' => 'id', 'metadata_type' => 'Tainacan\Metadata_Types\Relationship' ] );
if ( is_array( $metadatas ) ) {
foreach ( $metadatas as $meta ) {
if(!empty($meta)) {
$meta_id = $meta->get_metadatum()->get_id();
$title = $meta->get_value_as_string();
$description = '';
$post_args['meta'][$meta_id][0][$name_field] = $title;
//$post_args['meta'][$meta_id][0][$name_field]['description'] = $description;
}
}
}
}
return $post_args;
}
function filter_args($args, $type) {
if ($type == 'items') {
if ($type == 'items' && (!isset($args['ep_integrate']) || $args['ep_integrate'] === true)) {
$args['ep_integrate'] = true;
$args = $this->add_items_args($args);
}
@ -38,6 +120,7 @@ class Elastic_Press {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$Tainacan_Filters = \Tainacan\Repositories\Filters::get_instance();
if (is_array($args['post_type']) && isset($args['s']) && !empty($args['s'])) {
@ -78,10 +161,599 @@ class Elastic_Press {
}
return $args;
if ( is_array($args['post_type']) ) {
$this->facets = [];
if ( isset($args['facet_metadatum_id']) ) {
$this->aggregation_type = 'facets';
$metadatum = Repositories\Metadata::get_instance()->fetch($args['facet_metadatum_id']);
$metadatum_options = $metadatum->get_metadata_type_options();
$metadata_type = $metadatum->get_metadata_type();
if ($metadata_type == 'Tainacan\Metadata_Types\Taxonomy') {
$taxonomy_id = $metadatum_options['taxonomy_id'];
$taxonomy_slug = Repositories\Taxonomies::get_instance()->get_db_identifier_by_id($taxonomy_id);
$id = "taxonomy.$taxonomy_slug";
$key = "terms.$taxonomy_slug.term_id";
$field = "terms.$taxonomy_slug";
} else {
$metadatum_id = $args['facet_metadatum_id'];
$id = "meta.$metadatum_id";
$key = "meta.$metadatum_id.raw";
$field = "meta.$metadatum_id.raw";
}
$this->facets[$id] = [
"key" => $key,
"field" => $field,
"metadata_type" => $metadata_type,
"last_term" => $args['facet_last_term'],
"parent" => $args['facet_term_parent_id'],
"pagesize" => !isset($args['facet_pagesize']) && empty($args['facet_pagesize']) ? 10 : $args['facet_pagesize'],
"search" => !isset($args['facet_search']) && empty($args['facet_search']) ? '' : $args['facet_search'],
"include" => $args['facet_include'],
];
} else {
foreach ( $args['post_type'] as $cpt ) {
$col = $Tainacan_Collections->fetch_by_db_identifier($cpt);
$_filters = $Tainacan_Filters->fetch_by_collection($col, ['posts_per_page' => -1], 'OBJECT');
foreach ($_filters as $filter) {
$include = [];
$filter_id = $filter->get_id();
$metadata_type = $filter->get_metadatum()->get_metadata_type();
if ($metadata_type == 'Tainacan\Metadata_Types\Taxonomy') {
$metadatum_options = $filter->get_metadatum()->get_metadata_type_options();
$taxonomy_id = $metadatum_options['taxonomy_id'];
$taxonomy_slug = Repositories\Taxonomies::get_instance()->get_db_identifier_by_id($taxonomy_id);
$id = "$filter_id.taxonomy.$taxonomy_slug";
$key = "terms.$taxonomy_slug.term_id";
$field = "terms.$taxonomy_slug";
if( isset($args['tax_query']) ) {
foreach( $args['tax_query'] as $taxquery ) {
if( $taxquery['taxonomy'] === $taxonomy_slug ) {
$include = is_array($taxquery['terms']) ? $taxquery['terms'] : [$taxquery['terms']];
}
}
}
} else {
$metadatum_id = $filter->get_metadatum()->get_ID();
$id = "$filter_id.meta.$metadatum_id";
$key = "meta.$metadatum_id.raw";
$field = "meta.$metadatum_id.raw";
if( isset($args['meta_query']) ) {
foreach( $args['meta_query'] as $metaquery ) {
if( $metaquery['key'] == $metadatum_id ){
$include = is_array($metaquery['value']) ? $metaquery['value'] : [$metaquery['value']];
}
}
}
}
$this->aggregation_type = 'items';
$this->facets[$id] = [
"key" => $key,
"field" => $field,
"use_max_options" => $filter->get_filter_type_object()->get_use_max_options(),
"max_options" => $filter->get_max_options(),
"metadata_type" => $metadata_type,
"include" => $include
];
}
}
}
}
add_filter('ep_formatted_args', array($this, "prepare_request")); //filtro para os argumentos já no formato a ser enviado para o elasticpress.
return $args;
}
/**
* Create a formatted array of args to send to elasticpress containing the aggregations for items or for one single facet depending on the request
*
* @param \Array $formatted_args initial array generated by plugin elasticpress
*
* @return \Array with formatted array of args.
*/
public function prepare_request($formatted_args) {
switch ($this->aggregation_type) {
case 'items':
$formatted_args = $this->prepare_request_for_items($formatted_args);
break;
case 'facets':
$formatted_args = $this->prepare_request_for_facet($formatted_args);
break;
}
return $formatted_args;
}
/**
* Formats the response from Elastic Search to Tainacan API format
*
*/
public function format_aggregations($aggregations) {
switch ($this->aggregation_type) {
case 'items':
return $this->format_aggregations_items($aggregations);
case 'facets':
return $this->format_aggregations_facet($aggregations);
}
}
public function fetch_all_metadatum_values($return, $metadatum, $args) {
$metadatum_type = $metadatum->get_metadata_type();
$metadatum_id = $metadatum->get_id();
$metadatum_options = $metadatum->get_metadata_type_options();
$args['items_filter']['ep_integrate'] = true;
$args['items_filter']['facet_term_parent_id'] = $args['parent_id'];
$args['items_filter']['facet_pagesize'] = $args['number'];
$args['items_filter']['facet_last_term'] = $args['last_term'];
$args['items_filter']['facet_search'] = $args['search'];
$args['items_filter']['facet_metadatum_id'] = $metadatum_id;
$args['items_filter']['facet_include'] = $args['include'];
$itemsRepo = \Tainacan\Repositories\Items::get_instance();
$items = $itemsRepo->fetch($args['items_filter'], $args['collection_id'], 'WP_Query');
$items_aggregations = $this->last_aggregations; //if elasticPress active
return [
// 'total' => count($items_aggregations),
// 'pages' => '0', //TODO get a total of pages
'values' => $items_aggregations['values'],
'last_term' => $items_aggregations['last_term']
];
}
/**
* Prepare the request to fetch items with information about all facets
* Used by the /items API endpoint
* WIll add all the facets (filters) for the current collection
*
* JSON exemple:
*
* {
* "from" : 0,
* "size" : 12,
* "sort" : [ { "post_date" : { "order" : "desc" } } ],
* "query" : { "match_all":{ "boost":1 } },
* "post_filter" : {
* "bool" : {
* "must" : [
* { "term" : { "post_type.raw" : "tnc_col_6_item" } },
* { "term" : { "post_status":"publish" } }
* ]
* }
* },
* "aggs" : {
* "872.taxonomy.tnc_tax_5" : {
* "filter" : {
* "bool" : {
* "must" : [
* { "term" : { "post_type.raw":"tnc_col_6_item" } },
* { "term" : { "post_status":"publish" } }
* ]
* }
* },
* "aggs":{
* "872.taxonomy.tnc_tax_5":{
* "terms":{
* "size":"4",
* "script":{
* "lang":"painless",
* "source":"def c= ['']; for(term in params._source.terms.tnc_tax_5) { if(term.parent==0) { c.add(term.term_id); }} return c;"
* }
* }
* }
* }
* },
* "1026.meta.14" : {
* "filter":{
* "bool":{
* "must":[
* { "term" : { "post_type.raw":"tnc_col_6_item" } },
* { "term" : { "post_status":"publish" } }
* ]
* }
* },
* "aggs":{
* "1026.meta.14":{
* "terms":{
* "size":"4",
* "field":"meta.14.raw"
* }
* }
* }
* }
* }
* }
*/
private function prepare_request_for_items($formatted_args) {
$default_filters = $formatted_args['post_filter'];
$aggs = [];
foreach($this->facets as $id => $filter) {
$custom_filter = $default_filters;
$temp = [];
foreach ($custom_filter['bool']['must'] as $item) {
if ( isset($item['bool'])) {
foreach ($item['bool']["must"] as $item_filter) {
if ( !isset( $item_filter["terms"][$filter['key']] ) ) { //do use array_filter ?
$temp[] = $item;
}
}
} elseif ( isset($item['term'])) {
$temp[] = $item;
}
}
$custom_filter['bool']['must'] = $temp;
$parent = 0;
if ($filter['metadata_type'] == 'Tainacan\Metadata_Types\Taxonomy') {
$field = $filter['field'];
$aggs[$id] = [
"filter" => $custom_filter,
"aggs" => array(
$id => array(
"terms"=>array(
//"size" => $filter['max_options'],
"script" => [
"lang" => "painless",
"source"=> "def c= [''];if(!params._source.terms.empty && params._source.$field != null){ for(term in params._source.$field) { if(term.parent==$parent) { c.add(term.term_id); }}} return c;"
]
)
)
)
];
if (!empty($filter['include'])) {
$custom_filter_include = $custom_filter;
$custom_filter_include['bool']['must'][] = ["bool" => [ "must"=> [ [ "terms" => ["$field.term_id" => $filter['include'] ] ] ] ] ];
$terms_id_inlcude = \implode($filter['include'], ",");
$aggs[$id.'.include'] = [
"filter" => $custom_filter_include,
"aggs" => array(
$id.'.include' => array(
"terms"=>array(
"script" => [
"lang" => "painless",
"source"=> "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if( [$terms_id_inlcude].contains(term.term_id) ) { c.add(term.term_id); }}} return c;"
]
)
)
)
];
}
} else {
$field = $filter['field'];
$aggs[$id] = [
"filter" => $custom_filter,
"aggs" => array(
$id => array(
"terms"=>array(
//"size" => $filter['max_options'],
"field"=> $filter['field']
)
)
)
];
if (!empty($filter['include'])) {
$custom_filter_include = $custom_filter;
$custom_filter_include['bool']['must'][] = ["bool" => [ "must"=> [ [ "terms" => ["$field" => $filter['include'] ] ] ] ] ];
$meta_label = explode(".",$id)[1] . '.' . explode(".",$id)[2];
$meta_id_inlcude = "'" . \implode($filter['include'], "','") . "'";
$aggs[$id.'.include'] = [
"filter" => $custom_filter_include,
"aggs" => array(
$id.'.include' => array(
"terms"=>array(
"script" => [
"lang" => "painless",
"source"=> "def c= ['']; if(!params._source.meta.empty && params._source.$meta_label != null) { for(meta in params._source.$meta_label) { if([$meta_id_inlcude].contains(meta.raw)) { c.add(meta.raw); }}} return c;"
]
//"field"=> $filter['field']
)
)
)
];
}
}
if($filter['use_max_options'] == true ) {
$aggs[$id]['aggs'][$id]['terms']['size'] = $filter['max_options'];
}
}
$formatted_args['aggs'] = $aggs;
return $formatted_args;
}
/**
* Prepare the request to get information about one facet (facets API endpoint)
*
* JSON exemple:
*
* {
* "from":0,
* "size":0,
* "sort":[{"post_date":{"order":"desc"}}],
* "query":{
* "bool":{
* "must":[
* {"term":{"post_type.raw":"tnc_col_6_item"}},
* {"term":{"post_status":"publish"}}
* ]
* }
* },
* "aggs":{
* "872.taxonomy.tnc_tax_5":{
* "composite" : {
* "size": 2,
* "after" : { "tnc_tax_5" : "2" },
* "sources" : [
* { "tnc_tax_5": {
* "terms": {
* "script":{
* "lang":"painless",
* "source":"def c= ['']; for(term in params._source.terms.tnc_tax_5) { if(term.parent==0) { c.add(term.term_id); }} return c;"
* }
* }
* } }
* ]
* }
* }
* }
* }
*/
private function prepare_request_for_facet($formatted_args) {
$formatted_args['size'] = 0;
$formatted_args['query'] = $formatted_args['post_filter'];
$custom_filter_include = $formatted_args['post_filter'];
unset($formatted_args['post_filter']);
foreach($this->facets as $id => $filter) {
$search = $filter['search'];
$field = $filter['field'];
if ($filter['metadata_type'] == 'Tainacan\Metadata_Types\Taxonomy') {
$parent = $filter['parent'];
$aggs[$id] = [
"composite" => array(
"size" => $filter['pagesize'],
"sources" => [
$id => [
"terms" => [
"script" => [
"lang" => "painless",
"source" => "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if(term.parent==$parent) { c.add(term.term_id); }}} return c;"
]
]
]
]
)
];
if (!empty($filter['include'])) {
$custom_filter_include['bool']['must'][] = ["bool" => [ "must"=> [ [ "terms" => ["$field.term_id" => $filter['include'] ] ] ] ] ];
$aggs[$id.'.include'] = [
"filter" => $custom_filter_include,
"aggs" => array(
$id.'.include' => array(
"terms" => array(
"script" => [
"lang" => "painless",
"source"=> "def c= ['']; if(!params._source.terms.empty && params._source.$field != null) { for(term in params._source.$field) { if(term.parent==$parent) { c.add(term.term_id); }}} return c;"
]
)
)
)
];
}
if($search != '') {
$formatted_args['query']['bool']['must'][] = ["wildcard"=>["$field.name.raw" => "*$search*"]];
}
} else {
$aggs[$id] = [
"composite" => array(
"size" => $filter['pagesize'],
"sources" => [ $id => [ "terms" => [ "field" => $field ] ] ]
)
];
if (!empty($filter['include'])) {
$custom_filter_include['bool']['must'][] = ["bool" => [ "must"=> [ [ "terms" => ["$field" => $filter['include'] ] ] ] ] ];
$aggs[$id.'.include'] = [
"filter" => $custom_filter_include,
"aggs" => array(
$id => array(
"terms"=>array(
"field"=> $field
)
)
)
];
}
if($search != '') {
$field_relationship_label = explode ( ".", $field);
$field_relationship_label = "$field_relationship_label[0].$field_relationship_label[1].relationship_label";
//$formatted_args['query']['bool']['must'][] = ["wildcard"=>["$field" => "*$search*"]];
$formatted_args['query']['bool']['must'][] = ["bool"=>["should"=>[
["wildcard"=>["$field"=>"*$search*"]],
["wildcard"=>["$field_relationship_label"=>"*$search*"]] //pega nome do metadado é melhor!
]]];
}
}
$aggs[$id]['composite']['after'] = [$id => $filter['last_term'] ];
}
$formatted_args['aggs'] = $aggs;
return $formatted_args;
}
/**
* Format ES aggregation response for items request
*/
private function format_aggregations_items($aggregations) {
global $wpdb;
$formated_aggs = [];
foreach($aggregations as $key => $aggregation) {
$description_types = \explode(".", $key);
$filter_id = $description_types[0];
$formated_aggs[$filter_id] = isset($formated_aggs[$filter_id]) ? $formated_aggs[$filter_id] : [];
if($description_types[1] == 'taxonomy') {
$taxonomy_slug = $description_types[2];
$taxonomy_id = Repositories\Taxonomies::get_instance()->get_id_by_db_identifier($taxonomy_slug);
foreach ($aggregation[$key]['buckets'] as $term) {
$term_id = $term['key'];
$term_object = \Tainacan\Repositories\Terms::get_instance()->fetch($term_id, $taxonomy_slug);
$count_query = $wpdb->prepare("SELECT COUNT(term_id) FROM $wpdb->term_taxonomy WHERE parent = %d", $term_id);
$total_children = $wpdb->get_var($count_query);
$fct = [
"type" => "Taxonomy",
"value" => $term['key'],
"taxonomy" => $taxonomy_slug,
"taxonomy_id" => $taxonomy_id,
"total_children" => $total_children,
"total_items" => $term['doc_count'],
"label" => $term_object->get('name'),
"parent" => $term_object->get('parent')
];
if (isset($description_types[3])) {
array_unshift($formated_aggs[$filter_id], $fct);
} else {
$formated_aggs[$filter_id][] = $fct;
}
}
} else {
$metada_label = $description_types[1];
$metada_id = $description_types[2];
if (isset($aggregation[$key]['buckets']))
foreach ($aggregation[$key]['buckets'] as $term) {
$label = $term['key'];
if (\is_numeric($term['key'])) {
$metadatadum = \Tainacan\Repositories\Metadata::get_instance()->fetch($metada_id);
if ( isset($metadatadum->get_metadata_type_options()['collection_id'])) {
$item = \Tainacan\Repositories\Items::get_instance()->fetch(intval($term['key']));
$label = $item->get_title();
}
}
$fct = [
"type" => "Text",
"label" => $label,
"value" => $term['key'],
"total_items" => $term['doc_count']
];
if (isset($description_types[3])) {
array_unshift($formated_aggs[$filter_id], $fct);
} else {
$formated_aggs[$filter_id][] = $fct;
}
}
}
//remove duplicates
$formated_aggs[$filter_id] = array_values( array_map( 'unserialize', array_unique( array_map( 'serialize', $formated_aggs[$filter_id] ) ) ) );
//$formated_aggs[$filter_id] = array_intersect_key($formated_aggs[$filter_id], array_unique(array_map('serialize', $formated_aggs[$filter_id])));
}
return $formated_aggs;
}
/**
* Format ES aggregation response for one facet request
*/
private function format_aggregations_facet($aggregations) {
global $wpdb;
$formated_aggs = ['values'=>[]];
foreach($aggregations as $key => $aggregation) {
$description_types = \explode(".", $key);
if($description_types[0] == 'taxonomy') {
$has_include = isset($description_types[2]);
$taxonomy_label = $description_types[0].'.'.$description_types[1];
$taxonomy_slug = $description_types[1];
$taxonomy_id = Repositories\Taxonomies::get_instance()->get_id_by_db_identifier($taxonomy_slug);
$buckets = ($has_include == false ? $aggregation['buckets'] : $aggregation[$key]['buckets']);
foreach ($buckets as $term) {
if ($has_include) {
$term_id = $term['key'];
$doc_count = $term['doc_count'];
} else {
$term_id = $term['key'][$key];
$doc_count = $term['doc_count'];
}
if ($term_id == '') continue;
$term_object = \Tainacan\Repositories\Terms::get_instance()->fetch($term_id, $taxonomy_slug);
$count_query = $wpdb->prepare("SELECT COUNT(term_id) FROM $wpdb->term_taxonomy WHERE parent = %d", $term_id);
$total_children = $wpdb->get_var($count_query);
$fct = [
"type" => "Taxonomy",
"value" => $term_id,
"taxonomy" => $taxonomy_slug,
"taxonomy_id" => $taxonomy_id,
"total_children" => $total_children,
"total_items" => $term['doc_count'],
"label" => $term_object->get('name'),
"parent" => $term_object->get('parent')
];
if ($has_include) {
array_unshift($formated_aggs['values'], $fct);
} else {
$after_key = $aggregation['after_key'];
$formated_aggs['values'][] = $fct;
$formated_aggs['last_term'] = $after_key[$key];
}
}
} else {
$metada_id = $description_types[1];
$metada_label = $description_types[0].'.'.$description_types[1];
if (isset($aggregation['buckets'])) {
foreach ($aggregation['buckets'] as $term) {
$label = $term['key'][$key];
if (\is_numeric($term['key'][$key])) {
$metadatadum = \Tainacan\Repositories\Metadata::get_instance()->fetch($metada_id);
if ( isset($metadatadum->get_metadata_type_options()['collection_id'])) {
$item = \Tainacan\Repositories\Items::get_instance()->fetch($term['key'][$key]);
$label = $item->get_title();
}
}
if ( isset($term['key'][$key]) ) {
$fct = [
"type" => "Text",
"label" => $label,
"value" => $term['key'][$key],
"total_items" => $term['doc_count']
];
$formated_aggs['values'][] = $fct;
}
}
$after_key = $aggregation['after_key'];
$formated_aggs['last_term'] = $after_key[$key];
} elseif ( isset($aggregation[$metada_label]['buckets'])) {
foreach ($aggregation[$metada_label]['buckets'] as $term) {
$fct = [
"type" => "Text",
"label" => $term['key'],
"value" => $term['key'],
"total_items" => $term['doc_count']
];
array_unshift($formated_aggs['values'], $fct);
}
}
}
//remove duplicates
$formated_aggs['values'] = array_intersect_key($formated_aggs['values'], array_unique(array_map('serialize', $formated_aggs['values'])));
}
return $formated_aggs;
}
} // END

View File

@ -70,7 +70,11 @@ class Entity {
public $cap;
/**
* Create an instance of Entity and get post data from database or create a new StdClass if $which is 0
* Create an instance of Entity
*
* If ID or WP Post is passed, it retrieves the object from the database
*
* Attention: If the ID or Post provided do not match the Entity post type, an Exception will be thrown
*
* @param integer|\WP_Post optional $which Entity ID or a WP_Post object for existing Entities. Leave empty to create a new Entity.
*
@ -79,9 +83,10 @@ class Entity {
function __construct($which = 0) {
if (is_numeric($which) && $which > 0) {
$post = get_post($which);
if ($post instanceof \WP_Post) {
$this->WP_Post = get_post($which);
} else {
throw new \Exception( 'No entity was found with ID ' . $which );
}
} elseif ($which instanceof \WP_Post) {
@ -98,17 +103,20 @@ class Entity {
} else {
$this->WP_Post = new \StdClass();
}
$collection_pt_pattern = '/' . Collection::$db_identifier_prefix . '\d+' . Collection::$db_identifier_sufix . '/';
if(
is_int($which) &&
$this->WP_Post instanceof \WP_Post &&
$which != 0 &&
isset( $this->WP_Post->ID ) &&
(
( $this->get_post_type() !== false && $this->WP_Post->post_type != $this->get_post_type() ) ||
// Lets check if it is a collection and have rigth post_type
( $this->get_post_type() === false && $this->WP_Post->post_type != Collection::$db_identifier_prefix.$this->get_db_identifier().Collection::$db_identifier_sufix ) // TODO check if we can use only get_db_identifier for this
( $this->get_post_type() === false && $this->WP_Post->post_type && ! preg_match($collection_pt_pattern, $this->WP_Post->post_type) )
)
) {
if($this->get_post_type() === false) {
throw new \Exception('the returned post is not the same type of the entity! expected: '.Collection::$db_identifier_prefix.$this->get_db_identifier().Collection::$db_identifier_sufix.' and actual: '.$this->WP_Post->post_type );
}
else {

View File

@ -114,14 +114,10 @@
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, query, this.isRepositoryLevel );
} else {
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' )
promise = this.getValuesRelationship( query, this.isRepositoryLevel );
else
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel );
}
promise.request.catch( error => {
this.$console.log('error select', error );

View File

@ -8,6 +8,9 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
*/
class Autocomplete extends Filter_Type {
//protected $default_max_options = -1;
protected $use_max_options = false;
function __construct(){
$this->set_supported_types(['string','long_string','item']);
$this->set_component('tainacan-filter-autocomplete');

View File

@ -9,7 +9,6 @@
class="icon has-text-centered loading-icon">
<div class="control has-icons-right is-loading is-clearfix" />
</span> -->
<div
v-for="(option, index) in options.slice(0, filter.max_options)"
v-if="!isLoadingOptions"
@ -47,7 +46,7 @@
</button>
</div>
<p
v-if="!isLoadingOptions && options.length != undefined && options.length <= 0"
v-if="isLoadingOptions == false && options.length != undefined && options.length <= 0"
class="no-options-placeholder">
{{ $i18n.get('info_no_options_avialable_filtering') }}
</p>
@ -63,21 +62,22 @@
created(){
this.collection = ( this.collection_id ) ? this.collection_id : this.filter.collection_id;
this.metadatum = ( this.metadatum_id ) ? this.metadatum_id : this.filter.metadatum.metadatum_id;
const vm = this;
let in_route = '/collection/' + this.collection + '/metadata/' + this.metadatum +'?nopaging=1';
let route = '/collection/' + this.collection + '/metadata/' + this.metadatum +'?nopaging=1';
if(this.isRepositoryLevel || this.collection == 'filter_in_repository'){
in_route = '/metadata?nopaging=1';
}
if (this.isRepositoryLevel || this.collection == 'filter_in_repository')
route = '/metadata?nopaging=1';
axios.get(in_route)
axios.get(route)
.then( res => {
let result = res.data;
if ( result && result.metadata_type ){
vm.metadatum_object = result;
vm.type = result.metadata_type;
vm.loadOptions();
this.metadatum_object = result;
this.type = result.metadata_type;
if (!this.isUsingElasticSearch)
this.loadOptions();
}
})
.catch(error => {
@ -85,6 +85,13 @@
});
this.$eventBusSearch.$on('removeFromFilterTag', this.cleanSearchFromTags);
if (this.isUsingElasticSearch) {
this.isLoadingOptions = false;
this.$eventBusSearch.$on('isLoadingItems', isLoading => {
this.isLoadingOptions = isLoading;
});
}
},
props: {
isRepositoryLevel: Boolean,
@ -108,43 +115,29 @@
},
methods: {
loadOptions(skipSelected) {
let promise = null;
// Cancels previous Request
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, null, this.isRepositoryLevel, [], 0, this.filter.max_options, false, '1');
promise.request
.then(() => {
if(this.options.length > this.filter.max_options){
this.options.splice(this.filter.max_options);
}
}).catch((error) => {
this.$console.error(error);
})
} else {
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' )
promise = this.getValuesRelationship( null, this.isRepositoryLevel, [], 0, this.filter.max_options, false, '1');
else
promise = this.getValuesPlainText( this.metadatum, null, this.isRepositoryLevel, [], 0, this.filter.max_options, false, '1' );
if (skipSelected != undefined && skipSelected == true) {
promise.request
.then(() => {
if(this.options.length > this.filter.max_options){
if (this.options.length > this.filter.max_options)
this.options.splice(this.filter.max_options);
}
}).catch((error) => {
this.$console.error(error);
});
}
if (skipSelected == undefined || skipSelected == false) {
} else {
promise.request
.then(() => {
this.selectedValues()
this.selectedValues();
})
.catch( error => {
this.$console.log('error select', error );
@ -186,6 +179,7 @@
if ( index >= 0){
let query = this.query.metaquery.slice();
this.selected = query[ index ].value;
} else {
this.selected = [];
return false;
@ -209,7 +203,9 @@
query: this.query
},
events: {
appliedCheckBoxModal: () => this.loadOptions()
appliedCheckBoxModal: () => {
this.loadOptions();
}
}
});
},
@ -248,6 +244,9 @@
},
beforeDestroy() {
this.$eventBusSearch.$off('removeFromFilterTag', this.cleanSearchFromTags);
if (this.isUsingElasticSearch)
this.$eventBusSearch.$off('isLoadingItems');
}
}
</script>

View File

@ -11,6 +11,7 @@ abstract class Filter_Type {
private $options = [];
private $component;
private $preview_template = '';
protected $use_max_options = true;
public function __construct(){
add_action('register_filter_types', array(&$this, 'register_filter_type'));
@ -75,6 +76,7 @@ abstract class Filter_Type {
$attributes['component'] = $this->get_component();
$attributes['supported_types'] = $this->get_supported_types();
$attributes['preview_template'] = $this->get_preview_template();
$attributes['use_max_options'] = $this->get_use_max_options();
return $attributes;
}
@ -125,4 +127,12 @@ abstract class Filter_Type {
public function get_options() {
return $this->options;
}
public function set_use_max_options($use_max_options) {
$this->use_max_options = $use_max_options;
}
public function get_use_max_options() {
return $this->use_max_options;
}
}

View File

@ -1,11 +1,15 @@
import qs from 'qs';
import axios from '../../js/axios/axios';
import { mapGetters } from 'vuex';
import { resolve } from 'bluebird';
export const filter_type_mixin = {
data () {
return {
thumbPlaceholderPath: tainacan_plugin.base_url + '/admin/images/placeholder_square.png',
getOptionsValuesCancel: undefined
getOptionsValuesCancel: undefined,
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false,
isLoadingOptions: false
}
},
props: {
@ -16,10 +20,9 @@ export const filter_type_mixin = {
collection_id: [Number], // not required, but overrides the filter metadatum id if is set
filter_type: [String], // not required, but overrides the filter metadatum type if is set
id: '',
query: {},
isLoadingOptions: false
query: {}
},
mounted() {
created() {
// We listen to event, but reload event if hasFiltered is negative, as
// an empty query also demands filters reloading.
this.$eventBusSearch.$on('hasFiltered', () => {
@ -27,9 +30,22 @@ export const filter_type_mixin = {
this.loadOptions(true);
});
},
mounted() {
},
computed: {
facetsFromItemSearch() {
return this.getFacets();
}
},
methods: {
...mapGetters('search', [
'getFacets'
]),
getValuesPlainText(metadatumId, search, isRepositoryLevel, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
if (isInCheckboxModal || search || !this.isUsingElasticSearch) {
const source = axios.CancelToken.source();
let currentQuery = JSON.parse(JSON.stringify(this.query));
@ -49,7 +65,10 @@ export const filter_type_mixin = {
url = `/collection/${this.collection}/facets/${metadatumId}?getSelected=${getSelected}&`;
if (offset != undefined && number != undefined) {
if (!this.isUsingElasticSearch)
url += `offset=${offset}&number=${number}&`;
else
url += `last_term=${offset}&number=${number}&`;
}
if(search && offset != undefined && number != undefined){
@ -64,83 +83,47 @@ export const filter_type_mixin = {
return new Object ({
request:
new Promise((resolve, reject) => {
axios.tainacan.get(url, { cancelToken: source.token })
.then(res => {
this.isLoadingOptions = false;
let sResults = [];
let opts = [];
for (let metadata of res.data) {
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == metadata.value);
if (search && isInCheckboxModal) {
sResults.push({
label: metadata.label,
value: metadata.value,
total_items: metadata.total_items
});
} else if (indexToIgnore < 0) {
opts.push({
label: metadata.label,
value: metadata.value,
total_items: metadata.total_items
});
}
} else {
if (search && isInCheckboxModal) {
sResults.push({
label: metadata.label,
value: metadata.value,
total_items: metadata.total_items
});
} else {
opts.push({
label: metadata.label,
value: metadata.value,
total_items: metadata.total_items
});
}
}
}
this.searchResults = sResults;
if (opts.length) {
this.options = opts;
} else if(!search) {
this.noMorePage = 1;
}
if(this.options.length < this.maxNumOptionsCheckboxList && !search){
this.noMorePage = 1;
}
if (this.filter.max_options && this.options.length >= this.filter.max_options) {
let showViewAllButton = true;
if(this.options.length === this.filter.max_options){
this.options[this.filter.max_options-1].showViewAllButton = showViewAllButton;
} else {
this.options[this.options.length-1].showViewAllButton = showViewAllButton;
}
}
if (res.data.values)
this.prepareOptionsForPlainText(res.data.values, search, valuesToIgnore, isInCheckboxModal);
else
this.prepareOptionsForPlainText(res.data, search, valuesToIgnore, isInCheckboxModal);
resolve(res.data);
})
.catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log('Request canceled: ', thrown.message);
} else {
this.isLoadingOptions = false;
reject(thrown);
}
reject(thrown);
})
}),
source: source
});
} else {
let callback = new Promise((resolve) => {
for (const facet in this.facetsFromItemSearch) {
if (facet == this.filter.id)
this.prepareOptionsForPlainText(this.facetsFromItemSearch[facet], search, valuesToIgnore, isInCheckboxModal);
}
resolve();
});
return new Object ({
request: callback
});
}
},
getValuesRelationship(collectionTarget, search, isRepositoryLevel, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
getValuesRelationship(search, isRepositoryLevel, valuesToIgnore, offset, number, isInCheckboxModal, getSelected = '0') {
if (isInCheckboxModal || search || !this.facetsFromItemSearch || Object.values(this.facetsFromItemSearch).length <= 0) {
const source = axios.CancelToken.source();
@ -174,15 +157,112 @@ export const filter_type_mixin = {
return new Object ({
request:
new Promise((resolve, reject) => {
axios.tainacan.get(url + '&fetch_only=thumbnail,title,id&' + qs.stringify(query_items))
.then(res => {
this.isLoadingOptions = false;
if (res.data.values)
this.prepareOptionsForRelationship(res.data.values, search, valuesToIgnore, isInCheckboxModal);
else
this.prepareOptionsForRelationship(res.data, search, valuesToIgnore, isInCheckboxModal);
resolve(res.data);
})
.catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log('Request canceled: ', thrown.message);
} else {
this.isLoadingOptions = false;
}
reject(thrown);
})
}),
source: source
});
} else {
let callback = new Promise((resolve) => {
for (const facet in this.facetsFromItemSearch) {
if (facet == this.filter.id) {
this.prepareOptionsForRelationship(this.facetsFromItemSearch[facet], search, valuesToIgnore, isInCheckboxModal);
}
}
resolve();
});
return new Object ({
request: callback
});
}
},
prepareOptionsForPlainText(metadata, search, valuesToIgnore, isInCheckboxModal) {
let sResults = [];
let opts = [];
if (res.data.length > 0) {
for (let item of res.data) {
if (!Array.isArray(metadata))
metadata = Object.values(metadata);
for (let metadatum of metadata) {
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == metadatum.value);
if (search && isInCheckboxModal) {
sResults.push({
label: metadatum.label,
value: metadatum.value,
total_items: metadatum.total_items
});
} else if (indexToIgnore < 0) {
opts.push({
label: metadatum.label,
value: metadatum.value,
total_items: metadatum.total_items
});
}
} else {
if (search && isInCheckboxModal) {
sResults.push({
label: metadatum.label,
value: metadatum.value,
total_items: metadatum.total_items
});
} else {
opts.push({
label: metadatum.label,
value: metadatum.value,
total_items: metadatum.total_items
});
}
}
}
this.searchResults = sResults;
if (opts.length)
this.options = opts;
else if(!search)
this.noMorePage = 1;
if(this.options.length < this.maxNumOptionsCheckboxList && !search)
this.noMorePage = 1;
if (this.filter.max_options && this.options.length >= this.filter.max_options) {
let showViewAllButton = true;
if(this.options.length === this.filter.max_options){
this.options[this.filter.max_options-1].showViewAllButton = showViewAllButton;
} else {
this.options[this.options.length-1].showViewAllButton = showViewAllButton;
}
}
},
prepareOptionsForRelationship(items, search, valuesToIgnore, isInCheckboxModal) {
let sResults = [];
let opts = [];
if (items.length > 0) {
for (let item of items) {
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == item.value);
@ -222,15 +302,14 @@ export const filter_type_mixin = {
this.searchResults = sResults;
if (opts.length) {
if (opts.length)
this.options = opts;
} else {
else
this.noMorePage = 1;
}
if(this.options.length < this.maxNumOptionsCheckboxList){
if(this.options.length < this.maxNumOptionsCheckboxList)
this.noMorePage = 1;
}
if (this.filter.max_options && this.options.length >= this.filter.max_options) {
let showViewAllButton = true;
@ -241,18 +320,6 @@ export const filter_type_mixin = {
this.options[this.options.length-1].showViewAllButton = showViewAllButton;
}
}
})
.catch((thrown) => {
if (axios.isCancel(thrown)) {
console.log('Request canceled: ', thrown.message);
} else {
this.isLoadingOptions = false;
reject(thrown);
}
}),
source: source
});
}
},
beforeDestroy() {
@ -260,5 +327,6 @@ export const filter_type_mixin = {
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
this.$eventBusSearch.$off('hasFiltered');
},
};

View File

@ -46,6 +46,8 @@
if( result && result.metadata_type ){
vm.metadatum_object = result;
vm.type = result.metadata_type;
if (!this.isUsingElasticSearch)
vm.loadOptions();
}
})
@ -54,6 +56,12 @@
});
this.$eventBusSearch.$on('removeFromFilterTag', this.cleanSearchFromTags);
if (this.isUsingElasticSearch) {
this.$eventBusSearch.$on('isLoadingItems', isLoading => {
this.isLoadingOptions = isLoading;
});
}
},
props: {
isRepositoryLevel: Boolean,
@ -68,6 +76,16 @@
}
},
mixins: [filter_type_mixin],
watch: {
selected(value) {
if (value) {
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: value
});
}
}
},
computed: {
selected() {
if ( this.query && this.query.metaquery && Array.isArray( this.query.metaquery ) ) {
@ -83,7 +101,6 @@
},
methods: {
loadOptions(){
// Cancels previous Request
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
@ -101,33 +118,13 @@
this.getOptionsValuesCancel = promise.source;
},
onSelect(value){
this.selected = value;
//this.selected = value;
this.$emit('input', {
filter: 'selectbox',
metadatum_id: this.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: ( value ) ? value : ''
});
if (value) {
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: value
});
}
},
selectedValues(){
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
return false;
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key === this.metadatum );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
this.selected = metadata.value;
} else {
return false;
}
},
cleanSearchFromTags(filterTag) {
if (filterTag.filterId == this.filter.id)
@ -136,6 +133,9 @@
},
beforeDestroy() {
this.$eventBusSearch.$off('removeFromFilterTag', this.cleanSearchFromTags);
if (this.isUsingElasticSearch)
this.$eventBusSearch.$off('isLoadingItems');
}
}
</script>

View File

@ -8,6 +8,7 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
*/
class Selectbox extends Filter_Type {
protected $use_max_options = false;
function __construct(){
$this->set_supported_types(['string', 'long_string']);
$this->set_component('tainacan-filter-selectbox');

View File

@ -128,14 +128,10 @@
if (this.getOptionsValuesCancel != undefined)
this.getOptionsValuesCancel.cancel('Facet search Canceled.');
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, query, this.isRepositoryLevel, valuesToIgnore );
} else {
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' )
promise = this.getValuesRelationship( query, this.isRepositoryLevel, valuesToIgnore );
else
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel, valuesToIgnore );
}
promise.request
.catch( error => {
@ -163,9 +159,11 @@
axios.get('/collection/' + collectionTarget + '/items?' + query)
.then( res => {
if (res.data.items) {
for (let item of res.data) {
instance.selected.push({ label: item.title, value: item.id, img: item.thumbnail.thumbnail[0] });
}
}
})
.catch(error => {
this.$console.log(error);

View File

@ -32,7 +32,7 @@
</label>
<button
class="view-all-button link-style"
v-if="option.showViewAllButton && index == options.slice(0, filter.max_options).length - 1"
v-if="option.showViewAllButton"
@click="openCheckboxModal(option.parent)">
{{ $i18n.get('label_view_all') }}
</button>
@ -48,6 +48,7 @@
<script>
import qs from 'qs';
import { tainacan as axios } from '../../../js/axios/axios';
import { mapGetters } from 'vuex';
import CheckboxRadioModal from '../../../admin/components/other/checkbox-radio-modal.vue';
export default {
@ -55,9 +56,15 @@
this.collection = ( this.collection_id ) ? this.collection_id : this.filter.collection_id;
this.metadatum = ( this.metadatum_id ) ? this.metadatum_id : this.filter.metadatum.metadatum_id ;
this.type = ( this.filter_type ) ? this.filter_type : this.filter.metadatum.metadata_type;
this.loadOptions();
this.$eventBusSearch.$on('removeFromFilterTag', this.cleanSearchFromTag);
if (this.isUsingElasticSearch) {
this.$eventBusSearch.$on('isLoadingItems', isLoading => {
this.isLoading = isLoading;
});
}
},
mounted(){
// We listen to event, but reload event if hasFiltered is negative, as
@ -77,6 +84,7 @@
selected: [],
taxonomy: '',
taxonomy_id: Number,
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false
}
},
props: {
@ -95,10 +103,24 @@
selected: function(){
//this.selected = val;
this.onSelect();
},
facetsFromItemSearch() {
if (this.isUsingElasticSearch)
this.loadOptions();
}
},
computed: {
facetsFromItemSearch() {
return this.getFacets();
}
},
methods: {
...mapGetters('search', [
'getFacets'
]),
loadOptions(skipSelected) {
if (!this.isUsingElasticSearch) {
this.isLoading = true;
let query_items = { 'current_query': this.query };
@ -113,52 +135,25 @@
axios.get(route)
.then( res => {
for (let item of res.data) {
this.taxonomy = item.taxonomy;
this.taxonomy_id = item.taxonomy_id;
let existingOptionIndex = this.options.findIndex(anOption => anOption.value == item.value)
if (existingOptionIndex < 0)
this.options.push(item);
else
this.$set(this.options, item, existingOptionIndex);
}
if (this.options) {
let hasChildren = false;
for( let term of this.options ){
if(term.total_children > 0){
hasChildren = true;
break;
}
}
if(this.filter.max_options && (this.options.length >= this.filter.max_options || hasChildren)){
if(this.options.length > this.filter.max_options){
this.options.splice(this.filter.max_options);
}
let showViewAllButton = true;
if(this.options.length === this.filter.max_options){
this.options[this.filter.max_options-1].showViewAllButton = showViewAllButton;
} else {
this.options[this.options.length-1].showViewAllButton = showViewAllButton;
}
}
}
this.prepareOptionsForTaxonomy(res.data.values ? res.data.values : res.data, skipSelected);
this.isLoading = false;
if (skipSelected == undefined || skipSelected == false) {
this.selectedValues();
}
})
.catch(error => {
this.$console.log(error);
this.isLoading = false;
});
} else {
for (const facet in this.facetsFromItemSearch) {
if (facet == this.filter.id) {
if (Array.isArray(this.facetsFromItemSearch[facet]))
this.prepareOptionsForTaxonomy(this.facetsFromItemSearch[facet], skipSelected);
else
this.prepareOptionsForTaxonomy(Object.values(this.facetsFromItemSearch[facet]), skipSelected);
}
}
}
},
selectedValues(){
@ -185,53 +180,58 @@
});
let onlyLabels = [];
for (let selected of this.selected) {
let valueIndex = this.options.findIndex(option => option.value == selected );
if (valueIndex >= 0) {
let existingLabelIndex = onlyLabels.findIndex(aLabel => aLabel == this.options[valueIndex].label)
if (existingLabelIndex < 0)
onlyLabels.push(this.options[valueIndex].label);
else
this.$set(onlyLabels, onlyLabels.push(this.options[valueIndex].label), existingLabelIndex);
} else {
let route = '';
// Not finding all options will happen on elastic search,
// as the facetsFromItemSearch will not be ready yet
if (!this.isUsingElasticSearch)
this.$console.log("Looking for terms that are not in the options list... ");
if(this.collection == 'filter_in_repository')
route = '/facets/' + this.metadatum +`?term_id=${selected}&fetch_only=name,id`;
else
route = '/collection/'+ this.collection +'/facets/' + this.metadatum +`?term_id=${selected}&fetch_only=name,id`;
// let route = '';
axios.get(route)
.then( res => {
if(!res || !res.data){
return false;
}
// if (this.collection == 'filter_in_repository')
// route = '/facets/' + this.metadatum +`?term_id=${selected}&fetch_only=name,id`;
// else
// route = '/collection/'+ this.collection +'/facets/' + this.metadatum +`?term_id=${selected}&fetch_only=name,id`;
let existingLabelIndex = onlyLabels.findIndex(aLabel => aLabel == res.data[0].label)
if (existingLabelIndex < 0) {
onlyLabels.push(res.data[0].label);
this.options.push({
isChild: true,
label: res.data[0].label,
value: res.data[0].value
});
} else {
this.$set(onlyLabels, onlyLabels.push(res.data[0].label), existingLabelIndex);
this.$set(this.options, {
isChild: true,
label: res.data[0].label,
value: res.data[0].value
}
, existingLabelIndex);
}
})
.catch(error => {
this.$console.log(error);
});
// axios.get(route)
// .then( res => {
// if(!res || !res.data || !res.data.values){
// return false;
// }
// let existingLabelIndex = onlyLabels.findIndex(aLabel => aLabel == res.data.values[0].label)
// if (existingLabelIndex < 0) {
// onlyLabels.push(res.data.values[0].label);
// this.options.push({
// isChild: true,
// label: res.data.values[0].label,
// value: res.data.values[0].value
// });
// } else {
// this.$set(onlyLabels, onlyLabels.push(res.data.values[0].label), existingLabelIndex);
// this.$set(this.options, {
// isChild: true,
// label: res.data.values[0].label,
// value: res.data.values[0].value
// }
// , existingLabelIndex);
// }
// })
// .catch(error => {
// this.$console.log(error);
// });
}
}
@ -256,7 +256,9 @@
query: this.query
},
events: {
appliedCheckBoxModal: () => this.loadOptions()
appliedCheckBoxModal: () => {
this.loadOptions();
}
},
width: 'calc(100% - 8.333333333%)',
});
@ -291,10 +293,48 @@
}
}
}
},
prepareOptionsForTaxonomy(items, skipSelected) {
if (items[0] != undefined) {
this.taxonomy = items[0].taxonomy;
this.taxonomy_id = items[0].taxonomy_id;
}
this.options = [];
this.options = items.slice(); // copy array.
if (this.options) {
let hasChildren = false;
for( let term of this.options ){
if (term.total_children > 0){
hasChildren = true;
break;
}
}
if (this.filter.max_options && (this.options.length >= this.filter.max_options || hasChildren)) {
let showViewAllButton = true;
if (this.options.length > this.filter.max_options){
this.options[this.filter.max_options - 1].showViewAllButton = showViewAllButton;
} else {
this.options[this.options.length - 1].showViewAllButton = showViewAllButton;
}
}
}
if (skipSelected == undefined || skipSelected == false) {
this.selectedValues();
}
}
},
beforeDestroy() {
this.$eventBusSearch.$off('removeFromFilterTag', this.cleanSearchFromTags);
if (this.isUsingElasticSearch)
this.$eventBusSearch.$off('isLoadingItems');
}
}
</script>

View File

@ -67,7 +67,8 @@
type: '',
collection: '',
metadatum: '',
taxonomy: ''
taxonomy: '',
isUsingElasticSearch: tainacan_plugin.wp_elasticpress == "1" ? true : false
}
},
props: {
@ -129,19 +130,28 @@
}
return axios.get(endpoint).then( res => {
for (let term of res.data) {
for (let term of res.data.values) {
this.taxonomy = term.taxonomy;
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == term.value);
if (indexToIgnore < 0) {
if( term.label.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){
this.taxonomy = term.taxonomy;
this.options.push({label: term.label, value: term.value});
this.options.push({
label: term.label,
value: term.value,
total_items: term.total_items
});
}
}
} else {
if( term.label.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){
this.taxonomy = term.taxonomy;
this.options.push({label: term.label, value: term.value});
this.options.push({
label: term.label,
value: term.value,
total_items: term.total_items
});
}
}
}
@ -152,15 +162,18 @@
this.$console.log(error);
});
}, 500),
selectedValues( taxonomy ){
selectedValues( taxonomyId ){
if ( !this.query || !this.query.taxquery || !Array.isArray( this.query.taxquery ) )
return false;
let index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy == 'tnc_tax_' + taxonomy );
this.taxonomy = 'tnc_tax_' + taxonomyId;
let index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy == this.taxonomy );
if ( index >= 0){
let metadata = this.query.taxquery[ index ];
for ( let id of metadata.terms ){
this.getTerm( taxonomy, id );
this.getTerm( taxonomyId, id );
}
} else {
return false;
@ -170,7 +183,7 @@
//getting a specific value from api, does not need be in fecat api
return axios.get('/taxonomy/' + taxonomy + '/terms/' + id + '?order=asc' )
.then( res => {
this.selected.push({ label: res.data.name, value: res.data.id })
this.selected.push({ label: res.data.name, value: res.data.id });
})
.catch(error => {
this.$console.log(error);
@ -204,7 +217,6 @@
filterId: this.filter.id,
value: labels
});
}
}
}

View File

@ -27,9 +27,11 @@
let query = qs.stringify({ postin: ( Array.isArray( this.metadatum.value ) ) ? this.metadatum.value : [ this.metadatum.value ] });
axios.get('/collection/'+collectionId+'/items?' + query + '&nopaging=1')
.then( res => {
for (let item of res.data) {
if (res.data.items) {
for (let item of res.data.items) {
this.selected.push({ label: item.title, value: item.id, img: '' });
}
}
})
.catch(error => {
this.$console.log(error);
@ -115,9 +117,12 @@
this.loading = false;
this.options = [];
let result = res.data;
for (let item of result) {
if (result.items) {
for (let item of result.items) {
this.options.push({ label: item.title, value: item.id })
}
}
})
.catch(error => {
this.$console.log(error);

View File

@ -125,7 +125,10 @@ class Relationship extends Metadata_Type {
try {
$item = new \Tainacan\Entities\Item($item_id);
//$item = new \Tainacan\Entities\Item($item_id);
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$item = $Tainacan_Items->fetch($item_id);
$count ++;

View File

@ -336,6 +336,9 @@ class Collections extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Collection object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* @param array $args WP_Query args || int $args the collection id
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
@ -345,7 +348,11 @@ class Collections extends Repository {
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Collection( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}

View File

@ -233,6 +233,9 @@ class Filters extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Filter object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* @param array $args WP_Query args || int $args the filter id
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
@ -240,15 +243,19 @@ class Filters extends Repository {
*/
public function fetch( $args = [], $output = null ) {
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Filter( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}
} elseif ( is_array( $args ) ) {
// TODO: get filters from parent collections
$args = array_merge( [
'posts_per_page' => - 1,
], $args );

View File

@ -195,6 +195,9 @@ class Items extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Item object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* The second paramater specifies from which collections item should be fetched.
* You can pass the Collection ID or object, or an Array of IDs or collection objects
*
@ -209,9 +212,14 @@ class Items extends Repository {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Item( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}

View File

@ -176,6 +176,9 @@ class Logs extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Log object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* @param array $args WP_Query args || int $args the log id
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
@ -183,9 +186,14 @@ class Logs extends Repository {
*/
public function fetch( $args = [], $output = null ) {
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Log( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}

View File

@ -300,6 +300,9 @@ class Metadata extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Metadatum object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* @param array $args WP_Query args || int $args the metadatum id
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
@ -311,7 +314,11 @@ class Metadata extends Repository {
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Metadatum( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}
@ -736,6 +743,11 @@ class Metadata extends Repository {
* @throws \Exception
*/
public function disable_delete_core_metadata( $before, $post ) {
if ( Entities\Metadatum::get_post_type() != $post->post_type ) {
return null;
}
$metadatum = $this->fetch( $post->ID );
if ( $metadatum && in_array( $metadatum->get_metadata_type(), $this->core_metadata ) && is_numeric( $metadatum->get_collection_id() ) ) {
@ -755,6 +767,11 @@ class Metadata extends Repository {
* @internal param The $post_id post ID which is deleting
*/
public function force_delete_core_metadata( $before, $post, $force_delete ) {
if ( Entities\Metadatum::get_post_type() != $post->post_type ) {
return null;
}
$metadatum = $this->fetch( $post->ID );
if ( $metadatum && in_array( $metadatum->get_metadata_type(), $this->core_metadata ) && is_numeric( $metadatum->get_collection_id() ) ) {
@ -894,6 +911,8 @@ class Metadata extends Repository {
*
* @type bool $count_items Include the count of items that can be found in each value (uses $items_filter as well). Default false
*
* @type string $last_term The last term returned when using a elasticsearch for calculates the facet.
*
* }
*
* @return array Array with the total number of values found. The total number of pages with the current number and the results with id and label for each value. Terms also include parent, taxonomy and number of children.
@ -908,7 +927,8 @@ class Metadata extends Repository {
'include' => [],
'items_filter' => [],
'parent_id' => 0,
'count_items' => false
'count_items' => false,
'last_term' => ''
);
$args = wp_parse_args($args, $defaults);
@ -927,12 +947,9 @@ class Metadata extends Repository {
}
//////////////////////////////////////////
// Get the query for current items
// this avoids wp_query to run the query. We just want to build the query
$items_query = false;
if ( false !== $args['items_filter'] && is_array($args['items_filter']) ) {
add_filter('posts_pre_query', '__return_empty_array');
$args['items_filter']['fields'] = 'ids';
unset($args['items_filter']['paged']);
@ -954,15 +971,27 @@ class Metadata extends Repository {
//var_dump($args['items_filter']['meta_query']);
}
}
$filter = apply_filters('tainacan-fetch-all-metadatum-values', null, $metadatum, $args);
if ($filter !== null) {
return $filter;
}
//////////////////////////////////////////
// Get the query for current items
// this avoids wp_query to run the query. We just want to build the query
if ( false !== $args['items_filter'] && is_array($args['items_filter']) ) {
add_filter('posts_pre_query', '__return_empty_array');
$items_query = $itemsRepo->fetch($args['items_filter'], $args['collection_id']);
$items_query = $items_query->request;
remove_filter('posts_pre_query', '__return_empty_array');
}
//// end filtering query ////////
////////////////////////////////////////////
////////////////////////////////////////////
$pagination = '';
if ( $args['offset'] >= 0 && $args['number'] >= 1 ) {
$pagination = $wpdb->prepare( "LIMIT %d,%d", (int) $args['offset'], (int) $args['number'] );
@ -1163,7 +1192,8 @@ class Metadata extends Repository {
return [
'total' => $total,
'pages' => $pages,
'values' => $values
'values' => $values,
'last_term' => $args['last_term']
];
}

View File

@ -159,6 +159,9 @@ class Taxonomies extends Repository {
* You can also use a mapped property, such as name and description, as an argument and it will be mapped to the
* appropriate WP_Query argument
*
* If a number is passed to $args, it will return a \Tainacan\Entities\Taxonomy object. But if the post is not found or
* does not match the entity post type, it will return an empty array
*
* @param array $args WP_Query args | int $args the taxonomy id
* @param string $output The desired output format (@see \Tainacan\Repositories\Repository::fetch_output() for possible values)
*
@ -171,10 +174,15 @@ class Taxonomies extends Repository {
if ( is_numeric( $args ) ) {
$existing_post = get_post( $args );
if ( $existing_post instanceof \WP_Post ) {
try {
return new Entities\Taxonomy( $existing_post );
} catch (\Exception $e) {
return [];
}
} else {
return [];
}
} elseif ( is_array( $args ) ) {
$args = array_merge( [

View File

@ -164,7 +164,7 @@ $Tainacan_Theme_Helper = \Tainacan\Theme_Helper::get_instance();
require_once(__DIR__ . '/../gutenberg-blocks/class-tainacan-gutenberg-block.php');
$Tainacan_Search_Engine = new \Tainacan\Search_Engine();
$Tainacan_Elastic_press = new \Tainacan\Elastic_Press();
$Tainacan_Elastic_press = \Tainacan\Elastic_Press::get_instance();
require_once(__DIR__ . '/class-tainacan-background-process-heartbeat.php');
$Tainacan_Importer_Heartbeat = new \Tainacan\Background_Importer_Heartbeat();

View File

@ -137,7 +137,7 @@ registerBlockType('tainacan/items-grid', {
if(collectionID) {
return tainacan.get(`/collection/${collectionID}/items?${query}`)
.then(response => {
return response.data;
return response.data.items;
})
.catch(error => {
console.error(error);
@ -145,7 +145,7 @@ registerBlockType('tainacan/items-grid', {
} else {
return tainacan.get(`/items?${query}`)
.then(response => {
return response.data;
return response.data.items;
})
.catch(error => {
console.error(error);

View File

@ -571,6 +571,8 @@ class Oaipmh_Importer extends Importer {
$this->add_transient('collection_resump', (string) $xml->ListSets->resumptionToken);
}
// TODO: verify if exists resumption token
return ($collections_array) ? $collections_array : [];
}
@ -856,7 +858,11 @@ class Oaipmh_Importer extends Importer {
</span>
<div class="control is-clearfix">
<div class="select">
<<<<<<< HEAD
<select disabled name="using_set">
=======
<select name="using_set">
>>>>>>> develop
<option value="collection" <?php selected($this->get_option('using_set'), 'collection'); ?> ><?php _e('Collections', 'tainacan'); ?></option>
<option value="taxonomy" <?php selected($this->get_option('using_set'), 'taxonomy'); ?> ><?php _e('Taxonomies', 'tainacan'); ?></option>
</select>

View File

@ -315,13 +315,14 @@ export default {
this.$store.dispatch('search/set_postquery', this.$route.query);
},
loadItems(to) {
this.$emit( 'isLoadingItems', true);
// Forces fetch_only to be filled before any search happens
if (this.$store.getters['search/getPostQuery']['fetch_only'] == undefined) {
this.$emit( 'hasToPrepareMetadataAndFilters', to);
} else {
this.$emit( 'isLoadingItems', true);
// Cancels previous Request
if (this.searchCancel != undefined)
this.searchCancel.cancel('Item search Canceled.');

View File

@ -73,7 +73,7 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
})
.then(res => {
let items = res.data;
let items = res.data.items;
let viewModeObject = tainacan_plugin.registered_view_modes[postQueries.view_mode];
if (isOnTheme && viewModeObject != undefined && viewModeObject.type == 'template') {
@ -97,6 +97,12 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
dispatch('search/setTotalItems', res.headers['x-wp-total'], { root: true } );
dispatch('search/setTotalPages', res.headers['x-wp-totalpages'], { root: true } );
dispatch('search/setItemsPerPage', res.headers['x-wp-itemsperpage'], { root: true } );
if (res.data.filters && Object.values(res.data.filters) && Object.values(res.data.filters).length > 0)
dispatch('search/setFacets', res.data.filters, { root: true } );
else
dispatch('search/setFacets', {}, { root: true } );
})
.catch((thrown) => {
if (axios.isCancel(thrown)) {

View File

@ -70,6 +70,10 @@ export const setItemsPerPage = ({ commit }, perPage ) => {
commit('setItemsPerPage', perPage );
};
export const setFacets = ({ commit }, facets) => {
commit('setFacets', facets);
};
export const setStatus= ({ commit }, status ) => {
if (status == undefined || status == '')
commit('removePostQueryAttribute', 'status');

View File

@ -79,3 +79,7 @@ export const getFetchOnlyMeta = state => {
export const getFilterTags = state => {
return state.filter_tags;
};
export const getFacets = state => {
return state.facets;
};

View File

@ -22,6 +22,7 @@ const state = {
totalItems: 0,
totalPages: 0,
itemsPerPage: 12, // Not the same as postquery.perpage as API may have limited it's value
facets: {},
orderByName: ''
};

View File

@ -184,3 +184,7 @@ export const cleanTaxQueries = (state) => {
export const cleanFetchOnly = (state) => {
delete state.postquery.fetch_only;
};
export const setFacets = (state, facets) => {
state.facets = facets;
}

View File

@ -71,7 +71,7 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
$response = $this->server->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$data = $response->get_data()['items'];
$items_titles = [$data[0]['title'], $data[1]['title']];
@ -248,7 +248,7 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
$response = $this->server->dispatch($request);
$data = $response->get_data();
$data = $response->get_data()['items'];
$this->assertCount(1, $data);
$this->assertEquals('SCRUM', $data[0]['title']);
@ -366,7 +366,7 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
'GET', $this->namespace . '/items'
);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$data = $response->get_data()['items'];
$this->assertEquals( 2, sizeof($data) );
$this->assertEquals( 5, sizeof($data[0]['metadata']) );
@ -377,7 +377,7 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
);
$request->set_query_params($attributes);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$data = $response->get_data()['items'];
$this->assertEquals( 2, sizeof($data) );
@ -395,7 +395,7 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
);
$request->set_query_params($attributes);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$data = $response->get_data()['items'];
$this->assertEquals( 2, sizeof($data) );
$this->assertEquals( 1, sizeof($data[0]['metadata']) );

View File

@ -262,7 +262,7 @@ class TAINACAN_REST_Metadatum_Mappers_Controller extends TAINACAN_UnitApiTestCas
]));
$response = $this->server->dispatch($item_request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$data = $response->get_data()['items'];
$this->assertEquals(1, sizeof($data), 'Response should contain 1 item');

View File

@ -216,7 +216,7 @@ class TAINACAN_REST_Queries extends TAINACAN_UnitApiTestCase {
$meta_query_request->set_query_params($meta_query);
$meta_query_response = $this->server->dispatch($meta_query_request);
$data3 = $meta_query_response->get_data();
$data3 = $meta_query_response->get_data()['items'];
$this->assertCount(2, $data3);
@ -290,7 +290,7 @@ class TAINACAN_REST_Queries extends TAINACAN_UnitApiTestCase {
$tax_query_request_collections->set_query_params($tax_query);
$tax_query_response_collections = $this->server->dispatch($tax_query_request_collections);
$data6 = $tax_query_response_collections->get_data();
$data6 = $tax_query_response_collections->get_data()['items'];
$this->assertCount(2, $data6);

View File

@ -351,7 +351,7 @@ class TAINACAN_REST_Visibilility_Controller extends TAINACAN_UnitApiTestCase {
$status = $response->status;
$data = $response->get_data();
$this->assertEquals(200, $status);
$this->assertEquals(1, sizeof($data));
$this->assertEquals(1, sizeof($data['items']));
//tax public - context=edit:
$request_public_edit = new \WP_REST_Request(
@ -363,7 +363,7 @@ class TAINACAN_REST_Visibilility_Controller extends TAINACAN_UnitApiTestCase {
$status = $response->status;
$data = $response->get_data();
$this->assertEquals(200, $status);
$this->assertEquals(1, sizeof($data));
$this->assertEquals(1, sizeof($data['items']));
//tax private:
$request_private = new \WP_REST_Request(
@ -381,7 +381,7 @@ class TAINACAN_REST_Visibilility_Controller extends TAINACAN_UnitApiTestCase {
$status = $response->status;
$data = $response->get_data();
$this->assertEquals(200, $status);
$this->assertEquals(1, sizeof($data));
$this->assertEquals(1, sizeof($data['items']));
//tax private - context=edit:
$request_private_edit = new \WP_REST_Request(
@ -393,7 +393,7 @@ class TAINACAN_REST_Visibilility_Controller extends TAINACAN_UnitApiTestCase {
$status = $response->status;
$data = $response->get_data();
$this->assertEquals(200, $status);
$this->assertEquals(1, sizeof($data));
$this->assertEquals(1, sizeof($data['items']));
}
public function test_get_items_not_logged() {
@ -415,7 +415,7 @@ class TAINACAN_REST_Visibilility_Controller extends TAINACAN_UnitApiTestCase {
$status = $response->status;
$data = $response->get_data();
$this->assertEquals(200, $status);
$this->assertEquals(1, sizeof($data));
$this->assertEquals(1, sizeof($data['items']));
//tax public - context=edit:
$request_public_edit = new \WP_REST_Request(

119
tests/test-entities.php Normal file
View File

@ -0,0 +1,119 @@
<?php
namespace Tainacan\Tests;
/**
* Class TestCollections
*
* @package Test_Tainacan
*/
/**
* Sample test case.
*/
class TestEntities extends TAINACAN_UnitTestCase {
function setUp() {
parent::setUp();
$this->collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste',
'description' => 'Filter teste colletion'
),
true
);
$this->collection2 = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'teste2',
'description' => 'Filter teste colletion'
),
true
);
$this->filter = $this->tainacan_entity_factory->create_entity(
'filter',
array(
'name' => 'filtro',
'collection' => $this->collection,
'description' => 'Teste Filtro'
),
true
);
$this->item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem',
'collection' => $this->collection,
),
true
);
$this->id_filter = $this->filter->get_id();
$this->id_collection = $this->collection->get_id();
$this->post_filter = get_post($this->filter->get_id());
$this->post_collection = get_post($this->collection->get_id());
}
public function test_construct_with_id() {
$test_filter = new \Tainacan\Entities\Filter( $this->id_filter );
$this->assertTrue( $test_filter instanceof \Tainacan\Entities\Filter );
}
public function test_contruct_with_post() {
$new_test_filter = new \Tainacan\Entities\Filter( $this->post_filter );
$this->assertTrue( $new_test_filter instanceof \Tainacan\Entities\Filter );
}
public function test_construct_with_wrong_id() {
$this->expectException(\Exception::class);
$test_wrong = new \Tainacan\Entities\Filter( $this->id_collection );
}
public function test_construct_with_wrong_post() {
$this->expectException(\Exception::class);
$test_wrong = new \Tainacan\Entities\Filter( $this->post_collection );
}
public function test_contruct_item() {
$item = new \Tainacan\Entities\Item( $this->item->get_id() );
$this->assertTrue( $item instanceof \Tainacan\Entities\Item );
$this->assertEquals( $item->get_collection_id(), $this->id_collection );
}
public function test_contruct_wrong_item() {
$this->expectException(\Exception::class);
$item = new \Tainacan\Entities\Item( $this->collection2->get_id() );
}
}

View File

@ -2,7 +2,6 @@
namespace Tainacan\Tests;
use Tainacan\Importer;
use Tainacan\Entities;
/**
* Class Importer
*

View File

@ -379,4 +379,39 @@ class Items extends TAINACAN_UnitTestCase {
$this->assertFalse(comments_open($item->get_id()));
}
public function test_delete_item() {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'collectionComments',
'allow_comments' => 'closed'
),
true,
true
);
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'itemComments1',
'collection' => $collection,
'comment_status' => 'open'
),
true,
true
);
$item_id = $item->get_id();
$items = \Tainacan\Repositories\Items::get_instance();
$items->delete($item_id);
$fetch_item = $items->fetch($item_id);
$this->assertEmpty($fetch_item);
}
}