The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Locate line variable in JSON dumpzone data

Discussion in 'cPanel Developers' started by mikelegg, Dec 23, 2010.

  1. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    In the documentation for the EditZoneRecord function it says "In the output of the dumpzone function, locate the Line variable corresponding to the data you wish to edit."

    This is easier said than done.

    I've just about gone nuts using json_decode() and then trying to write a recursive search function that will loop through a multi-dimensional array (in which not all of the mid-level elements are arrays), find a match on two elements (name and type) and then return the value of another element (Line).

    So instead, I've written my own function that just treats the JSON data as a string, which is then manipulated into a two dimensional array using split(). I can then use in_array() to identify and extract the line number.

    It's not as elegant as I would like and it doesn't work with any of the SOA data - only the individual DNS records, but it does the job that I need it to.

    Code:
    function GetLineNumber($strZoneDump, $strType, $strName){
    
    	// Set a default return value of zero
    	$intReturn = 0;
    
    	// Remove double quotes
    	$strZoneDump = str_replace('"', '', $strZoneDump);
    	
    	// Split on },{ to create an array of rows
    	$arrRows = split("},{", $strZoneDump);
    	
    	$i = 0;
    	$blnFound = false;
    	
    	// Loop through rows 
    	foreach($arrRows as $key => $value){
    	
    		// Create a multi-dimensional array from each row by splitting on commas
    		$arrDetails[$i] = split(",", $value);
    		
    		// Loop through each detail array
    		foreach($arrDetails[$i] as $key2 => $value2){
    			
    			// Look for an array that contains matches for both the 'name' and 'type' specified 
    			if(in_array('name:'. $strName, $arrDetails[$i]) && in_array('type:'. $strType, $arrDetails[$i])){
    			
    				// if found, set the return value to the number part of the 'Line' element
    				$intReturn = substr($arrDetails[$i][0], 5, strlen($arrDetails[$i][0]) - 5);
    				$blnFound = true;
    				break;
    			}
    		}
    		
    		// break out of the outer loop once the line has been located
    		if($blnFound){
    			break;
    		}
                 
                    $i++;
    	}
    	
    	return $intReturn;
    }
    What is everybody else doing to locate the line numbers?
     
    #1 mikelegg, Dec 23, 2010
    Last edited: Dec 23, 2010
  2. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    Here's a slightly more elegant version using json_decode

    PHP:
    function GetLineNumber($strZoneDump$strType$strName){

        
    $intReturn 0;
        
    $blnFound false;
        
        
    $arrZoneDump json_decode($strZoneDumptrue);

        foreach(
    $arrZoneDump as $key0 => $value0){
            foreach(
    $value0 as $key1 => $value1){
                foreach(
    $value1 as $key2 => $value2){
                    if(
    is_array($value2)){
                        foreach(
    $value2 as $key3 => $value3){
                            if( 
    in_array($strName$value3) && in_array($strType$value3) ){
                                
    $intReturn $value3["Line"];
                                
    $blnFound true;
                                break;
                            }
                        }
                    } 
                    if(
    $blnFound){break;}
                }
                if(
    $blnFound){break;}
            }
            if(
    $blnFound){break;}
        }
        
        return 
    $intReturn;
    }
    If I can make it recursive I'll be happier, but this works because there is a known depth to the sub-arrays.
     
  3. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    Slightly more compact version ...

    PHP:
    function GetLineNumber($strZoneDump$strType$strName){
        
        
    $arrZoneDump json_decode($strZoneDumptrue);

        foreach(
    $arrZoneDump as $key0 => $value0){
            foreach(
    $value0 as $key1 => $value1){
                foreach(
    $value1 as $key2 => $value2){
                    if(
    is_array($value2)){
                        foreach(
    $value2 as $key3 => $value3){
                            if(
    in_array($strName$value3) && in_array($strType$value3)){
                                return 
    $value3["Line"];
                            }
                        }
                    } 
                }
            }
        }
        
        return 
    0;
    }
     
  4. MattDees

    MattDees cPanel Product Owner
    Staff Member

    Joined:
    Apr 29, 2005
    Messages:
    417
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    With dumpzone, I have been unable to find a circumstance where those arrays contain more than one element. So something like the following should be alot more elegant and easier to work with:

    PHP:
    include("../xmlapi.php");

    $xmlapi = new xmlapi($ip'root'$pass);

    $xmlapi->set_debug(1);
    $xmlapi->set_output('json');
    $out $xmlapi->dumpzone$domain );
    $parsed_out json_decode$out );
    // Every line above this is merely performing query + placing the response from the API and json_decode into $parsed_out

    foreach ( $parsed_out->result[0]->record as $record ) {
        
    // Do individual record logic here
        //print_r($record);
        
    print "line: " $record->Line "\n";
        print 
    "type:  " $record->type "\n\n";
    }
     
  5. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    Thanks Matt

    I'll have a play with it and see how it goes.
     
  6. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    I've tried to get this working on the understanding that $parsed_out is just json_decode(<dumpzone output>)
    But I just get ...
    on the line
    I can loop through the data using a normal foreach, but that just takes me back to square one where I have to loop within loops to get to the actual data I want.
     
    #6 mikelegg, Jun 3, 2011
    Last edited: Jun 3, 2011
  7. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Hi mikelegg,

    I tested the example that Matt provided and it worked fine for me.
    The only thing I did, to reproduced your issue, that came close to the error that you are reporting was by passing an invalid zone in the query:


    Code:
    URL: https://10.1.1.1:2087/json-api/dumpzone
    DATA: domain=asfaewrowejknfasierfaerf.fake
    Authentication Header: Authorization: Basic cm9vdDpyb290c2VjcmF0
    
    
    RESPONSE:
     {"result":[{"status":0,"statusmsg":"Zone does not exist."}]}
    PHP Notice:  Undefined property: stdClass::$record in /Users/david/tmp/cp_xmlapi_php/dumpzone.php on line 14
    PHP Warning:  Invalid argument supplied for foreach() in /Users/david/tmp/cp_xmlapi_php/dumpzone.php on line 14
    
    This situation should be easy to test for before performing the loop
    PHP:
    $parsed_out json_decode$out );

    if ( !
    is_array($parsed_out->result
     
    15    || $parsed_out->result[0]->status == 
     16    
    || !array_key_exists('record'get_object_vars($parsed_out->result[0]))
     
    17    || !is_array($parsed_out->result[0]->record))
     
    18 {    
     
    19     print "Cannot iterate over returned result.\nThere must be an error.\n";
     
    20     exit;
     
    21 }
    Regards,
    -DavidN
     
  8. mikelegg

    mikelegg Well-Known Member

    Joined:
    Mar 29, 2005
    Messages:
    330
    Likes Received:
    0
    Trophy Points:
    16
    I think I might know why I'm having problems, I'm writing my code from scratch, but the example provided uses the xmlapi.php which I didn't know existed until today.
     
  9. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Oh! Well, sorry about that. Poor assumption on Matt and I's side.

    You can grab a copy at cPanel's github.

    Let me know if you have any questions about it!

    Regards,
    -DavidN
     
Loading...

Share This Page