<commit_before><?php

namespace Redmine;

use Redmine\Api\SimpleXMLElement;

/**
 * Simple PHP Redmine client
 * @author <NAME> <kevin at saliou dot name>
 * Website: http://github.com/kbsali/php-redmine-api
 */
class Client
{
    /**
     * @var array
     */
    private static $defaultPorts = array(
        'http'  => 80,
        'https' => 443,
    );

    /**
     * @var int
     */
    private $port;

    /**
     * @var string
     */
    private $url;

    /**
     * @var string
     */
    private $apikeyOrUsername;

    /**
     * @var string
     */
    private $apikeyHeaderName = 'X-Redmine-API-Key';

    /**
     * @var string or null
     */
    private $pass;

    /**
     * @var boolean
     */
    private $checkSslCertificate = false;

    /**
     * @var boolean
     */
    private $checkSslHost = false;

    /**
     *
     * Flag to determine authentication method
     *
     * @var boolean
     */
    private $useHttpAuth = true;

    /**
     * @var array APIs
     */
    private $apis = array();

    /**
     * @var int|null Redmine response code, null if request is not still completed
     */
    private $responseCode = null;

    /**
     * Error strings if json is invalid
     */
    private static $json_errors = array(
        JSON_ERROR_NONE      => 'No error has occurred',
        JSON_ERROR_DEPTH     => 'The maximum stack depth has been exceeded',
        JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
        JSON_ERROR_SYNTAX    => 'Syntax error',
    );

    /**
     * Usage: apikeyOrUsername can be auth key or username.
     * Password needs to be set if username is given.
     *
     * @param string $url
     * @param string $apikeyOrUsername
     * @param string $pass             (string or null)
     */
    public function __construct($url, $apikeyOrUsername, $pass = null)
    {
        $this->url = $url;
        $this->getPort($url);
        $this->apikeyOrUsername = $apikeyOrUsername;
        $this->pass = $pass;
    }

    /**
     * @param  string                    $name
     * @return Api\AbstractApi
     * @throws \InvalidArgumentException
     */
    public function api($name)
    {
        $classes = array(
            'attachment'          => 'Attachment',
            'group'               => 'Group',
            'custom_fields'       => 'CustomField',
            'issue'               => 'Issue',
            'issue_category'      => 'IssueCategory',
            'issue_priority'      => 'IssuePriority',
            'issue_relation'      => 'IssueRelation',
            'issue_status'        => 'IssueStatus',
            'membership'          => 'Membership',
            'news'                => 'News',
            'project'             => 'Project',
            'query'               => 'Query',
            'role'                => 'Role',
            'time_entry'          => 'TimeEntry',
            'time_entry_activity' => 'TimeEntryActivity',
            'tracker'             => 'Tracker',
            'user'                => 'User',
            'version'             => 'Version',
            'wiki'                => 'Wiki',
        );
        if (!isset($classes[$name])) {
            throw new \InvalidArgumentException();
        }
        if (isset($this->apis[$name])) {
            return $this->apis[$name];
        }
        $c = 'Redmine\Api\\'.$classes[$name];
        $this->apis[$name] = new $c($this);

        return $this->apis[$name];
    }

    /**
     * Returns Url
     * @return string
     */
    public function getUrl()
    {
       return $this->url;
    }

    /**
     * HTTP GETs a json $path and tries to decode it
     * @param  string $path
     * @return array
     */
    public function get($path)
    {
        if (false === $json = $this->runRequest($path, 'GET')) {
            return false;
        }

        return $this->decode($json);
    }

    /**
     * Decodes json response
     * @param  string $json
     * @return array
     */
    public function decode($json)
    {
        $decoded = json_decode($json, true);
        if (null !== $decoded) {
            return $decoded;
        }
        if (JSON_ERROR_NONE === json_last_error()) {
            return $json;
        }

        return self::$json_errors[json_last_error()];
    }

    /**
     * HTTP POSTs $params to $path
     * @param  string $path
     * @param  string $data
     * @return mixed
     */
    public function post($path, $data)
    {
        return $this->runRequest($path, 'POST', $data);
    }

    /**
     * HTTP PUTs $params to $path
     * @param  string $path
     * @param  string $data
     * @return array
     */
    public function put($path, $data)
    {
        return $this->runRequest($path, 'PUT', $data);
    }

    /**
     * HTTP PUTs $params to $path
     * @param  string $path
     * @return array
     */
    public function delete($path)
    {
        return $this->runRequest($path, 'DELETE');
    }

    /**
     * Turns on/off ssl certificate check
     * @param  boolean $check
     * @return Client
     */
    public function setCheckSslCertificate($check = false)
    {
        $this->checkSslCertificate = $check;

        return $this;
    }

    /**
     * Turns on/off ssl host certificate check
     * @param  boolean $check
     * @return Client
     */
    public function setCheckSslHost($check = false)
    {
        $this->checkSslHost = $check;

        return $this;
    }

    /**
     * Turns on/off http auth
     * @param  bool   $use
     * @return Client
     */
    public function setUseHttpAuth($use = true)
    {
        $this->useHttpAuth = $use;

        return $this;
    }

    /**
     * Set the port of the connection
     * @param  int    $port
     * @return Client
     */
    public function setPort($port = null)
    {
        if (null !== $port) {
            $this->port = (int) $port;
        }

        return $this;
    }

    /**
     * Set the name of the HTTP header used to set the API key for authentication
     * @param  string $name
     * @return Client
     */
    public function setApikeyHeaderName($name = null)
    {
        if (null !== $name) {
            $this->apikeyHeaderName = $name;
        }

        return $this;
    }

    /**
     * Returns the name of the HTTP header used to set the API key for authentication
     * @return string
     */
    public function getApikeyHeaderName()
    {
        return $this->apikeyHeaderName;
    }

    /**
     * Returns Redmine response code
     * @return int
     */
    public function getResponseCode()
    {
        return $this->responseCode;
    }

    /**
     * Returns the port of the current connection,
     * if not set, it will try to guess the port
     * from the url of the client.
     *
     * @return int    the port number
     */
    public function getPort()
    {
        if (null !== $this->port) {
            return $this->port;
        }
        $tmp = parse_url($this->getUrl());

        if (isset($tmp['port'])) {
            $this->setPort($tmp['port']);

            return $this->port;
        }
        $this->setPort(self::$defaultPorts[$tmp['scheme']]);

        return $this->port;
    }

    /**
     * @param  string                        $path
     * @param  string                        $method
     * @param  string                        $data
     * @return false|SimpleXMLElement|string
     * @throws \Exception                    If anything goes wrong on curl request
     */
    protected function runRequest($path, $method = 'GET', $data = '')
    {
        $this->responseCode = null;

        $curl = curl_init();
        if (isset($this->apikeyOrUsername) && $this->useHttpAuth) {<commit_msg>fixed setPort if no port or scheme is detected<commit_after><?php

namespace Redmine;

use Redmine\Api\SimpleXMLElement;

/**
 * Simple PHP Redmine client
 * @author <NAME> <kevin at saliou dot name>
 * Website: http://github.com/kbsali/php-redmine-api
 */
class Client
{
    /**
     * @var array
     */
    private static $defaultPorts = array(
        'http'  => 80,
        'https' => 443,
    );

    /**
     * @var int
     */
    private $port;

    /**
     * @var string
     */
    private $url;

    /**
     * @var string
     */
    private $apikeyOrUsername;

    /**
     * @var string
     */
    private $apikeyHeaderName = 'X-Redmine-API-Key';

    /**
     * @var string or null
     */
    private $pass;

    /**
     * @var boolean
     */
    private $checkSslCertificate = false;

    /**
     * @var boolean
     */
    private $checkSslHost = false;

    /**
     *
     * Flag to determine authentication method
     *
     * @var boolean
     */
    private $useHttpAuth = true;

    /**
     * @var array APIs
     */
    private $apis = array();

    /**
     * @var int|null Redmine response code, null if request is not still completed
     */
    private $responseCode = null;

    /**
     * Error strings if json is invalid
     */
    private static $json_errors = array(
        JSON_ERROR_NONE      => 'No error has occurred',
        JSON_ERROR_DEPTH     => 'The maximum stack depth has been exceeded',
        JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
        JSON_ERROR_SYNTAX    => 'Syntax error',
    );

    /**
     * Usage: apikeyOrUsername can be auth key or username.
     * Password needs to be set if username is given.
     *
     * @param string $url
     * @param string $apikeyOrUsername
     * @param string $pass             (string or null)
     */
    public function __construct($url, $apikeyOrUsername, $pass = null)
    {
        $this->url = $url;
        $this->getPort($url);
        $this->apikeyOrUsername = $apikeyOrUsername;
        $this->pass = $pass;
    }

    /**
     * @param  string                    $name
     * @return Api\AbstractApi
     * @throws \InvalidArgumentException
     */
    public function api($name)
    {
        $classes = array(
            'attachment'          => 'Attachment',
            'group'               => 'Group',
            'custom_fields'       => 'CustomField',
            'issue'               => 'Issue',
            'issue_category'      => 'IssueCategory',
            'issue_priority'      => 'IssuePriority',
            'issue_relation'      => 'IssueRelation',
            'issue_status'        => 'IssueStatus',
            'membership'          => 'Membership',
            'news'                => 'News',
            'project'             => 'Project',
            'query'               => 'Query',
            'role'                => 'Role',
            'time_entry'          => 'TimeEntry',
            'time_entry_activity' => 'TimeEntryActivity',
            'tracker'             => 'Tracker',
            'user'                => 'User',
            'version'             => 'Version',
            'wiki'                => 'Wiki',
        );
        if (!isset($classes[$name])) {
            throw new \InvalidArgumentException();
        }
        if (isset($this->apis[$name])) {
            return $this->apis[$name];
        }
        $c = 'Redmine\Api\\'.$classes[$name];
        $this->apis[$name] = new $c($this);

        return $this->apis[$name];
    }

    /**
     * Returns Url
     * @return string
     */
    public function getUrl()
    {
       return $this->url;
    }

    /**
     * HTTP GETs a json $path and tries to decode it
     * @param  string $path
     * @return array
     */
    public function get($path)
    {
        if (false === $json = $this->runRequest($path, 'GET')) {
            return false;
        }

        return $this->decode($json);
    }

    /**
     * Decodes json response
     * @param  string $json
     * @return array
     */
    public function decode($json)
    {
        $decoded = json_decode($json, true);
        if (null !== $decoded) {
            return $decoded;
        }
        if (JSON_ERROR_NONE === json_last_error()) {
            return $json;
        }

        return self::$json_errors[json_last_error()];
    }

    /**
     * HTTP POSTs $params to $path
     * @param  string $path
     * @param  string $data
     * @return mixed
     */
    public function post($path, $data)
    {
        return $this->runRequest($path, 'POST', $data);
    }

    /**
     * HTTP PUTs $params to $path
     * @param  string $path
     * @param  string $data
     * @return array
     */
    public function put($path, $data)
    {
        return $this->runRequest($path, 'PUT', $data);
    }

    /**
     * HTTP PUTs $params to $path
     * @param  string $path
     * @return array
     */
    public function delete($path)
    {
        return $this->runRequest($path, 'DELETE');
    }

    /**
     * Turns on/off ssl certificate check
     * @param  boolean $check
     * @return Client
     */
    public function setCheckSslCertificate($check = false)
    {
        $this->checkSslCertificate = $check;

        return $this;
    }

    /**
     * Turns on/off ssl host certificate check
     * @param  boolean $check
     * @return Client
     */
    public function setCheckSslHost($check = false)
    {
        $this->checkSslHost = $check;

        return $this;
    }

    /**
     * Turns on/off http auth
     * @param  bool   $use
     * @return Client
     */
    public function setUseHttpAuth($use = true)
    {
        $this->useHttpAuth = $use;

        return $this;
    }

    /**
     * Set the port of the connection
     * @param  int    $port
     * @return Client
     */
    public function setPort($port = null)
    {
        if (null !== $port) {
            $this->port = (int) $port;
        }

        return $this;
    }

    /**
     * Set the name of the HTTP header used to set the API key for authentication
     * @param  string $name
     * @return Client
     */
    public function setApikeyHeaderName($name = null)
    {
        if (null !== $name) {
            $this->apikeyHeaderName = $name;
        }

        return $this;
    }

    /**
     * Returns the name of the HTTP header used to set the API key for authentication
     * @return string
     */
    public function getApikeyHeaderName()
    {
        return $this->apikeyHeaderName;
    }

    /**
     * Returns Redmine response code
     * @return int
     */
    public function getResponseCode()
    {
        return $this->responseCode;
    }

    /**
     * Returns the port of the current connection,
     * if not set, it will try to guess the port
     * from the url of the client.
     *
     * @return int    the port number
     */
    public function getPort()
    {
        if (null !== $this->port) {
            return $this->port;
        }

        $tmp = parse_url($this->getUrl());
        if (isset($tmp['port'])) {
            $this->setPort($tmp['port']);
        } elseif (isset($tmp['scheme'])) {
            $this->setPort(self::$defaultPorts[$tmp['scheme']]);
        }

        return $this->port;
    }

    /**
     * @param  string                        $path
     * @param  string                        $method
     * @param  string                        $data
     * @return false|SimpleXMLElement|string
     * @throws \Exception                    If anything goes wrong on curl request
     */
    protected function runRequest($path, $method = 'GET', $data = '')
    {
        $this->responseCode = null;

        $curl = curl_init();
        if (isset($this->apikeyOrUsername) && $this->useHttpAuth) {
{'fraction_non_alphanumeric': 0.13002637843402173, 'fraction_numerical': 0.0006433764395547835, 'mean_word_length': 1.5739360821328034, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 118, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4000714', 'n_tokens_mistral': 4577, 'n_tokens_neox': 4454, 'n_words': 1158}