phpsorting

PHP LDAP list all OU and sort with correct parent ID in each


My code does not work as intended and after sometime it starts putting the wrong data, find the ID based on the DN name and add it as the true parent_id. What I am trying to do fix an out of order list in order based on the DN

Base array

array 
[
    {
        "id": 0,
        "dn": "OU=Microsoft Exchange Security Groups,DC=local,DC=com"
    },
    {
        "id": 1,
        "dn": "OU=Domain Controllers,DC=local,DC=com"
    },
    {
        "id": 2,
        "dn": "OU=DIT,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 3,
        "dn": "OU=Service Accounts,DC=local,DC=com"
    },
    {
        "id": 4,
        "dn": "OU=STT,OU=DIT,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 5,
        "dn": "OU=STX,OU=DIT,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 6,
        "dn": "OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 7,
        "dn": "OU=DPW,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 8,
        "dn": "OU=STT,OU=DPW,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 9,
        "dn": "OU=OLG,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 10,
        "dn": "OU=DIT_Consultants,OU=DIT,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 11,
        "dn": "OU=911,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 12,
        "dn": "OU=Users,OU=911,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 13,
        "dn": "OU=PERB,OU=DVIOU,DC=local,DC=com"
    },
    {
        "id": 14,
        "dn": "OU=STX,OU=PERB,OU=DVIOU,DC=local,DC=com"
    },
    {

End result should be ... { "name": "STT", "id": 4, "level": 2, "parent": 1, "parent_name": "DIT", "dn": "OU=STT,OU=DIT,OU=DVIOU,DC=local,DC=com" },

But it does not work right because it does not sort most of the array correctly based on the DN value. I know the code needs to be reworked but cant figure out how.

    $fl;
    $fltree;
    $n = 1;
    $subparent;
    $prevparent;
    $prevDN;
    
    foreach ($values as $key => $value) {
    if($key == 'count')
        continue;   
    $d = explode(',', str_replace(",DC=local,DC=com", "", $value['dn']));

    $fl = (str_replace("OU=", "", ($d)));   
    $fo;    
    foreach ($fo as $ke => $va) {
        $r = str_replace("OU=".$fl[0].",", "", $value['dn']);
        if ($r == $va['dn'])
            $prevparent = array($ke,$va);
    }
        //get level
    $level = 1;
    foreach (array_reverse($fl) as $k => $v) {
        //$p = $fl[0];
        if ($fl[0] == $v) {
            $level = $k;
            //$prevparent = $p;
        break;
            }   
    }
        
        if (count($fl) == 1) {
        //echo ('key ' . $key .' name: ' . $fl[0] .' parent_id: ' .null . ' dn: ' . ($value['dn'])."</br>");
        $fo[$key] = (array('name' => $fl[0], 'id' => $key, 'parent_id' => 0, 'dn' => $value['dn']));
        //$n-1;
        } else {
        //echo ('key ' . $v .' name: ' . $fl[0] .' parent_id: ' . $key . ' dn: ' . ($value['dn'])."</br>");
        $fo[$key] = (array('name' => $fl[0], 'id' => $key, 'level' => $level, 'parent_id' => ($subparent[0] == $fl[1] ? ($subparent[1]) : $prevparent[0]), 'parent_name' => $prevparent[1]['name'], 'dn' => $value['dn']));
        //echo json_encode($subparent)." === ".json_encode($fl[1])."</br>";
        $n++;
        }
    $subparent = array($fl[0], $key);
        }       
    }
}
return $fo;

Solution

  • Please see the code below. If I understood something wrong, please comment and I'll correct.

    <?php
    $values=[
        ["id"=> 0,"dn"=> "OU=Microsoft Exchange Security Groups,DC=local,DC=com"],
        ["id"=> 1,"dn"=> "OU=Domain Controllers,DC=local,DC=com"],
        ["id"=> 2,"dn"=> "OU=DIT,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 3,"dn"=> "OU=Service Accounts,DC=local,DC=com"],
        ["id"=> 4,"dn"=> "OU=STT,OU=DIT,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 5,"dn"=> "OU=STX,OU=DIT,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 6,"dn"=> "OU=DVIOU,DC=local,DC=com"],
        ["id"=> 7,"dn"=> "OU=DPW,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 8,"dn"=> "OU=STT,OU=DPW,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 9,"dn"=> "OU=OLG,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 10,"dn"=> "OU=DIT_Consultants,OU=DIT,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 11,"dn"=> "OU=911,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 12,"dn"=> "OU=Users,OU=911,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 13,"dn"=> "OU=PERB,OU=DVIOU,DC=local,DC=com"],
        ["id"=> 14,"dn"=> "OU=STX,OU=PERB,OU=DVIOU,DC=local,DC=com"]
    ];
    
    //Let's make dictionary
    foreach($values as $val){
        //Find all OU
        preg_match_all('/OU=([^,]+)/',$val['dn'],$m);
        //print_r($m);
        $name=$m[1][0];
        //Add elements to array
        $val=array_merge($val,[
            'name'=>$name,
            'parent'=>null, //This will be done later
            'level'=>count($m[1]),
            'parent_name'=>$m[1][1] ?? '',
        ]);
    
        $dict[$name]=$val;
    }
    print_r($dict);
    
    //Let's get parent IDs from dictionary by name
    foreach($dict as &$val)
        $val['parent']=$dict[$val['parent_name']]['id'] ?? null;
    
    //Be careful using values by reference.
    //If you use it again later, you can break last array element 
    //to which it references. So better unset it.
    unset($val);
    
    print_r($dict);
    
    //Remove keys
    $result=array_values($dict);
    //Sort by IDs
    sort($result);
    print_r($result);
    

    https://3v4l.org/5dSC1