Manually write a url query string containing nested array data - php

I'm looking to manually write a multidimensional $_GET query string, saw this done the other day, but can't quite remember it!
something like:
www.url.com?val1=abc&val2=cde&[val3=fgh&val4=ijk]

http://domain.tld/path/to/script.php?arr[a][b][c]=foo
and
var_dump($_GET);

Since array parameters in URL's are postfixed by brackets, I'd try a function like this:
<?php
function array_map_scope( $callback, array $array, array $arguments = array(), $scope = array() ) {
if( !is_callable( $callback ) ) {
return( false );
}
$output = array();
foreach( $array as $key => $value ) {
if( is_array( $value ) ) {
$output[$key] = array_map_scope( $callback, $value, $arguments, array_push_value( $scope, $key ) );
} else {
$output[$key] = call_user_func_array( $callback, array_merge( array( $value, array_push_value( $scope, $key ) ), $arguments ) );
}
}
return( $output );
}
function array_push_value( $array, $value ) {
$array[] = $value;
return( $array );
}
function urlParam( $value, $key, $name ) {
return( $name.'['.implode( array_map( 'urlencode', $key ), '][' ).']='.urlencode( $value ) );
}
function array_values_recursive( $array ) {
$output = array();
foreach( $array as $value ) {
if( is_array( $value ) ) {
$output = array_merge( $output, array_values_recursive( $value ) );
} else {
$output[] = $value;
}
}
return( $output );
}
function array2URL( $name, $array ) {
$array = array_map_scope( 'urlParam', $array, array( urlencode( $name ) ) );
return( implode( array_values_recursive( $array ), '&' ) );
}
echo array2URL('test', array( 'a'=>'a','b'=>array('ba'=>'ba','bb'=>'bb'),'c'=>'c' ) );
?>

Rely on http_build_query() to perfectly format a query string for you.
Either use it directly in your script to generate the substring after ? in the url or use a sandbox to set up your array data, call the function, then copy-paste the output in your static file.
Code: (Demo)
$array = [
'indexed value',
'foo' => 'first level value',
'bar' => ['baz' => 'second level']
];
echo http_build_query($array);
// 0=indexed+value&foo=first+level+value&bar%5Bbaz%5D=second+level
A fringe case consideration

Related

get all custom post type titles and show it as selectbox in a meta box

i have a custome post type known as "Motor_supply"
i want to show "Motor_supply" titles by a category as a "selectbox" in metabox on shop_order
i want to know how can i create a loop and put published "Motor_supply" posts titles in it
i have this code
class select_motor {
private $config = '{"title":"\u062a\u062e\u0635\u06cc\u0635 \u0645\u0648\u062a\u0648\u0631","prefix":"select_motor","domain":"select_motor","class_name":"select_motor","post-type":["post"],"context":"normal","priority":"default","cpt":"shop_order","fields":[{"type":"select","label":"select motor","options":"option-one : MOTOR_1\r\noption-one : MOTOR_2","id":"select_motorselect-motor"}]}';
public function __construct() {
$this->config = json_decode( $this->config, true );
$this->process_cpts();
add_action( 'add_meta_boxes', [ $this, 'add_meta_boxes' ] );
add_action( 'save_post', [ $this, 'save_post' ] );
}
public function process_cpts() {
if ( !empty( $this->config['cpt'] ) ) {
if ( empty( $this->config['post-type'] ) ) {
$this->config['post-type'] = [];
}
$parts = explode( ',', $this->config['cpt'] );
$parts = array_map( 'trim', $parts );
$this->config['post-type'] = array_merge( $this->config['post-type'], $parts );
}
}
private function select( $field ) {
printf(
'<select id="%s" name="%s">%s</select>',
$field['id'], $field['id'],
$this->select_options( $field )
);
}
private function select_options( $field ) {
$output = [];
$options = explode( "\r\n", $field['options'] );
$i = 0;
foreach ( $options as $option ) {
$pair = explode( ':', $option );
$pair = array_map( 'trim', $pair );
$output[] = sprintf(
'<option %s value="%s"> %s</option>',
$this->select_selected( $field, $pair[0] ),
$pair[0], $pair[1]
);
$i++;
}
return implode( '<br>', $output );
}
private function value( $field ) {
global $post;
if ( metadata_exists( 'post', $post->ID, $field['id'] ) ) {
$value = get_post_meta( $post->ID, $field['id'], true );
} else if ( isset( $field['default'] ) ) {
$value = $field['default'];
} else {
return '';
}
return str_replace( '\u0027', "'", $value );
}
}
new select_motor;

WooCommerce Memberships. In admin list view of Members, how do I add "user ID" column

I am using the WooCommerce Memberships plugin.
In the admin dashboard, when I go to WooCommerce > Members there is a list view which has the column headers:
Name, Email, Plan, Team, Status, Member since, Expires
I would like to add the USER ID to this column. Does anyone know how to do this?
Modified some code I found online here. This should work for the original ask.
add_filter( 'manage_edit-wc_user_membership_columns', function( $columns ) {
$userID_column = array( 'id' => __( 'User ID', 'woocommerce-memberships' ) );
if ( isset( $columns['title'] ) ) {
$columns = sv_wc_array_insert_after( $columns, 'title', $userID_column );
} else {
$columns = array_merge( $columns, $userID_column );
}
return $columns;
}, 20 );
add_action( 'manage_wc_user_membership_posts_custom_column', function( $column, $user_membership_id ) {
if ( 'id' === $column ) {
$user_id = get_post_field( 'post_author', $user_membership_id );
$user = get_userdata( $user_id );
if ( $user ) {
echo $user_id;
} else {
echo '–';
}
}
}, 20, 2 );
if ( ! function_exists( 'sv_wc_array_insert_after' ) ) :
/**
* Insert the given element after the given key in the array
*
* Sample usage:
* array( 'item_1' => 'foo', 'item_2' => 'bar' )
*
* array_insert_after( $array, 'item_1', array( 'item_1.5' => 'w00t' ) )
*
* becomes
* array( 'item_1' => 'foo', 'item_1.5' => 'w00t', 'item_2' => 'bar' )
*
* #param array $array array to insert the given element into
* #param string $insert_key key to insert given element after
* #param array $element element to insert into array
* #return array
*/
function sv_wc_array_insert_after( Array $array, $insert_key, Array $element ) {
$new_array = array();
foreach ( $array as $key => $value ) {
$new_array[ $key ] = $value;
if ( $insert_key == $key ) {
foreach ( $element as $k => $v ) {
$new_array[ $k ] = $v;
}
}
}
return $new_array;
}
endif;
add_filter('manage_edit-wc_user_membership_columns', 'customize_columns');
function customize_columns($columns) {
$columns['UID'] = __('USER ID', 'woocommerce-memberships');
return $columns;
}
add_action('manage_wc_user_membership_posts_custom_column', 'custom_column_content');
function custom_column_content($column, $post_id) {
$user_membership = wc_memberships_get_user_membership($post_id);
If(!$user_membership) return;
$userid = $user_membership->get_user_id();
switch ($column) {
case 'UID':
echo $userid;
break;
}
}
Tested OK with WooCommerce 3.5.6

Logical Operators expression to a PHP array

I have expressions like this =>
({2606} OR {2549} OR {2543} OR ({2605} AND {2562})) AND ({2387} OR {2383} OR {1990} OR {2412} OR {2411} OR {2409} OR ({2408} AND {2593}))
I want output like this Array.
[
"AND" => [
"OR" => [ 2606, 2549, 2543, "AND" => [ 2605, 2562 ] ],
"OR" => [ 2387, 2383, 1990, 2412, 2411, 2409, "AND" => [ 2408, 2593 ] ]
]
]
Need a php script for this.
$rule = "({2606} OR {2549} OR {2543} OR ({2605} AND {2562})) AND ({2387} OR {2383} OR {1990} OR {2412} OR {2411} OR {2409} OR ({2408} AND {2593}))";
$previous_rule = '';
// Clean Curly Braces and Trim is there's a space.
$rule = trim( str_replace( array( "{", "}" ) , "", $rule ) );
echo "INPUT: " . $rule . "<br><br>";
foreach( range('a', 'z') as $letter ){
$substituted_part = "(". substitution( $rule ) . ")";
$$letter = $substituted_part;
$rule = str_replace( $substituted_part, $letter, $rule );
if( $previous_rule != $rule )
$previous_rule = $rule;
else
break;
}
echo "<PRE>";
print_r( replaceOriginal($rule) );
function replaceOriginal( $rule ){
if( preg_match("/[a-z]/i", $rule) ){
if( strpos( $rule, "AND" ) !== false )
$processed_rule = array( "AND" => explode(" AND ", $rule ) );
else if( strpos( $rule, "OR" ) !== false )
$processed_rule = array( "OR" => explode(" OR ", $rule ) );
foreach( $processed_rule as $operator => $values ){
$processed_rule[$operator] = process( $values );
}
return $processed_rule;
}
}
function process( $values ){
foreach( $values as $key => $value ){
if( !empty( $GLOBALS[$value] ) ){
$substituted_value = str_replace( array( "(", ")" ) , "", $GLOBALS[$value] );
$values[$key] = replaceOriginal( $substituted_value );;
}
}
return $values;
}
function substitution( $rule ){
// Get anything thats wrapped in parentheses.
if( preg_match_all('#\((([^()]+|(?R))*)\)#', $rule, $matches) ){
foreach( $matches[1] as $value ){
return substitution( $value );
}
}else{
return $rule;
}
}

Replacing text within string that contains serialize arrays

Thanks for clicking on the question. I am trying to find and replace text within a string that contains serialize arrays. For example :
'fgm2wc_options', 'a:19:{s:15:"automatic_empty";N;s:3:"url";s:25:"http://example.com/store/";s:8:"hostname";s:9:"localhost";s:4:"port";s:4:"3306";s:8:"database";s:22:"apgadmin_store_magento";s:8:"username" ... }
I want to change http://example.com/ to smth else I can do it with str_replace but it will not change the string length indicator ( e.g s:25 ).
This is a function i am using:
function recursive_unserialize_replace( $old_url = '', $new_url = '', $data = '', $serialised = false ) {
$new_url = rtrim( $new_url, '/' );
$data = explode( ', ', $data );
try {
if ( is_string( $data ) && ( $unserialized = #unserialize( $data ) ) !== false ) {
$data = recursive_unserialize_replace( $old_url, $new_url, $unserialized, true );
} elseif ( is_array( $data ) ) {
$_tmp = array( );
foreach ( $data as $key => $value ) {
$_tmp[ $key ] = recursive_unserialize_replace( $old_url, $new_url, $value );
}
$data = $_tmp;
unset( $_tmp );
} else {
if ( is_string( $data ) ) {
$data = str_replace( $old_url, $new_url, $data );
}
}
if ( $serialised ) {
return serialize( $data );
}
} catch( Exception $error ) {
}
return $data;
}
Any ideas ?
For anyone interested this is the solution i came up with:
function unserialize_replace( $old_url = '', $new_url = '', $database_string = '' ) {
if ( substr( $old_url, -1 ) !== '/' ) {
$new_url = rtrim( $new_url, '/' );
}
$serialized_arrays = preg_match_all( "/a:\d+:.*\;\}+/", $database_string, $matches );
if( !empty( $serialized_arrays ) && is_array( $matches ) ) {
foreach ( $matches[ 0 ] as $match ) {
$unserialized = #unserialize( $match );
if ( $unserialized ) {
$buffer = str_replace( $old_url, $new_url, $unserialized );
$buffer = serialize( $buffer );
$database_string = str_replace( $match, $buffer, $database_string );
}
}
}
if ( is_string( $database_string ) ) {
$database_string = str_replace( $old_url, $new_url, $database_string );
}
return $database_string;
}
Thanks for the suggestions. Please let me know if you see anything wrong and anything i can improve

Why is this mode function returning null?

In the below function, when I call
mmmr(array(1,2,3,3,4,3), 'mode', 'ceil'); // null
it returns null. Works fine if I don't set the third ($round) argument.
mmmr(array(1,2,3,3,4,3), 'mode'); // 3
What am I missing? Coffee?
function mmmr( array $array, $output = 'mean', $round = false ) {
switch( $output ) {
case 'mode':
if( $round == "ceil" ) {
foreach( $array as $key => $value ) {
$array[$key] = ceil( $value );
}
} elseif( $round == "floor" ) {
foreach( $array as $key => $value ) {
$array[$key] = floor( $value );
}
} elseif( $round == "normal" ) {
foreach( $array as $key => $value ) {
$array[$key] = round( $value );
}
}
$v = array_count_values( $array );
arsort( $v );
foreach( $v as $k => $v ) {
$total = $k;
break;
}
break;
}
return $total;
}
array_count_values() can only count STRING and INTEGER values. ceil(), floor(), and round() return a float. Casting it to an int fixes your problem:
<?php
function mmmr( array $array, $output = 'mean', $round = false ) {
switch( $output ) {
case 'mode':
if( $round == "ceil" ) {
foreach( $array as $key => $value ) {
$array[$key] = (int) ceil( $value ); // (int)
}
} elseif( $round == "floor" ) {
foreach( $array as $key => $value ) {
$array[$key] = (int) floor( $value ); // (int)
}
} elseif( $round == "normal" ) {
foreach( $array as $key => $value ) {
$array[$key] = (int) round( $value ); // (int)
}
}
$v = array_count_values( $array );
arsort( $v );
foreach( $v as $k => $v ) {
$total = $k;
break;
}
break;
}
return $total;
}
echo mmmr(array(1,2,3,3,4,3), 'mode', 'ceil'); // Returns 3

Categories