<?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;
}
}
?>