skip to Main Content

I’m creating a Perl plugin for cPanel which has to get all domains in the account of a user and display it in a HTML select field. Originally, I’m a PHP developer, so I’m having a hard time understanding some of the logic of Perl. I do know that cPanel plugins can also be written in PHP, but for this plugin I’m limited to Perl.

This is how I get the data from cPanel:

my @user_domains = $cpliveapi->uapi('DomainInfo', 'list_domains');
@user_domains = $user_domains[0]{cpanelresult}{result}{data};

This is what it looks like using print Dumper @user_domains:

$VAR1 = {
    'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
    'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
    'main_domain' => 'main-domain.com',
    'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com']
};

I want the data to look like this (thanks @simbabque):

@domains = qw(domain1.com domain2.com domain3.com main-domain.com parked1.com parked2.com parked3.com);

So, I want to exclude sub_domains and merge the others in 1 single-dimensional array so I can loop through them with a single loop. I’ve struggled the past few days with what sounds like an extremely simple task, but I just can’t wrap my head around it.

2

Answers


  1. That isn’t doing what you think it’ doing. {} is the anonymous hash constructor, so you’re making a 1 element array, with a hash in it.

    You probably want:

    use Data::Dumper;
    
    my %user_domains = (
        'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
        'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
        'main_domain' => 'main-domain.com',
        'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com'],
    );
    
    print Dumper %user_domains;
    

    And at which point the ‘other’ array elements you can iterate through either a double loop:

    foreach my $key ( keys %user_domains ) { 
        if ( not ref $user_domains{$key} ) { 
            print $user_domains{$key},"n";
            next;
        }
        foreach my $domain (  @{$user_domains{$key}} ) {
            print $domain,"n";
        }
    }
    

    Or if you really want to ‘flatten’ your hash:

    my @flatten = map { ref $_ : @$_ ? $_ } values %user_domains;
    print Dumper @flatten;
    

    (You need the ref test, because without it, the non-array main-domain won’t work properly)

    So for the sake of consistency, you might be better off with:

    my %user_domains = (
        'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
        'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
        'main_domain' => ['main-domain.com'],
        'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com'],
    );
    
    Login or Signup to reply.
  2. You need something like this

    If you find you have a copy of List::Util that doesn’t include uniq then you can either upgrade the module or use this definition

    sub uniq {
        my %seen;
        grep { not $seen{$_}++ } @_;
    }
    

    From your dump, the uapi call is returning a reference to a hash. That goes into $cp_response and then drilling down into the structure fetches the data hash reference into $data

    delete removes the subdomain information from the hash.

    The lists you want are the values of the hash to which $data refers, so I extract those. Those values are references to arrays of strings if there is more than one domain in the list, or simple strings if there is only one

    The map converts all the domain names to a single list by dereferencing array references, or passing strings straight through. That is what the ref() ? @$_ : $_ is doing. FInally uniq removes multiple occurrences of the same name

    use List::Util 'uniq';
    
    my $cp_response = $cpliveapi->uapi('DomainInfo', 'list_domains');
    my $data        = $cp_response->{cpanelresult}{result}{data};
    
    delete $data->{sub_domains};
    
    my @domains = uniq map { ref() ? @$_ : $_ } values %$data;
    

    output

    parked1.com
    parked2.com
    parked3.com
    domain1.com
    domain2.com
    domain3.com
    main-domain.com
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search