Location: PHPKode > scripts > cpResellerClients > cpResellerClients.class.php
<?php
/*
 cpResellerClients.class.php v0.1 2011-01-05
 
 ________________________________________________________

 Copyright © 2011 Tony Phelps
 
 For how to use this class, see example.php
 
 Download from http://tweezy.net.au/cpResellerClients.html
 For enquiries contact hide@address.com
 ________________________________________________________
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ________________________________________________________
 
PUBLIC METHODS
--------------

    ->AddReseller($Domain, $User, $Password, $UseSSL=true)
        Include clients for an additional reseller account

    ->SortClients($SortField, $SortOrder=SORT_ASC)
        Sorts the client list by any field (specify field name or id)
        Use this prior to calling ->GetClients()

    ->GetClients($TemplateName='')
        Returns a list of all clients.
        If you don't specify a template, an array is returned.

    ->GetClientsOver($PercentUsed=80, $TemplateName='')
        Returns a sorted list of client whose usage is over $PercentUsed 
        If you don't specify a template, an array is returned.

    ->GetFieldNames()
        Returns a list of all field names

    ->GetTotalAllocated()
        Returns space allocated to all clients

    ->GetTotalUsed()
        Returns space used by all clients

    ->GetErrors($ClearErrors=false)
        Returns a list of any errors encountered
        If $ClearErrors is true, the error list will be emptied

NOTE:
-----
    Three fields are used internally, and have constants defined for them.
        const FIELD_START_TMST = 'Unix Startdate';
        const FIELD_QUOTA_BYTES = 'Quota (bytes)';
        const FIELD_USED_MB = 'Disk Space Used';
    If cPanel ever renames these fields you will need to change their values accordingly.

*/

class cpResellerClients {

//fields we use.. (defined here in case Panel renames them in future)
const FIELD_START_TMST = 'Unix Startdate';
const FIELD_QUOTA_BYTES = 'Quota (bytes)';
const FIELD_USED_MB = 'Disk Space Used';

const CUSTOM_USED_BYTES='Used_bytes';
const CUSTOM_PERCENT_USED='Percent_used';
const CUSTOM_START_DATE='Start_date';

protected $Client=array();
protected $Errors=array();
protected $FieldName;

public function __construct($Domain, $User, $Password, $UseSSL=true)
    { $this->_addReseller($Domain, $User, $Password, $UseSSL); }

public function AddReseller($Domain, $User, $Password, $UseSSL=true)
    {
    if(defined('SOURCE_CSV_FILE') and file_exists(SOURCE_CSV_FILE)) return;
    $this->_addReseller($Domain, $User, $Password, $UseSSL);
    }

public function SortClients($SortField, $SortOrder=SORT_ASC)
    {
    if(is_numeric($SortField) and isset($this->FieldName[$SortField]))
        { $SortField=$this->FieldName[$SortField]; }
    $this->_sortClients($this->Client, $SortField, $SortOrder);
    }

public function GetClients($TemplateName='')
    { return $this->_applyTemplate($TemplateName, $this->Client); }
    
public function GetClientsOver($PercentUsed=80, $TemplateName='')
    {
    // sort Client by descending percent used, and return those over $PercentUsed
    
    //Work on a COPY of client array..
    $Client=array();
    foreach($this->Client as $ThisClient)
        { if($ThisClient[self::CUSTOM_PERCENT_USED]>$PercentUsed) { $Client[]=$ThisClient; } }

    $this->_sortClients($Client, self::CUSTOM_PERCENT_USED, SORT_DESC);
    
    return $this->_applyTemplate($TemplateName, $Client);
    }

public function GetFieldNames()
    { return $this->FieldName; }

public function GetTotalAllocated()
    { return $this->_getTotal(self::FIELD_QUOTA_BYTES); }

public function GetTotalUsed()
    { return 1024 * $this->_getTotal(self::FIELD_USED_MB); }

public function GetErrors($ClearErrors=false)
    {
    $Errors=$this->Errors;
    if($ClearErrors) $this->Errors=array();
    return $Errors;
    }

protected function _addReseller($Domain, $User, $Password, $UseSSL)
    {
    //get response from cPanel..
    $CSV = (defined('SOURCE_CSV_FILE') and file_exists(SOURCE_CSV_FILE)) 
        ? file_get_contents(SOURCE_CSV_FILE) 
        : $this->_fetchCsv($Domain, $User, $Password, $UseSSL);
    
    //populate $this->Client array..
    if($CSV)
        { $this->_extractClients($CSV); }
        
    //add special fields..
    $this->_addCustomFields();
    }

protected function _fetchCsv($Domain, $User, $Password, $UseSSL)
    {
    // Get CSV data from cPanel..
    if ($UseSSL) 
        { $url = 'ssl:/'.'/'.$Domain; $port = 2087; } // split // for NP++ FunctionList!
    else 
        { $url = $Domain; $port = 2086; }

    $socket = @fsockopen($url, $port, $errno, $errstr);
    if ($socket) 
        {
        fputs($socket, 'POST /scripts/fetchcsv HTTP/1.0'."\r\n");
        fputs($socket, 'Host: '.$Domain."\r\n");
        fputs($socket, 'Authorization: Basic '.base64_encode($User.':'.$Password)."\r\n");
        fputs($socket, "Connection: Close\r\n");
        fputs($socket, "\r\n");
        $response='';
        while (!feof($socket))
            { $response.=fgets($socket,16384); }
        fclose($socket);

        list($Header, $TheCsv)=explode("\r\n\r\n", $response, 2);

        if(preg_match('#HTTP/1\.[01] 200#', $Header)) //success - http 200 response
            { return $TheCsv; }
        else
            {
            $this->Errors['header']=$Header;
            $this->Errors['output']=$TheCsv;
            return false;
            }
        }
    else // socket error
        {
        $this->Errors[]="Failed to open socket connection; error $errno - $errstr";
        return false;
        }
    }

protected function _extractClients($TheCsv)
    {
    // extract client details from CSV; populating $this->Client

    // $this->FieldName is regenerated for each reseller!
    $this->FieldName=array();
    $Base=count($this->Client);
    
    //split $TheCsv into array of lines..
    foreach(explode("\n", $TheCsv) as $idx=>$CsvLine)
        {
        if(''==trim($CsvLine)) break;
        //split line into fields..
        foreach(explode(',', trim($CsvLine)) as $FieldIndex=>$ThisField)
            {
            if(0==$idx) //1st row is field names
                { $this->FieldName[$FieldIndex]=$ThisField; }
            else
                { $this->Client[$Base+$idx-1][$this->FieldName[$FieldIndex]]=$ThisField; }
            }
        }
        
    //check required fields..
    if(!in_array(self::FIELD_START_TMST, $this->FieldName))
        $this->Errors[]=self::FIELD_START_TMST.' is missing - check const FIELD_START_TMST';
    if(!in_array(self::FIELD_QUOTA_BYTES, $this->FieldName))
        $this->Errors[]=self::FIELD_QUOTA_BYTES.' is missing - check const FIELD_QUOTA_BYTES';
    if(!in_array(self::FIELD_USED_MB, $this->FieldName))
        $this->Errors[]=self::FIELD_USED_MB.' is missing - check const FIELD_USED_MB';
        
    //add custom fields..
    $this->FieldName[]=self::CUSTOM_USED_BYTES;
    $this->FieldName[]=self::CUSTOM_PERCENT_USED;
    $this->FieldName[]=self::CUSTOM_START_DATE;
    }


protected function _sortClients(&$ClientArray, $SortField, $SortOrder=SORT_ASC)
    {
    if(0==count($ClientArray)) return;
    foreach ($ClientArray as $key=>$row)
        {
        if(!isset($row[$SortField])) // check done inside loop as each reseller could have different fields?
            {
            $this->Errors[]='Unknown field: '.$SortField;
            return false;
            }
        $subarray[$key]=$row[$SortField];
        }
    array_multisort($subarray, $SortOrder, $ClientArray);
    }

protected function _applyTemplate($TemplateName, $ClientArray)
    {
    //Applies a template to each client in $ClientArray; returns the output
    if(''==$TemplateName or !file_exists($TemplateName))
        { return $ClientArray; }
    
    $Template=file_get_contents($TemplateName);
    
    $Result=''; $match=array();
    preg_match_all('/\[\[(.*)\]\]/U', $Template, $match);
    
    foreach($ClientArray as $ThisClient)
        {
        $ThisTemplate=$Template;
        if($match) foreach($match[1] as $ThisMatch)
            {
            if(isset($ThisClient[$ThisMatch]))
                { $ThisTemplate=str_replace('[['.$ThisMatch.']]', $ThisClient[$ThisMatch], $ThisTemplate); }
            else
                { $this->Errors[]='Unknown template field: '.$ThisMatch; }
            }
        
        $Result.=$ThisTemplate;
        }

    return $Result;
    
    }

protected function _addCustomFields()
    {
    // add custom fields.. (underscores for spaces so we won't overwrite any cPanel field)

    // this is called after both __construct and AddReseller, so is repeated for some clients!
    foreach($this->Client as $Idx=>$ThisClient)
        {
        $this->Client[$Idx][self::CUSTOM_USED_BYTES]=(isset($ThisClient[self::FIELD_USED_MB]))
            ? 1024*$ThisClient[self::FIELD_USED_MB]
            : 0;
        $this->Client[$Idx][self::CUSTOM_PERCENT_USED]=(isset($ThisClient[self::FIELD_USED_MB]) and isset($ThisClient[self::FIELD_QUOTA_BYTES]))
            ? number_format(100*1024*$ThisClient[self::FIELD_USED_MB]/$ThisClient[self::FIELD_QUOTA_BYTES], 1)
            : 0;
        $this->Client[$Idx][self::CUSTOM_START_DATE]=(isset($ThisClient[self::FIELD_START_TMST]))
            ? date('j M Y H:i:s', $ThisClient[self::FIELD_START_TMST])
            : '?';
        }
    }

protected function _getTotal($Fieldname)
    {
    $Total=0;
    foreach($this->Client as $Idx=>$ThisClient)
        { $Total+=$ThisClient[$Fieldname]; }
    return $Total;
    }

}

?>
Return current item: cpResellerClients