First, the approach for setting up a sorting algorithm depends on where/how those street name and address numbers are stored. Single line in a meta_key
, two separate meta_key
entries, dumped into content for some reason, etc. etc. etc.
OP is dealing with addresses stored as post_title
values. So below assumes string like:
1234 Main Street
The rest of it, matching and updating the page menu_order
key is fairly straightforward.
Perhaps a process like this:
-
from
init
hook:[
order_pages_by_values()
] -
get an array of page objects:
[
$pages = get_pages_wrapper();
] -
for each page object, pass the ID to a function that gets number/street values:
1) [
$addresses = extract_and_conflate_address( $pages );
]2) [
$number = get_address_number( $page->ID );
]3) [
$street = get_address_street( $page->ID );
]4) [
$split = explode( ' ', $address, 2 );
]
if ( $value === 'number' ) {
$return = $split[0];
}
elseif ( $value === 'street' ) {
$return = $split[1];
} -
add number and street values to array as
key => value
, i.e.numeric => street
:[
$address_k_v[$number] = $street;
] sort the values and then keys of that array-
create a multi-dimensional array of
street => array ( numeric, )
1) [
$flatten_array = sort_values_and_keys_and_flatten( $addresses )
]2) [
foreach( $array as $n => $s ) { if ( array_key_exists( $s, $multi_array ) ) { $multi_array[$s][] = $n; } else { $multi_array[$s] = array( $n ); } }
]
-
sort the
street
keys of outer array, then for eachstreet
, sort the inner numeric values array1) [
ksort($multi_array);
]2) [
foreach ($multi_array as $street => $numbers_array ) {
]
asort($numbers_array); -
for each (now sorted)number => street
entry, make that a string ofnumber-street
, and add it to a new array -
for each (now sorted)
street => array ( numeric )
(the inner array), add a string ofnumber-street
to a new array:[
foreach( $numbers_array as $na ) {
]
$flatten_array[] = $na .'-'. $street; -
for each page object, get the number and the street again, this time using them to create a string of
numberic-street
:$number = get_address_number( $page->ID ); $street = get_address_street( $page->ID ); $match_string = $number . '-' . $street;`
-
search the array of sorted
numberic-street
strings for thisnumberic-street
string, returning the index number to set$menu_order
:[
$menu_order = array_search( $match_string, $flatten_array );
] -
create args array for post with
ID => page->ID
andmenu_order => index number
:$update_post_args = array( 'ID' => $page->ID, 'menu_order' => $menu_order );
-
update post with those args:
[
wp_update_post( $update_post_args )
]
It’s impossible to guess a solution without where those address fields are stored, but I’ve included a possible approach using explode
on post_title
in case that’s part of your current nightmare. 😉
The below is just an example of a possible process to start with of course, test it before giving it a full go. I’d probably wrap it all in a class of a plugin.
add_action( 'init', 'order_pages_by_values' );
function get_pages_wrapper() {
$args = array( 'post_type' => 'page',
'post_status' => 'publish'
);
$pages = get_pages( $args );
return $pages;
}
function extract_and_conflate_address( $pages ) {
foreach ( $pages as $page ) {
$number = get_address_number( $page->ID ); //depends on where value is stored
$street = get_address_street( $page->ID ); //depends on where value is store
$address_k_v[$number] = $street;
}
return $address_k_v;
}
//old version, several issues with this.
// First, it is more of a re-sort, ignoring previously sorted items.
/// Second, it cannot preserve instances where same post box address (1234) for different street would overwrite previous entry.
/* function sort_values_and_keys( &$array, $valrev = false, $keyrev = false ) {
//adopted from http://php.net/manual/en/function.asort.php#80798
if ( $valrev ) {
arsort( $array );
} else {
asort( $array );
}
$vals = array_count_values( $array );
$i = 0;
foreach ( $vals AS $val => $num ) {
$first = array_splice( $array, 0, $i );
$tmp = array_splice( $array, 0, $num );
if ( $keyrev ) {
krsort( $tmp );
} else {
ksort( $tmp );
}
$array = array_merge( $first, $tmp, $array );
unset( $tmp );
$i = $num;
}
} */
//Here we are creating a multidimensional array with the outer being Street
// and inner being an array of corresponding numerical post addresses.
function sort_values_and_keys_and_flatten( $array ) {
//need array declared already for conditional inside foreach
$multi_array = array();
foreach( $array as $n => $s ) {
//makes sure Street doesn't exist yet. If it does, append, if not add.
if ( array_key_exists( $s, $multi_array ) ) {
$multi_array[$s][] = $n;
}
else {
$multi_array[$s] = array( $n );
}
}
//sort the street names
ksort($multi_array);
foreach ($multi_array as $street => $numbers_array ) {
//sort the numerical addresses
asort($numbers_array);
//build $flatten_array
foreach( $numbers_array as $na ) {
$flatten_array[] = $na .'-'. $street;
}
}
return $flatten_array;
}
function order_pages_by_values() {
$pages = get_pages_wrapper();
$addresses = extract_and_conflate_address( $pages );
/**
Replacing these lines with new sort function and setting $flatten to its return
sort_values_and_keys( $addresses );
foreach ( $addresses as $number => $street ) {
$flatten_array[] = $number . '-' . $street;
}
*/
$flatten_array = sort_values_and_keys_and_flatten( $addresses );
foreach ( $pages as $page ) {
$number = get_address_number( $page->ID ); //depends on where value is stored
$street = get_address_street( $page->ID ); //depends on where value is stored
$match_string = $number . '-' . $street;
$menu_order = array_search( $match_string, $flatten_array );
$update_post_args = array( 'ID' => $page->ID,
'menu_order' => $menu_order
);
wp_update_post( $update_post_args );
}
}
function get_address_number( $id ) {
//assuming post_meta key of 'address_number'
//$number = get_post_meta( $id, 'address_number', true );
//assuming all addresses have format 1234 Main Street and saved as post title
$number = extract_address( get_the_title( $id ), 'number' );
return $number;
}
function get_address_street( $id ) {
//assumes post_meta key of 'address_street'
//$street = get_post_meta( $id, 'address_street', true );
//assuming all addresses have format 1234 Main Street and saved as post title
$street = extract_address( get_the_title( $id ), 'street' );
return $street;
}
function extract_address( $address, $value ) {
$split = explode( ' ', $address, 2 );
if ( $value === 'number' ) {
$return = $split[0];
}
elseif ( $value === 'street' ) {
$return = $split[1];
}
return $return;
}
Update
I updated the code block above, but below is a quick test sample of the sorting function. I can’t say how economical it is, but it is working on my end.
Since it is returning the value needed for $flatten_array
in the previous version, note above that I have removed those lines from order_pages_by_value()
Here is the testable code sample for the sort:
//array as would be returned by extract_and_conflate_addresses()
$the_array = array(
'1234' => 'Main Street',
'100' => 'Avenue Road',
'105' => 'Avenue Road',
'106' => 'Avenue Road',
'106a' => 'Avenue Road',
'107' => 'Avenue Road',
'103' => 'Front Street',
'42' => '5 Lane',
'42000' => 'B Street',
);
function sort_values_and_keys_and_flatten( $array ) {
//need array declared already for conditional inside foreach
$multi_array = array();
foreach( $array as $n => $s ) {
//makes sure Street doesn't exist yet. If it does, append, if not add.
if ( array_key_exists( $s, $multi_array ) ) {
$multi_array[$s][] = $n;
}
else {
$multi_array[$s] = array( $n );
}
}
//sort the street names
ksort($multi_array);
foreach ($multi_array as $street => $numbers_array ) {
//sort the numerical addresses
asort($numbers_array);
//build $flatten_array
foreach( $numbers_array as $na ) {
$flatten_array[] = $na .'-'. $street;
}
}
return $flatten_array;
}
$test = sort_values_and_keys_and_flatten( $the_array );
print_r($test);
That should yield:
Array
(
[0] => 42-5 Lane
[1] => 100-Avenue Road
[2] => 105-Avenue Road
[3] => 106-Avenue Road
[4] => 106a-Avenue Road
[5] => 107-Avenue Road
[6] => 42000-B Street
[7] => 103-Front Street
[8] => 1234-Main Street
)