Match two arrays and put post in pending if no IDs match - php

So I'm somewhat confused and need some assistance from the community, so I have a piece of code that I'm working on and I would like to compare two arrays and then if IDs don't match, to put the post in pending state.
I have the following method:
/**
* Update Office titles
*/
function update_office_titles() {
$office_data = build_offices_array();
$compare_ids = [];
foreach ($office_data as $office) {
$compare_ids[] = [
'wp_office_id' => $office['office_id']
];
}
foreach (api_offices_raw() as $api_office_id) {
$compare_ids[] = [
'api_id' => $api_office_id->id
];
}
print_r($compare_ids);
echo 'All of the office titles have been updated';
}
Here, I'm grabbing all the office_id post_meta and getting all the post_meta values in the DB:
foreach ($office_data as $office) {
$compare_ids[] = [
'wp_office_id' => $office['office_id']
];
}
I get the following return:
[243] => Array
(
[wp_office_id] => 3
)
[244] => Array
(
[wp_office_id] => 4
)
Then I have this foreach that loops through an API with IDs:
foreach (api_offices_raw() as $api_office_id) {
$compare_ids[] = [
'api_id' => $api_office_id->id
];
}
I get this output:
[246] => Array
(
[api_id] => 1
)
[247] => Array
(
[api_id] => 3
)
Here is what I was attempting to achieve:
Check api_id's and match them to the wp_office_id key values, if there are matching IDs, don't do nothing, otherwise call a wp_update_post and set the status to pending on $office['post_id'] on all IDs from wp_office_id that don't match.
All help is appreciated!

Related

Remove similar from foreach

Trying use array_unique but this did not help, since not all fields are repeated for me.
My array:
'Rows' =>
array (
0 =>
array (
'HotelId' => 94852,
'OfferId' => 858080496,
'OfferIdStr' => '858080496',
'Price' => 2762,
),
1 =>
array (
'HotelId' => 94852,
'OfferId' => 858080497,
'OfferIdStr' => '858080497',
'Price' => 3000,
),
And my try:
$allHotels['Rows'] = array_unique($allHotels['Rows'], SORT_REGULAR);
Changed flags, didn't help either (SORT_NORMAL, etc...).
It deletes absolutely everything, i need to ignore the HotelId replay, only first need.
If you want to delete duplicated entries based solely on the HotelId value, it's probably easiest just to iterate over the array, storing the seen HotelId values and deleting the current entry if it's HotelId value has already been seen.
$seenHotels = array();
foreach ($allHotels['Rows'] as $key => $hotel) {
if (in_array($hotel['HotelId'], $seenHotels)) {
unset($allHotels['Rows'][$key]);
}
else {
$seenHotels[] = $hotel['HotelId'];
}
}
print_r($allHotels);
Demo on 3v4l.org

how to turn this function to be recursive with multiple dimensional array?

Hello I am think about how to build this array with a recursive function with a lot of layer.
So the data would like that.
id belongs_to
1a NULL
2a NULL
3a 1a
4a NULL
5a 2a
And non-recursive function like:
foreach ($first_layer as $first_layer_obj) {
$array[$first_layer_obj->id] = [];
$second_layer = /* SELECT id FROM client WHERE belongs_to $first_layer_obj->id */;
foreach ($second_layer as $second_layer_obj) {
$array[$first_layer_obj->id][$second_layer_obj->id] = [];
$third_layer = /* SELECT id FROM client WHERE belongs_to $second_layer_obj->id */;
foreach ($third_layer as $third_layer_obj->id) {
$array[$first_layer_obj->id][$second_layer_obj->id][$third_layer_obj->id] = [];
}
}
I am expecting the output is:
array(3) {
["1a"]=>
array(1){
["3a"]=>[]
}
["2a"]=>
array(1){
["5a"]=>[]
}
["4a"]=>[]
}
Certainly the first piece of advice that I have is, you should avoid performing recursive/iterated calls to your database. You should make a single call to extract all of the desired rows in a single result set and let php do the hard part.
I've decided to try a non-recursive approach. To permit this, the result set must be prepared so that "grander" children are listed first. Now, I realize that it is entirely possible that your sample data doesn't actually represent your project values and sorting cannot be used to prepare the result set adequately -- you'll have to let me know (and perhaps update your question with more accurate sample data).
[see inline comments for what's happening in my script]
*If you aren't using php7+, then my null coalescing operator ($row1['children'] ?? []) will cause issues. You can use: (isset($row1['children']) ? $row1['children'] : []
Code: (Demo)
// use ORDER BY belongs_to DESC, id ASC ... or usort() to prepare result set
$resultset = [
['id' => '6a', 'belongs_to' => '5a'],
['id' => '5a', 'belongs_to' => '3a'],
['id' => '8a', 'belongs_to' => '3a'],
['id' => '3a', 'belongs_to' => '1a'],
['id' => '1a', 'belongs_to' => null],
['id' => '2a', 'belongs_to' => null],
['id' => '4a', 'belongs_to' => null],
['id' => '7a', 'belongs_to' => null]
];
foreach ($resultset as $index1 => &$row1) { // make input array modifiable by reference (not working with a copy)
if ($row1['belongs_to']) { // original belongs_to value is not null (not a top-level parent)
foreach ($resultset as $index2 => $row2) { // search for targeted parent
if ($row2['id'] == $row1['belongs_to']) { // parent found
$resultset[$index2]['children'][] = [$row1['id'] => $row1['children'] ?? []]; // store original row as child
unset($resultset[$index1]); // remove original row (no reason to iterate it again in outer loop)
break; // halt inner loop (no reason to iterate further)
}
}
} else { // original belongs_to value is null (top-level parent)
$output[$row1['id']] = $row1['children'] ?? []; // store children to top
}
}
var_export($output);
Output:
array (
'1a' =>
array (
0 =>
array (
'3a' =>
array (
0 =>
array (
'5a' =>
array (
0 =>
array (
'6a' =>
array (
),
),
),
),
1 =>
array (
'8a' =>
array (
),
),
),
),
),
'2a' =>
array (
),
'4a' =>
array (
),
'7a' =>
array (
),
)

Find value in multidimensional array then use it to only print sibling values - PHP

this is the furthest I've gone into looping through and outputting data from arrays. It may be scratching the surface to some but I'm still wrapping my head around the basic concepts of working with arrays.
I have an multidimensional array with two main sets, each one is nested 5 deep.
I've formatted a var_dump(); of the arrays - so I can see more clearly what's going on.
Array (
'set_56aad4d86660c' => Array ( // first foreach
'conditions' => Array ( // second foreach
'1' => Array (
'type' => apply_to
'args' => Array (
'applies_to' => roles
'roles' => Array (
'0' => administrator
)
)
)
)
'rules' => Array (
'1' => Array (
'from' => 1
'to' => 4
'type' => fixed_price
'amount' => 10
)
)
)
'set_56aad4d867064' => Array (
'conditions' => Array (
'1' => Array (
'type' => apply_to
'args' => Array (
'applies_to' => roles
'roles' => Array (
'0' => trader
)
)
)
)
'rules' => Array (
'1' => Array (
'from' => 5
'to' => 10
'type' => fixed_price
'amount' => 5
)
)
)
)
I'm not having an issue looping through and printing any of the values in the array, I've made sure I can print them all.
Where I'm stuck
What I'm trying to do is - when an array set has the role of administrator, only output the values in it's corresponding array.
i.e the data in the 'rules' array - 'from', 'to', 'amount'.
I can print the details from all sets but not based on condition (current user)
Here's where I am so far
// Pull the data
global $post, $product;
// get the current user's details
$current_user = wp_get_current_user();
// Loop through main rule sets array
$array_rule_sets = get_post_meta($post->ID, '_pricing_rules', true);
// Check to see if there are rule sets
if ($array_rule_sets && is_array($array_rule_sets) && sizeof($array_rule_sets) > 0) {
// Loop through rule sets
foreach ( $array_rule_sets as $rule_set ) {
// Get conditions
$conditions = $rule_set['conditions'];
// Loop through conditions
foreach ( $conditions as $key => $condition ) {
// Get Roles
$roles = $condition['args']['roles'];
// Loop through roles
foreach ( $roles as $role ) {
if ( in_array( $role, (array)$current_user->roles ) ) {
$role_rules[] = $key; // getting stuck here
}
}
// Loop through rules array and print pricing table values based on key
foreach ( $rule_set['rules'] as $key => $value ) {
$tempstring .= $rule_set['rules'][$key]['from']."- ".$rule_set['rules'][$key]['to']."</td>";
$tempstring .= $rule_set['rules'][$key]['amount'];
}
// Print results
echo $tempstring;
}
}
}
I went through a tutorial which is where a lot of this code came from. It was for a slightly different case but it had enough to start me off.
I spent the day re-building it bit by bit. I've commented where I get stuck.
I'd really appreciate if someone can understand what I'm trying to do and if possible explain to me where I'm going wrong and if it's possible to achieve the desired outcome.
Many thanks in advance
It's taken ages to tap this in on my tab - so I hope it works for you - basically I stored all the set keys which have the users role in an array, then put all rules in an array using the set key as the key.
I then fetch the required data after all the loops have finished.
Here goes:
// Pull the data
global $post, $product;
//** NEW: store user set keys and available rules **//
$user_set_keys = array();
$all_rules = array();
// get the current user's details
$current_user = wp_get_current_user();
// Loop through main rule sets array
$array_rule_sets = get_post_meta($post->ID, '_pricing_rules', true);
// Check to see if there are rule sets
if ($array_rule_sets && is_array($array_rule_sets) && sizeof($array_rule_sets) > 0) {
// Loop through rule sets
foreach ( $array_rule_sets as $rule_key => $rule_set ) { // ** UPDATED
// Get conditions
$conditions = $rule_set['conditions'];
// Loop through conditions
foreach ( $conditions as $key => $condition ) {
// Get Roles
$roles = $condition['args']['roles'];
// Loop through roles
foreach ( $roles as $role ) {
if ( in_array( $role, (array)$current_user->roles ) ) {
$user_set_keys[] = $rule_key; // ** UPDATED **
}
}
}
// Loop through rules array and print pricing table values based on key
foreach ( $rule_set['rules'] as $ruleArray ) {
$all_rules[$rule_key] = array(
'from' => $ruleArray['from'],
'to' => $ruleArray['to'],
'amount' => $ruleArray['amount']
);
}
}
}
// all done now show the data here!
foreach($user_set_keys as $user_set){
print_r($all_rules[$user_set]);
}
Answer to your comment:
If you really don't want the final loop the you could change your second loop to this - I'm not 100% without being able to run, but I'm sure my logic is right:
// Loop through rules array and print pricing table values based on key
foreach ( $rule_set['rules'] as $ruleArray ) {
if(in_array($rule_key, $user_set_keys)){
print_r($ruleArray);
}
}
If I understand you correctly then I think this is what you need to change :
// Loop through rules array and print pricing table values based on key
// foreach ( $rule_set['rules'] as $key => $value ) { // remove this and replace with....
for($i=0; $i<count($role_rules); $i++){
$key = $role_rules[$i];
$tempstring .= $rule_set['rules'][$key]['from']."- ".$rule_set['rules'][$key]['to']."</td>";
$tempstring .= $rule_set['rules'][$key]['amount'];
}

Building an array of search parameters

I need some help wrapping my head around a problem. I have an array filled with other arrays. I need to:
Loop through the entire array and build a new array called finalOptions
Each iteration of the loop will take a new SearchIndex and apply the other paramenters
i.e
SearchIndex => SportingGoods
MinPercentageOff => 50
MinimumPrice => 1
ItemPage => 1
Sort => salesrank
BrowseNode => 2342470011
THEN:
Final array should contain data like this
SearchIndex => SportingGoods
MinPercentageOff => 60
MinimumPrice => 100
ItemPage => 2
Sort => salesrank
BrowseNode => 3403201
Basically, I'm creating a new array and sending it to another method that will execute a call to an API and return a result, then doing it again until my array options are complete.
This might not be the way to go and I'm looking for suggestions/pseudo code on an approach. Here is the basics of what I have so far:
Starting with this code
$allOptions = array(
"SearchIndex" => array("SportingGoods", "Tools"),
"MinPercentageOff" => array("50", "60", "70"),
"MinimumPrice" => array("1", "100", "1000"),
"ItemPage" => array("1", "2"),
"Sort" => array("salesrank")
"BrowseNode" => array(
"SportingGoods" => array("2342470011", "3403201"),
"Tools" => array("511364")
)
)
$finalOptions = array();
foreach($allOptions as $options){
foreach($options["SearchIndex"] as $searchIndex){
$finalOptions[] = "SearchIndex" => $searchIndex[]
}
$this->itemSearch($finalOptions);
}
EDIT
The arrays will contain more values. i.e "ItemPage" => array("1", "2"), will have 1 - 10. The others will have more values as well.
From the given array it will produce 54 possible combinations as you described.
Also you need to make sure you have array in $allOptions['BrowseNode'] indexed as each value of $allOptions['SearchIndex']. Otherwise it will produce error.
Cartesian function from here.
$allOptions = [
"SearchIndex" => ["SportingGoods", "Tools"],
"MinPercentageOff" => ["50", "60", "70"],
"MinimumPrice" => ["1", "100", "1000"],
"ItemPage" => ["1", "2"],
"Sort" => ["salesrank"],
"BrowseNode" => ["SportingGoods" => ["2342470011", "3403201"], "Tools" => ["511364"] ] ];
$finalOptions = $allOptions; // copy our initial $allOptions array
unset($finalOptions['BrowseNode']); // deal with BrowseNode key later with custom iterator
$cartesian_product = cartesian($finalOptions); // find cartesian except BrowseNode
foreach($cartesian_product as $cartesian) // each member of cartesian product will iterate here
{
foreach($allOptions['BrowseNode'][$cartesian['SearchIndex']] as $possible)
/*
We have unset the BrowseNode, so need to refer original $allOptions array for BrowseNode,
In every cartesian product, we will get $cartesian['SearchIndex'] and it will contain either
'SportingGoods' or 'Tools' , so in our original array, look for 'BrowseNode' value, having key
same as $cartesian['SearchIndex'].
$allOptions['BrowseNode'][$cartesian['SearchIndex']] <---- is similar to below two lines
$key = $cartesian['SearchIndex'];
$allOptions['BrowseNode'][$key];
Finally iterate through $allOptions['BrowseNode'][$cartesian['SearchIndex']] will iterate as many times,
as many values there are
*/
{
$cartesian['BrowseNode'] = $possible; // assign the long waited key here to 'BrowseNode'
var_dump($cartesian); // here you can do $this->itemSearch($cartesian);
}
}
function cartesian($input) {
$input = array_filter($input);
/*
will renove any false values in input array,
in our array's case, it will do nothing.
*/
$result = [[]];
foreach ($input as $key => $values) {
$append = [];
foreach($result as $product) {
foreach($values as $item) {
$product [$key] = $item;
$append [] = $product;
}
}
$result = $append;
}
return $result;
}

Key Manipulation In PHP Array

So I have a function that merges two arrays replacing "variables" that are in the $template array with values from the $marketArray. It's nice tight bit of code from some kind contributor's here. Now due to a new requirement I need to switch things a bit.
First I need to make it an array of arrays that essentially groups the stuff by market instead of one giant list in a single large array. Secondly I need the keys in the new arrays to be of the format market-counter
e.g. gb/en-1, gb/en-2 etc etc (this is so a JQuery gets an id it can use to determine where the results go later.
So I have entered a couple of new entries (marked //NEW) that would get the value for the market and started a counter. It's twisting my brain around the next step that hurts!
$marketArray is a multidimensional associative array of the markets like this (but a lot more markets!)
$markets = array(
array(market => 'se/sv', storeid => 'storeId=66', langid => 'langId=-14', storenumber => '109', prodid => '741586', artid => '22112334'),
array(market => 'at/de', storeid => 'storeId=82', langid => 'langId=-11', storenumber => '234', prodid => '374637', artid => '45678214')
);
$template is a bunch of url templates that need to be manipulated on a market by market basis (again shortened)
$template = array (
'/$market',
'/$market/catalog/',
'/$marketproducts/$artid',
'StockSearchForm?&productId=$prodid'
);
Here is the function
function urlBuilder($marketArray,$template) {
$urlstohit=array();
foreach ($marketArray as $m) {
$market = $m['market']; //NEW
$counter = 1; //NEW
foreach ($template as $t) {
$tt=$t;
foreach ($m as $k=>$v)
$tt=str_replace('$'.$k, $v, $tt);
$urlstohit[]=$tt;
}
}
return ($urlstohit);
}
so what I am trying to achieve is instead of one giant array like
$urlstohit (
[0] => '/se/sv/catalog/categories/',
[1] => '/se/sv/catalog/news/',
[2] => '/se/sv/catalog/categories/departments/',
[3] => '/se/sv/search/?query=giant'
[4] => '/at/de/catalog/categories/',
[5] => '/at/de/catalog/news/',
[6] => '/at/de/catalog/categories/departments/',
[7] => '/at/de/search/?query=giant'
)
a md-array grouped by market with the market-counter as keys
$urlstohit (
['se/sv'] => array(
['se/sv-1'] => '/se/sv/catalog/categories/',
['se/sv-2'] => '/se/sv/catalog/news/',
['se/sv-3'] => '/se/sv/catalog/categories/departments/',
['se/sv-4'] => '/se/sv/search/?query=giant'
),
['at/de'] => array(
['at/de-1'] => '/at/de/catalog/categories/',
['at/de-2'] => '/at/de/catalog/news/',
['at/de-3'] => '/at/de/catalog/categories/departments/',
['at/de-4'] => '/at/de/search/?query=giant'
)
)
Try this
function urlBuilder($marketArray,$template) {
$urlstohit=array();
foreach ($marketArray as $m) {
$market = $m['market'];
$counter = 1;
$urlstohit[$market] = array(); / ADDED
foreach ($template as $t) {
$tt=$t;
foreach ($m as $k=>$v)
$tt=str_replace('$'.$k, $v, $tt);
$urlstohit[$market][$market.'-'.$counter]=$tt; // EDITED
$counter++; // ADDED
}
}
} // ADDED
return ($urlstohit);
}
I've marked the lines I've added and edited (I think you were also missing a curly brace).

Categories