Fill a Tree in an multidimensional array in php - algorithm

I create a Tree in an multidimensional array for my different post. A post can have one parent and now I want to be able to my tree with the different level.
Here an exemple of what I want :
array(1) {
[3258]=>
array(2) {
["post"]=>
string(30) "bank and you - publish"
["children"]=>
array(3) {
[0]=>
array(1) {
[3067]=>
array(3) {
["post"]=>
string(37) "solution - publish"
["parent"]=>
int(3258)
["children"]=>
array(1) {
[3069]=>
array(3) {
["post"]=>
string(37) "Test - publish"
["parent"]=>
int(3258)
["children"]=>
array(0) {
}
}
}
}
}
[1]=>
array(1) {
[3070]=>
array(3) {
["post"]=>
string(25) "file - publish"
["parent"]=>
int(3258)
["children"]=>
array(0) {
}
}
}
[2]=>
array(1) {
[3076]=>
array(3) {
["post"]=>
string(72) "Utils - publish"
["parent"]=>
int(3258)
["children"]=>
array(0) {
}
}
}
}
}
I have a function which can gave me all his ancestors. Which mean that when I use it, I return :
[post_parent, post_grandparent , ....]
For now I Succeed to do when my post have only 1 ancestor and I try to do for 2 or more. And this is at this moment that block for me. Because for the case of 2 ancestors I suppose to have something like :
$data[$post->ancestors[n]]['children'][$post->ancestors[n-1]]['children'][] = $item_post
And as you can imagine, more ancestors you have, more the array is complex to fill dynamically
<?php
public function process_construction( $array, $wpquery, $counter ) {
while ( $wpquery->have_posts() ) {
$post = $wpquery->post;
if ( $counter == count( $post->ancestors ) ) {
$item_post = [];
$item_post[ $post->ID ] = [
'post' => $post->post_title . ' - ' . $post->post_status,
'parent' => $post->post_parent,
'children' => [],
];
if ( $counter < 2 ) {
$array[ $post->ancestors[ $counter - 1 ] ]['children'][] = $item_post;
} else {
$this->add_item_with_multiple_ancestors( $array, $post, $item_post );
}
}
$wpquery->next_post();
}
return $array;
}
public function add_item_with_multiple_ancestors( $array, $post, $item_post ) {
for($i = count($post->ancestors)-1 ; $i => 0; $i--){
}
}
Do you have some ideas.
Thanks

Related

Trying to do VLQ Base64 decoding of a LESS source map and getting odd results

See this tutorial for context.
Here is a single source mapped line from my .css.map file: 'AILJ,CAAC,GAAgB,CAAC,EAAe,CAAC'
When I try to decode it, I'm getting negative numbers.
class VLQDecoder {
public $charToInt = [];
function __construct() {
foreach (str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') as $i => $char) {
$this->charToInt[ $char ] = $i;
}
}
public function uRShift(int $a, int $b): int {
if ($b == 0) {
return $a;
}
return ($a >> $b) & ~(1 << (8 * PHP_INT_SIZE - 1) >> ($b - 1));
}
public function segmentToArray(string $segment): array {
$result = [];
$shift = 0;
$value = 0;
foreach (str_split($segment) as $char) {
$integer = $this->charToInt[ $char ];
$has_continuation_bit = $integer & 32;
$integer = $integer & 31;
$value += $integer << $shift;
if ($has_continuation_bit) {
$shift += 5;
} else {
$should_negate = $value & 1;
$value = $this->uRShift($value, 1);
if ($should_negate) {
$result[] = $value === 0 ? - 0x80000000 : $value * - 1;
} else {
$result[] = $value;
}
$value = $shift = 0;
}
}
return $result;
}
}
$VLQDecoder = new VLQDecoder();
$mappings = ['AILJ,CAAC,GAAgB,CAAC,EAAe,CAAC'];
foreach ($mappings as $mapping) {
$segments = array_filter(explode(',', $mapping));
foreach ($segments as $segment) {
$array = $VLQDecoder->segmentToArray($segment);
var_dump([$segment=>$array]);
}
}
This outputs:
array(1) {
["AILJ"]=>
array(4) {
[0]=>
int(0)
[1]=>
int(4)
[2]=>
int(-5)
[3]=>
int(-4)
}
}
array(1) {
["CAAC"]=>
array(4) {
[0]=>
int(1)
[1]=>
int(0)
[2]=>
int(0)
[3]=>
int(1)
}
}
array(1) {
["GAAgB"]=>
array(4) {
[0]=>
int(3)
[1]=>
int(0)
[2]=>
int(0)
[3]=>
int(16)
}
}
array(1) {
["CAAC"]=>
array(4) {
[0]=>
int(1)
[1]=>
int(0)
[2]=>
int(0)
[3]=>
int(1)
}
}
array(1) {
["EAAe"]=>
array(4) {
[0]=>
int(2)
[1]=>
int(0)
[2]=>
int(0)
[3]=>
int(15)
}
}
array(1) {
["CAAC"]=>
array(4) {
[0]=>
int(1)
[1]=>
int(0)
[2]=>
int(0)
[3]=>
int(1)
}
}
The first segment has negative numbers for the row and column indexes. How is this possible?
I also don't see how any value higher than 64 is going to come out of this, yet I have hundreds of CSS files in my source map. How does that work?

laravel request ajax always return false

i have problem working with laravel request->ajax() its always return false. so the if statement is not working on what function is to be called. Im using datatables to render the table.
this code i have is not working properply
ContactController.php
public function index()
{
$type = request()->get('type');
$types = ['supplier', 'customer'];
if (empty($type) || !in_array($type, $types)) {
return redirect()->back();
}
if (request()->ajax()) {
if ($type == 'supplier') {
return $this->indexSupplier();
} elseif ($type == 'customer') {
return $this->indexCustomer();
} else {
die("Not Found");
}
}
$reward_enabled = (request()->session()->get('business.enable_rp') == 1 && in_array($type, ['customer'])) ? true : false;
return view('contact.index')
->with(compact('type', 'reward_enabled'));
}
private function indexSupplier()
{
if (!auth()->user()->can('supplier.view') && !auth()->user()->can('supplier.view_own')) {
abort(403, 'Unauthorized action.');
}
$business_id = request()->session()->get('user.business_id');
$contact = $this->contactUtil->getContactQuery($business_id, 'supplier');
if (request()->has('has_purchase_due')) {
$contact->havingRaw('(total_purchase - purchase_paid) > 0');
}
if (request()->has('has_purchase_return')) {
$contact->havingRaw('total_purchase_return > 0');
}
if (request()->has('has_advance_balance')) {
$contact->where('balance', '>', 0);
}
if (request()->has('has_opening_balance')) {
$contact->havingRaw('opening_balance > 0');
}
return Datatables::of($contact)
...
}
private function indexCustomer()
{
if (!auth()->user()->can('customer.view') && !auth()->user()->can('customer.view_own')) {
abort(403, 'Unauthorized action.');
}
$business_id = request()->session()->get('user.business_id');
$is_admin = $this->contactUtil->is_admin(auth()->user());
$query = $this->contactUtil->getContactQuery($business_id, 'customer');
return Datatables::of($query)
...
}
this is the sidebarblade that links to the controller.
if (auth()->user()->can('supplier.view') || auth()->user()->can('supplier.view_own')) {
$sub->url(action('ContactController#index', ['type' => 'supplier']),__('report.supplier'),
['icon' => 'fa fas fa-star', 'active' => request()->input('type') == 'upplier']);
}
if (auth()->user()->can('customer.view') || auth()->user()->can('customer.view_own')) {
$sub->url(action('ContactController#index', ['type' => 'customer']),__('report.customer'),
['icon' => 'fa fas fa-star', 'active' => request()->input('type') == 'customer']);
$sub->url(action('CustomerGroupController#index'),__('lang_v1.customer_groups'),
['icon' => 'fa fas fa-users', 'active' => request()->segment(1) == 'customer-group']);
}

Codeigniter3 - FormValidation - validate for boolean is always "false"

I'm checking JSON input data with codeigniters native FormValidation library.
I've set up the validation rules like this:
$this->form_validation->set_rules(
'active', 'myCheckbox',
'required|is_bool'
);
here is the JSON data
{
"data": {
"type": "items",
"attributes": {
"category": "5",
"description" : "my description",
"active": false
}
}
}
Problem: The rule "required" interprets the input as not present as soon as the JSON value of active is false, so that the validation only succeed if value of active is true
Question: Is there a way around this, besides changing value of active into a numeric value 1or 0 and therefore change lots of other correspondending code?
EDIT: trying isset instead of required behaves different, but also not satisfying
$this->form_validation->set_rules(
'active', 'myCheckbox',
'isset|is_bool'
);
EDIT No.2: trying in_list[false,true] instead of is_bool behaves right, but the JSON does not look right anymore, because the boolean value must be sent as a string
$this->form_validation->set_rules(
'active', 'myCheckbox',
'required|in_list[false,true]'
);
here is the JSON data
{
"data": {
"type": "items",
"attributes": {
"category": "5",
"description" : "my description",
"active": "false"
}
}
}
I had the same probleam.
I fixed it creating my own "required" and my own "is_bool".
I created a "is_required_not_null" and "is_boolean" functions and put then in my helper, so I can use it where I need.
Note that I used Identical operator(===) to make sure of variables types and values.
See below...
Helper File:
/yourApplication/helpers/yourHelperFileName_helper.php
function is_boolean($value)
{
try {
if ($value === true || $value === false)
return true;
else
return false;
} catch (\Throwable $th) {
return false;
}
}
function is_required_not_null($value)
{
try {
if ($value === null)
return false;
if ($value === true || $value === false)
return true;
if (is_array($value) && count($value) == 0) {
return false;
} else {
if (trim($value) == "")
return false;
}
return true;
} catch (\Throwable $th) {
return false;
}
}
Usage sample:
$data = $this->input->post(); //yours inputs ...
$rules = [
[
'field' => 'fieldName',
'rules' => 'is_required_not_null|is_boolean',
'label' => 'Field Name',
'errors' => [
'is_required_not_null' => 'Field %s is required.',
'is_boolean' => 'Field %s must be boolean.',
],
],
]; //yours rules ...
$this->load->library('form_validation');
$this->form_validation->set_data($data);
$this->form_validation->set_rules($rules);
if ($this->form_validation->run()) {
//Valid Code ...
}
else{
//Not Valid Code ...
}
Source docs:
https://codeigniter.com/userguide3/libraries/form_validation.html#validating-an-array-other-than-post
https://codeigniter.com/userguide3/libraries/form_validation.html#setting-rules-using-an-array
https://codeigniter.com/userguide3/libraries/form_validation.html#callable-use-anything-as-a-rule
https://codeigniter.com/userguide3/libraries/form_validation.html#setting-validation-rules

What might be best solution to get camelCase data from angular,integrate with snake_case mysql and send response in camelCase back to angular?

what i did is:
$input = $request->all();
//convert the post camelcase to snakecase
foreach ($input as $key => $val) {
$newKey = snake_case($key);
$input[$newKey] = $val;
if ($newKey != $key) {
unset($input[$key]);
}
}
after integrating data,use helper function to convert snakecase to camelcase again by the following function:
function convert_snakeCase_to_CamelCase($data)
{
if ($data) {
foreach ($data as $key1 => $val1) {
$newKey1 = camel_case($key1);
if ($newKey1 != $key1) {
unset($data[$key1]);
}
$data[$newKey1] = $val1;
if (is_array($val1) && !empty($val1)) {
foreach ($val1 as $key2 => $val2) {
$newKey2 = camel_case($key2);
if ($newKey2 != $key2) {
unset($data[$newKey1][$key2]);
}
$data[$newKey1][$newKey2] = $val2;
if (is_array($val2) && !empty($val2)) {
foreach ($val2 as $key3 => $val3) {
$newKey3 = camel_case($key3);
if ($newKey3 != $key3) {
unset($data[$newKey1][$newKey2][$key3]);
}
$data[$newKey1][$newKey2][$newKey3] = $val3;
if (is_array($val3) && !empty($val3)) {
foreach ($val3 as $key4 => $val4) {
$newKey4 = camel_case($key4);
if ($newKey4 != $key4) {
unset($data[$newKey1][$newKey2][$newKey3][$key4]);
}
$data[$newKey1][$newKey2][$newKey3][$newKey4] = $val4;
if (is_array($val4) && !empty($val4)) {
foreach ($val4 as $key5 => $val5) {
$newKey5 = camel_case($key5);
if ($newKey5 != $key5) {
unset($data[$newKey1][$newKey2][$newKey3][$newKey4][$key5]);
}
$data[$newKey1][$newKey2][$newKey3][$newKey4][$newKey5] = $val5;
if (is_array($val5) && !empty($val5)) {
foreach ($val5 as $key6 => $val6) {
$newKey6 = camel_case($key6);
if ($newKey6 != $key6) {
unset($data[$newKey1][$newKey2][$newKey3][$newKey4][$newKey5][$key6]);
}
$data[$newKey1][$newKey2][$newKey3][$newKey4][$newKey5][$newKey6] = $val6;
}
}
}
}
}
}
}
}
}
}
}
}
return $data;
}
its working absolutely fine.I was wondering is there any solution better plugins for angular or laravel to convert the post data and send response data in required case?

PHP Function to Extract Parts of a Multi-Dimensional Array Based Upon Variable Criteria

Given a multi-dimensional array, I'm looking for a method that will extract various parts of that array, given variable (i.e., different) criteria.
For example, if this is my data:
array(
'0' => array(
'0' => 'aaaaaa',
'1' => 'bbbbb',
'2' => 'ccccc'
),
'1' => array(
'0' => 'aa2ssa',
'1' => 'bb3242bb,
'2' => 'ccccc234'
),
'2' => array(
'0' => 'aaa234aa',
'1' => 'b3242b',
'2' => 'cewrcc'
),
(etc)
)
I want to be able to call a function
function new_array( index, sub_index )
that returns an array based upon the index and sub_index parameters. Using the same data but different parameters would return different data.
Example 1
new_array( array(0, 2), ( array(1, 2), array(0, 2) ) )
Expected results:
array(
'0' => array(
'1' => 'bbbbb',
'2' => 'ccccc'
),
'2' => array(
'0' => 'aaa234aa',
'2' => 'cewrcc'
)
)
Example 2
new_array( array(2), ( array(0, 2) ) )
Expected results:
array(
'2' => array(
'0' =>'aaa234aa',
'1' => 'b3242b'
)
)
Anybody know how to do this? Thank you!
An alternate solution to #Orbling's is this:
function populateData() // CHANGE ME to populate the info how you please
{
$seed = 'abcdefghijklmnopqrstuvwxyz0123456789';
$_ = ''; $length = rand(5,8);
for ($__ = 0; $__ < $length; $__++) $_ .= substr($seed,rand(0,strlen($seed)),1);
return $_;
}
function new_array()
{
$args = func_num_args();
if ($args == 0)
return FALSE; // flag error if no arguments are passed
$template = func_get_arg(0);
if ($template == null || !is_array($template) || $args < (count($template)+1))
return FALSE; // flag error if we don't have enough information
$resultAry = Array();
$arg = 1;
foreach ($template as $t)
{
$resultArySub = Array();
$templateSub = func_get_arg($arg++);
if ($templateSub == FALSE || !is_array($templateSub))
return FALSE; // error checking for valid input
foreach ($templateSub as $tS)
$resultArySub[$tS] = populateData();
$resultAry[$t] = $resultArySub;
}
return $resultAry;
}
header('Content-Type: text/plain');
echo "your request (or so i understood):\r\n";
$test = new_array(array(0,2),array(1,2),array(0,2));
var_dump($test);
echo "\r\nextra array on end is ignored:\r\n";
$test = new_array(array(4,2),array(1,2),array(0,2),array(3,5));
var_dump($test);
echo "\r\nno data is a FALSE:\r\n";
$test = new_array();
var_dump($test);
echo "\r\ntoo few arguments for what was supplied in first argument is a FALSE:\r\n";
$test = new_array(array(1,2,3),array(4,5),array(6,7));
var_dump($test);
echo "\r\nas long as there's as \"array argument\" for every element of the \"first argument\", this will work:\r\n";
$test = new_array(array(1,2,3,4,5,6,7),array(1),array(2),array(3),array(4),array(5),array(6),array(7));
var_dump($test);
echo "\r\nall arguments must be an array\r\n";
$test = new_array(array(1,2),'not','arrays');
var_dump($test);
Results in an array with random entries. The outcome of the above would be:
your request (or so i understood):
array(2) {
[0]=>
array(2) {
[1]=>
string(8) "mjdfsmda"
[2]=>
string(8) "qg2bzsj6"
}
[2]=>
array(2) {
[0]=>
string(7) "345plm8"
[2]=>
string(7) "1exlla6"
}
}
extra array on end is ignored:
array(2) {
[4]=>
array(2) {
[1]=>
string(5) "0ngei"
[2]=>
string(5) "q6tmg"
}
[2]=>
array(2) {
[0]=>
string(7) "4enz61q"
[2]=>
string(6) "6bojtn"
}
}
no data is a FALSE:
bool(false)
too few arguments for what was supplied in first argument is a FALSE:
bool(false)
as long as there's as "array argument" for every element of the "first argument", this will work:
array(7) {
[1]=>
array(1) {
[1]=>
string(7) "ndulmi9"
}
[2]=>
array(1) {
[2]=>
string(7) "jip402j"
}
[3]=>
array(1) {
[3]=>
string(5) "3bn0d"
}
[4]=>
array(1) {
[4]=>
string(8) "b80le1jh"
}
[5]=>
array(1) {
[5]=>
string(5) "x31sw"
}
[6]=>
array(1) {
[6]=>
string(8) "x8e3dge7"
}
[7]=>
array(1) {
[7]=>
string(8) "vcpf997y"
}
}
all arguments must be an array
bool(false)
Assuming that you wish the function to process an existing array and filter out the data, as seems to be the case then you could do this:
function new_array($original, $topKeys, $subKeys) {
if (count($topKeys) != count($subKeys)) {
return $original;
}
$newArray = array();
foreach ($topKeys as $cTopKey) {
$cSubKeys = array_shift($subKeys);
if (array_key_exists($cTopKey, $original)) {
$newArray[$cTopKey] = array();
foreach ($cSubKeys as $cSubKey) {
if (array_key_exists($cSubKey, $original[$cTopKey])) {
$newArray[$cTopKey][$cSubKey] = $original[$cTopKey][$cSubKey];
}
}
}
}
return $newArray;
}
If you have PHP v5.1+ and the indexes are guaranteed to be available, and in order, then I believe you can do it more simply:
function new_array($original, $topKeys, $subKeys) {
$newArray = array_intersect_key($original, array_flip($topKeys));
foreach ($newArray as $cKey => $cSub) {
$cSubKeys = array_shift($subKeys);
$newArray[$cKey] = array_intersect_key($cSub, $cSubKeys);
}
return $newArray;
}
The danger in that is I do not know if array_intersect_key() is defined to keep the original ordering of elements. If not, then further code would need to be added to match the sub keys with the original, ideally the subkeys would be sub arrays of the first parameter anyhow.
why not just
$a = array('0' =>
array('1' => 'bbbb',
'2' => 'ccccc'),
'2' =>
array('0' => 'aaaa',
'2' => 'cewrcc')
);
Why use a function to do the same?

Resources