-
-
Save wpeasy/9ec1dfbe8411dd56657a0eca920552ef to your computer and use it in GitHub Desktop.
<?php | |
define("WPE_JSON_TRANSIENT_NAME", "wpe_dummyjson"); | |
define("WPE_JSON_TRANSIENT_TTL", 60); | |
define("WPE_JSON_ENDPOINT_BASE", "https://dummyjson.com/"); | |
/** Add query type to dropdown */ | |
add_filter("bricks/setup/control_options", function ($control_options) { | |
// Add a new query loop type | |
$control_options["queryTypes"]["wpe_json"] = esc_html__( | |
"DummyJSON", | |
"bricks" | |
); | |
return $control_options; | |
}); | |
/* Add controls to the query when selected */ | |
add_action( | |
"init", | |
function () { | |
// Only container, block and div element have query controls | |
$elements = ["container", "block", "div"]; | |
foreach ($elements as $name) { | |
add_filter( | |
"bricks/elements/{$name}/controls", | |
function ($controls) { | |
// Define the new controls | |
$new_controls = [ | |
"wpe_action" => [ | |
"tab" => "content", | |
"label" => esc_html__("Action", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Enter Action part of URL", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_json"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
"wpe_result_path" => [ | |
"tab" => "content", | |
"label" => esc_html__("Result Path", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Array Path to result", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_json"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
]; | |
return wpe_move_controls_to_after_query( | |
$controls, | |
$new_controls | |
); | |
}, | |
40 | |
); | |
} | |
}, | |
40 | |
); | |
/* Run the query */ | |
add_filter( | |
"bricks/query/run", | |
function ($results, $query_obj) { | |
// Only target if query type set is je_qb | |
if ($query_obj->object_type !== "wpe_json") { | |
return $results; | |
} | |
$settings = $query_obj->settings; | |
$action = isset($settings["wpe_action"]) ? $settings["wpe_action"] : ''; | |
// Return empty results if no query selected or Use Query is not checked | |
if (empty($action)) { | |
return []; | |
} | |
// Get the results | |
$result = wpe_dummy_json_get($action); | |
if (empty($settings["wpe_result_path"])) { | |
return $result; | |
} | |
$wanted_array = wpe_get_deep_array_dot_notation( | |
$result, | |
[ | |
'key_path' => $settings["wpe_result_path"] | |
] | |
); | |
//wpe_bugfu_if_active($wanted_array, __FUNCTION__); | |
return $wanted_array; | |
}, | |
10, | |
2 | |
); | |
/*##################################### | |
GENERIC GET FROM https://dummyjson.com/ | |
#####################################*/ | |
function wpe_dummy_json_get($action) | |
{ | |
$transient_uid = WPE_JSON_TRANSIENT_NAME . "_" . md5($action); | |
/* Add some caching to speed things up */ | |
$result = get_transient($transient_uid); | |
if ($result) { | |
wpe_bugfu_if_active( | |
"Got from Transient: " . $transient_uid, | |
__FUNCTION__ | |
); | |
//wpe_bugfu_if_active($result); | |
return $result; | |
} | |
// API Endpoint | |
$endpoint = WPE_JSON_ENDPOINT_BASE . $action; | |
// Make the HTTP request using wp_remote_get | |
$response = wp_remote_get($endpoint); | |
// Check for errors | |
if (is_wp_error($response) || $response["response"]["code"] !== 200) { | |
delete_transient($transient_uid); | |
wpe_bugfu_if_active("Error", __FUNCTION__); | |
return [ | |
"posts" => [ | |
[ | |
"title" => "Error fetching from. code " .$response["response"]["code"] , | |
], | |
], | |
]; // Return an empty array if there's an error | |
} | |
$result = json_decode(wp_remote_retrieve_body($response), true); | |
set_transient($transient_uid, $result, WPE_JSON_TRANSIENT_TTL); | |
wpe_bugfu_if_active("Got from API", __FUNCTION__); | |
return $result; | |
} |
<?php | |
define("WPE_GR_TRANSIENT_NAME", "wpe_google_reviews"); | |
define("WPE_GR_TRANSIENT_TTL", HOUR_IN_SECONDS ); | |
/** Add query type to dropdown */ | |
add_filter("bricks/setup/control_options", function ($control_options) { | |
// Add a new query loop type | |
$control_options["queryTypes"]["wpe_gr"] = esc_html__( | |
"Google Reviews", | |
"bricks" | |
); | |
return $control_options; | |
}); | |
/* Add controls to the query when selected */ | |
add_action( | |
"init", | |
function () { | |
// Only container, block and div element have query controls | |
$elements = ["container", "block", "div"]; | |
foreach ($elements as $name) { | |
add_filter( | |
"bricks/elements/{$name}/controls", | |
function ($controls) { | |
// Define the new controls | |
$new_controls = [ | |
"wpe_places_id" => [ | |
"tab" => "content", | |
"label" => esc_html__("Places ID", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Enter Places ID", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_gr"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
"wpe_api_key" => [ | |
"tab" => "content", | |
"label" => esc_html__("API Key", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Enter API Key", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_gr"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
]; | |
return wpe_move_controls_to_after_query( | |
$controls, | |
$new_controls | |
); | |
}, | |
40 | |
); | |
} | |
}, | |
40 | |
); | |
/* Run the query */ | |
add_filter( | |
"bricks/query/run", | |
function ($results, $query_obj) { | |
// Only target if query type set is je_qb | |
if ($query_obj->object_type !== "wpe_gr") { | |
return $results; | |
} | |
$settings = $query_obj->settings; | |
$places_id = $settings["wpe_places_id"]; | |
$api_key = $settings["wpe_api_key"]; | |
// Return empty results if no query selected or Use Query is not checked | |
if ( | |
strlen($places_id) < 10 || | |
strlen($api_key) < 10 || | |
!$settings["hasLoop"] | |
) { | |
return []; | |
} | |
// Get the results | |
$result = wpe_fetch_google_details( | |
$places_id, | |
$api_key, | |
$fields = "name,reviews,rating" | |
); | |
if (isset($result["result"]["reviews"])) { | |
$result = $result["result"]["reviews"]; | |
} else { | |
$result = []; | |
} | |
//wpe_bugfu_if_active($result); | |
return $result; | |
}, | |
10, | |
2 | |
); | |
/********************** | |
Generic fetch reviews from Google API | |
**************************************/ | |
function wpe_fetch_google_details($places_id, $api_key, $fields) | |
{ | |
$transient_uid = WPE_GR_TRANSIENT_NAME . "_" . $places_id; | |
/* Add some caching to speed things up */ | |
$result = get_transient($transient_uid); | |
if ($result) { | |
wpe_bugfu_if_active( | |
[ | |
"message" => "Got from Transient: " . $transient_uid, | |
"data" => $result, | |
], | |
__FUNCTION__ | |
); | |
return $result; | |
} | |
// API Endpoint | |
$endpoint = "https://maps.googleapis.com/maps/api/place/details/json"; | |
// API Parameters | |
$params = [ | |
"place_id" => $places_id, | |
"fields" => $fields, | |
"key" => $api_key, | |
]; | |
// Build the URL with query parameters | |
$url = add_query_arg($params, $endpoint); | |
// Make the HTTP request using wp_remote_get | |
$response = wp_remote_get($url); | |
// Check for errors | |
if (is_wp_error($response) || $response["response"]["code"] !== 200) { | |
delete_transient($transient_uid); | |
wpe_bugfu_if_active("Error", __FUNCTION__); | |
return [ | |
"result" => [ | |
"reviews" => [ | |
"author_name" => | |
"Error fetching from " . $url . " : code -" . $response["response"]["code"], | |
] | |
], | |
]; // Return an empty array if there's an error | |
} | |
$result = json_decode(wp_remote_retrieve_body($response), true); | |
set_transient($transient_uid, $result, WPE_GR_TRANSIENT_TTL); | |
wpe_bugfu_if_active("Got from API", __FUNCTION__); | |
return $result; | |
} |
<?php | |
define("WPE_GOOGLE_SHEET_TRANSIENT_NAME", "wpe_google_sheets"); | |
define("WPE_GOOGLE_SHEET_TRANSIENT_TTL", 15); | |
define("WPE_GOOGLE_SHEET_AUTH_TRANSIENT_NAME", "wpe_google_sheets_auth"); | |
define("WPE_GOOGLE_SHEET__AUTH_TRANSIENT_TTL", 3600); | |
/** Add query type to dropdown */ | |
add_filter("bricks/setup/control_options", function ($control_options) { | |
// Add a new query loop type | |
$control_options["queryTypes"]["wpe_google_sheet"] = esc_html__( | |
"Google Sheet", | |
"bricks" | |
); | |
return $control_options; | |
}); | |
/* Add controls to the query when selected */ | |
add_action( | |
"init", | |
function () { | |
// Only container, block and div element have query controls | |
$elements = ["container", "block", "div"]; | |
foreach ($elements as $name) { | |
add_filter( | |
"bricks/elements/{$name}/controls", | |
function ($controls) { | |
// Define the new controls | |
$new_controls = [ | |
"wpe_sheet_id" => [ | |
"tab" => "content", | |
"label" => esc_html__("Sheet ID", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Your Google Sheet ID", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_google_sheet"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
"wpe_sheet_range" => [ | |
"tab" => "content", | |
"label" => esc_html__("Sheet Range", "bricks"), | |
"type" => "text", | |
"placeholder" => esc_html__( | |
"Your Google Sheet Range", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_google_sheet"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
"wpe_json_key" => [ | |
"tab" => "content", | |
"label" => esc_html__("JSON Key", "bricks"), | |
"type" => "textarea", | |
"placeholder" => esc_html__( | |
"Generated JSON Key", | |
"bricks" | |
), | |
"required" => [ | |
["query.objectType", "=", "wpe_google_sheet"], | |
["hasLoop", "!=", false], | |
], | |
"spellcheck" => false, | |
], | |
]; | |
return wpe_move_controls_to_after_query( | |
$controls, | |
$new_controls | |
); | |
}, | |
40 | |
); | |
} | |
}, | |
40 | |
); | |
/* Run the query */ | |
add_filter( | |
"bricks/query/run", | |
function ($results, $query_obj) { | |
// Only target if query type set is je_qb | |
if ($query_obj->object_type !== "wpe_google_sheet") { | |
return $results; | |
} | |
$settings = $query_obj->settings; | |
// Return empty results if no query selected or Use Query is not checked | |
if (empty($settings["wpe_sheet_id"])) { | |
return []; | |
} | |
if (empty($settings["wpe_sheet_range"])) { | |
return []; | |
} | |
if (empty($settings["wpe_json_key"])) { | |
return []; | |
} | |
// Get the results | |
$result = wpe_get_google_sheet( | |
$settings["wpe_sheet_id"], | |
$settings["wpe_sheet_range"], | |
$settings["wpe_json_key"] | |
); | |
if (empty($settings["wpe_result_path"])) { | |
return $result; | |
} | |
$wanted_array = wpe_get_deep_array_dot_notation( | |
$result, | |
[ | |
'key_path' => $settings["wpe_result_path"] | |
] | |
); | |
//wpe_bugfu_if_active($wanted_array, __FUNCTION__); | |
return $wanted_array; | |
}, | |
10, | |
2 | |
); | |
/*##################################### | |
GENERIC GET FROM Google | |
#####################################*/ | |
function wpe_get_google_sheet( $sheet_id, $sheet_range, $json_key ) | |
{ | |
/******* | |
Get Authentication and store as a JWT | |
*******/ | |
$service_account = (array)json_decode($json_key); | |
/* Add some caching to speed things up */ | |
$auth_key = get_transient(WPE_GOOGLE_SHEET_AUTH_TRANSIENT_NAME); | |
if(!$auth_key){ | |
$auth_key = wpe_get_google_access_token($service_account); | |
if(is_wp_error($auth_key)){ | |
wpe_bugfu_if_active($auth_key, __FUNCTION__); | |
}else{ | |
set_transient(WPE_GOOGLE_SHEET_AUTH_TRANSIENT_NAME, $auth_key, WPE_GOOGLE_SHEET__AUTH_TRANSIENT_TTL); | |
} | |
} | |
/************ | |
Get the sheet and range | |
***********/ | |
$sheet_transient_id = WPE_GOOGLE_SHEET_TRANSIENT_NAME . md5($service_account['client_email'] . $sheet_id . $sheet_range); | |
/* Get from transient first */ | |
$result = get_transient($sheet_transient_id); | |
if ($result) { | |
wpe_bugfu_if_active( | |
"Got from Transient: " . $sheet_transient_id, | |
__FUNCTION__ | |
); | |
//wpe_bugfu_if_active($result); | |
return $result; | |
} | |
$result = wpe_get_google_sheet_fom_api( | |
$auth_key, | |
$sheet_id, | |
$sheet_range | |
); | |
if(!is_wp_error($result)){ | |
set_transient($sheet_transient_id, $result, WPE_GOOGLE_SHEET_TRANSIENT_TTL); | |
} | |
wpe_bugfu_if_active("Got from API", __FUNCTION__); | |
wpe_bugfu_if_active($result, __FUNCTION__); | |
return $result; | |
} | |
function wpe_get_google_access_token($service_account){ | |
// Prepare JWT header and claims | |
$header = base64_encode(json_encode(['alg' => 'RS256', 'typ' => 'JWT'])); | |
$now = time(); | |
$claims = base64_encode(json_encode([ | |
'iss' => $service_account['client_email'], | |
'scope' => 'https://www.googleapis.com/auth/spreadsheets.readonly', | |
'aud' => 'https://oauth2.googleapis.com/token', | |
'exp' => $now + WPE_GOOGLE_SHEET__AUTH_TRANSIENT_TTL, | |
'iat' => $now, | |
])); | |
// Create the JWT | |
$jwt = $header . '.' . $claims; | |
$signature = ''; | |
openssl_sign($jwt, $signature, $service_account['private_key'], 'SHA256'); | |
$jwt .= '.' . base64_encode($signature); | |
// Exchange the JWT for an access token | |
$response = wp_remote_post('https://oauth2.googleapis.com/token', [ | |
'body' => [ | |
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', | |
'assertion' => $jwt, | |
], | |
]); | |
if (is_wp_error($response)) { | |
return $response; | |
} | |
$body = json_decode(wp_remote_retrieve_body($response), true); | |
if (empty($body['access_token'])) { | |
return new WP_Error('Error fetching access token: Invalid response.'); | |
} | |
return $body['access_token']; | |
} | |
function wpe_get_google_sheet_fom_api($access_token, $sheet_id, $range){ | |
// Fetch data from the Google Sheet | |
$url = "https://sheets.googleapis.com/v4/spreadsheets/{$sheet_id}/values/{$range}"; | |
$response = wp_remote_get($url, [ | |
'headers' => [ | |
'Authorization' => "Bearer $access_token", | |
], | |
]); | |
if (is_wp_error($response)) { | |
return $response; | |
} | |
$sheet_data = json_decode(wp_remote_retrieve_body($response), true); | |
if (isset($sheet_data['values']) && count($sheet_data['values']) > 1) { | |
// Extract the headers (first row) | |
$headers = array_shift($sheet_data['values']); // Removes the first row and stores it as headers | |
// Map each subsequent row to the headers | |
$formatted_data = array_map(function ($row) use ($headers) { | |
return array_combine($headers, $row + array_fill(0, count($headers), null)); // Fill missing values with null | |
}, $sheet_data['values']); | |
return $formatted_data; | |
} | |
return new WP_Error('No data found or invalid API response.'); | |
} |
<?php | |
/*##################################### | |
COMMON FUNCTIONS FOR WP EASY CODE | |
#####################################*/ | |
/* BugFu wrapper so we don't generate errors if BugFu is disabled */ | |
define("WPE_DEBUG", true); | |
function wpe_bugfu_if_active($obj, $context = 'default') | |
{ | |
if (WPE_DEBUG && class_exists("BugFu")) { | |
BugFu::log( | |
[ | |
'context' => $context, | |
'data' => $obj | |
] | |
); | |
} | |
} | |
/*##################################### | |
DYNAMIC TAG TO DEEP ACCESS ARAY KEYS | |
#####################################*/ | |
/* | |
Example: {deep_array_from_loop @key_path:ingredients @is_indexed:false @formatter:callback_function @fallback:'Ingredients not found'} | |
The only required attribute is @key_path | |
If @is_indexed:true an HTML Ul is returned | |
If @formatter:callback_function , your formatting function is called | |
If @fallback is not speciied it has a default value | |
*/ | |
add_filter("bricks/dynamic_tags_list", function ($dynamic_tags) { | |
// Add a new dynamic tag for "Deep Array From Loop" | |
$dynamic_tags[] = [ | |
"name" => | |
"{deep_array_from_loop @key_path:path @is_indexed:false @formatter:callback_function @fallback='Fallback Text'}", // Unique name for the dynamic tag | |
"label" => esc_html__("Deep Array From Loop", "bricks"), | |
"group" => "WP Easy", | |
]; | |
return $dynamic_tags; | |
}); | |
add_filter( | |
"bricks/dynamic_data/render_content", | |
"wpe_render_deep_array_from_loop", | |
20, | |
3 | |
); | |
add_filter( | |
"bricks/frontend/render_data", | |
"wpe_render_deep_array_from_loop", | |
20, | |
2 | |
); | |
function wpe_render_deep_array_from_loop($content, $post, $context = "text") | |
{ | |
//wpe_bugfu_if_active($content); | |
// $content is the content of the element, including other dynamic tags, HTML, etc. | |
// Only look for content starts with {my_dd_tag: | |
if (strpos($content, "{deep_array_from_loop") === false) { | |
return $content; | |
} | |
// Regex to match my_dd_tag: tag | |
preg_match_all("/{(deep_array_from_loop[^}]+)}/", $content, $matches); | |
// Nothing grouped in the regex, return the original content | |
if (empty($matches[0])) { | |
return $content; | |
} | |
//wpe_bugfu_if_active($matches); | |
foreach ($matches[1] as $key => $match) { | |
$attribute_array = []; | |
$tag = $matches[0][$key]; | |
/* Arguments | |
Note: complex reex to allow for escaped, quoted and unquoted values | |
*/ | |
preg_match_all( | |
'/@(\w+):(?:\'((?:\\\\.|[^\'])*)\'|([^@\s]+))/', | |
$tag, | |
$attribute_matches | |
); | |
if (!empty($attribute_matches[1])) { | |
foreach ($attribute_matches[1] as $index => $key) { | |
// Check if the value is in single quotes or not | |
$value = !empty($attribute_matches[2][$index]) | |
? $attribute_matches[2][$index] | |
: $attribute_matches[3][$index]; | |
$attribute_array[$key] = trim($value); | |
} | |
} | |
if (isset($attribute_array["key_path"])) { | |
// Replace the tag with the transformed value | |
if (!isset($attribute_array["fallback"])) { | |
$attribute_array["fallback"] = | |
"Value not found in path: " . $attribute_array["key_path"]; | |
} | |
$content = str_replace( | |
$tag, | |
wpe_dot_notation_from_current_loop_object( | |
$attribute_array | |
), | |
$content | |
); | |
} | |
} | |
return $content; | |
} | |
/*##################################### | |
COMMIN UTILITIES | |
#####################################*/ | |
/* Pass in $controls to reorder teh array placing your conteols after "Query" */ | |
function wpe_move_controls_to_after_query($controls, $new_controls) | |
{ | |
// Locate the index of the 'query' control | |
$query_key_index = array_search("query", array_keys($controls), true); | |
if ($query_key_index !== false) { | |
// Insert the new controls after the 'query' control | |
$controls = | |
array_slice($controls, 0, $query_key_index + 1, true) + | |
$new_controls + | |
array_slice($controls, $query_key_index + 1, null, true); | |
} else { | |
// If 'query' control doesn't exist, append the new controls to the end | |
$controls += $new_controls; | |
} | |
return $controls; | |
} | |
/* Use dot notation to traverse an array form the current Query Object */ | |
function wpe_dot_notation_from_current_loop_object($attributes) { | |
return wpe_get_deep_array_dot_notation( | |
Bricks\Query::get_loop_object(), | |
$attributes | |
); | |
} | |
/* Use dot notation to traverse an array */ | |
function wpe_get_deep_array_dot_notation($source_array, $attributes = []) | |
{ | |
$key_path = isset($attributes['key_path'])? $attributes['key_path'] : ''; | |
$formatter = !empty($attributes["formatter"])? $attributes["formatter"] : null; | |
$is_indexed = isset($attributes["is_indexed"]) && $attributes["is_indexed"] == 'true'; | |
$fallback = isset($attributes["fallback"]) ? $attributes["fallback"]: "Keypath $key_path not found"; | |
$keys = explode(".", $key_path); | |
foreach ($keys as $key) { | |
if (is_array($source_array) && array_key_exists($key, $source_array)) { | |
$source_array = $source_array[$key]; | |
} else { | |
return $fallback; | |
} | |
} | |
if($formatter){ | |
return call_user_func($formatter, $source_array, $attributes); | |
} | |
if($is_indexed){ | |
return wpe_indexed_array_to_list($source_array, $attributes); | |
} | |
return $source_array; | |
} | |
function wpe_is_indexed_array($array) { | |
// Check if it's an array and all keys are numeric | |
return is_array($array) && array_keys($array) === range(0, count($array) - 1); | |
} | |
function wpe_indexed_array_to_list($array, $attributes, $type ='ul', $class_name='wpe-api-indexed-array'){ | |
if(!is_array($array)){ | |
return "Error: " . wpe_indexed_array_to_list . " $array is not an array"; | |
} | |
$is_indexed = wpe_is_indexed_array($array); | |
$block_class_name = $class_name . '-' . $type; | |
$aria_label = !empty($attributes['aria_label']) ? "aria-label=\"{$attributes['aria_label']}\"" : '' ; | |
$html = "<" . $type . " class=\"$block_class_name\" $aria_label>"; | |
foreach($array as $key=>$value){ | |
if($is_indexed ){ | |
$html.= "<li class=\"{$block_class_name}__li\" data-list-index=[$key]>$value</li>"; | |
} | |
} | |
$html.= '</' . $type . '>'; | |
return $html; | |
} | |
function wpe_test_formatter($array, $attributes){ | |
$block_class_name = 'wpe-test-formatter-test'; | |
$aria_label = !empty($attributes['aria_label']) ? "aria-label=\"{$attributes['aria_label']}\"" : '' ; | |
$data_puropse = !empty($attributes['data_purpose']) ? "data-purpose=\"{$attributes['data_purpose']}\"" : '' ; | |
$html = "<ol class=\"$block_class_name\" $aria_label $data_puropse >"; | |
foreach($array as $key=>$value){ | |
$html.= "<li class=\"{$block_class_name}__li\" data-list-index=[$key]>$value</li>"; | |
} | |
$html.= '</ol>'; | |
return $html; | |
} |
@wpeasy Thanks Alan! One more thing, seems it only works with single array, and it isn't build for sub-array keys when the api json output is a nested array. Would be nice if we could cater for that as well. It was very smooth using the deep array logic.
[
{
"id": "value",
"key": "value",
"key2": "value",
"bookmakers": [
{
"key": "value",
"keu": "value",
"last_update": "2025-01-06T18:45:43Z",
"key": [
{
"key": "value",
"last_update": "2025-01-06T18:45:43Z",
"key": [
{
"key": "value",
"key": 123
},
{
"key": "value",
"key": 123
}
]
}
]
}
]
}
]
@wpeasy Thanks Alan! One more thing, seems it only works with single array, and it isn't build for sub-array keys when the api json output is a nested array. Would be nice if we could cater for that as well. It was very smooth using the deep array logic.
[ { "id": "value", "key": "value", "key2": "value", "bookmakers": [ { "key": "value", "keu": "value", "last_update": "2025-01-06T18:45:43Z", "key": [ { "key": "value", "last_update": "2025-01-06T18:45:43Z", "key": [ { "key": "value", "key": 123 }, { "key": "value", "key": 123 } ] } ] } ] } ]
Ah OK, that would be an indexed Sub Array. You would need to either create another dynamic tag or a function to use with {echo:} which just gets that array and formats an HTML response. Alternately, you could have test in wpe_get_deep_array_dot_notation, if the result is an indexed array, return an HTML LI ?? I'll have to think about that.
wpe_action
Hmm.. Maybe the Bricks Settings doesn't set the key until it is edited?
May have to add to the bricks/query/run anonymous function.
$action = isset($settings["wpe_action"]) ? $settings["wpe_action"] : '';
Just updated code. The WP_Common code now adds the dynamic tag as
{deep_array_from_loop @key_path:reviewer.name @is_indexed:false @fallback:'Reviewer name not found'}
If is_indexed is true, the indexed array is returned as an HTML list with class names and data-list-index.
Just updated code. The WP_Common code now adds the dynamic tag as {deep_array_from_loop @key_path:reviewer.name @is_indexed:false @fallback:'Reviewer name not found'}
If is_indexed is true, the indexed array is returned as an HTML list with class names and data-list-index.
Ok need to see how it looks what you mean with returned as HTML list with class names and data list index. Ideally, you want to fetch the values just like you do without is_indexed.
I'm still getting when I try to fetch the first key in the example above after bookmakers.
Value not found in path:
If @is_indexed:true an HTML Ul is returned
Is it not possible to fetch the single value for the path you want to fully control where you put each key value path to value. This would not work in my case as it would just give a HTML ul list rather than single value.
{deep_array_from_loop @key_path:reviewer.name.key.key @is_indexed:true @fallback:'Reviewer name not found'}
etc like a nested tree.
Would it be possible? @wpeasy
If @is_indexed:true an HTML Ul is returned
Is it not possible to fetch the single value for the path you want to fully control where you put each key value path to value. This would not work in my case as it would just give a HTML ul list rather than single value.
{deep_array_from_loop @key_path:reviewer.name.key.key @is_indexed:true @fallback:'Reviewer name not found'}
etc like a nested tree.
Would it be possible? @wpeasy
It would be possible to allow for that. However, you would not know how many values the indexed array would have. So you would need to create another sub loop. That could be done, probably would need a second Bricks query defined.
I'm just about to do an update video showing how you can also provide your own formatter callback.
This should be viewed as starter code that works for most scenarios, but may need additional coding for specific situations.
It would be possible to allow for that. However, you would not know how many values the indexed array would have. So you would need to create another sub loop. That could be done, probably would need a second Bricks query defined.
I'm just about to do an update video showing how you can also provide your own formatter callback.
This should be viewed as starter code that works for most scenarios, but may need additional coding for specific situations.
@wpeasy
I think the HTML list will be helpful for some that want it as in your example video, but if you want to control it at a granular level set it into what ever HTML block you want and style it with custom classes it would be ideal if we could keep using child nested paths.
Would it be possible to add another option in the query to set "start index key" if empty it ignores and indexed is false but if a key is set there it knows where to start and it would narrow down to that index? That would require multiple query loops so not ideal.
Or best would be if we just could get the raw values of a indexed. But maybe in the key_path specify what index we want first, second etc.
[0] specify the index key path and which index.
{deep_array_from_loop @key_path:reviewer.name[0].key.key @is_indexed:true @fallback:'Reviewer name not found'}
But its like any array and loop and query you specify the start and in this case it needs to know the specific key is an array and then it loops through that until there is no more. So the query loop only needs to a logic for it to know where to start?
Here's a good example: We want to get the single value of the rating and comment under reviews from here or cratedAt under meta?
@wpeasy did you see my last comment above? Let me know what you think.
Warning: Undefined array key "wpe_action" in
/app/public/wp-content/plugins/wpcodebox2/src/Runner/QueryRunner.php(126) : eval()'d code
on line 86