How do I get Elementor's custom query filter to work with both GET and pagination? - elementor

I am trying to make a custom filter for the loop grid in Elementor, and am having an issue. This code lists the items as they should be listed.
function my_query_by_filter( $query ) {
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
$floorplans = '93';
//$floorplans = $_GET['floorplans'];
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
While this code only shows correctly for the first page when using pagination.
function my_query_by_filter( $query ) {
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
//$floorplans = '93';
$floorplans = $_GET['floorplans'];
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
Please also note that this is a simplification of the code to hilight the issue. My actual code looks like this.
function my_query_by_filter( $query ) {
$start_time = hrtime(false);
// Get current meta Query
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
global $wpdb;
//filter based on city
$city = $_GET['city'];
echo '<script>console.log("city: ' . $city . '");</script>';
$floorplans = array();
$layouts = $wpdb->get_results('SELECT term_id FROM wp_termmeta INNER JOIN wp_postmeta ON wp_termmeta.meta_value=wp_postmeta.post_id WHERE wp_postmeta.meta_key="city" AND wp_postmeta.meta_value="' . $city . '" GROUP BY term_id', ARRAY_N);//returns each layout //I will take care of security flaws later
foreach($layouts as $layout) {
$floorplans[] = '' . $layout[0];
}
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
$end_time = hrtime(false);
$execution_time = ($end_time[1] - $start_time[1]);
echo '<script>console.log("Query took ' . $execution_time . ' nanoseconds to execute");</script>';
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
I am using Elementor Pro and Pods Admin, along with code snippets.
I have tried setting both global and static variables, along with everything that I can think of, but nothing has worked so far. If there is a better technique to do this, I am open to hearing about it. I just need the user to be able to filter.

Related

register_graphql_field returning null values

I am trying to return values from a query that is only returning null values or is giving me errors based upon everything that I have tried. I have created a WP Plugin to put this code. I have pasted my code below
I have edited this code to what is currently working, but it is only giving me that last entry in the DB table. How would I get them all to display
function register_contact_form_fields() {
register_graphql_field( 'RootQuery', 'contactForm', [
'description' => __( 'Get a user submission', 'codmoncai-contact' ),
'type' => 'ContactForm',
'resolve' => function( $root, $args, $context, $info ) {
global $wpdb;
$combined_data = [];
$results = $wpdb->get_results("SELECT * FROM wpxd_contact_us");
}
return $data;
] );
}
By changing the 'type' in the register_graphql_field function to
'type' => [ 'list_of' => 'ContactForm' ],
Fixed my issue and allowed me to get all rows in the query

Merge multiple ACF variables in one array

I'm using ACF relationship fields. I'm displaying multiple hand selected posts blocks. There is a last posts block where I want to exclude all the hand selected ones before.
How do I make an array of all ACF's to select them to exclude them from the loop?
This is my code so far (not working, it works if I only use one variable)
<?php
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
$excluirtodo = array (
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => $excluirtodo
);
$the_query = new WP_Query( $args );
?>
EDIT [SOLVED]: as #disinfor pointed on the comments the solution was array_merge instead of array
Adding my answer from the comments to help future visitors
You are currently passing an array of arrays to the post__not_in. You need to use array_merge to combine the arrays into a single array.
<?php
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
// NEW CODE HERE
$excluirtodo = array_merge(
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
// END ARRAY_MERGE
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => $excluirtodo
);
$the_query = new WP_Query( $args );
?>
It seems to me a bad method to call 5 ACF fields and then combine them into an array at the time the page is built.
For me, this method is better:
1. Create a text AСF field - hide_excluir
2. Add filter in functions.php (When editing our page, all ACF fields with exceptions will be merged into an array and saved in the field that we created before).
add_filter('acf/save_post', 'excluir_post_filter', 20);
function excluir_post_filter($post_id) {
if ( $post_id != 2 ) //Change to your page ID (or if you need use post type or page template, need modify)
return;
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
$all_excluir = array_merge(
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
update_post_meta($post_id, 'hide_excluir', $all_excluir ); //Save array to our field
}
3. We use our field with get_post_meta
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => get_post_meta( $post->ID, 'hide_excluir', true ) //Get our field with post array
);
$the_query = new WP_Query( $args );
For testing methods, you can install the Query Monitor plugin and see the difference in the number of queries to the database.

No Response Through facebook api tag code

i am using this array for tag friends in a photo but no one is tagged , help me if i wrong.
$tags = array(
"tag_uid" => $id,
"tag_text" => $name,
"x" => 20,
"y" => 20
);
$facebook->api('/' . $new . '/tags?','post', array( $tags ));
this is because you are not doing the correct tags arrays. Try the following codes:
// Set tags limit
$f1 = $facebook->api('me/friends?limit=10');
// Get access token
$access_token = $facebook->getAccessToken();
// First post photo and then tag id
$post_photo = $facebook->api('/me/photos', 'POST', array(
'source' => '#' . $photo,
'message' => $message
)
);
// Creating Tags arrays for Tagging in the photo
foreach($f1['data'] as $fbu){
$tagx = array('tag_uid' => $fbu['id'],'x' => 30,'y' => 30 );
$ftags[] = $tagx;
}
// Tags generated now giving variable
$tagargs = array (
'tags' => json_encode($ftags),
'access_token' => $access_token,
);
// Posting the tags in photo
$result = $facebook->api('/' . $post_photo['id'] . '/tags', 'post', $tagargs);

CakePHP Pagination: how can I sort by multiple columns to achieve "sticky" functionality?

I see that this paginate can't sort two columns at the same time ticket is still open, which leads me to believe that what I'm trying to do is not possible without a workaround. So I guess what I'm looking for is a workaround.
I'm trying to do what many message boards do: have a "sticky" function. I'd like to make it so that no matter which table header link the user clicks on to sort, my model's "sticky" field is always the first thing sorted, followed by whatever column the user clicked on. I know that you can set $this->paginate['Model']['order'] to whatever you want, so you could hack it to put the "sticky" field first and the user's chosen column second. The problem with this method is that pagination doesn't behave properly after you do it. The table header links don't work right and switching pages doesn't work right either. Is there some other workaround?
User ten1 on the CakePHP IRC channel helped me find the solution. I told him that if he posted the answer here then I would mark it as the correct one, but he said I should do it myself since he doesn't have a Stack Overflow account yet.
The trick is to inject the "sticky" field into the query's "order" setting using the model's "beforeFind" callback method, like this:
public function beforeFind($queryData) {
$sticky = array('Model.sticky' => 'DESC');
if (is_array($queryData['order'][0])) {
$queryData['order'][0] = $sticky + $queryData['order'][0];
}
else {
$queryData['order'][0] = $sticky;
}
return $queryData;
}
What you can do is code it in the action. Just create the query you want when some parameters exist on the URL. (parameters has to be sent by GET)
For example:
public function posts(){
$optional= array();
if(!empty($this->params->query['status'])){
if(strlower($this->params->query['status']=='des')){
$optional= array('Post.status DESC');
}
else if(strlower($this->params->query['status']=='asc')){
$optional= array('Post.status ASC');
}
}
if(!empty($this->params->query['department'])){
//same...
}
//order first by the sticky field and then by the optional parameters.
$order = array('Post.stickyField DESC') + $optional;
$this->paginate = array(
'conditions' => $conditions,
'order' => $order,
'paramType' => 'querystring',
);
$this->set('posts', $this->paginate('Post'));
}
I have used something similar to filter some data using $conditions instead of $order and it works well.
You can use custom field for sorting and update pagination component.
Controller code
$order['Document.DATE'] = 'asc';
$this->paginate = array(
"conditions"=> $conditions ,
"order" => $order ,
"limit" => 10,
**"sortcustom" => array('field' =>'Document.DATE' , 'direction' =>'desc'),**
);
Changes in pagination component.
public function validateSort($object, $options, $whitelist = array()) {
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
if ($direction != 'asc' && $direction != 'desc') {
$direction = 'asc';
}
$options['order'] = array($options['sort'] => $direction);
}
if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) {
$field = key($options['order']);
if (!in_array($field, $whitelist)) {
$options['order'] = null;
}
}
if (!empty($options['order']) && is_array($options['order'])) {
$order = array();
foreach ($options['order'] as $key => $value) {
$field = $key;
$alias = $object->alias;
if (strpos($key, '.') !== false) {
list($alias, $field) = explode('.', $key);
}
if ($object->hasField($field)) {
$order[$alias . '.' . $field] = $value;
} elseif ($object->hasField($key, true)) {
$order[$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
$order[$alias . '.' . $field] = $value;
}
}
**if(count($options['sortcustom']) > 0 )
{
$order[$options['sortcustom']['field']] = $options['sortcustom']['direction'];
}**
$options['order'] = $order;
}
return $options;
}
Easy insert 'paramType' => 'querystring',
Show Code Example:
$this->paginate = array(
'conditions' => $conditions,
'order' => array(
'Post.name' => 'ASC',
'Post.created' => 'DESC',
),
'paramType' => 'querystring',
);
$this->set('posts', $this->paginate('Post'));

CakePHP find conditions not working

I have an action for CommentsView in which i want to retrieve all the comments with a condition that Comment.post_id = Post.id but when i debug it, it gives me an empty array.
Action CommentsView:
public function commentsview()
{
$commentsview = $this->Comment->find('all', array('conditions'=>array('Comment.post_id' => 'Post.id')));
if (!empty($this->params['requested']))
{
return $commentsview;
}
}
You are providing the condition for a join which is passed differently.
The conditions arguments are for a WHERE clause.
But you only need to specify:
$comments = $this->Comment->find('all',
array(
'conditions'=>array(
'Comment.post_id' => $post_id
)
)
);
Or when you are fetching the comments from the PostsController
$comments = $this->Post->Comment->find('all',
array(
'fields'=>array(
'Comment.*'
)
'conditions'=>array(
'Post.id' => $post_id
)
)
);
change your function to this:
public function commentsview($post_id=null) {
$commentsview = $this->Comment->find('all', array('conditions'=>
array('Comment.post_id' => $post_id))
);
debug($commentsview);
exit;
}
Visit this URL: yourapp.com/comments/commentsview/37
The comments will be output. Now you know it's working. Then you can pass it to the view or do whatever.
You have asked similar questions several times. This is a BASIC concept.

Resources