Form submissions loop query on Bricks Builder
How to create a loop query for form submissions on Bricks Builder ?
Firstly, I will suggest reading the article from the brickslabs.com: “Adding any Custom WP_Query loop to Bricks’ Query Loop”
After you have read this article, we can continue:
Introduction
- We will add a new query type control:
- The “add_filter” function is used to modify the query options in Bricks.
- The “ntamas_setup_query_controls” function is hooked into the bricks/setup/control_options filter.
- It adds a new option called “Bricks Form Submissions Query” to the query type dropdown.
- We will add custom extra query controls:
- The add_action function is used to hook the ntamas_add_control_to_elements function to the WordPress init action. This means that when WordPress initializes, the “ntamas_add_control_to_elements” function will be executed.
- The “ntamas_add_controls will wrap all the custom” controls that we need (such as: Form ID, and Query Limit).
- We will be running a new query and return data:
- The “ntamas_maybe_run_new_query” function is hooked into the bricks/query/run filter.
- It checks if the selected query type is “bricks_form_submissions_query”.
- If so, it runs a custom database query with the form ID with specific data (page number, query limit).
- Format data and add to an object.
- Return object.
- We will create a custom echo get function to display form columns:
- The “get_value_from_form_by_key” function is designed to retrieve a specific value from a form based on a given key.
- The key (or field name) for which you want to retrieve the value. By default, it’s set to “name” if no specific key is provided
- Last step: How to use all of this on Bricks builder.
- Create some extra things like pagination custom Bricks element and custom PHP filter
Step #1
In the following snippet, we add a query type control to the query options:
add_filter( 'bricks/setup/control_options', 'ntamas_setup_query_controls');
function ntamas_setup_query_controls( $control_options ) {
$control_options['queryTypes']['bricks_form_submissions_query'] = esc_html__( 'Bricks Form Submissions Query' );
return $control_options;
};
You can change my prefix “ntamas” with your prefix. This step is simple, so I will not explain it.
Step #2
On the second step, we will add custom extra query controls because we need to pass the form ID every time we create a new loop. Also, we need to add a default limit to query:
add_action( 'init', 'ntamas_add_control_to_elements', 40 );
function ntamas_add_control_to_elements() {
// Only container, block and div element have query controls
$elements = [ 'container', 'block', 'div' ];
foreach ( $elements as $name ) {
add_filter( "bricks/elements/{$name}/controls", 'ntamas_add_controls', 40 );
}
}
function ntamas_add_controls( $controls ) {
$my_controls = [
'bricks_form_submissions_query_form_id' => [
'tab' => 'content',
'label' => esc_html__( 'Form ID', 'bricks' ),
'type' => 'text',
'inline' => true,
'rerender' => true,
'description' => esc_html__( 'Unique Form ID', 'bricks' ),
'required' => array(
[ 'query.objectType', '=', 'bricks_form_submissions_query' ],
),
],
'bricks_form_submissions_query_form_limit' => [
'tab' => 'content',
'label' => esc_html__( 'Query Limit', 'bricks' ),
'type' => 'number',
'min' => 5,
'units' => false,
'inline' => true,
'default' => 5,
'rerender' => true,
'required' => array(
[ 'query.objectType', '=', 'bricks_form_submissions_query' ],
),
]
];
// Below 2 lines is just some php array functions to force my new control located after the query control
$query_key_index = absint( array_search( 'query', array_keys( $controls ) ) );
$new_controls = array_slice( $controls, 0, $query_key_index + 1, true ) + $my_controls + array_slice( $controls, $query_key_index + 1, null, true );
return $new_controls;
}
These snippets have 5 important subjects to cover:
- The “add_action” function is used to hook a callback function “ntamas_add_control_to_elements” to the WordPress initialization process (init). The priority of 40 ensures that this action runs after other actions with lower priorities.
- Inside “ntamas_add_control_to_elements”, an array called “$elements” contains the names of elements (such as ‘container’, ‘block’, and ‘div’) that will have query controls added to them.
- A “foreach” loop iterates through each element name in “$elements”. For each element, it adds a filter to modify the controls for that element type. The filter is hooked to “bricks/elements/{$name}/controls” and calls the “ntamas_add_controls function”.
- The “ntamas_add_controls” function defines two custom controls:
- “bricks_form_submissions_query_form_id”: This control is for specifying a unique form ID. It’s a text input field located in the ‘content’ tab. It’s required only when the query object type is “bricks_form_submissions_query”.
- “bricks_form_submissions_query_form_limit”: This control sets the query limit (a number input field). It has a minimum value of 5, no units, and a default value of 5. Like the previous control, it’s required for the same query object type.
- The last lines of the “ntamas_add_controls” function rearrange the controls array to ensure that the new controls appear after the existing query control.
Step #3
After all the important previous steps, we can finally continue with query the Bricks submissions table from WordPress database:
add_filter( 'bricks/query/run', 'ntamas_maybe_run_new_query', 10, 2);
function ntamas_maybe_run_new_query( $results, $query_obj ) {
if ( $query_obj->object_type !== 'bricks_form_submissions_query' ) {
return $results;
}
$settings = $query_obj->settings;
$form_id = $settings['bricks_form_submissions_query_form_id'];
$page = isset($_GET['content_page']) ? $_GET['content_page'] : '1';
$default_limit = isset($settings['bricks_form_submissions_query_form_limit']) ? $settings['bricks_form_submissions_query_form_limit'] : '5';
$limit = isset($_GET['limit']) ? $_GET['limit'] : $default_limit;
if(isset($form_id)){
global $wpdb;
$table_name = $wpdb->prefix . 'bricks_form_submissions';
$count_query = $wpdb->prepare("SELECT COUNT(form_data) FROM $table_name WHERE form_id = %s", $form_id);
$rows_num = $wpdb->get_var($count_query);
if((int)$rows_num<1){
$output .= '<div class="ntamas_no_results">No results found as there are no allocations yet</div>';
echo "<script>console.log('No results found as there are no allocations yet')</script>";
}
else{
$output=array();
$offset = (((int)$page - 1)*(int)$limit);
$query = $wpdb->prepare("SELECT form_data FROM $table_name WHERE form_id = %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", $form_id, $offset,$limit);
$queryResults = $wpdb->get_results($query);
foreach ($queryResults as $row) {
$obj = json_decode(implode(', ', (array)$row),true);
$output[] = $obj;
}
return $output;
}
}
return $results;
};
So let’s move on to explain everything:
- The code snippet is a WordPress filter hook that modifies the behavior of a query in the context of Bricks.
- The filter hook is named “bricks/query/run”, and it accepts two parameters: “$results” (the existing query results) and “$query_obj” (the query object).
- The purpose of this filter is to conditionally run a new query for form submissions when certain conditions are met.
Here’s what the code does step by step:
- It checks whether the query object’s “object_type” is “bricks_form_submissions_query”. If not, it returns the original results unchanged.
- If the query object is related to form submissions, it proceeds with additional logic.
- It retrieves settings from the query object, including the form ID and pagination-related parameters.
- Next, it checks if the form ID is set. If not, it doesn’t perform any further actions.
- If the form ID is set, it interacts with the WordPress database using “$wpdb” (WordPress Database API).
- It calculates the total number of form submissions for the specified form ID.
- If there are no submissions (“$rows_num < 1”), it generates a message indicating that no results were found.
- Otherwise, it calculates the offset for pagination based on the current page and limit.
- It constructs a SQL query to retrieve form data for the specified form ID, applying pagination.
- The retrieved form data is decoded from JSON and added to the output array.
- Finally, the modified results (either the original results or the form submission data) are returned.
Step #4
On this step, we will create a custom echo get function to display form columns:
function get_value_from_form_by_key($key="name"){
$loop_object = \Bricks\Query::get_loop_object();
if(! $loop_object) return false;
if(! is_array($loop_object)) return false;
if(! array_key_exists($key,$loop_object)) return false;
if(isset($loop_object[$key])){
$val=$loop_object[$key]["value"];
if(! is_string($val)){
$val=$loop_object[$key]["value"][0];
}
return $val;
}
else{
return "NA";
}
}
Explanation:
- The function is named “get_value_from_form_by_key”.
- It accepts an optional parameter “$key”, which defaults to “name”.
- It starts by getting the loop object using “\Bricks\Query::get_loop_object()”.
- If the loop object is not available (“$loop_object” is falsy), the function returns “false”.
- Next, it checks if the loop object is an array. If not, it also returns “false”.
- Then, it verifies if the specified key exists in the loop object. If not, it returns “false”.
- If the key exists, it retrieves the value associated with that key. If the value is not a string, it assumes an array and retrieves the first element.
- Finally, if the key doesn’t exist, it returns the string “NA”.
Step #5
Finaly we can use all of the codes that we have create to build our table.
1. On the first screenshot, I have created with table structure Bricks.
As you can see we have created all the necessary elements (table, thead, th, tbody, tr etc.):
- On every th we have the form titles.
- The “tr” have the custom query options that we have create.
- On every td we have the custom echo function with specific form filed ID as a key.
2. On the second and third screenshot, we have the tr loop query settings:
On this screenshot, you can see the custom option we have added on step #2 (Form ID and Query Limit)
3. On the second and third screenshot, we have the td loop query settings:
Every td has different filed ID on echo function based on with form filed value we want to echo.
And that’s all about the form submissions.
Now if you want to create a limit controller filed or a pagination follow the see the codes below.
(I will not explain all of this because it’s not for this topic)
1. How to create a limit controller filed. Above the table (see screenshot 1) we put a Bricks builder custom code element and paste the following code:
<?php
$limit = isset($_GET['limit'])?$_GET['limit']:"10";
?>
<div class="ntamas_filters">
<form class="ntamas_filter_limit" action="" method="get">
<label for="limit">Change of limit</label>
<input value=<?php echo $limit ?> type="number" id="limit" name="limit" min="5" max="50">
<input type="submit" id="submit_button" value="Apply">
</form>
</div>
You must put the default value the same as the loop query setting (Query limit) in our example “10”
2. How to create a Bricks builder custom element (in our example pagination element).
We have to go on themes>Bricks Child Theme>elements and create a file pagination_bricks_form_submissions.php with the following code:
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
class Prefix_Element_Test extends \Bricks\Element {
// Element properties
public $category = 'general'; // Use predefined element category 'general'
public $name = 'ntamas-pagination'; // Make sure to prefix your elements
public $icon = 'fa-solid fa-angles-right';
public $css_selector = '.ntamas-pagination-wrapper'; // Default CSS selector
public $scripts = ['prefixElementTest']; // Script(s) run when element is rendered on frontend or updated in builder
// Return localised element label
public function get_label() {
return esc_html__( 'Pagination Bricks Form Submissions', 'bricks' );
}
// Set builder controls
public function set_controls() {
$this->controls['ntamas_pagination_form_id'] = [ // Unique control identifier (lowercase, no spaces)
'tab' => 'content',
'label' => esc_html__( 'Form ID', 'bricks' ),
'type' => 'text',
'description' => esc_html__( 'Unique Form ID', 'bricks' ),
'inline' => true,
];
$this->controls['ntamas_pagination_form_limit'] = [ // Unique control identifier (lowercase, no spaces)
'tab' => 'content',
'label' => esc_html__( 'Query Limit', 'bricks' ),
'description' => esc_html__( 'Please put the limit of the loop above', 'bricks' ),
'type' => 'number',
'min' => 5,
'units' => false,
'inline' => true,
'default' => 5,
];
}
// Enqueue element styles and scripts
public function enqueue_scripts() {
wp_enqueue_script( 'ntamas-pagination-script' );
}
// Render element HTML
public function render() {
// Set element attributes
$root_classes[] = 'ntamas-pagination-wrapper';
// Add 'class' attribute to element root tag
$this->set_attribute( '_root', 'class', $root_classes );
if(empty($this->settings['ntamas_pagination_form_id'])){
echo "Please provide Form Id";
return false;
}
$output = "";
$form_id=$this->settings['ntamas_pagination_form_id'];
global $wpdb;
$table_name = $wpdb->prefix . 'bricks_form_submissions';
$count_query = $wpdb->prepare("SELECT COUNT(form_data) FROM $table_name WHERE form_id = %s", $form_id);
$rows_num = $wpdb->get_var($count_query);
if((int)$rows_num<1){
$output = '<div class="ntamas_no_results">No results found as there are no allocations yet</div>';
}
else{
$default_limit = isset($this->settings['ntamas_pagination_form_limit']) ? $this->settings['ntamas_pagination_form_limit'] : '5';
$limit = isset($_GET['limit']) ? $_GET['limit'] : $default_limit;
$content_page = isset($_GET['content_page']) ? $_GET['content_page'] : "1";
$paginations = ceil((int)$rows_num/(int)$limit);
$output .="<div {$this->render_attributes( '_root' )}>";
if($paginations>1){
for ($i = 1; $i <= $paginations; $i++) {
$curent=(int)$content_page==$i?"current":"not";
$output .='<a href="?limit='.(int)$limit.'&content_page='.$i.'" class="pagination_button pagination_button_'.$i.' '.$curent.'">'.$i.'</a>';
}
}
$output .='</div>';
}
echo $output;
}
}
After that, we can use the custom Bricks element below the table. On the screenshot below, you will see the settings of the custom element that we have created:
You must put the default value the same as the loop query setting (Query limit) in our example “10”
That’s it!!!
Thanks for following on this topic. I hope that it was helpful after all!
If you like it, share it with: