xmlapi::__construct()   F
last analyzed

Complexity

Conditions 27
Paths 3536

Size

Total Lines 82

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 82
rs 0
c 0
b 0
f 0
cc 27
nc 3536
nop 3

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * cPanel XMLAPI Client Class
5
 *
6
 * This class allows for easy interaction with cPanel's XML-API allow functions within the XML-API to be called 
7
 * by calling funcions within this class
8
 *  
9
 * LICENSE:
10
 *
11
 * Copyright (c) 2009, cPanel, Inc.
12
 * All rights reserved.
13
 *
14
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
15
 * that the following conditions are met:
16
 *
17
 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the
18
 *   following disclaimer.
19
 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20
 *   following disclaimer in the documentation and/or other materials provided with the distribution.
21
 * * Neither the name of the cPanel, Inc. nor the names of its contributors may be used to endorse or promote
22
 *   products derived from this software without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
25
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
26
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
 * POSSIBILITY OF SUCH DAMAGE.
32
 *
33
 * Version: 1.0.7
34
 * Last updated: 10 November 2010
35
 *
36
 * Changes
37
 *
38
 * 1.0.8:
39
 * correct unpark bug as reported by Randall Kent
40
 *
41
 * 1.0.7:
42
 * Corrected typo for setrellerlimits where xml_query incorrectly called xml-api's setresellerips 
43
 *
44
 * 1.0.6:
45
 * Changed 'user' URL parameter for API1/2 calls to 'cpanel_xmlapi_user'/'cpanel_jsonapi_user' to resolve conflicts with API2 functions that use 'user' as a parameter
46
 * Relocated exmaple script to Example subdirectory
47
 * Modified example scripts to take remote server IP and root password from environment variables REMOTE_HOST and REMOTE_PASSWORD, respectively
48
 * Created subdirectory Tests for PHPUnit tests
49
 * Add PHPUnit test BasicParseTest.php
50
 *
51
 * 1.0.5:
52
 * fix bug where api1_query and api2_query would not return JSON data
53
 *
54
 * 1.0.4:
55
 * set_port will now convert non-int values to ints
56
 *
57
 * 1.0.3:
58
 * Fixed issue with set_auth_type using incorrect logic for determining acceptable auth types
59
 * Suppress non-UTF8 encoding when using curl 
60
 *
61
 * 1.0.2:
62
 * Increased curl buffer size to 128kb from 16kb
63
 * Fix double encoding issue in terminateresellers()
64
 *
65
 * 1.0.1:
66
 * Fixed use of wrong variable name in curl error checking
67
 * adjust park() to use api2 rather than API1
68
 *
69
 * 1.0
70
 * Added in 11.25 functions
71
 * Changed the constructor to allow for either the "DEFINE" config setting method or using parameters
72
 * Removed used of the gui setting
73
 * Added fopen support
74
 * Added auto detection for fopen or curl (uses curl by default)
75
 * Added ability to return in multiple formats: associative array, simplexml, xml, json
76
 * Added PHP Documentor documentation for all necessary functions
77
 * Changed submission from GET to POST
78
 *
79
 *
80
 * @copyright 2009 cPanel, Inc
81
 * @license http://sdk.cpanel.net/license/bsd.html
82
 * @version 1.0.6
83
 * @link http://twiki.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/XmlApi
84
 * @since File available since release 0.1
85
 * */
86
/**
87
 * The base XML-API class
88
 *
89
 * The XML-API class allows for easy execution of cPanel XML-API calls.  The goal of this project is to create 
90
 * an open source library that can be used for multiple types of applications.  This class relies on PHP5 compiled
91
 * with both curl and simplexml support.
92
 *
93
 * Making Calls with this class are done in the following steps:
94
 *
95
 * 1.) Instaniating the class:
96
 * $xmlapi = new xmlapi($host);
97
 *
98
 * 2.) Setting access credentials within the class via either set_password or set_hash:
99
 * $xmlapi->set_hash("username", $accessHash);
100
 * $xmlapi->set_password("username", "password");
101
 * 
102
 * 3.) Execute a function
103
 * $xmlapi->listaccts();
104
 *
105
 * @category Cpanel
106
 * @package xmlapi
107
 * @copyright 2009 cPanel, Inc.
108
 * @license http://sdk.cpanel.net/license/bsd.html
109
 * @version Release: 1.0.6
110
 * @link http://twiki.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/XmlApi
111
 * @since Class available since release 0.1
112
 * */
113
114
namespace ExpressApi\Apis;
115
116
use Exception;
117
118
class xmlapi {
119
120
    // should debugging statements be printed?
121
    private $debug = false;
122
    // The host to connect to
123
    private $host = '127.0.0.1';
124
    // the port to connect to
125
    private $port = '2087';
126
    // should be the literal strings http or https
127
    private $protocol = 'https';
128
    // output that should be given by the xml-api
129
    private $output = 'simplexml';
130
    // literal strings hash or password
131
    private $auth_type = null;
132
    //  the actual password or hash
133
    private $auth = null;
134
    // username to authenticate as
135
    private $user = null;
136
    // The HTTP Client to use
137
138
    private $http_client = 'curl';
139
140
    /**
141
     * Instantiate the XML-API Object
142
     * All parameters to this function are optional and can be set via the accessor functions or constants
143
     * This defaults to password auth, however set_hash can be used to use hash authentication
144
     *
145
     * @param string $host The host to perform queries on
146
     * @param string $user The username to authenticate as
147
     * @param string $password The password to authenticate with
148
     * @return Xml_Api object
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
149
     */
150
    public function __construct($host = null, $user = null, $password = null) {
151
152
        // Check if debugging must be enabled
153
        if ((defined('XMLAPI_DEBUG')) && (XMLAPI_DEBUG == '1')) {
154
            $this->debug = true;
155
        }
156
157
        // Check if raw xml output must be enabled
158
        if ((defined('XMLAPI_RAW_XML')) && (XMLAPI_RAW_XML == '1')) {
159
            $this->raw_xml = true;
0 ignored issues
show
Bug introduced by
The property raw_xml does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
160
        }
161
162
        /**
163
         * Authentication
164
         * This can either be passed at this point or by using the set_hash or set_password functions
165
         * */
166
        if (( defined('XMLAPI_USER') ) && ( strlen(XMLAPI_USER) > 0 )) {
167
            $this->user = XMLAPI_USER;
168
169
            // set the authtype to pass and place the password in $this->pass
170
            if (( defined('XMLAPI_PASS') ) && ( strlen(XMLAPI_PASS) > 0 )) {
171
                $this->auth_type = 'pass';
172
                $this->auth = XMLAPI_PASS;
173
            }
174
175
            // set the authtype to hash and place the hash in $this->auth
176
            if (( defined('XMLAPI_HASH') ) && ( strlen(XMLAPI_HASH) > 0 )) {
177
                $this->auth_type = 'hash';
178
                $this->auth = preg_replace("/(\n|\r|\s)/", '', XMLAPI_HASH);
179
            }
180
181
            // Throw warning if XMLAPI_HASH and XMLAPI_PASS are defined
182
            if (( ( defined('XMLAPI_HASH') ) && ( strlen(XMLAPI_HASH) > 0 ) ) && ( ( defined('XMLAPI_PASS') ) && ( strlen(XMLAPI_PASS) > 0 ) )) {
183
                error_log('warning: both XMLAPI_HASH and XMLAPI_PASS are defined, defaulting to XMLAPI_HASH');
184
            }
185
186
187
            // Throw a warning if XMLAPI_HASH and XMLAPI_PASS are undefined and XMLAPI_USER is defined
188
            if (!(defined('XMLAPI_HASH') ) || !defined('XMLAPI_PASS')) {
189
                error_log('warning: XMLAPI_USER set but neither XMLAPI_HASH or XMLAPI_PASS have not been defined');
190
            }
191
        }
192
193
        if (( $user != null ) && ( strlen($user) < 9 )) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $user of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
194
            $this->user = $user;
195
        }
196
197
        if ($password != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $password of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
198
            $this->set_password($password);
199
        }
200
201
        /**
202
         * Connection
203
         * 
204
         * $host/XMLAPI_HOST should always be equal to either the IP of the server or it's hostname
205
         */
206
        // Set the host, error if not defined
207
        if ($host == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $host of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
208
            if ((defined('XMLAPI_HOST')) && (strlen(XMLAPI_HOST) > 0)) {
209
                $this->host = XMLAPI_HOST;
210
            } else {
211
                throw new Exception("No host defined");
212
            }
213
        } else {
214
            $this->host = $host;
215
        }
216
217
218
        // disabling SSL is probably a bad idea.. just saying.		
219
        if (defined('XMLAPI_USER_SSL') && (XMLAPI_USE_SSL == '0' )) {
220
            $this->protocol = "http";
221
        }
222
223
        // Detemine what the default http client should be.
224
        if (function_exists('curl_setopt')) {
225
            $this->http_client = "curl";
226
        } elseif (ini_get('allow_url_fopen')) {
227
            $this->http_client = "fopen";
228
        } else {
229
            throw new Exception('allow_url_fopen and curl are neither available in this PHP configuration');
230
        }
231
    }
232
233
    /**
234
     * Accessor Functions
235
     * */
236
237
    /**
238
     * Return whether the debug option is set within the object
239
     *
240
     * @return boolean
241
     * @see set_debug()
242
     */
243
    public function get_debug() {
244
        return $this->debug;
245
    }
246
247
    /**
248
     * Turn on debug mode
249
     *
250
     * Enabling this option will cause this script to print debug information such as
251
     * the queries made, the response XML/JSON and other such pertinent information.
252
     * Calling this function without any parameters will enable debug mode.
253
     *
254
     * @param bool $debug turn on or off debug mode
255
     * @see get_debug()
256
     */
257
    public function set_debug($debug = 1) {
258
        $this->debug = $debug;
0 ignored issues
show
Documentation Bug introduced by
The property $debug was declared of type boolean, but $debug is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
259
    }
260
261
    /**
262
     * Get the host being connected to
263
     *
264
     * This function will return the host being connected to
265
     * @return string host
266
     * @see set_host()
267
     */
268
    public function get_host() {
269
        return $this->host;
270
    }
271
272
    /**
273
     * Set the host to query
274
     *
275
     * Setting this will set the host to be queried
276
     * @param string $host The host to query
277
     * @see get_host()
278
     */
279
    public function set_host($host) {
280
        $this->host = $host;
281
    }
282
283
    /**
284
     * Get the port to connect to
285
     *
286
     * This will return which port the class is connecting to
287
     * @return int $port
288
     * @see set_port()
289
     */
290
    public function get_port() {
291
        return $this->port;
292
    }
293
294
    /**
295
     * Set the port to connect to
296
     *
297
     * This will allow a user to define which port needs to be connected to.
298
     * The default port set within the class is 2087 (WHM-SSL) however other ports are optional
299
     * this function will automatically set the protocol to http if the port is equal to:
300
     *    - 2082
301
     *    - 2086
302
     *    - 2095
303
     *    - 80
304
     * @param int $port the port to connect to
305
     * @see set_protocol()
306
     * @see get_port()
307
     */
308
    public function set_port($port) {
309
        if (!is_int($port)) {
310
            $port = intval($port);
311
        }
312
313
        if ($port < 1 || $port > 65535) {
314
            throw new Exception('non integer or negative integer passed to set_port');
315
        }
316
317
        // Account for ports that are non-ssl
318
        if ($port == '2086' || $port == '2082' || $port == '80' || $port == '2095') {
319
            $this->set_protocol('http');
320
        }
321
322
        $this->port = $port;
0 ignored issues
show
Documentation Bug introduced by
The property $port was declared of type string, but $port is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
323
    }
324
325
    /**
326
     * Return the protocol being used to query
327
     *
328
     * This will return the protocol being connected to
329
     * @return string
330
     * @see set_protocol()
331
     */
332
    public function get_protocol() {
333
        return $this->protocol;
334
    }
335
336
    /**
337
     * Set the protocol to use to query
338
     *
339
     * This will allow you to set the protocol to query cpsrvd with.  The only to acceptable values
340
     * to be passed to this function are 'http' or 'https'.  Anything else will cause the class to throw
341
     * an Exception.
342
     * @param string $proto the protocol to use to connect to cpsrvd
343
     * @see get_protocol()
344
     */
345
    public function set_protocol($proto) {
346
        if ($proto != 'https' && $proto != 'http') {
347
            throw new Exception('https and http are the only protocols that can be passed to set_protocol');
348
        }
349
        $this->protocol = $proto;
350
    }
351
352
    /**
353
     * Return what format calls with be returned in
354
     *
355
     * This function will return the currently set output format
356
     * @see set_output()
357
     * @return string
358
     */
359
    public function get_output() {
360
        return $this->output;
361
    }
362
363
    /**
364
     * Set the output format for call functions
365
     *
366
     * This class is capable of returning data in numerous formats including:
367
     *   - json
368
     *   - xml
369
     *   - {@link http://php.net/simplexml SimpleXML}
370
     *   - {@link http://us.php.net/manual/en/language.types.array.php Associative Arrays}
371
     *
372
     * These can be set by passing this class any of the following values:
373
     *   - json - return JSON string
374
     *   - xml - return XML string
375
     *   - simplexml - return SimpleXML object
376
     *   - array - Return an associative array
377
     *
378
     * Passing any value other than these to this class will cause an Exception to be thrown.
379
     * @param string $output the output type to be set
380
     * @see get_output()
381
     */
382
    public function set_output($output) {
383
        if ($output != 'json' && $output != 'xml' && $output != 'array' && $output != 'simplexml') {
384
            throw new Exception('json, xml, array and simplexml are the only allowed values for set_output');
385
        }
386
        $this->output = $output;
387
    }
388
389
    /**
390
     * Return the auth_type being used
391
     *
392
     * This function will return a string containing the auth type in use
393
     * @return string auth type
394
     * @see set_auth_type()
395
     */
396
    public function get_auth_type() {
397
        return $this->auth_type;
398
    }
399
400
    /**
401
     * Set the auth type
402
     *
403
     * This class is capable of authenticating with both hash auth and password auth
404
     * This function will allow you to manually set which auth_type you are using.
405
     *
406
     * the only accepted parameters for this function are "hash" and "pass" anything else will cuase
407
     * an exception to be thrown
408
     *
409
     * @see set_password()
410
     * @see set_hash()
411
     * @see get_auth_type()
412
     * @param string auth_type the auth type to be set
413
     */
414
    public function set_auth_type($auth_type) {
415
        if ($auth_type != 'hash' && $auth_type != 'pass') {
416
            throw new Exception('the only two allowable auth types arehash and path');
417
        }
418
        $this->auth_type = $auth_type;
419
    }
420
421
    /**
422
     * Set the password to be autenticated with
423
     *
424
     * This will set the password to be authenticated with, the auth_type will be automatically adjusted
425
     * when this function is used
426
     *
427
     * @param string $pass the password to authenticate with
428
     * @see set_hash()
429
     * @see set_auth_type()
430
     * @see set_user()
431
     */
432
    public function set_password($pass) {
433
        $this->auth_type = 'pass';
434
        $this->auth = $pass;
435
    }
436
437
    /**
438
     * Set the hash to authenticate with
439
     *
440
     * This will set the hash to authenticate with, the auth_type will automatically be set when this function
441
     * is used.  This function will automatically strip the newlines from the hash.
442
     * @param string $hash the hash to autenticate with
443
     * @see set_password()
444
     * @see set_auth_type()
445
     * @see set_user()
446
     */
447
    public function set_hash($hash) {
448
        $this->auth_type = 'hash';
449
        $this->auth = preg_replace("/(\n|\r|\s)/", '', $hash);
450
    }
451
452
    /**
453
     * Return the user being used for authtication
454
     *
455
     * This will return the username being authenticated against.
456
     *
457
     * @return string
458
     */
459
    public function get_user() {
460
        return $this->user;
461
    }
462
463
    /**
464
     * Set the user to authenticate against
465
     *
466
     * This will set the user being authenticated against.
467
     * @param string $user username
468
     * @see set_password()
469
     * @see set_hash()
470
     * @see get_user()
471
     */
472
    public function set_user($user) {
473
        $this->user = $user;
474
    }
475
476
    /**
477
     * Set the user and hash to be used for authentication
478
     *
479
     * This function will allow one to set the user AND hash to be authenticated with
480
     * 
481
     * @param string $user username
482
     * @param string $hash WHM Access Hash
483
     * @see set_hash()
484
     * @see set_user()
485
     */
486
    public function hash_auth($user, $hash) {
487
        $this->set_hash($hash);
488
        $this->set_user($user);
489
    }
490
491
    /**
492
     * Set the user and password to be used for authentication
493
     *
494
     * This function will allow one to set the user AND password to be authenticated with
495
     * @param string $user username
496
     * @param string $pass password
497
     * @see set_pass()
498
     * @see set_user()
499
     */
500
    public function password_auth($user, $pass) {
501
        $this->set_password($pass);
502
        $this->set_user($user);
503
    }
504
505
    /**
506
     * Return XML format
507
     *
508
     * this function will cause call functions to return XML format, this is the same as doing:
509
     *   set_output('xml')
510
     *
511
     * @see set_output()
512
     */
513
    public function return_xml() {
514
        $this->set_output('xml');
515
    }
516
517
    /**
518
     * Return simplexml format
519
     *
520
     * this function will cause all call functions to return simplexml format, this is the same as doing:
521
     *   set_output('simplexml')
522
     *
523
     * @see set_output()
524
     */
525
    public function return_object() {
526
        $this->set_output('simplexml');
527
    }
528
529
    /**
530
     * Set the HTTP client to use
531
     *
532
     * This class is capable of two types of HTTP Clients:
533
     *   - curl
534
     *   - fopen
535
     *
536
     * When using allow url fopen the class will use get_file_contents to perform the query
537
     * The only two acceptable parameters for this function are 'curl' and 'fopen'.
538
     * This will default to fopen, however if allow_url_fopen is disabled inside of php.ini
539
     * it will switch to curl
540
     *
541
     * @param string client The http client to use
542
     * @see get_http_client()
543
     */
544
    public function set_http_client($client) {
545
        if (( $client != 'curl' ) && ( $client != 'fopen' )) {
546
            throw new Exception('only curl and fopen and allowed http clients');
547
        }
548
        $this->http_client = $client;
549
    }
550
551
    /**
552
     * Get the HTTP Client in use
553
     *
554
     * This will return a string containing the HTTP client currently in use
555
     *
556
     * @see set_http_client()
557
     * @return string
558
     */
559
    public function get_http_client() {
560
        return $this->http_client;
561
    }
562
563
    /* 	
564
     * 	Query Functions
565
     * 	--
566
     * 	This is where the actual calling of the XML-API, building API1 & API2 calls happens
567
     */
568
569
    /**
570
     * Perform an XML-API Query
571
     *
572
     * This function will perform an XML-API Query and return the specified output format of the call being made
573
     *
574
     * @param string $function The XML-API call to execute
575
     * @param array $vars An associative array of the parameters to be passed to the XML-API Calls
576
     * @return mixed
577
     */
578
    public function xmlapi_query($function, $vars = array()) {
579
580
        // Check to make sure all the data needed to perform the query is in place
581
        if (!$function) {
582
            throw new Exception('xmlapi_query() requires a function to be passed to it');
583
        }
584
585
        if ($this->user == null) {
586
            throw new Exception('no user has been set');
587
        }
588
589
        if ($this->auth == null) {
590
            throw new Exception('no authentication information has been set');
591
        }
592
593
        // Build the query:
594
595
        $query_type = '/xml-api/';
596
597
        if ($this->output == 'json') {
598
            $query_type = '/json-api/';
599
        }
600
601
        $args = http_build_query($vars, '', '&');
602
        $url = $this->protocol . '://' . $this->host . ':' . $this->port . $query_type . $function;
603
604
        if ($this->debug) {
605
            error_log('URL: ' . $url);
606
            error_log('DATA: ' . $args);
607
        }
608
609
        // Set the $auth string
610
611
        $authstr;
0 ignored issues
show
Bug introduced by
The variable $authstr seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
612
        if ($this->auth_type == 'hash') {
613
            $authstr = 'Authorization: WHM ' . $this->user . ':' . $this->auth . "\r\n";
614
        } elseif ($this->auth_type == 'pass') {
615
            $authstr = 'Authorization: Basic ' . base64_encode($this->user . ':' . $this->auth) . "\r\n";
616
        } else {
617
            throw new Exception('invalid auth_type set');
618
        }
619
620
        if ($this->debug) {
621
            error_log("Authentication Header: " . $authstr . "\n");
622
        }
623
624
        // Perform the query (or pass the info to the functions that actually do perform the query)
625
626
        $response;
0 ignored issues
show
Bug introduced by
The variable $response seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
627
        if ($this->http_client == 'curl') {
628
            $response = $this->curl_query($url, $args, $authstr);
629
        } elseif ($this->http_client == 'fopen') {
630
            $response = $this->fopen_query($url, $args, $authstr);
631
        }
632
633
634
635
        /*
636
         * 	Post-Query Block
637
         * Handle response, return proper data types, debug, etc
638
         */
639
640
        // print out the response if debug mode is enabled.
641
        if ($this->debug) {
642
            error_log("RESPONSE:\n " . $response);
0 ignored issues
show
Bug introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
643
        }
644
645
        // The only time a response should contain <html> is in the case of authentication error
646
        // cPanel 11.25 fixes this issue, but if <html> is in the response, we'll error out.
647
648
        if (stristr($response, '<html>') == true) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($response, '<html>') of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
649
            if (stristr($response, 'Login Attempt Failed') == true) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($response, 'Login Attempt Failed') of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
650
                error_log("Login Attempt Failed");
651
                return;
652
            }
653
            if (stristr($response, 'action="/login/"') == true) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($response, 'action="/login/"') of type string to the boolean true. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
654
                error_log("Authentication Error");
655
                return;
656
            }
657
            return;
658
        }
659
660
661
        // perform simplexml transformation (array relies on this)
662
        if (($this->output == 'simplexml') || $this->output == 'array') {
663
            $response = simplexml_load_string($response, null, LIBXML_NOERROR | LIBXML_NOWARNING);
664
            if (!$response) {
665
                error_log("Some error message here");
666
                return;
667
            }
668
            if ($this->debug) {
669
                error_log("SimpleXML var_dump:\n" . print_r($response, true));
670
            }
671
        }
672
673
        // perform array tranformation
674
        if ($this->output == 'array') {
675
            $response = $this->unserialize_xml($response);
676
            if ($this->debug) {
677
                error_log("Associative Array var_dump:\n" . print_r($response, true));
678
            }
679
        }
680
        return $response;
681
    }
682
683
    private function curl_query($url, $postdata, $authstr) {
684
        $curl = curl_init();
685
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
686
        // Return contents of transfer on curl_exec
687
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
688
        // Allow self-signed certs
689
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
690
        // Set the URL
691
        curl_setopt($curl, CURLOPT_URL, $url);
692
        // Increase buffer size to avoid "funny output" exception
693
        curl_setopt($curl, CURLOPT_BUFFERSIZE, 131072);
694
695
        // Pass authentication header
696
        $header[0] = $authstr .
0 ignored issues
show
Coding Style Comprehensibility introduced by
$header was never initialized. Although not strictly required by PHP, it is generally a good practice to add $header = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
697
                "Content-Type: application/x-www-form-urlencoded\r\n" .
698
                "Content-Length: " . strlen($postdata) . "\r\n" . "\r\n" . $postdata;
699
700
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
701
702
        curl_setopt($curl, CURLOPT_POST, 1);
703
704
        $result = curl_exec($curl);
705
        if ($result == false) {
706
            throw new Exception("curl_exec threw error \"" . curl_error($curl) . "\" for " . $url . "?" . $postdata);
707
        }
708
        curl_close($curl);
709
        return $result;
710
    }
711
712
    private function fopen_query($url, $postdata, $authstr) {
713
        if (!(ini_get('allow_url_fopen') )) {
714
            throw new Exception('fopen_query called on system without allow_url_fopen enabled in php.ini');
715
        }
716
717
        $opts = array(
718
            'http' => array(
719
                'allow_self_signed' => true,
720
                'method' => 'POST',
721
                'header' => $authstr .
722
                "Content-Type: application/x-www-form-urlencoded\r\n" .
723
                "Content-Length: " . strlen($postdata) . "\r\n" .
724
                "\r\n" . $postdata
725
            )
726
        );
727
        $context = stream_context_create($opts);
728
        return file_get_contents($url, false, $context);
729
    }
730
731
    /*
732
     * Convert simplexml to associative arrays
733
     *
734
     * This function will convert simplexml to associative arrays.
735
     */
736
737
    private function unserialize_xml($input, $callback = null, $recurse = false) {
738
        // Get input, loading an xml string with simplexml if its the top level of recursion
739
        $data = ( (!$recurse) && is_string($input) ) ? simplexml_load_string($input) : $input;
740
        // Convert SimpleXMLElements to array
741
        if ($data instanceof SimpleXMLElement) {
0 ignored issues
show
Bug introduced by
The class ExpressApi\Apis\SimpleXMLElement does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
742
            $data = (array) $data;
743
        }
744
        // Recurse into arrays
745
        if (is_array($data)) {
746
            foreach ($data as &$item) {
747
                $item = $this->unserialize_xml($item, $callback, true);
748
            }
749
        }
750
        // Run callback and return
751
        return (!is_array($data) && is_callable($callback)) ? call_user_func($callback, $data) : $data;
752
    }
753
754
    /* TO DO:
755
      Implement API1 and API2 query functions!!!!!
756
     */
757
758
    /**
759
     * Call an API1 function
760
     *
761
     * This function allows you to call API1 from within the XML-API,  This allowes a user to peform actions
762
     * such as adding ftp accounts, etc
763
     *
764
     * @param string $user The username of the account to perform API1 actions on
765
     * @param string $module The module of the API1 call to use
766
     * @param string $function The function of the API1 call
767
     * @param array $args The arguments for the API1 function, this should be a non-associative array
768
     * @return mixed
769
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CallingAPIFunctions XML API Call documentation
770
     * @link http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiRef/WebHome API1 & API2 Call documentation
771
     * @link http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiBasics/CallingApiOne API1 Documentation
772
     */
773
    public function api1_query($user, $module, $function, $args = array()) {
774
        if (!isset($module) || !isset($function) || !isset($user)) {
775
            error_log("api1_query requires that a module and function are passed to it");
776
            return false;
777
        }
778
779
        if (!is_array($args)) {
780
            error_log('api1_query requires that it is passed an array as the 4th parameter');
781
            return false;
782
        }
783
784
        $cpuser = 'cpanel_xmlapi_user';
785
        $module_type = 'cpanel_xmlapi_module';
786
        $func_type = 'cpanel_xmlapi_func';
787
        $api_type = 'cpanel_xmlapi_apiversion';
788
789
        if ($this->get_output() == 'json') {
790
            $cpuser = 'cpanel_jsonapi_user';
791
            $module_type = 'cpanel_jsonapi_module';
792
            $func_type = 'cpanel_jsonapi_func';
793
            $api_type = 'cpanel_jsonapi_apiversion';
794
        }
795
796
        $call = array(
797
            $cpuser => $user,
798
            $module_type => $module,
799
            $func_type => $function,
800
            $api_type => '1'
801
        );
802
        for ($int = 0; $int < count($args); $int++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
803
            $call['arg-' . $int] = $args[$int];
804
        }
805
        return $this->xmlapi_query('cpanel', $call);
806
    }
807
808
    /**
809
     * Call an API2 Function
810
     *
811
     * This function allows you to call an API2 function, this is the modern API for cPanel and should be used in preference over
812
     * API1 when possible
813
     *
814
     * @param string $user The username of the account to perform API2 actions on
815
     * @param string $module The module of the API2 call to use
816
     * @param string $function The function of the API2 call
817
     * @param array $args An associative array containing the arguments for the API2 call
818
     * @return mixed
819
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CallingAPIFunctions XML API Call documentation
820
     * @link http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiRef/WebHome API1 & API2 Call documentation
821
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ApiTwo Legacy API2 Documentation
822
     * @link http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiBasics/CallingApiTwo API2 Documentation
823
     */
824
    public function api2_query($user, $module, $function, $args = array()) {
825
        if (!isset($user) || !isset($module) || !isset($function)) {
826
            error_log("api2_query requires that a username, module and function are passed to it");
827
            return false;
828
        }
829
        if (!is_array($args)) {
830
            error_log("api2_query requires that an array is passed to it as the 4th parameter");
831
            return false;
832
        }
833
834
        $cpuser = 'cpanel_xmlapi_user';
835
        $module_type = 'cpanel_xmlapi_module';
836
        $func_type = 'cpanel_xmlapi_func';
837
        $api_type = 'cpanel_xmlapi_apiversion';
838
839
        if ($this->get_output() == 'json') {
840
            $cpuser = 'cpanel_jsonapi_user';
841
            $module_type = 'cpanel_jsonapi_module';
842
            $func_type = 'cpanel_jsonapi_func';
843
            $api_type = 'cpanel_jsonapi_apiversion';
844
        }
845
846
        $args[$cpuser] = $user;
847
        $args[$module_type] = $module;
848
        $args[$func_type] = $function;
849
        $args[$api_type] = '2';
850
        return $this->xmlapi_query('cpanel', $args);
851
    }
852
853
    ####
854
    #  XML API Functions
855
    ####
856
857
    /**
858
     * Return a list of available XML-API calls
859
     *
860
     * This function will return an array containing all applications available within the XML-API
861
     *
862
     * @return mixed
863
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListAvailableCalls XML API Call documentation
864
     */
865
    public function applist() {
866
        return $this->xmlapi_query('applist');
867
    }
868
869
    ####
870
    # Account functions
871
    ####
872
873
    /**
874
     * Create a cPanel Account
875
     *
876
     * This function will allow one to create an account, the $acctconf parameter requires that the follow 
877
     * three associations are defined:
878
     * 	- username
879
     * 	- password
880
     * 	- domain
881
     *
882
     * Failure to prive these will cause an error to be logged.  Any other key/value pairs as defined by the createaccount call 
883
     * documentation are allowed parameters for this call.
884
     * 
885
     * @param array $acctconf
886
     * @return mixed
887
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CreateAccount XML API Call documentation
888
     */
889
    public function createacct($acctconf) {
890
        if (!is_array($acctconf)) {
891
            error_log("createacct requires that first parameter passed to it is an array");
892
            return false;
893
        }
894
        if (!isset($acctconf['username']) || !isset($acctconf['password']) || !isset($acctconf['domain'])) {
895
            error_log("createacct requires that username, password & domain elements are in the array passed to it");
896
            return false;
897
        }
898
        return $this->xmlapi_query('createacct', $acctconf);
899
    }
900
901
    /**
902
     * Change a cPanel Account's Password
903
     * 
904
     * This function will allow you to change the password of a cpanel account
905
     *
906
     * @param string $username The username to change the password of
907
     * @param string $pass The new password for the cPanel Account
908
     * @return mixed
909
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ChangePassword XML API Call documentation
910
     */
911
    public function passwd($username, $pass) {
912
        if (!isset($username) || !isset($pass)) {
913
            error_log("passwd requires that an username and password are passed to it");
914
            return false;
915
        }
916
        return $this->xmlapi_query('passwd', array('user' => $username, 'pass' => $pass));
917
    }
918
919
    /**
920
     * Limit an account's monthly bandwidth usage
921
     *
922
     * This function will set an account's bandwidth limit.
923
     *
924
     * @param string $username The username of the cPanel account to modify
925
     * @param int $bwlimit The new bandwidth limit in megabytes
926
     * @return mixed
927
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/LimitBandwidth XML API Call documentation
928
     */
929
    public function limitbw($username, $bwlimit) {
930
        if (!isset($username) || !isset($bwlimit)) {
931
            error_log("limitbw requires that an username and bwlimit are passed to it");
932
            return false;
933
        }
934
        return $this->xmlapi_query('limitbw', array('user' => $username, 'bwlimit' => $bwlimit));
935
    }
936
937
    /**
938
     * List accounts on Server
939
     *
940
     * This call will return a list of account on a server, either no parameters or both parameters may be passed to this function.
941
     *
942
     * @param string $searchtype Type of account search to use, allowed values: domain, owner, user, ip or package
943
     * @param string $search the string to search against
944
     * @return mixed
945
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListAccounts XML API Call documentation
946
     */
947
    public function listaccts($searchtype = null, $search = null) {
948
        if ($search) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $search of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
949
            return $this->xmlapi_query('listaccts', array('searchtype' => $searchtype, 'search' => $search));
950
        }
951
        return $this->xmlapi_query('listaccts');
952
    }
953
954
    /**
955
     * Modify a cPanel account
956
     *
957
     * This call will allow you to change limitations and information about an account.  See the XML API call documentation for a list of
958
     * acceptable values for args.
959
     *
960
     * @param string $username The username to modify
961
     * @param array $args the new values for the modified account (see {@link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ModifyAccount modifyacct documentation})
962
     * @return mixed
963
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ModifyAccount XML API Call documentation 
964
     */
965
    public function modifyacct($username, $args = array()) {
966
        if (!isset($username)) {
967
            error_log("modifyacct requires that username is passed to it");
968
            return false;
969
        }
970
        $args['user'] = $username;
971
        if (sizeof($args) < 2) {
972
            error_log("modifyacct requires that at least one attribute is passed to it");
973
            return false;
974
        }
975
        return $this->xmlapi_query('modifyacct', $args);
976
    }
977
978
    /**
979
     * Edit a cPanel Account's Quota
980
     *
981
     * This call will allow you to change a cPanel account's quota
982
     *
983
     * @param string $username The username of the account to modify the quota.
984
     * @param int $quota the new quota in megabytes
985
     * @return mixed
986
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/EditQuota XML API Call documentation
987
     */
988
    public function editquota($username, $quota) {
989
        if (!isset($username) || !isset($quota)) {
990
            error_log("editquota requires that an username and quota are passed to it");
991
            return false;
992
        }
993
        return $this->xmlapi_query('editquota', array('user' => $username, 'quota' => $quota));
994
    }
995
996
    /**
997
     * Return a summary of the account's information
998
     *
999
     * This call will return a brief report of information about an account, such as:
1000
     * 	- Disk Limit
1001
     * 	- Disk Used
1002
     * 	- Domain
1003
     * 	- Account Email
1004
     * 	- Theme
1005
     * 	- Start Data
1006
     *
1007
     * Please see the XML API Call documentation for more information on what is returned by this call
1008
     *
1009
     * @param string $username The username to retrieve a summary of
1010
     * @return mixed
1011
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ShowAccountInformation XML API Call documenation
1012
     */
1013
    public function accountsummary($username) {
1014
        if (!isset($username)) {
1015
            error_log("accountsummary requires that an username is passed to it");
1016
            return false;
1017
        }
1018
        return $this->xmlapi_query('accountsummary', array('user' => $username));
1019
    }
1020
1021
    /**
1022
     * Suspend a User's Account
1023
     *
1024
     * This function will suspend the specified cPanel users account.
1025
     * The $reason parameter is optional, but can contain a string of any length
1026
     *
1027
     * @param string $username The username to suspend
1028
     * @param string $reason The reason for the suspension
1029
     * @return mixed
1030
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SuspendAccount XML API Call documentation
1031
     */
1032
    public function suspendacct($username, $reason = null) {
1033
        if (!isset($username)) {
1034
            error_log("suspendacct requires that an username is passed to it");
1035
            return false;
1036
        }
1037
        if ($reason) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $reason of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1038
            return $this->xmlapi_query('suspendacct', array('user' => $username, 'reason' => $reason));
1039
        }
1040
        return $this->xmlapi_query('suspendacct', array('user' => $username));
1041
    }
1042
1043
    /**
1044
     * List suspended accounts on a server
1045
     *
1046
     * This function will return an array containing all the suspended accounts on a server
1047
     *
1048
     * @return mixed
1049
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListSuspended XML API Call documentation
1050
     */
1051
    public function listsuspended() {
1052
        return $this->xmlapi_query('listsuspended');
1053
    }
1054
1055
    /**
1056
     * Remove an Account
1057
     *
1058
     * This XML API call will remove an account on the server
1059
     * The $keepdns parameter is optional, when enabled this will leave the DNS zone on the server
1060
     *
1061
     * @param string $username The usename to delete
1062
     * @param bool $keepdns When pass a true value, the DNS zone will be retained
1063
     * @return mixed
1064
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/TerminateAccount
1065
     */
1066
    public function removeacct($username, $keepdns = false) {
1067
        if (!isset($username)) {
1068
            error_log("removeacct requires that a username is passed to it");
1069
            return false;
1070
        }
1071
        if ($keepdns) {
1072
            return $this->xmlapi_query('removeacct', array('user' => $username, 'keepdns' => '1'));
1073
        }
1074
        return $this->xmlapi_query('removeacct', array('user' => $username));
1075
    }
1076
1077
    /**
1078
     * Unsuspend an Account
1079
     *
1080
     * This XML API call will unsuspend an account
1081
     *
1082
     * @param string $username The username to unsuspend
1083
     * @return mixed
1084
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/UnsuspendAcount XML API Call documentation
1085
     */
1086
    public function unsuspendacct($username) {
1087
        if (!isset($username)) {
1088
            error_log("unsuspendacct requires that a username is passed to it");
1089
            return false;
1090
        }
1091
        return $this->xmlapi_query('unsuspendacct', array('user' => $username));
1092
    }
1093
1094
    /**
1095
     * Change an Account's Package
1096
     *
1097
     * This XML API will change the package associated account.
1098
     *
1099
     * @param string $username the username to change the package of
1100
     * @param string $pkg The package to change the account to.
1101
     * @return mixed
1102
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ChangePackage XML API Call documentation
1103
     */
1104
    public function changepackage($username, $pkg) {
1105
        if (!isset($username) || !isset($pkg)) {
1106
            error_log("changepackage requires that username and pkg are passed to it");
1107
            return false;
1108
        }
1109
        return $this->xmlapi_query('changepackage', array('user' => $username, 'pkg' => $pkg));
1110
    }
1111
1112
    /**
1113
     * Return the privileges a reseller has in WHM
1114
     *
1115
     * This will return a list of the privileges that a reseller has to WHM
1116
     * @return mixed
1117
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ViewPrivileges XML API Call documentation
1118
     */
1119
    public function myprivs() {
1120
        return $this->xmlapi_query('myprivs');
1121
    }
1122
1123
    /**
1124
     * Display Data about a Virtual Host
1125
     * 
1126
     * This function will return information about a specific domain.  This data is essentially a representation of the data
1127
     * Contained in the httpd.conf VirtualHost for the domain.
1128
     *
1129
     * @return mixed
1130
     * @param string $domain The domain to fetch information for
1131
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DomainUserData
1132
     */
1133
    public function domainuserdata($domain) {
1134
        if (!isset($domain)) {
1135
            error_log("domainuserdata requires that domain is passed to it");
1136
            return false;
1137
        }
1138
        return $this->xmlapi_query("domainuserdata", array('domain' => $domain));
1139
    }
1140
1141
    /**
1142
     * Change a site's IP Address
1143
     * 
1144
     * This function will allow you to change the IP address that a domain listens on.
1145
     * In order to properly call this function Either $user or $domain parameters must be defined
1146
     * @param string $ip The $ip address to change the account or domain to
1147
     * @param string $user The username to change the IP of
1148
     * @param string $domain The domain to change the IP of
1149
     * @return mixed
1150
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetSiteIp XML API Call documentation
1151
     */
1152
    public function setsiteip($ip, $user = null, $domain = null) {
1153
1154
        if (!isset($ip)) {
1155
            error_log("setsiteip requires that ip is passed to it");
1156
            return false;
1157
        }
1158
1159
        if ($user == null && $domain == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $user of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
Bug introduced by
It seems like you are loosely comparing $domain of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
1160
            error_log("setsiteip requires that either domain or user is passed to it");
1161
            return false;
1162
        }
1163
1164
        if ($user == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $user of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
1165
            return $this->xmlapi_query("setsiteip", array("ip" => $ip, "domain" => $domain));
1166
        } else {
1167
            return $this->xmlapi_query("setsiteip", array("ip" => $ip, "user" => $user));
1168
        }
1169
    }
1170
1171
    ####
1172
    # DNS Functions
1173
    ####
1174
    // This API function lets you create a DNS zone.
1175
    /**
1176
     * Add a DNS Zone
1177
     *
1178
     * This XML API function will create a DNS Zone.  This will use the "standard" template when
1179
     * creating the zone.
1180
     *
1181
     * @param string $domain The DNS Domain that you wish to create a zone for
1182
     * @param string $ip The IP you want the domain to resolve to
1183
     * @return mixed
1184
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AddDNSZone XML API Call documentation
1185
     */
1186
    public function adddns($domain, $ip) {
1187
        if (!isset($domain) || !isset($ip)) {
1188
            error_log("adddns require that domain, ip are passed to it");
1189
            return false;
1190
        }
1191
        return $this->xmlapi_query('adddns', array('domain' => $domain, 'ip' => $ip));
1192
    }
1193
1194
    /**
1195
     * Add a record to a zone
1196
     *
1197
     * This will append a record to a DNS Zone.  The $args argument to this function 
1198
     * must be an associative array containing information about the DNS zone, please 
1199
     * see the XML API Call documentation for more info
1200
     *
1201
     * @param string $zone The DNS zone that you want to add the record to
1202
     * @param array $args Associative array representing the record to be added
1203
     * @return mixed
1204
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AddZoneRecord XML API Call documentation
1205
     */
1206
    public function addzonerecord($zone, $args) {
1207
        if (!is_array($args)) {
1208
            error_log("addzonerecord requires that $args passed to it is an array");
1209
            return;
1210
        }
1211
1212
        $args['zone'] = $zone;
1213
        return $this->xmlapi_query('addzonerecord', $args);
1214
    }
1215
1216
    /**
1217
     * Edit a Zone Record
1218
     *
1219
     * This XML API Function will allow you to edit an existing DNS Zone Record.
1220
     * This works by passing in the line number of the record you wish to edit.
1221
     * Line numbers can be retrieved with dumpzone()
1222
     *
1223
     * @param string $zone The zone to edit
1224
     * @param int $line The line number of the zone to edit
1225
     * @param array $args An associative array representing the zone record
1226
     * @return mixed
1227
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/EditZoneRecord XML API Call documentation
1228
     * @see dumpzone()
1229
     */
1230
    public function editzonerecord($zone, $line, $args) {
1231
        if (!is_array($args)) {
1232
            error_log("editzone requires that $args passed to it is an array");
1233
            return;
1234
        }
1235
1236
        $args['domain'] = $zone;
1237
        $args['Line'] = $line;
1238
        return $this->xmlapi_query('editzonerecord', $args);
1239
    }
1240
1241
    /**
1242
     * Retrieve a DNS Record
1243
     *
1244
     * This function will return a data structure representing a DNS record, to 
1245
     * retrieve all lines see dumpzone.
1246
     * @param string $zone The zone that you want to retrieve a record from
1247
     * @param string $line The line of the zone that you want to retrieve
1248
     * @return mixed
1249
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/GetZoneRecord XML API Call documentation
1250
     */
1251
    public function getzonerecord($zone, $line) {
1252
        return $this->xmlapi_query('getzonerecord', array('domain' => $zone, 'Line' => $line));
1253
    }
1254
1255
    /**
1256
     * Remove a DNS Zone
1257
     *
1258
     * This function will remove a DNS Zone from the server
1259
     *
1260
     * @param string $domain The domain to be remove
1261
     * @return mixed
1262
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DeleteDNSZone XML API Call documentation
1263
     */
1264
    public function killdns($domain) {
1265
        if (!isset($domain)) {
1266
            error_log("killdns requires that domain is passed to it");
1267
            return false;
1268
        }
1269
        return $this->xmlapi_query('killdns', array('domain' => $domain));
1270
    }
1271
1272
    /**
1273
     * Return a List of all DNS Zones on the server
1274
     * 
1275
     * This XML API function will return an array containing all the DNS Zones on the server
1276
     *
1277
     * @return mixed
1278
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListDNSZone XML API Call documentation
1279
     */
1280
    public function listzones() {
1281
        return $this->xmlapi_query('listzones');
1282
    }
1283
1284
    /**
1285
     * Return all records in a zone
1286
     *
1287
     * This function will return all records within a zone.
1288
     * @param string $domain The domain to return the records from.
1289
     * @return mixed
1290
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListOneZone XML API Call documentation
1291
     * @see editdnsrecord()
1292
     * @see getdnsrecord()
1293
     */
1294
    public function dumpzone($domain) {
1295
        if (!isset($domain)) {
1296
            error_log("dumpzone requires that a domain is passed to it");
1297
            return false;
1298
        }
1299
        return $this->xmlapi_query('dumpzone', array('domain' => $domain));
1300
    }
1301
1302
    /**
1303
     * Return a Nameserver's IP
1304
     *
1305
     * This function will return a nameserver's IP
1306
     *
1307
     * @param string $nameserver The nameserver to lookup
1308
     * @return mixed
1309
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/LookupIP XML API Call documentation
1310
     */
1311
    public function lookupnsip($nameserver) {
1312
        if (!isset($nameserver)) {
1313
            error_log("lookupnsip requres that a nameserver is passed to it");
1314
            return false;
1315
        }
1316
        return $this->xmlapi_query('lookupnsip', array('nameserver' => $nameserver));
1317
    }
1318
1319
    /**
1320
     * Remove a line from a zone
1321
     *
1322
     * This function will remove the specified line from a zone
1323
     * @param string $zone The zone to remove a line from
1324
     * @param int $line The line to remove from the zone
1325
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/RemoveZone XML API Call documentation
1326
     */
1327
    public function removezonerecord($zone, $line) {
1328
        if (!isset($zone) || !isset($line)) {
1329
            error_log("removezone record requires that a zone and line number is passed to it");
1330
            return false;
1331
        }
1332
        return $this->xmlapi_query('removezonerecord', array('zone' => $zone, 'Line' => $line));
1333
    }
1334
1335
    /**
1336
     * Reset a zone
1337
     *
1338
     * This function will reset a zone removing all custom records.  Subdomain records will be readded by scanning the userdata datastore.
1339
     * @param string $domain the domain name of the zone to reset
1340
     * @return mixed
1341
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ResetZone XML API Call documentation
1342
     */
1343
    public function resetzone($domain) {
1344
        if (!isset($domain)) {
1345
            error_log("resetzone requires that a domain name is passed to it");
1346
            return false;
1347
        }
1348
        return $this->xmlapi_query('resetzone', array('domain' => $domain));
1349
    }
1350
1351
    ####
1352
    # Package Functions
1353
    ####
1354
1355
    /**
1356
     * Add a new package
1357
     * 
1358
     * This function will allow you to add a new package
1359
     * This function should be passed an associative array containing elements that define package parameters.
1360
     * These variables map directly to the parameters for the XML-API Call, please refer to the link below for a complete 
1361
     * list of possible variable.  The "name" element is required.
1362
     * @param array $pkg an associative array containing package parameters
1363
     * @return mixed 
1364
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AddPackage XML API Call documentation
1365
     */
1366
    public function addpkg($pkg) {
1367
        if (!isset($pkg['name'])) {
1368
            error_log("addpkg requires that name is defined in the array passed to it");
1369
            return false;
1370
        }
1371
        return $this->xmlapi_query('addpkg', $pkg);
1372
    }
1373
1374
    /**
1375
     * Remove a package
1376
     * 
1377
     * This function allow you to delete a package
1378
     * @param string $pkgname The package you wish to delete
1379
     * @return mixed
1380
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DeletePackage XML API Call documentation
1381
     */
1382
    public function killpkg($pkgname) {
1383
        if (!isset($pkgname)) {
1384
            error_log("killpkg requires that the package name is passed to it");
1385
            return false;
1386
        }
1387
        return $this->xmlapi_query('killpkg', array('pkg' => $pkgname));
1388
    }
1389
1390
    /**
1391
     * Edit a package
1392
     *
1393
     * This function allows you to change a package's paremeters.  This is passed an associative array defining
1394
     * the parameters for the package.  The keys within this array map directly to the XML-API call, please see the link
1395
     * below for a list of possible keys within this package.  The name element is required.
1396
     * @param array $pkg An associative array containing new parameters for the package
1397
     * @return mixed
1398
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/EditPackage XML API Call documentation
1399
     */
1400
    public function editpkg($pkg) {
1401
        if (!$isset($pkg['name'])) {
0 ignored issues
show
Bug introduced by
The variable $isset does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1402
            error_log("editpkg requires that name is defined in the array passed to it");
1403
            return false;
1404
        }
1405
        return $this->xmlapi_query('editpkg', $pkg);
1406
    }
1407
1408
    /**
1409
     * List Packages
1410
     *
1411
     * This function will list all packages available to the user
1412
     * @return mixed
1413
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListPackages XML API Call documentation
1414
     */
1415
    public function listpkgs() {
1416
        return $this->xmlapi_query('listpkgs');
1417
    }
1418
1419
    ####
1420
    # Reseller functions
1421
    ####
1422
1423
    /**
1424
     * Make a user a reseller
1425
     *
1426
     * This function will allow you to mark an account as having reseller privileges
1427
     * @param string $username The username of the account you wish to add reseller privileges to
1428
     * @param int $makeowner Boolean 1 or 0 defining whether the account should own itself or not
1429
     * @see setacls()
1430
     * @see setresellerlimits()
1431
     * @return mixed
1432
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AddResellerPrivileges XML API Call documentation
1433
     */
1434
    public function setupreseller($username, $makeowner = true) {
1435
        if (!isset($username)) {
1436
            error_log("setupreseller requires that username is passed to it");
1437
            return false;
1438
        }
1439
        if ($makeowner) {
1440
            return $this->xmlapi_query('setupreseller', array('user' => $username, 'makeowner' => '1'));
1441
        }
1442
        return $this->xmlapi_query('setupreseller', array('user' => $username, 'makeowner' => '0'));
1443
    }
1444
1445
    /**
1446
     * Create a New ACL List
1447
     *
1448
     * This function allows you to create a new privilege set for reseller accounts.  This is passed an
1449
     * Associative Array containing the configuration information for this variable.  Please see the XML API Call documentation
1450
     * For more information.  "acllist" is a required element within this array
1451
     * @param array $acl an associative array describing the parameters for the ACL to be create
1452
     * @return mixed
1453
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CreateResellerACLList XML API Call documentation
1454
     */
1455
    public function saveacllist($acl) {
1456
        if (!isset($acl['acllist'])) {
1457
            error_log("saveacllist requires that acllist is defined in the array passed to it");
1458
            return false;
1459
        }
1460
        return $this->xmlapi_query('saveacllist', $acl);
1461
    }
1462
1463
    /**
1464
     * List available saved ACLs
1465
     *
1466
     * This function will return a list of Saved ACLs for reseller accounts
1467
     * @return mixed
1468
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListCurrentResellerACLLists XML API Call documentation
1469
     */
1470
    public function listacls() {
1471
        return $this->xmlapi_query('listacls');
1472
    }
1473
1474
    /**
1475
     * List Resellers
1476
     *
1477
     * This function will return a list of resellers on the server
1478
     * @return mixed
1479
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListResellerAccounts XML API Call documentation
1480
     */
1481
    public function listresellers() {
1482
        return $this->xmlapi_query('listresellers');
1483
    }
1484
1485
    /**
1486
     * Get a reseller's statistics
1487
     *
1488
     * This function will return general information on a reseller and all it's account individually such as disk usage and bandwidth usage
1489
     *
1490
     * @param string $username The reseller to be checked
1491
     * @return mixed
1492
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListResellersAccountsInformation XML API Call documentation
1493
     */
1494
    public function resellerstats($username) {
1495
        if (!isset($username)) {
1496
            error_log("resellerstats requires that a username is passed to it");
1497
            return false;
1498
        }
1499
        return $this->xmlapi_query('resellerstats', array('reseller' => $username));
1500
    }
1501
1502
    /**
1503
     * Remove Reseller Privileges
1504
     *
1505
     * This function will remove an account's reseller privileges, this does not remove the account.
1506
     *
1507
     * @param string $username The username to remove reseller privileges from
1508
     * @return mixed
1509
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/RemoveResellerPrivileges XML API Call documentation
1510
     */
1511
    public function unsetupreseller($username) {
1512
        if (!isset($username)) {
1513
            error_log("unsetupreseller requires that a username is passed to it");
1514
            return false;
1515
        }
1516
        return $this->xmlapi_query('unsetupreseller', array('user' => $username));
1517
    }
1518
1519
    /**
1520
     * Set a reseller's privileges
1521
     *
1522
     * This function will allow you to set what parts of WHM a reseller has access to.  This is passed an associative array
1523
     * containing the privleges that this reseller should have access to.  These map directly to the parameters passed to the XML API Call
1524
     * Please view the XML API Call documentation for more information.  "reseller" is the only required element within this array
1525
     * @param array $acl An associative array containing all the ACL information for the reseller
1526
     * @return mixed
1527
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellersACLList XML API Call documentation
1528
     */
1529
    public function setacls($acl) {
1530
        if (!isset($acl['reseller'])) {
1531
            error_log("setacls requires that reseller is defined in the array passed to it");
1532
            return false;
1533
        }
1534
        return $this->xmlapi_query('setacls', $acl);
1535
    }
1536
1537
    /**
1538
     * Terminate a Reseller's Account
1539
     *
1540
     * This function will terminate a reseller's account and all accounts owned by the reseller
1541
     *
1542
     * @param string $reseller the name of the reseller to terminate
1543
     * @param boolean $terminatereseller Passing this as true will terminate the the reseller's account as well as all the accounts owned by the reseller
1544
     * @return mixed
1545
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/TerminateResellerandAccounts XML API Call documentation
1546
     *
1547
     * */
1548
    public function terminatereseller($reseller, $terminatereseller = true) {
1549
        if (!isset($reseller)) {
1550
            error_log("terminatereseller requires that username is passed to it");
1551
            return false;
1552
        }
1553
        $verify = 'I understand this will irrevocably remove all the accounts owned by the reseller ' . $reseller;
1554
        if ($terminatereseller) {
1555
            return $this->xmlapi_query('terminatereseller', array('reseller' => $reseller, 'terminatereseller' => '1', 'verify' => $verify));
1556
        }
1557
        return $this->xmlapi_query('terminatereseller', array('reseller' => $reseller, 'terminatereseller' => '0', 'verify' => $verify));
1558
    }
1559
1560
    /**
1561
     * Set a reseller's dedicated IP addresses
1562
     *
1563
     * This function will set a reseller's dedicated IP addresses.  If an IP is not passed to this function, 
1564
     * it will reset the reseller to use the server's main shared IP address.
1565
     * @param string $user The username of the reseller to change dedicated IPs for
1566
     * @param string $ip The IP to assign to the  reseller, this can be a comma-seperated list of IPs to allow for multiple IP addresses
1567
     * @return mixed
1568
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellerIps XML API Call documentation
1569
     */
1570
    public function setresellerips($user, $ip = null) {
1571
        if (!isset($user)) {
1572
            error_log("setresellerips requires that a username is passed to it");
1573
            return false;
1574
        }
1575
        $params = array("user" => $user);
1576
        if ($ip != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $ip of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1577
            $params['ip'] = $ip;
1578
        }
1579
        return $this->xmlapi_query('setresellerips', $params);
1580
    }
1581
1582
    /**
1583
     * Set Accounting Limits for a reseller account
1584
     *
1585
     * This function allows you to define limits for reseller accounts not included with in access control such as
1586
     * the number of accounts a reseller is allowed to create, the amount of disk space to use.
1587
     * This function is passed an associative array defining these limits, these map directly to the parameters for the XML API
1588
     * Call, please refer to the XML API Call documentation for more information.  The only required parameters is "user"
1589
     *
1590
     * @param array $reseller_cfg An associative array containing configuration information for the specified reseller
1591
     * @return mixed
1592
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellerLimits XML API Call documentation
1593
     *
1594
     */
1595
    public function setresellerlimits($reseller_cfg) {
1596
        if (!isset($reseller_cfg['user'])) {
1597
            error_log("setresellerlimits requires that a user is defined in the array passed to it");
1598
            return false;
1599
        }
1600
        return $this->xmlapi_query('setresellerlimits', $reseller_cfg);
1601
    }
1602
1603
    /**
1604
     * Set a reseller's main IP
1605
     *
1606
     * This function will allow you to set a reseller's main IP.  By default all accounts created by this reseller
1607
     * will be created on this IP
1608
     * @param string $reseller the username of the reseller to change the main IP of
1609
     * @param string $ip The ip you would like this reseller to create accounts on by default
1610
     * @return mixed
1611
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellerMainIp XML API Call documentation
1612
     */
1613
    public function setresellermainip($reseller, $ip) {
1614
        if (!isset($reseller) || !isset($ip)) {
1615
            error_log("setresellermainip requires that an reseller and ip are passed to it");
1616
            return false;
1617
        }
1618
        return $this->xmlapi_query("setresellermainip", array('user' => $reseller, 'ip' => $ip));
1619
    }
1620
1621
    /**
1622
     * Set reseller package limits
1623
     *
1624
     * This function allows you to define which packages a reseller has access to use
1625
     * @param string $user The reseller you wish to define package limits for
1626
     * @param boolean $no_limit Whether or not you wish this reseller to have packages limits
1627
     * @param string $package if $no_limit is false, then the package you wish to modify privileges for
1628
     * @param boolean $allowed if $no_limit is false, then defines if the reseller should have access to the package or not
1629
     * @param int $number if $no_limit is false, then defines the number of account a reseller can create of a specific package
1630
     * @return mixed
1631
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellerPkgLimit XML API Call documentation
1632
     */
1633
    public function setresellerpackagelimits($user, $no_limit, $package = null, $allowed = null, $number = null) {
1634
        if (!isset($user) || !isset($no_limit)) {
1635
            error_log("setresellerpackagelimits requires that a username and no_limit are passed to it by default");
1636
            return false;
1637
        }
1638
        if ($no_limit) {
1639
            return $this->xmlapi_query("setresellerpackagelimits", array('user' => $user, "no_limit" => '1'));
1640
        } else {
1641
            if (is_null($package) || is_null($allowed)) {
1642
                error_log('setresellerpackagelimits requires that package and allowed are passed to it if no_limit eq 0');
1643
                return false;
1644
            }
1645
            $params = array(
1646
                'user' => $user,
1647
                'no_limit' => '0'
1648
            );
1649
            if ($allowed) {
1650
                $params['allowed'] = 1;
1651
            } else {
1652
                $params['allowed'] = 0;
1653
            }
1654
            if (!is_null($number)) {
1655
                $params['number'] = $number;
1656
            }
1657
            return $this->xmlapi_query('setresellerpackagelimits', $params);
1658
        }
1659
    }
1660
1661
    /**
1662
     * Suspend a reseller and all accounts owned by a reseller
1663
     *
1664
     * This function, when called will suspend a reseller account and all account owned by said reseller
1665
     * @param string $reseller The reseller account to be suspended
1666
     * @param string $reason (optional) The reason for suspending the reseller account
1667
     * @return mixed
1668
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SuspendReseller XML API Call documentation
1669
     */
1670
    public function suspendreseller($reseller, $reason = null) {
1671
        if (!isset($reseller)) {
1672
            error_log("suspendreseller requires that the reseller's username is passed to it");
1673
            return false;
1674
        }
1675
        $params = array("user" => $reseller);
1676
        if ($reason) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $reason of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1677
            $params['reason'] = $reason;
1678
        }
1679
        return $this->xmlapi_query('suspendreseller', $params);
1680
    }
1681
1682
    /**
1683
     * Unsuspend a Reseller Account
1684
     *
1685
     * This function will unsuspend a reseller account and all accounts owned by the reseller in question
1686
     * @param string $user The username of the reseller to be unsuspended
1687
     * @return mixed
1688
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/UnsuspendReseller XML API Call documentation
1689
     */
1690
    public function unsuspendreseller($user) {
1691
        if (!isset($user)) {
1692
            error_log("unsuspendreseller requires that a username is passed to it");
1693
            return false;
1694
        }
1695
        return $this->xmlapi_query('unsuspendreseller', array('user' => $user));
1696
    }
1697
1698
    /**
1699
     * Get the number of accounts owned by a reseller
1700
     *
1701
     * This function will return the number of accounts owned by a reseller account, along with information such as the number of active, suspended and accounting limits
1702
     * @param string $user The username of the reseller to get account information from
1703
     * @return mixed
1704
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AcctCounts XML API Call documentation
1705
     */
1706
    public function acctcounts($user) {
1707
        if (!isset($user)) {
1708
            error_log('acctcounts requires that a username is passed to it');
1709
            return false;
1710
        }
1711
        return $this->xmlapi_query('acctcounts', array('user' => $user));
1712
    }
1713
1714
    /**
1715
     * Set a reseller's nameservers
1716
     *
1717
     * This function allows you to change the nameservers that account created by a specific reseller account will use.
1718
     * If this function is not passed a $nameservers parameter, it will reset the nameservers for the reseller to the servers's default
1719
     * @param string $user The username of the reseller account to grab reseller accounts from
1720
     * @param string $nameservers A comma seperate list of nameservers
1721
     * @return mixed
1722
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResellerNameservers XML API Call documentation
1723
     */
1724
    public function setresellernameservers($user, $nameservers = null) {
1725
        if (!isset($user)) {
1726
            error_log("setresellernameservers requires that a username is passed to it");
1727
            return false;
1728
        }
1729
        $params = array('user' => $user);
1730
        if ($nameservers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $nameservers of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1731
            $params['nameservers'] = $nameservers;
1732
        }
1733
        return $this->xmlapi_query('setresellernameservers', $params);
1734
    }
1735
1736
    ####
1737
    # Server information
1738
    ####
1739
1740
    /**
1741
     * Get a server's hostname
1742
     *
1743
     * This function will return a server's hostname
1744
     * @return mixed
1745
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DisplayServerHostname XML API Call documentation
1746
     */
1747
    public function gethostname() {
1748
        return $this->xmlapi_query('gethostname');
1749
    }
1750
1751
    /**
1752
     * Get the version of cPanel running on the server
1753
     *
1754
     * This function will return the version of cPanel/WHM running on the remote system
1755
     * @return mixed
1756
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DisplaycPanelWHMVersion XML API Call documentation
1757
     */
1758
    public function version() {
1759
        return $this->xmlapi_query('version');
1760
    }
1761
1762
    /**
1763
     * Get Load Average
1764
     *
1765
     * This function will return the loadavg of the remote system
1766
     *
1767
     * @return mixed
1768
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/LoadAvg XML API Call documentation
1769
     */
1770
    public function loadavg() {
1771
        return $this->xmlapi_query('loadavg');
1772
    }
1773
1774
    /**
1775
     * Get a list of languages on the remote system
1776
     *
1777
     * This function will return a list of available langauges for the cPanel interface
1778
     * @return mixed
1779
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/GetLangList XML API Call documentation
1780
     *
1781
     */
1782
    public function getlanglist() {
1783
        return $this->xmlapi_query('getlanglist');
1784
    }
1785
1786
    ####
1787
    # Server administration
1788
    ####
1789
1790
    /**
1791
     * Reboot server
1792
     *
1793
     * This function will reboot the server
1794
     * @param boolean $force This will determine if the server should be given a graceful or forceful reboot
1795
     * @return mixed
1796
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/RebootServer XML API Call documentation
1797
     */
1798
    public function reboot($force = false) {
1799
        if ($force) {
1800
            return $this->xmlapi_query('reboot', array('force' => '1'));
1801
        }
1802
        return $this->xmlapi_query('reboot');
1803
    }
1804
1805
    /**
1806
     * Add an IP to a server
1807
     *
1808
     * This function will add an IP alias to your server
1809
     * @param string $ip The IP to be added
1810
     * @param string $netmask The netmask of the IP to be added
1811
     * @return mixed
1812
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/AddIPAddress XML API Call documentation
1813
     */
1814
    public function addip($ip, $netmask) {
1815
        if (!isset($ip) || !isset($netmask)) {
1816
            error_log("addip requires that an IP address and Netmask are passed to it");
1817
            return false;
1818
        }
1819
        return $this->xmlapi_query('addip', array('ip' => $ip, 'netmask' => $netmask));
1820
    }
1821
1822
    // This function allows you to delete an IP address from your server.
1823
    /**
1824
     * Delete an IP from a server
1825
     *
1826
     * Remove an IP from the server
1827
     * @param string $ip The IP to remove
1828
     * @param string $ethernetdev The ethernet device that the IP is bound to
1829
     * @param bool $skipifshutdown Whether the function should remove the IP even if the ethernet interface is down
1830
     * @return mixed
1831
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DeleteIPAddress XML API Call documentation
1832
     */
1833
    public function delip($ip, $ethernetdev = null, $skipifshutdown = false) {
1834
        $args = array();
1835
        if (!isset($ip)) {
1836
            error_log("delip requires that an IP is defined in the array passed to it");
1837
            return false;
1838
        }
1839
        $args['ip'] = $ip;
1840
        if ($ethernetdev) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $ethernetdev of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1841
            $args['ethernetdev'] = $ethernetdev;
1842
        }
1843
        $args['skipifshutdown'] = ($skipifshutdown) ? '1' : '0';
1844
        return $this->xmlapi_query('delip', $args);
1845
    }
1846
1847
    /**
1848
     * List IPs
1849
     *
1850
     * This should return a list of IPs on a server
1851
     * @return mixed
1852
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/DeleteIPAddress XML API Call documentation
1853
     */
1854
    public function listips() {
1855
        return $this->xmlapi_query('listips');
1856
    }
1857
1858
    /**
1859
     * Set Hostname
1860
     *
1861
     * This function will allow you to set the hostname of the server
1862
     * @param string $hostname the hostname that should be assigned to the serve
1863
     * @return mixed
1864
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetHostname XML API Call documentation
1865
     */
1866
    public function sethostname($hostname) {
1867
        if (!isset($hostname)) {
1868
            error_log("sethostname requires that hostname is passed to it");
1869
            return false;
1870
        }
1871
        return $this->xmlapi_query('sethostname', array('hostname' => $hostname));
1872
    }
1873
1874
    /**
1875
     * Set the resolvers used by the server
1876
     * 
1877
     * This function will set the resolvers in /etc/resolv.conf for the server
1878
     * @param string $nameserver1 The IP of the first nameserver to use
1879
     * @param string $nameserver2 The IP of the second namesever to use
1880
     * @param string $nameserver3 The IP of the third nameserver to use
1881
     * @param string $nameserver4 The IP of the forth nameserver to use
0 ignored issues
show
Documentation introduced by
There is no parameter named $nameserver4. Did you maybe mean $nameserver1?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
1882
     * @return mixed
1883
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/SetResolvers XML API Call documentation
1884
     */
1885
    public function setresolvers($nameserver1, $nameserver2 = null, $nameserver3 = null) {
1886
        $args = array();
1887
        if (!isset($nameserver1)) {
1888
            error_log("setresolvers requires that nameserver1 is defined in the array passed to it");
1889
            return false;
1890
        }
1891
        $args['nameserver1'] = $nameserver1;
1892
        if ($nameserver2) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $nameserver2 of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1893
            $args['nameserver2'] = $nameserver2;
1894
        }
1895
        if ($nameserver3) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $nameserver3 of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1896
            $args['nameserver3'] = $nameserver3;
1897
        }
1898
        return $this->xmlapi_query('setresolvers', $args);
1899
    }
1900
1901
    /**
1902
     * Display bandwidth Usage
1903
     *
1904
     * This function will return all bandwidth usage information for the server,
1905
     * The arguments for this can be passed in via an associative array, the elements of this array map directly to the
1906
     * parameters of the call, please see the XML API Call documentation for more information
1907
     * @param array $args The configuration for what bandwidth information to display
1908
     * @return mixed
1909
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ShowBw XML API Call documentation
1910
     */
1911
    public function showbw($args = null) {
1912
        if (is_array($args)) {
1913
            return $this->xmlapi_query('showbw', $args);
1914
        }
1915
        return $this->xmlapi_query('showbw');
1916
    }
1917
1918
    public function nvset($key, $value) {
1919
        if (!isset($key) || !isset($value)) {
1920
            error_log("nvset requires that key and value are passed to it");
1921
            return false;
1922
        }
1923
        return $this->xmlapi_query('nvset', array('key' => $key, 'value' => $value));
1924
    }
1925
1926
    // This function allows you to retrieve and view a non-volatile variable's value.
1927
    public function nvget($key) {
1928
        if (!isset($key)) {
1929
            error_log("nvget requires that key is passed to it");
1930
            return false;
1931
        }
1932
        return $this->xmlapi_query('nvget', array('key' => $key));
1933
    }
1934
1935
    ####
1936
    # Service functions
1937
    ####
1938
1939
    /**
1940
     * Restart a Service
1941
     *
1942
     * This function allows you to restart a service on the server
1943
     * @param string $service the service that you wish to restart please view the XML API Call documentation for acceptable values to this parameters
1944
     * @return mixed
1945
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/RestartService XML API Call documentation
1946
     */
1947
    public function restartsrv($service) {
1948
        if (!isset($service)) {
1949
            error_log("restartsrv requires that service is passed to it");
1950
            return false;
1951
        }
1952
        return $this->xmlapi_query('restartservice', array('service' => $service));
1953
    }
1954
1955
    /**
1956
     * Service Status
1957
     *
1958
     * This function will return the status of all services on the and whether they are running or not
1959
     * @return mixed
1960
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ServiceStatus XML API Call documentation
1961
     */
1962
    public function servicestatus() {
1963
        return $this->xmlapi_query('servicestatus');
1964
    }
1965
1966
    /**
1967
     * Configure A Service
1968
     *
1969
     * This function will allow you to enabled or disable services along with their monitoring by chkservd
1970
     * @param string $service The service to be monitored
1971
     * @param bool $enabled Whether the service should be enabled or not
1972
     * @param bool $monitored Whether the service should be monitored or not
1973
     * @return mixed
1974
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ConfigureService XML API Call documentation
1975
     */
1976
    public function configureservice($service, $enabled = true, $monitored = true) {
1977
        if (!isset($service)) {
1978
            error_log("configure service requires that a service is passed to it");
1979
            return false;
1980
        }
1981
        $params = array('service' => $service);
1982
1983
        if ($enabled) {
1984
            $params['enabled'] = 1;
1985
        } else {
1986
            $params['enabled'] = 0;
1987
        }
1988
1989
        if ($monitored) {
1990
            $params['monitored'] = 1;
1991
        } else {
1992
            $params['monitored'] = 0;
1993
        }
1994
1995
        return $this->xmlapi_query('configureservice', $params);
1996
    }
1997
1998
    ####
1999
    # SSL functions
2000
    ####
2001
2002
    /**
2003
     * Display information on an SSL host
2004
     *
2005
     * This function will return information on an SSL Certificate, CSR, cabundle and SSL key for a specified domain
2006
     * @param array $args Configuration information for the SSL certificate, please see XML API Call documentation for required values
2007
     * @return mixed
2008
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/FetchSSL XML API Call documentation
2009
     */
2010
    public function fetchsslinfo($args) {
2011
        if ((isset($args['domain']) && isset($args['crtdata'])) || (!isset($args['domain']) && !isset($args['crtdata']))) {
2012
            error_log("fetchsslinfo requires domain OR crtdata is passed to it");
2013
        }
2014
        if (isset($args['crtdata'])) {
2015
            // crtdata must be URL-encoded!
2016
            $args['crtdata'] = urlencode(trim($args['crtdata']));
2017
        }
2018
        return $this->xmlapi_query('fetchsslinfo', $args);
2019
    }
2020
2021
    /**
2022
     * Generate an SSL Certificate
2023
     *
2024
     * This function will generate an SSL Certificate, the arguments for this map directly to the call for the XML API call.  Please consult the XML API Call documentation for more information
2025
     * @param array $args the configuration for the SSL Certificate being generated
2026
     * @return mixed
2027
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/GenerateSSL XML API Call documentation
2028
     */
2029
    public function generatessl($args) {
2030
        if (!isset($args['xemail']) || !isset($args['host']) || !isset($args['country']) || !isset($args['state']) || !isset($args['city']) || !isset($args['co']) || !isset($args['cod']) || !isset($args['email']) || !isset($args['pass'])) {
2031
            error_log("generatessl requires that xemail, host, country, state, city, co, cod, email and pass are defined in the array passed to it");
2032
            return false;
2033
        }
2034
        return $this->xmlapi_query('generatessl', $args);
2035
    }
2036
2037
    /**
2038
     * Install an SSL certificate
2039
     *
2040
     * This function will allow you to install an SSL certificate that is uploaded via the $argument parameter to this call.  The arguments for this call map directly to the parameters for the XML API call, 
2041
     * please consult the XML API Call documentation for more information.
2042
     * @param array $args The configuration for the SSL certificate
2043
     * @return mixed
2044
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/InstallSSL XML API Call documentation
2045
     */
2046
    public function installssl($args) {
2047
        if (!isset($args['user']) || !isset($args['domain']) || !isset($args['cert']) || !isset($args['key']) || !isset($args['cab']) || !isset($args['ip'])) {
2048
            error_log("installssl requires that user, domain, cert, key, cab and ip are defined in the array passed to it");
2049
            return false;
2050
        }
2051
        return $this->xmlapi_query('installssl', $args);
2052
    }
2053
2054
    /**
2055
     * List SSL Certs
2056
     *
2057
     * This function will list all SSL certificates installed on the server
2058
     * @return mixed
2059
     * @link http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/ListSSL XML API Call documentation
2060
     */
2061
    public function listcrts() {
2062
        return $this->xmlapi_query('listcrts');
2063
    }
2064
2065
    ####
2066
    # cPanel API1 functions
2067
    # Note: A cPanel account username is required
2068
    # Some cPanel features must be enabled to be able to use some function (f.e. park, unpark)
2069
    ####
2070
    // This API1 function adds a emailaccount for a specific user.
2071
    public function addpop($username, $args) {
2072
        if (!isset($username) || !isset($args)) {
2073
            error_log("addpop requires that a user and args are passed to it");
2074
            return false;
2075
        }
2076
        if (is_array($args) && (sizeof($args) < 3)) {
2077
            error_log("addpop requires that args at least contains an email_username, email_password and email_domain");
2078
            return false;
2079
        }
2080
        return $this->api1_query($username, 'Email', 'addpop', $args);
2081
    }
2082
2083
    // This API function displays a list of all parked domains for a specific user.
2084
    public function park($username, $newdomain, $topdomain) {
2085
        $args = array();
2086
        if ((!isset($username)) && (!isset($newdomain)) && (!isset($topdomain))) {
2087
            error_log("park requires that a username, new domain and topdomain are passed to it");
2088
            return false;
2089
        }
2090
        $args['domain'] = $newdomain;
2091
        $args['topdomain'] = $topdomain;
2092
        return $this->api2_query($username, 'Park', 'park', $args);
2093
    }
2094
2095
    // This API function displays a list of all parked domains for a specific user.
2096
    public function unpark($username, $domain) {
2097
        $args = array();
2098
        if ((!isset($username)) && (!isset($domain))) {
2099
            error_log("unpark requires that a username and domain are passed to it");
2100
            return false;
2101
        }
2102
        $args['domain'] = $domain;
2103
        return $this->api2_query($username, 'Park', 'unpark', $args);
2104
    }
2105
2106
    ####
2107
    # cPanel API2 functions
2108
    # Note: A cPanel account username is required
2109
    # Some cPanel features must be enabled to be able to use some function
2110
    ####
2111
    // This API2 function allows you to view the diskusage of a emailaccount.
2112
    public function getdiskusage($username, $args) {
2113
        if (!isset($username) || !isset($args)) {
2114
            error_log("getdiskusage requires that a username and args are passed to it");
2115
            return false;
2116
        }
2117
        if (is_array($args) && (!isset($args['domain']) || !isset($args['login']))) {
2118
            error_log("getdiskusage requires that args at least contains an email_domain and email_username");
2119
            return false;
2120
        }
2121
        return $this->api2_query($username, 'Email', 'getdiskusage', $args);
2122
    }
2123
2124
    // This API2 function allows you to list ftp-users associated with a cPanel account including disk information.
2125
    public function listftpwithdisk($username) {
2126
        if (!isset($username)) {
2127
            error_log("listftpwithdisk requires that user is passed to it");
2128
            return false;
2129
        }
2130
        return $this->api2_query($username, 'Ftp', 'listftpwithdisk');
2131
    }
2132
2133
    // This API2 function allows you to list ftp-users associated with a cPanel account.
2134
    public function listftp($username) {
2135
        if (!isset($username)) {
2136
            error_log("listftp requires that user is passed to it");
2137
            return false;
2138
        }
2139
        return $this->api2_query($username, 'Ftp', 'listftp');
2140
    }
2141
2142
    // This API function displays a list of all parked domains for a specific user.
2143
    public function listparkeddomains($username, $domain = null) {
2144
        $args = array();
2145
        if (!isset($username)) {
2146
            error_log("listparkeddomains requires that a user is passed to it");
2147
            return false;
2148
        }
2149
        if (isset($domain)) {
2150
            $args['regex'] = $domain;
2151
            return $this->api2_query($username, 'Park', 'listparkeddomains', $args);
2152
        }
2153
        return $this->api2_query($username, 'Park', 'listparkeddomains');
2154
    }
2155
2156
    // This API function displays a list of all addon domains for a specific user.
2157
    public function listaddondomains($username, $domain = null) {
2158
        $args = array();
2159
        if (!isset($username)) {
2160
            error_log("listaddondomains requires that a user is passed to it");
2161
            return false;
2162
        }
2163
        if (isset($domain)) {
2164
            $args['regex'] = $domain;
2165
            return $this->api2_query($username, 'AddonDomain', 'listaddondomains', $args);
2166
        }
2167
        return $this->api2_query($username, 'Park', 'listaddondomains');
2168
    }
2169
2170
    // This API function displays a list of all selected stats for a specific user.
2171
    public function stat($username, $args = null) {
2172
        if ((!isset($username)) || (!isset($args))) {
2173
            error_log("stat requires that a username and options are passed to it");
2174
            return false;
2175
        }
2176
        if (is_array($args)) {
2177
            $display = '';
2178
            foreach ($args as $key => $value) {
2179
                $display .= $value . '|';
2180
            }
2181
            $values['display'] = substr($display, 0, -1);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$values was never initialized. Although not strictly required by PHP, it is generally a good practice to add $values = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2182
        } else {
2183
            $values['display'] = substr($args, 0, -1);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$values was never initialized. Although not strictly required by PHP, it is generally a good practice to add $values = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2184
        }
2185
        return $this->api2_query($username, 'StatsBar', 'stat', $values);
2186
    }
2187
2188
}
2189