<?php

namespace Chefkoch\Morphoji;

class Converter implements ConverterInterface, WrapperInterface
{
    const DELIMITER = ':';

    /** @var Detector */
    private static $detector;

    /**
     * Converter constructor.
     *
     * @param Detector $detector
     */
    public function __construct(Detector $detector = null)
    {
        self::$detector = (null === $detector) ? new Detector() : $detector;
    }

    /**
     * @inheritdoc
     */
    public function fromEmojis($text)
    {
        $pattern = self::$detector->getEmojiPattern();

        $latin1Text = preg_replace_callback($pattern, function ($match) {
            $char = array_pop($match);
            $utf32 = mb_convert_encoding($char, 'UTF-32', 'UTF-8');
            $hex = ltrim(bin2hex($utf32), '0');

            return $this->getPlaceholder($hex);
        }, $text);

        return $latin1Text;
    }

    /**
     * @inheritdoc
     */
    public function toEmojis($text)
    {
        $unicodeText = preg_replace_callback(
            $this->getPlaceholderPattern(),
            function ($match)  {
                $hex4 = str_pad(array_pop($match), 8, '0', STR_PAD_LEFT);
                return mb_convert_encoding(hex2bin($hex4), 'UTF-8', 'UTF-32');
            },
            $text
        );

        return $unicodeText;
    }

    /**
     * @inheritdoc
     *
     * By default wraps with span tags with class 'emoji', overridable via
     * $prefix and $postfix variables. Optionally replaces the placeholder
     * between pre- and postfix with the given innerHtml string (e.g.
     *   could be a good choice for that).
     */
    public function wrap(
        $text,
        $innerHtml = null,
        $prefix = '',
        $postfix = ''
    )
    {
        $wrappedText = preg_replace_callback(
            $this->getPlaceholderPattern(),
            function ($match) use ($innerHtml, $prefix, $postfix) {
                list($placeholder, $code) = $match;
                list($pre, $post) = str_replace(':code:', $code, [$prefix, $postfix]);

                return $pre . ($innerHtml ?: $placeholder) . $post;
            },
            $text
        );

        return $wrappedText;
    }

    /**
     * Returns a placeholder for the given text.
     *
     * The text usually being the hex code for the emoji or the regex needed
     * to find the plaholders.
     *
     * @param string $text
     * @return string
     */
    private function getPlaceholder($text)
    {
        return sprintf(
            '%s%s-%s%s', self::DELIMITER, 'emoji', $text, self::DELIMITER);
    }

    /**
     * Returns a regex pattern to find emoji placeholders.
     *
     * @return string
     */
    private function getPlaceholderPattern()
    {
        return '/'.$this->getPlaceholder('([a-f\d]{2,8})').'/i';
    }
}


<?php

namespace Atrox;

/**
 * Class Haikunator
 *
 * @package Atrox
 */
class Haikunator
{
    /**
     * @var array Adjectives used by Haikunator
     */
    public static $ADJECTIVES = [
        "aged", "ancient", "autumn", "billowing", "bitter", "black", "blue", "bold",
        "broad", "broken", "calm", "cold", "cool", "crimson", "curly", "damp",
        "dark", "dawn", "delicate", "divine", "dry", "empty", "falling", "fancy",
        "flat", "floral", "fragrant", "frosty", "gentle", "green", "hidden", "holy",
        "icy", "jolly", "late", "lingering", "little", "lively", "long", "lucky",
        "misty", "morning", "muddy", "mute", "nameless", "noisy", "odd", "old",
        "orange", "patient", "plain", "polished", "proud", "purple", "quiet", "rapid",
        "raspy", "red", "restless", "rough", "round", "royal", "shiny", "shrill",
        "shy", "silent", "small", "snowy", "soft", "solitary", "sparkling", "spring",
        "square", "steep", "still", "summer", "super", "sweet", "throbbing", "tight",
        "tiny", "twilight", "wandering", "weathered", "white", "wild", "winter", "wispy",
        "withered", "yellow", "young",
    ];

    /**
     * @var array Nouns used by Haikunator
     */
    public static $NOUNS = [
        "art", "band", "bar", "base", "bird", "block", "boat", "bonus",
        "bread", "breeze", "brook", "bush", "butterfly", "cake", "cell", "cherry",
        "cloud", "credit", "darkness", "dawn", "dew", "disk", "dream", "dust",
        "feather", "field", "fire", "firefly", "flower", "fog", "forest", "frog",
        "frost", "glade", "glitter", "grass", "hall", "hat", "haze", "heart",
        "hill", "king", "lab", "lake", "leaf", "limit", "math", "meadow",
        "mode", "moon", "morning", "mountain", "mouse", "mud", "night", "paper",
        "pine", "poetry", "pond", "queen", "rain", "recipe", "resonance", "rice",
        "river", "salad", "scene", "sea", "shadow", "shape", "silence", "sky",
        "smoke", "snow", "snowflake", "sound", "star", "sun", "sun", "sunset",
        "surf", "term", "thunder", "tooth", "tree", "truth", "union", "unit",
        "violet", "voice", "water", "water", "waterfall", "wave", "wildflower", "wind",
        "wood",
    ];

    /**
     * @param array $params
     *
     * @return string
     */
    public function __invoke(array $params = [])
    {
        return static::haikunate($params);
    }

    /**
     * Generate Heroku-like random names to use in your applications.
     *
     * @param array $params Array containing the optinal parameters.
     * @return string
     */
    public static function haikunate(array $params = [])
    {
        $defaults = [
            "delimiter"   => "-",
            "tokenLength" => 4,
            "tokenHex"    => false,
            "tokenChars"  => "0123456789",
        ];

        $params = array_merge($defaults, $params);

        if ($params["tokenHex"] == true) {
            $params["tokenChars"] = "0123456789abcdef";
        }

        $adjective = self::$ADJECTIVES[mt_rand(0, count(self::$ADJECTIVES) - 1)];
        $noun = self::$NOUNS[mt_rand(0, count(self::$NOUNS) - 1)];
        $token = "";

        for ($i = 0; $i < $params["tokenLength"]; $i++) {
            $token .= $params["tokenChars"][mt_rand(0, strlen($params["tokenChars"]) - 1)];
        }

        $sections = [$adjective, $noun, $token];
        return implode($params["delimiter"], array_filter($sections));
    }
}


<?php

namespace Atrox;

use Zend\Console\Adapter\AdapterInterface as ConsoleAdapter;
use ZF\Console\Route;

/**
 * Class HaikunatorCommand
 *
 * @package Atrox
 */
class HaikunatorCommand
{
    /**
     * @var Haikunator
     */
    protected $haikunator;

    /**
     * HaikunatorCommand constructor.
     *
     * @param \Atrox\Haikunator|null $haikunator
     */
    public function __construct(Haikunator $haikunator = null)
    {
        if (! $haikunator) {
            $haikunator = new Haikunator();
        }

        $this->haikunator = $haikunator;
    }

    /**
     * @param \ZF\Console\Route                      $route
     * @param \Zend\Console\Adapter\AdapterInterface $console
     */
    public function __invoke(Route $route, ConsoleAdapter $console)
    {
        $params = $this->getParamsFromRoute($route);
        $params = $this->filterNullParams($params);

        $this->setNounsFromRoute($route);
        $this->setAdjectivesFromRoute($route);

        $console->writeLine($this->haikunator->__invoke($params));
    }

    /**
     * @param Route $route
     *
     * @return array
     */
    protected function getParamsFromRoute(Route $route)
    {
        $params = [
            'tokenLength' => $route->getMatchedParam('token-length'),
            'tokenHex'    => ($route->getMatchedParam('token-hex') || $route->getMatchedParam('x')) ?: null,
            'tokenChars'  => $route->getMatchedParam('token-chars'),
            'delimiter'   => $route->getMatchedParam('delimiter'),
        ];

        return $params;
    }

    /**
     * @param $params
     *
     * @return array
     */
    protected function filterNullParams($params)
    {
        return array_filter($params, function ($value) {
            return $value !== null;
        });
    }

    /**
     * @param Route $route
     */
    protected function setNounsFromRoute(Route $route)
    {
        $nouns = $route->getMatchedParam('nouns');
        if (! empty($nouns)) {
            Haikunator::$NOUNS = $this->getValuesFromFileIfExists($nouns);
        }
    }

    /**
     * @param Route $route
     */
    protected function setAdjectivesFromRoute(Route $route)
    {
        $adjectives = $route->getMatchedParam('adjectives');
        if (! empty($adjectives)) {
            Haikunator::$ADJECTIVES = $this->getValuesFromFileIfExists($adjectives);
        }
    }

    /**
     * @param array $values
     * @return array
     */
    protected function getValuesFromFileIfExists(array $values)
    {
        return count($values) === 1 && file_exists($values[0])
            ? preg_split('/[\s,]+/', file_get_contents($values[0]))
            : $values;
    }
}


<?php
namespace Myaf\Log;

/**
 * Created by PhpStorm.
 * User: linyang
 * Date: 2019/3/22
 * Time: 10:20 AM
 */
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

/**
 * Class Log
 * 标准数据日志
 */
class LogAction
{
    /**
     * @var string
     */
    private static $_logPath = '';
    /**
     * @var string
     */
    private static $_app;
    /**
     * @var string
     */
    private static $_version;
    /**
     * @var Logger
     */
    private static $_instance;

    /**
     * @var Logger
     */
    private $_logger;

    public function __construct()
    {
        $output = "%datetime%|%context.app%|%context.version%|%context.client%|%context.os%|%context.ip%|%context.from%|%context.uuid%|%context.action%|%context.uid%|%message%\n";
        $formatter = new LineFormatter($output, 'Y-m-d H:i:s');

        $stream = new StreamHandler(realpath(self::$_logPath) . '/' . date('Y-m-d') . '.bin');
        $stream->setFormatter($formatter);

        $this->_logger = new Logger('my_logger');
        $this->_logger->pushHandler($stream);
    }

    /**
     * 初始化全局配置变量
     * @param string $app
     * @param string $logPath
     * @param string $timeZone
     * @param bool $debug
     */
    public static function init($app = 'text', $version = '', $logPath = '/data/log', $timeZone = 'Asia/Shanghai')
    {
        if (!self::$_instance) {
            date_default_timezone_set($timeZone);
            self::$_app = $app;
            self::$_logPath = realpath($logPath);
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * log append
     * @param $level
     * @param string $route
     * @param string $uid
     * @param int $code
     * @param string $msg
     * @param string $ext
     */
    public function append($action, $uid, $ip, $ext)
    {
        if (is_array($ext)) {
            $ext = json_encode($ext, JSON_UNESCAPED_UNICODE);
        } else if (!is_string($ext)) {
            $ext = '';
        }
        $this->_logger->addInfo($ext, [
            'datetime' => date('Y-m-d H:i:s'),
            'app' => self::$_app,
            'version' => self::$_version,
            'client' => 0,
            'os' => strtolower(PHP_OS),
            'ip' => $ip ? $ip : self::requestIp(),
            'from' => '',
            'uuid' => '',
            'uid' => $uid,
            'action' => $action,
            'ext' => $ext,
        ]);
    }

    /**
     * 获取访问的用户IP
     * @return string
     */
    private static function requestIp()
    {
        if (isset($_SERVER['HTTP_REMOTEIP'])) {
            return $_SERVER['HTTP_REMOTEIP'];
        }
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
        }
        if (isset($_SERVER['HTTP_X_REAL_IP'])) {
            return $_SERVER['HTTP_X_REAL_IP'];
        }
        return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
    }

    /**
     * @param string $action
     * @param string $uid
     * @param string $ip
     * @param null $ext
     */
    public static function save($action = '', $uid = '', $ip = '', $ext = null)
    {
        self::init()->append($action, $uid, $ip, $ext);
    }

    public static function setAutoFlush($flag = true)
    {
        //...todo
    }

    public static function flush()
    {
        //...todo
    }
}


<?php
namespace Myaf\Log;

/**
 * Created by PhpStorm.
 * User: linyang
 * Date: 2019/3/22
 * Time: 10:20 AM
 */
use Exception;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

/**
 * Class Log
 * 标准业务日志
 */
class Log
{
    /**
     * 日志唯一id.
     */
    const LOG_REQUEST_ID = 'requestUniqueId';

    /**
     * @var bool
     */
    private static $_debug = false;
    /**
     * @var string
     */
    private static $_requestId = '';
    /**
     * @var string
     */
    private static $_logPath = '';
    /**
     * @var string
     */
    private static $_app;
    /**
     * @var Logger
     */
    private static $_instance;

    /**
     * @var Logger
     */
    private $_logger;

    public function __construct()
    {
        $output = "%datetime%|%context.ip%|%context.level%|%context.ruid%|%context.app%|%context.pid%|%context.route%|%context.uid%|%context.code%|%context.msg%|%message%\n";
        $formatter = new LineFormatter($output, 'Y-m-d H:i:s');

        $stream = new StreamHandler(realpath(self::$_logPath) . '/' . date('Y-m-d') . '.txt');
        $stream->setFormatter($formatter);
        $stream->setLevel(self::$_debug ? Logger::DEBUG : Logger::INFO);

        $this->_logger = new Logger('my_logger');
        $this->_logger->pushHandler($stream);
    }

    /**
     * 初始化全局配置变量
     * @param string $app
     * @param string $logPath
     * @param string $timeZone
     * @param bool $debug
     */
    public static function init($app = 'text', $logPath = '/data/log', $timeZone = 'Asia/Shanghai', $debug = false)
    {
        if (!self::$_instance) {
            date_default_timezone_set($timeZone);
            self::$_app = $app;
            self::$_debug = $debug;
            self::$_logPath = realpath($logPath);
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * log append
     * @param $level
     * @param string $route
     * @param string $uid
     * @param int $code
     * @param string $msg
     * @param string $ext
     */
    public function append($level, $route = '', $uid = '', $code = 0, $msg = '', $ext = '')
    {
        if (is_array($ext)) {
            $ext = json_encode($ext, JSON_UNESCAPED_UNICODE);
        } else if (!is_string($ext)) {
            $ext = '';
        }
        $funcName = 'addInfo';
        switch ($level) {
            case 'DEBUG':
                $funcName = 'addDebug';
                break;
            case 'INFO':
                $funcName = 'addInfo';
                break;
            case 'WARN':
                $funcName = 'addWarning';
                break;
            case 'ERROR':
                $funcName = 'addError';
                break;
            case 'FATAL':
                $funcName = 'addEmergency';
                break;
        }
        $this->_logger->$funcName($ext, [
            'datetime' => date('Y-m-d H:i:s'),
            'ip' => self::requestIp(),
            'level' => $level,
            'ruid' => self::getGlobalRequestId(),
            'app' => self::$_app,
            'pid' => getmygid(),
            'route' => $route,
            'uid' => $uid,
            'code' => $code,
            'msg' => $msg
        ]);
    }

    /**
     * 获取访问的用户IP
     * @return string
     */
    private static function requestIp()
    {
        if (isset($_SERVER['HTTP_REMOTEIP'])) {
            return $_SERVER['HTTP_REMOTEIP'];
        }
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
        }
        if (isset($_SERVER['HTTP_X_REAL_IP'])) {
            return $_SERVER['HTTP_X_REAL_IP'];
        }
        return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
    }

    /**
     * 获取全局唯一请求id.
     * 如果未设置则从$_GET、$_POST参数中区搜索.
     * 如果还未找到则直接创建.
     *
     * @return string
     */
    public static function getGlobalRequestId()
    {
        if (!self::$_requestId) {
            try {
                if (isset($_GET[self::LOG_REQUEST_ID]) && $_GET[self::LOG_REQUEST_ID]) {
                    self::$_requestId = $_GET[self::LOG_REQUEST_ID];
                } else if (isset($_POST[self::LOG_REQUEST_ID]) && $_POST[self::LOG_REQUEST_ID]) {
                    self::$_requestId = $_POST[self::LOG_REQUEST_ID];
                } else {
                    self::$_requestId = uniqid();
                }
            } catch (Exception $e) {
                self::$_requestId = uniqid();
            }
        }
        return self::$_requestId;
    }

    /**
     * debug日志
     *
     * @param string $route 路由
     * @param string $uid 用户类信息(例如: 相关用户id或用户名或手机号等)
     * @param string $code 业务错误码
     * @param string $msg 业务错误信息
     * @param string|array|number $ext 标准扩展字段
     * @throws Exception
     */
    public static function debug($route = '', $uid = '', $code = '', $msg = '', $ext = '')
    {
        self::init()->append('DEBUG', $route, $uid, $code, $msg, $ext);
    }

    /**
     * 常规日志
     *
     * @param string $route 路由
     * @param string $uid 用户类信息(例如: 相关用户id或用户名或手机号等)
     * @param string $code 业务错误码
     * @param string $msg 业务错误信息
     * @param string|array|number $ext 标准扩展字段
     * @throws Exception
     */
    public static function info($route = '', $uid = '', $code = '', $msg = '', $ext = '')
    {
        self::init()->append('INFO', $route, $uid, $code, $msg, $ext);
    }

    /**
     * 警告日志
     *
     * @param string $route 路由
     * @param string $uid 用户类信息(例如: 相关用户id或用户名或手机号等)
     * @param string $code 业务错误码
     * @param string $msg 业务错误信息
     * @param string|array|number $ext 标准扩展字段
     * @throws Exception
     */
    public static function warn($route = '', $uid = '', $code = '', $msg = '', $ext = '')
    {
        self::init()->append('WARN', $route, $uid, $code, $msg, $ext);
    }

    /**
     * 挂掉日志
     *
     * @param string $route 路由
     * @param string $uid 用户类信息(例如: 相关用户id或用户名或手机号等)
     * @param string $code 业务错误码
     * @param string $msg 业务错误信息
     * @param string|array|number $ext 标准扩展字段
     * @throws Exception
     */
    public static function fatal($route = '', $uid = '', $code = '', $msg = '', $ext = '')
    {
        self::init()->append('FATAL', $route, $uid, $code, $msg, $ext);
    }

    /**
     * 错误日志
     *
     * @param string $route 路由
     * @param string $uid 用户类信息(例如: 相关用户id或用户名或手机号等)
     * @param string $code 业务错误码
     * @param string $msg 业务错误信息
     * @param string|array|number $ext 标准扩展字段
     * @throws Exception
     */
    public static function error($route = '', $uid = '', $code = '', $msg = '', $ext = '')
    {
        self::init()->append('ERROR', $route, $uid, $code, $msg, $ext);
    }

    public static function setAutoFlush($flag = true)
    {
        //...todo
    }

    public static function flush()
    {
        //...todo
    }
}


<?php

namespace TransIP;

/**
 * The better TransIP SOAP client.
 *
 * @method Api\Colocation colocation()
 * @method Api\Colocation colocation_service()
 * @method Api\Colocation colocationService()
 * @method Api\Domain     domain()
 * @method Api\Domain     domain_service()
 * @method Api\Domain     domainService()
 * @method Api\Forward    forward()
 * @method Api\Forward    forward_service()
 * @method Api\Forward    forwardService()
 * @method Api\Vps        vps()
 * @method Api\Vps        vps_service()
 * @method Api\Vps        vpsService()
 * @method Api\WebHosting hosting()
 * @method Api\WebHosting web_hosting()
 * @method Api\WebHosting webHosting()
 * @method Api\WebHosting web_hosting_service()
 * @method Api\WebHosting webHostingService()
 * @method Api\Haip       haip()
 * @method Api\Haip       ha_ip()
 * @method Api\Haip       ha_ip_service()
 * @method Api\Haip       haip_service()
 * @method Api\Haip       haipService()
 *
 * @author Hidde Beydals <hello@hidde.co>
 */
class Client
{
    /**
     * @var string TransIP username
     */
    protected $username;

    /**
     * @var string TransIP private key
     */
    protected $privateKey;

    /**
     * @var string Accepted permission modes
     */
    protected $acceptedModes = [
        'readwrite',
        'readonly',
    ];

    /**
     * @var string Permission mode
     */
    protected $mode;

    /**
     * @var string TransIP endpoint
     */
    protected $endpoint;

    /**
     * Construct the TransIP client.
     *
     * @param string $username   TransIP username
     * @param string $privateKey TransIP private key
     * @param string $mode       Permission mode
     * @param string $endpoint   TransIP endpoint
     */
    public function __construct($username, $privateKey, $mode = 'readwrite', $endpoint = 'api.transip.nl')
    {
        $this->username = $username;
        $this->privateKey = $privateKey;
        $this->endpoint = $endpoint;

        $this->setMode($mode);
    }

    /**
     * Get the API.
     *
     * @param string $name Name/alias of the API
     *
     * @throws \InvalidArgumentException
     *
     * @return \TransIP\Api\ApiInterface
     */
    public function api($name)
    {
        switch ($name) {
            case 'domain':
            case 'domain_service':
            case 'domainService':
                return new Api\Domain($this);

            case 'colocation':
            case 'colocation_service':
            case 'colocationService':
                return new Api\Colocation($this);

            case 'forward':
            case 'forward_service':
            case 'forwardService':
                return new Api\Forward($this);

            case 'vps':
            case 'vps_service':
            case 'vpsService':
                return new Api\Vps($this);

            case 'hosting':
            case 'web_hosting':
            case 'webHosting':
            case 'web_hosting_service':
            case 'webHostingService':
                return new Api\WebHosting($this);

            case 'haip':
            case 'ha_ip':
            case 'ha_ip_service':
            case 'haip_service':
            case 'haipService':
                return new Api\Haip($this);

            default:
                throw new \InvalidArgumentException(sprintf('Undefined api instance called: [%s]', $name));
        }
    }

    /**
     * Build the SOAP client for the given service.
     *
     * @param string $service Name of the service to build the SOAP client for
     *
     * @throws \InvalidArgumentException
     *
     * @return \TransIP\Soap\SoapClient
     */
    public function buildSoapClient($service)
    {
        $director = new Soap\SoapClientDirector($this->username, $this->mode, $this->endpoint);

        switch ($service) {
            case 'DomainService':
                return $director->build(new Soap\Builder\DomainSoapClientBuilder);
            case 'ColocationService':
                return $director->build(new Soap\Builder\ColocationSoapClientBuilder);
            case 'ForwardService':
                return $director->build(new Soap\Builder\ForwardSoapClientBuilder);
            case 'VpsService':
                return $director->build(new Soap\Builder\VpsSoapClientBuilder);
            case 'WebhostingService':
                return $director->build(new Soap\Builder\WebHostingSoapClientBuilder);
            case 'HaipService':
                return $director->build(new Soap\Builder\HaipSoapClientBuilder);
            default:
                throw new \InvalidArgumentException(sprintf('Undefined soap client service builder called: [%s]', $service));
        }
    }

    /**
     * Set the permission mode.
     *
     * @param string $mode Permission mode
     *
     * @throws \InvalidArgumentException
     *
     * @return void
     */
    public function setMode($mode)
    {
        if (!in_array($mode, $this->acceptedModes)) {
            throw new \InvalidArgumentException(sprintf('Invalid mode: [%s]', $mode));
        }

        $this->mode = $mode;
    }

    /**
     * Get the private key.
     *
     * @return string
     */
    public function getPrivateKey()
    {
        return $this->privateKey;
    }

    /**
     * Get the endpoint.
     *
     * @return string
     */
    public function getEndpoint()
    {
        return $this->endpoint;
    }

    /**
     * Let some magic happen.
     *
     * @param string $name
     *
     * @throws \InvalidArgumentException
     *
     * @return \TransIP\Api\ApiInterface
     */
    public function __call($name, $args)
    {
        try {
            return $this->api($name);
        } catch (\InvalidArgumentException $e) {
            throw new \BadMethodCallException(sprintf('Undefined method called: [%s]', $name));
        }
    }
}


<?php

namespace TransIP\Api;

class Haip extends AbstractApi
{
    const SERVICE = 'HaipService';

    /**
     * Get a HA-IP by name.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Haip
     */
    public function getHaip($haipName)
    {
        return $this->call(self::SERVICE, 'getHaip', [$haipName]);
    }

    /**
     * Get all HA-IPs.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Haip[]
     */
    public function getHaips()
    {
        return $this->call(self::SERVICE, 'getHaips');
    }

    /**
     * Changes the VPS connected to the HA-IP.
     *
     * @param string $haipName The HA-IP name
     * @param string $vpsName  The VPS name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function changeHaipVps($haipName, $vpsName)
    {
        return $this->call(self::SERVICE, 'changeHaipVps', [$haipName, $vpsName]);
    }

    /**
     * Replaces the currently attached VPSes to the HA-IP with the provided list.
     *
     * @param string   $haipName The HA-IP name
     * @param string[] $vpsNames The VPS names
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setHaipVpses($haipName, $vpsNames)
    {
        return $this->call(self::SERVICE, 'setHaipVpses', [$haipName, $vpsNames]);
    }

    /**
     * Sets the provided IP setup for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     * @param string $ipSetup  ('both', 'noipv6', 'ipv6to4')
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setIpSetup($haipName, $ipSetup)
    {
        return $this->call(self::SERVICE, 'setIpSetup', [$haipName, $ipSetup]);
    }

    /**
     * Sets the provided balancing mode for the HA-IP.
     *
     * The cookie name is expected to be an empty string unless the balancing mode is set to 'cookie'.
     *
     * HA-IP Pro feature.
     *
     * @param string $haipName      The HA-IP name
     * @param string $balancingMode ('roundrobin', 'cookie', 'source')
     * @param string $cookieName    The cookie name that pins the session if the balancing mode is 'cookie'
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setBalancingMode($haipName, $balancingMode, $cookieName = '')
    {
        return $this->call(self::SERVICE, 'setBalancingMode', [$haipName, $balancingMode, $cookieName]);
    }

    /**
     * Configures the HTTP health check for the HA-IP. To disable use Haip::setTcpHealthCheck.
     *
     * HA-IP Pro feature.
     *
     * @param string $haipName  The HA-IP name
     * @param string $path      The path that will be accessed when performing health checks
     * @param int    $port      The port that will be used when performing health checks
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setHttpHealthCheck($haipName, $path, $port)
    {
        return $this->call(self::SERVICE, 'setHttpHealthCheck', [$haipName, $path, $port]);
    }

    /**
     * Configures a TCP health check for the HA-IP. This is the default health check.
     *
     * HA-IP Pro feature.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setTcpHealthCheck($haipName)
    {
        return $this->call(self::SERVICE, 'setTcpHealthCheck', [$haipName]);
    }

    /**
     * Get a status report for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return array
     */
    public function getStatusReport($haipName)
    {
        return $this->call(self::SERVICE, 'getStatusReport', [$haipName]);
    }

    /**
     * Get all certificates for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function getCertificatesByHaip($haipName)
    {
        return $this->call(self::SERVICE, 'getCertificatesByHaip', [$haipName]);
    }

    /**
     * Get all available certificates ready to attach to your HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function getAvailableCertificatesByHaip($haipName)
    {
        return $this->call(self::SERVICE, 'getAvailableCertificatesByHaip', [$haipName]);
    }

    /**
     * Add a certificate to the HA-IP.
     *
     * @param string $haipName      The HA-IP name
     * @param int    $certificateId The certificate ID
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function addCertificateToHaip($haipName, $certificateId)
    {
        return $this->call(self::SERVICE, 'addCertificateToHaip', [$haipName, $certificateId]);
    }

    /**
     * Remove a certificate from the HA-IP.
     *
     * @param string $haipName      The HA-IP name
     * @param int    $certificateId The certificate ID
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteCertificateFromHaip($haipName, $certificateId)
    {
        return $this->call(self::SERVICE, 'deleteCertificateFromHaip', [$haipName, $certificateId]);
    }

    /**
     * Add a LetsEncrypt certificate to the HA-IP.
     *
     * @param string $haipName   The HA-IP name
     * @param string $commonName The common name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function startHaipLetsEncryptCertificateIssue($haipName, $commonName)
    {
        return $this->call(self::SERVICE, 'startHaipLetsEncryptCertificateIssue', [$haipName, $commonName]);
    }

    /**
     * Returns the current ptr for the given HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function getPtrForHaip($haipName)
    {
        return $this->call(self::SERVICE, 'getPtrForHaip', [$haipName]);
    }

    /**
     * Update the ptr record for the given HA-IP.
     *
     * @param string $haipName The HA-IP name
     * @param string $ptr      The ptr record
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setPtrForHaip($haipName, $ptr)
    {
        return $this->call(self::SERVICE, 'setPtrForHaip', [$haipName, $ptr]);
    }

    /**
     * Update the description for the HA-IP.
     *
     * @param string $haipName    The HA-IP name
     * @param string $description The HA-IP description
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setHaipDescription($haipName, $description)
    {
        return $this->call(self::SERVICE, 'setHaipDescription', [$haipName, $description]);
    }

    /**
     * Get all port configurations for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @deprecated 5.6
     * @see Haip::getPortConfigurations()
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function getHaipPortConfigurations($haipName)
    {
        return $this->call(self::SERVICE, 'getHaipPortConfigurations', [$haipName]);
    }

    /**
     * Get all port configurations for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return array
     */
    public function getPortConfigurations($haipName)
    {
        return $this->call(self::SERVICE, 'getPortConfigurations', [$haipName]);
    }

    /**
     * Set the default port configuration for the HA-IP.
     *
     * @param string $haipName The HA-IP name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setDefaultPortConfiguration($haipName)
    {
        return $this->call(self::SERVICE, 'setDefaultPortConfiguration', [$haipName]);
    }

    /**
     * Add port configuration to the HA-IP.
     *
     * @param string $haipName   The HA-IP name
     * @param string $name       The port name
     * @param int    $portNumber The port number
     * @param string $mode       ('tcp','http','https','proxy')
     *
     * @deprecated 5.6
     * @see Haip::addPortConfiguration()
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function addHaipPortConfiguration($haipName, $name, $portNumber, $mode)
    {
        return $this->call(self::SERVICE, 'addHaipPortConfiguration', [$haipName, $name, $portNumber, $mode]);
    }

    /**
     * Add port configuration to the HA-IP.
     *
     * @param string $haipName        The HA-IP name
     * @param string $name            The name describing the port configuration
     * @param int    $sourcePort      The port that is addressed on the HA-IP
     * @param int    $targetPort      The port that is addressed on the VPS
     * @param string $mode            ('tcp', 'http', 'https', 'proxy')
     * @param string $endpointSslMode ('off, 'on' strict')
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function addPortConfiguration($haipName, $name, $sourcePort, $targetPort, $mode, $endpointSslMode)
    {
        $this->call(
            self::SERVICE,
            'addPortConfiguration',
            [$haipName, $name, $sourcePort, $targetPort, $mode, $endpointSslMode]
        );
    }

    /**
     * Update port configuration for the HA-IP.
     *
     * @param string $haipName        The HA-IP name
     * @param int    $configurationId The configuration ID
     * @param string $name            The port name
     * @param int    $portNumber      The port number
     * @param string $mode            ('tcp','http','https','proxy')
     *
     * @deprecated 5.6
     * @see Haip::updatePortConfiguration()
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function updateHaipPortConfiguration($haipName, $configurationId, $name, $portNumber, $mode)
    {
        return $this->call(
            self::SERVICE,
            'updateHaipPortConfiguration',
            [$haipName, $configurationId, $name, $portNumber, $mode]
        );
    }

    /**
     * Update port configuration for the HA-IP.
     *
     * @param string $haipName         The HA-IP name
     * @param int    $configurationId  The configuration ID
     * @param string $name             The name describing the port configuration
     * @param int    $sourcePort       The port that is addressed on the HA-IP
     * @param int    $targetPort       The port that is addressed on the VPS
     * @param string $mode             ('tcp', 'http', 'https', 'proxy')
     * @param string $endpointSslMode  ('off, 'on' strict')
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function updatePortConfiguration(
        $haipName,
        $configurationId,
        $name,
        $sourcePort,
        $targetPort,
        $mode,
        $endpointSslMode
    ) {
        $this->call(
            self::SERVICE,
            'updatePortConfiguration',
            [$haipName, $configurationId, $name, $sourcePort, $targetPort, $mode, $endpointSslMode]
        );
    }

    /**
     * Delete the port configuration for the HA-IP.
     *
     * @param string $haipName        The HA-IP name
     * @param int    $configurationId The configuration ID
     *
     * @deprecated 5.6
     * @see Haip::deletePortConfiguration()
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteHaipPortConfiguration($haipName, $configurationId)
    {
        return $this->call(self::SERVICE, 'deleteHaipPortConfiguration', [$haipName, $configurationId]);
    }

    /**
     * Delete the port configuration for the HA-IP.
     *
     * @param string $haipName     The HA-IP name
     * @param int $configurationId The configuration ID
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deletePortConfiguration($haipName, $configurationId)
    {
        return $this->call(self::SERVICE, 'deletePortConfiguration', [$haipName, $configurationId]);
    }

    /**
     * Cancel the HA-IP.
     *
     * @param string $haipName The HA-IP name
     * @param string $endTime  The time to cancel the HA-IP
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cancelHaip($haipName, $endTime)
    {
        return $this->call(self::SERVICE, 'cancelHaip', [$haipName, $endTime]);
    }
}


<?php

namespace TransIP\Api;

use TransIP\Client;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
abstract class AbstractApi implements ApiInterface
{
    /**
     * @var \TransIP\Client
     */
    protected $client;

    /**
     * @param Client $client
     */
    public function __construct(Client $client)
    {
        $this->client = $client;
    }

    /**
     * Make a SOAP call.
     *
     * @param string $service    WSDL service used for the call
     * @param string $method     Method used for the call
     * @param array  $parameters Parameters used for the call
     *
     * @return mixed
     */
    protected function call($service, $method, array $parameters = [])
    {
        return $this->getSoapClient($service, $method, $parameters)->__call($method, $parameters);
    }

    /**
     * Get the SOAP client and preset call parameters.
     *
     * @param string $service    WSDL service used for the call
     * @param string $method     Method used for the call
     * @param array  $parameters Parameters used for the call
     *
     * @return \TransIP\Soap\SoapClient
     */
    private function getSoapClient($service, $method, array $parameters)
    {
        $timestamp = time();
        $nonce = uniqid(null, true);

        $soapClient = $this->client->buildSoapClient($service);
        $soapClient->setTimestamp($timestamp);
        $soapClient->setNonce($nonce);
        $soapClient->setSignature(array_merge($parameters, ['__method' => $method]), $this->client->getPrivateKey(), $service, $this->client->getEndpoint(), $timestamp, $nonce);

        return $soapClient;
    }
}


<?php

namespace TransIP\Soap;

use TransIP\Soap\Builder\SoapClientBuilderInterface;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
class SoapClientDirector
{
    const CLIENT_VERSION = 5.8;

    /**
     * @var string
     */
    protected $login;

    /**
     * @var string
     */
    protected $mode;

    /**
     * @var string
     */
    protected $endpoint;

    /**
     * Construct the SOAP client director.
     *
     * @param string $login    TransIP login
     * @param string $mode     Permission mode
     * @param string $endpoint TransIP endpoint
     */
    public function __construct($login, $mode, $endpoint)
    {
        $this->login = $login;
        $this->mode = $mode;
        $this->endpoint = $endpoint;
    }

    /**
     * Build the the SOAP client.
     *
     * @param SoapClientBuilderInterface $builder
     *
     * @return SoapClient
     */
    public function build(SoapClientBuilderInterface $builder)
    {
        $builder->createWsdl($this->endpoint);
        $builder->createSoapClient();
        $builder->setLogin($this->login);
        $builder->setMode($this->mode);
        $builder->setClientVersion(self::CLIENT_VERSION);

        return $builder->getSoapClient();
    }
}


<?php

namespace TransIP\Soap;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
class SoapClientFactory implements SoapClientFactoryInterface
{
    /**
     * Make a new SoapClient instance.
     *
     * @param string $wsdl     WSDL
     * @param array  $classMap Class map
     *
     * @return \TransIP\Soap\SoapClient
     */
    public function make($wsdl, array $classMap = [])
    {
        return new SoapClient($wsdl, [
            'trace'      => true,
            'exceptions' => true,
            'encoding'   => 'utf-8',
            'features'   => SOAP_SINGLE_ELEMENT_ARRAYS,
            'classmap'   => $classMap,
            'cache_wsdl' => WSDL_CACHE_MEMORY,
        ]);
    }
}


<?php

namespace TransIP\Api;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
class Colocation extends AbstractApi
{
    const SERVICE = 'ColocationService';

    /**
     * Request access to the data-center.
     *
     * @param string   $when        Datetime of the wanted data-center access, in YYYY-MM-DD hh:mm:ss format
     * @param int      $duration    Expected duration of the visit, in minutes
     * @param string[] $visitors    Names of the visitors for this data-center visit, max amount of visitors is 20
     * @param string   $phoneNumber Phone number to receive access codes on
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\DataCenterVisitor[]
     */
    public function requestAccess($when, $duration, array $visitors, $phoneNumber)
    {
        return $this->call(self::SERVICE, 'requestAccess', [$when, $duration, $visitors, $phoneNumber]);
    }

    /**
     * Request remote hands to the data-center.
     *
     * @param string $colocationName   Name of the colocation
     * @param string $contactName      Contact name
     * @param string $phoneNumber      Phone number to contact
     * @param int    $expectedDuration Expected duration of the job in minutes
     * @param string $instructions     Instructions on what to do
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function requestRemoteHands($colocationName, $contactName, $phoneNumber, $expectedDuration, $instructions)
    {
        return $this->call(self::SERVICE, 'requestRemoteHands', [$colocationName, $contactName, $phoneNumber, $expectedDuration, $instructions]);
    }

    /**
     * Get colocation names.
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getColocationNames()
    {
        return $this->call(self::SERVICE, 'getColoNames');
    }

    /**
     * Get active IP addresses that are assigned to a colocation.
     * Both ipv4 (dot notation) and ipv6 addresses (ipv6 presentation) are returned.
     *
     * @param string $colocationName Name of the colocation to get the IP addresses for
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getIpAddresses($colocationName)
    {
        return $this->call(self::SERVICE, 'getIpAddresses', [$colocationName]);
    }

    /**
     * Get IP ranges that are assigned to a colocation.
     * Both ipv4 and ipv6 ranges are returned in CIDR notation.
     *
     * @see https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
     *
     * @param string $colocationName Name of the colocation to get the ranges for
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getIpRanges($colocationName)
    {
        return $this->call(self::SERVICE, 'getIpRanges', [$colocationName]);
    }

    /**
     * Create a new IP address, either ipv4 or ipv6.
     *
     * The service will validate the address, ensure the user is entitled
     * to the address and will add the address to the correct colocation
     * and range.
     *
     * @param string $ipAddress  IP address to create, can be ipv4 or ipv6
     * @param string $reverseDns Reverse DNS name for this IP address
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createIpAddress($ipAddress, $reverseDns)
    {
        return $this->call(self::SERVICE, 'createIpAddress', [$ipAddress, $reverseDns]);
    }

    /**
     * Delete an IP address, either ipv4 or ipv6.
     *
     * The service will validate the address, ensure the user is entitled
     * to remove the address and will remove it completely, together with
     * any Reverse DNS and monitoring assined to the address.
     *
     * @param string $ipAddress IP address to delete, can be ipv6 or ipv6
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteIpAddress($ipAddress)
    {
        return $this->call(self::SERVICE, 'deleteIpAddress', [$ipAddress]);
    }

    /**
     * Get the Reverse DNS for an IP address assigned to the user.
     *
     * @param string $ipAddress IP address, can be ipv4 or ipv6
     *
     * @throws \SoapFault
     *
     * @return string
     */
    public function getReverseDns($ipAddress)
    {
        return $this->call(self::SERVICE, 'getReverseDns', [$ipAddress]);
    }

    /**
     * Set the Reverse DNS name for an IP address.
     *
     * @param string $ipAddress  IP address to set the Reverse DNS for, can be ipv4 or ipv6
     * @param string $reverseDns New Reverse DNS, must be a valid value
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setReverseDns($ipAddress, $reverseDns)
    {
        return $this->call(self::SERVICE, 'setReverseDns', [$ipAddress, $reverseDns]);
    }
}


<?php

namespace TransIP\Api;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
class Vps extends AbstractApi
{
    const SERVICE = 'VpsService';

    /**
     * Get available VPS products.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Product[]
     */
    public function getAvailableProducts()
    {
        return $this->call(self::SERVICE, 'getAvailableProducts');
    }

    /**
     * Get available VPS add-ons.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Product[]
     */
    public function getAvailableAddons()
    {
        return $this->call(self::SERVICE, 'getAvailableAddons');
    }

    /**
     * Get all the active add-ons for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Product[]
     */
    public function getActiveAddonsForVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getActiveAddonsForVps', [$vpsName]);
    }

    /**
     * Get available upgrades for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Product[]
     */
    public function getAvailableUpgrades($vpsName)
    {
        return $this->call(self::SERVICE, 'getAvailableUpgrades', [$vpsName]);
    }

    /**
     * Get cancellable add-ons for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Product[]
     */
    public function getCancellableAddonsForVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getCancellableAddonsForVps', [$vpsName]);
    }

    /**
     * Order a VPS with optional add-ons.
     *
     * @param string   $productName         Name of the product
     * @param string[] $addons              Array with additional add-ons
     * @param string   $operatingSystemName Name of the operating system to install
     * @param string   $hostname            Hostname for the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function orderVps($productName, array $addons, $operatingSystemName, $hostname)
    {
        return $this->call(self::SERVICE, 'orderVps', [$productName, $addons, $operatingSystemName, $hostname]);
    }

    /**
     * Order a VPS with optional add-ons.
     *
     * @param string   $productName         Name of the product
     * @param string[] $addons              Array with additional add-ons
     * @param string   $operatingSystemName Name of the operating system to install
     * @param string   $hostname            Hostname for the VPS
     * @param string   $availabilityZone    Availability zone for the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function orderVpsInAvailabilityZone($productName, array $addons, $operatingSystemName, $hostname, $availabilityZone)
    {
        return $this->call(self::SERVICE, 'orderVps', [$productName, $addons, $operatingSystemName, $hostname, $availabilityZone]);
    }

    /**
     * Clone a VPS.
     *
     * @param string $vpsName The vps name
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cloneVps($vpsName)
    {
        return $this->call(self::SERVICE, 'cloneVps', [$vpsName]);
    }

    /**
     * Clone a VPS to AvailabilityZone.
     *
     * @param string $vpsName The vps name
     * @param string $availabilityZone Availability zone for the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cloneVpsToAvailabilityZone($vpsName, $availabilityZone)
    {
        return $this->call(self::SERVICE, 'cloneVps', [$vpsName, $availabilityZone]);
    }

    /**
     * Order add-ons for a VPS.
     *
     * @param string   $vpsName Name of the VPS
     * @param string[] $addons  Array with addons
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function orderAddon($vpsName, array $addons)
    {
        return $this->call(self::SERVICE, 'orderAddon', [$vpsName, $addons]);
    }

    /**
     * Order a private network.
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function orderPrivateNetwork()
    {
        return $this->call(self::SERVICE, 'orderPrivateNetwork');
    }

    /**
     * Upgrade a VPS.
     *
     * @param string $vpsName              Name of the VPS
     * @param string $upgradeToProductName Name of the product to upgrade to
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function upgradeVps($vpsName, $upgradeToProductName)
    {
        return $this->call(self::SERVICE, 'upgradeVps', [$vpsName, $upgradeToProductName]);
    }

    /**
     * Cancel a VPS.
     *
     * @param string $vpsName Name of the VPS
     * @param string $endTime Time to cancel the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cancelVps($vpsName, $endTime)
    {
        return $this->call(self::SERVICE, 'cancelVps', [$vpsName, $endTime]);
    }

    /**
     * Cancel a VPS add-on.
     *
     * @param string $vpsName   Name of the VPS
     * @param string $addonName Name of the add-on
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cancelAddon($vpsName, $addonName)
    {
        return $this->call(self::SERVICE, 'cancelAddon', [$vpsName, $addonName]);
    }

    /**
     * Cancel a private network.
     *
     * @param string $privateNetworkName Name of the private network
     * @param string $endTime            Time to cancel the private network
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cancelPrivateNetwork($privateNetworkName, $endTime)
    {
        return $this->call(self::SERVICE, 'cancelPrivateNetwork', [$privateNetworkName, $endTime]);
    }

    /**
     * Get private networks for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\PrivateNetwork
     */
    public function getPrivateNetworksByVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getPrivateNetworksByVps', [$vpsName]);
    }

    /**
     * Get all private networks.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\PrivateNetwork[]
     */
    public function getAllPrivateNetworks()
    {
        return $this->call(self::SERVICE, 'getAllPrivateNetworks');
    }

    /**
     * Add VPS to a private network.
     *
     * @param string $vpsName            Name of the VPS
     * @param string $privateNetworkName Name of the private network
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function addVpsToPrivateNetwork($vpsName, $privateNetworkName)
    {
        return $this->call(self::SERVICE, 'addVpsToPrivateNetwork', [$vpsName, $privateNetworkName]);
    }

    /**
     * Remove VPS from a private network.
     *
     * @param string $vpsName            Name of the VPS
     * @param string $privateNetworkName Name of the private network
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function removeVpsFromPrivateNetwork($vpsName, $privateNetworkName)
    {
        return $this->call(self::SERVICE, 'removeVpsFromPrivateNetwork', [$vpsName, $privateNetworkName]);
    }

    /**
     * Get traffic information for a VPS for this contract period.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return array
     */
    public function getTrafficInformationForVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getTrafficInformationForVps', [$vpsName]);
    }

    /**
     * Get pooled traffic information for the account.
     *
     * @throws \SoapFault
     *
     * @return array
     */
    public function getPooledTrafficInformation()
    {
        return $this->call(self::SERVICE, 'getPooledTrafficInformation');
    }

    /**
     * Start a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function start($vpsName)
    {
        return $this->call(self::SERVICE, 'start', [$vpsName]);
    }

    /**
     * Stop a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function stop($vpsName)
    {
        return $this->call(self::SERVICE, 'stop', [$vpsName]);
    }

    /**
     * Reset a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function reset($vpsName)
    {
        return $this->call(self::SERVICE, 'reset', [$vpsName]);
    }

    /**
     * Create a snapshot of a VPS.
     *
     * @param string $vpsName     Name of the VPS
     * @param string $description Snapshot description
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createSnapshot($vpsName, $description)
    {
        return $this->call(self::SERVICE, 'createSnapshot', [$vpsName, $description]);
    }

    /**
     * Revert a snapshot.
     *
     * @param string $vpsName      Name of the VPS
     * @param string $snapshotName Name of the snapshot
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function revertSnapshot($vpsName, $snapshotName)
    {
        return $this->call(self::SERVICE, 'revertSnapshot', [$vpsName, $snapshotName]);
    }

    /**
     * Revert a snapshot to another VPS.
     *
     * @param string $sourceVpsName      The name of the VPS where the snapshot is made
     * @param string $snapshotName       The snapshot name
     * @param string $destinationVpsName The name of the VPS where the snapshot should be reverted to
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function revertSnapshotToOtherVps($sourceVpsName, $snapshotName, $destinationVpsName)
    {
        return $this->call(self::SERVICE, 'revertSnapshotToOtherVps', [$sourceVpsName, $snapshotName, $destinationVpsName]);
    }

    /**
     * Remove a snapshot.
     *
     * @param string $vpsName      Name of the VPS
     * @param string $snapshotName Name of the snapshot
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function removeSnapshot($vpsName, $snapshotName)
    {
        return $this->call(self::SERVICE, 'removeSnapshot', [$vpsName, $snapshotName]);
    }

    /**
     * Revert a vps backup.
     *
     * @param string $vpsName     The vps name
     * @param int    $vpsBackupId The backup id
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function revertVpsBackup($vpsName, $vpsBackupId)
    {
        return $this->call(self::SERVICE, 'revertVpsBackup', [$vpsName, $vpsBackupId]);
    }

    /**
     * Get a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Vps
     */
    public function getVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getVps', [$vpsName]);
    }

    /**
     * Get all VPSes.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Vps[]
     */
    public function getVpses()
    {
        return $this->call(self::SERVICE, 'getVpses');
    }

    /**
     * Get all snapshots for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\Snapshot[]
     */
    public function getSnapshotsByVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getSnapshotsByVps', [$vpsName]);
    }

    /**
     * Get all operating systems.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\OperatingSystem[]
     */
    public function getOperatingSystems()
    {
        return $this->call(self::SERVICE, 'getOperatingSystems');
    }

    /**
     * Install an operating system on a VPS.
     *
     * @param string $vpsName             Name of the VPS
     * @param string $operatingSystemName Name of the operating system
     * @param string $hostname            Hostname
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function installOperatingSystem($vpsName, $operatingSystemName, $hostname)
    {
        return $this->call(self::SERVICE, 'installOperatingSystem', [$vpsName, $operatingSystemName, $hostname]);
    }

    /**
     * Install an operating system on a vps with a unattended install file.
     *
     * @param string $vpsName             The name of the VPS
     * @param string $operatingSystemName The name of the operating to install
     * @param string $base64InstallText   base64_encoded preseed/kickstart text
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function installOperatingSystemUnattended($vpsName, $operatingSystemName, $base64InstallText)
    {
        return $this->call(self::SERVICE, 'installOperatingSystemUnattended', [$vpsName, $operatingSystemName, $base64InstallText]);
    }

    /**
     * Get IP addresses for a VPS.
     *
     * @param string $vpsName Name of the VPS
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getIpsForVps($vpsName)
    {
        return $this->call(self::SERVICE, 'getIpsForVps', [$vpsName]);
    }

    /**
     * Get all IP addresses.
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getAllIps()
    {
        return $this->call(self::SERVICE, 'getAllIps');
    }

    /**
     * Add ipv6 address to a VPS.
     *
     * @param string $vpsName     Name of the VPS
     * @param string $ipv6Address ipv6 address
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function addIpv6ToVps($vpsName, $ipv6Address)
    {
        return $this->call(self::SERVICE, 'addIpv6ToVps', [$vpsName, $ipv6Address]);
    }

    /**
     * Update PTR record (reverse DNS) for an IP address.
     *
     * @param string $ipAddress IP address to update, can be ipv4 or ipv6
     * @param string $ptrRecord PTR record to update to
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function updatePtrRecord($ipAddress, $ptrRecord)
    {
        return $this->call(self::SERVICE, 'updatePtrRecord', [$ipAddress, $ptrRecord]);
    }

    /**
     * Enable or disable a customer lock for a VPS.
     *
     * @param string $vpsName Name of the VPS
     * @param bool   $enabled Status of the lock
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setCustomerLock($vpsName, $enabled)
    {
        return $this->call(self::SERVICE, 'setCustomerLock', [$vpsName, $enabled]);
    }

    /**
     * Handover a VPS to another TransIP user.
     *
     * @param string $vpsName           Name of the VPS
     * @param string $targetAccountName TransIP username of the other user
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function handoverVps($vpsName, $targetAccountName)
    {
        $this->call(self::SERVICE, 'handoverVps', [$vpsName, $targetAccountName]);
    }

    /**
     * Get all available availability zones.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\AvailabilityZone[]
     */
    public function getAvailableAvailabilityZones()
    {
        return $this->call(self::SERVICE, 'getAvailableAvailabilityZones');
    }
}


<?php

namespace TransIP\Api;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
class WebHosting extends AbstractApi
{
    const SERVICE = 'WebhostingService';

    /**
     * Get all domain names that have a web hosting package attached to them.
     *
     * @throws \SoapFault
     *
     * @return string[]
     */
    public function getWebHostingDomainNames()
    {
        return $this->call(self::SERVICE, 'getWebhostingDomainNames');
    }

    /**
     * Get available web hosting packages.
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\WebHostingPackage[]
     */
    public function getAvailablePackages()
    {
        return $this->call(self::SERVICE, 'getAvailablePackages');
    }

    /**
     * Get information about existing web hosting on a domain name.
     *
     * Be aware that the information returned is outdated after calling
     * a modifying function (e.g. create Cronjob()).
     *
     * Call this function again to refresh the information.
     *
     * @param string $domainName Domain name of the web hosting package to get info for
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\WebHost
     */
    public function getInfo($domainName)
    {
        return $this->call(self::SERVICE, 'getInfo', [$domainName]);
    }

    /**
     * Order web hosting for a domain name.
     *
     * @param string                                   $domainName        Domain name to order web hosting for
     * @param \TransIP\Model\WebHostingPackage $webHostingPackage Web hosting package to order
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function order($domainName, $webHostingPackage)
    {
        return $this->call(self::SERVICE, 'order', [$domainName, $webHostingPackage]);
    }

    /**
     * Get available upgrade packages for a domain name with web hosting.
     *
     * @param string $domainName Domain name to get the upgrades for
     *
     * @throws \SoapFault
     *
     * @return \TransIP\Model\WebHostingPackage[]
     */
    public function getAvailableUpgrades($domainName)
    {
        return $this->call(self::SERVICE, 'getAvailableUpgrades', [$domainName]);
    }

    /**
     * Upgrade the web hosting of a domain name.
     *
     * @param string $domainName        Domain name to upgrade web hosting for
     * @param string $webHostingPackage Web hosting package to upgrade to
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function upgrade($domainName, $webHostingPackage)
    {
        return $this->call(self::SERVICE, 'upgrade', [$domainName, $webHostingPackage]);
    }

    /**
     * Cancel web hosting for a domain name.
     *
     * @param string $domainName Domain name to cancel the web hosting for
     * @param string $endTime    Time to cancel the web hosting
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function cancel($domainName, $endTime)
    {
        return $this->call(self::SERVICE, 'cancel', [$domainName, $endTime]);
    }

    /**
     * Set a new FTP password for a web hosting package.
     *
     * @param string $domainName Domain name to set the FTP password for
     * @param string $password   New FTP password for the web hosting package
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setFtpPassword($domainName, $password)
    {
        return $this->call(self::SERVICE, 'setFtpPassword', [$domainName, $password]);
    }

    /**
     * Create a cronjob for a web hosting package.
     *
     * @param string                         $domainName Domain name to create the cronjob for
     * @param \TransIP\Model\Cronjob $cronjob    Cronjob to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createCronjob($domainName, $cronjob)
    {
        return $this->call(self::SERVICE, 'createCronjob', [$domainName, $cronjob]);
    }

    /**
     * Delete a cronjob for a web hosting package.
     * All completely matching cronjobs will be removed.
     *
     * @param string                         $domainName Domain name to create the cronjob for
     * @param \TransIP\Model\Cronjob $cronjob    Cronjob to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteCronjob($domainName, $cronjob)
    {
        return $this->call(self::SERVICE, 'deleteCronjob', [$domainName, $cronjob]);
    }

    /**
     * Create a mail box for a web hosting package.
     * The address field of the mail box object has to be unique.
     *
     * @param string                         $domainName Domain name to create the mail box for
     * @param \TransIP\Model\MailBox $mailBox    Mail box to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createMailBox($domainName, $mailBox)
    {
        return $this->call(self::SERVICE, 'createMailBox', [$domainName, $mailBox]);
    }

    /**
     * Modify the mail box settings for a web hosting package.
     *
     * @param string                         $domainName Domain name to modify the mail box for
     * @param \TransIP\Model\MailBox $mailBox    Mail box to modify
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function modifyMailBox($domainName, $mailBox)
    {
        return $this->call(self::SERVICE, 'modifyMailbox', [$domainName, $mailBox]);
    }

    /**
     * Set a new password for a mail box from a web hosting package.
     *
     * @param string                         $domainName Domain name to set the mail box password for
     * @param \TransIP\Model\MailBox $mailBox    Mail box to set the password for
     * @param string                         $password   New password for the mail box
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setMailBoxPassword($domainName, $mailBox, $password)
    {
        return $this->call(self::SERVICE, 'setMailBoxPassword', [$domainName, $mailBox, $password]);
    }

    /**
     * Delete a mail box from a web hosting package.
     *
     * @param string                         $domainName Domain name to remove the mail box from
     * @param \TransIP\Model\MailBox $mailBox    Mail box to remove
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteMailBox($domainName, $mailBox)
    {
        return $this->call(self::SERVICE, 'deleteMailBox', [$domainName, $mailBox]);
    }

    /**
     * Create a mail forward for a web hosting package.
     *
     * @param string                             $domainName  Domain name to create the mail forward for
     * @param \TransIP\Model\MailForward $mailForward Mail forward to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createMailForward($domainName, $mailForward)
    {
        return $this->call(self::SERVICE, 'createMailForward', [$domainName, $mailForward]);
    }

    /**
     * Modify a mail forward from a web hosting package.
     *
     * @param string                             $domainName  Domain name to modify the mail forward from
     * @param \TransIP\Model\MailForward $mailForward Mail forward to modify
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function modifyMailForward($domainName, $mailForward)
    {
        return $this->call(self::SERVICE, 'modifyMailForward', [$domainName, $mailForward]);
    }

    /**
     * Delete a mail forward from a web hosting package.
     *
     * @param string                             $domainName  Domain name to delete the mail forward from
     * @param \TransIP\Model\MailForward $mailForward Mail forward to delete
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteMailForward($domainName, $mailForward)
    {
        return $this->call(self::SERVICE, 'deleteMailForward', [$domainName, $mailForward]);
    }

    /**
     * Create a new database for a web hosting package.
     *
     * @param string                    $domainName Domain name to create the database for
     * @param \TransIP\Model\Db $database   Database to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createDatabase($domainName, $database)
    {
        return $this->call(self::SERVICE, 'createDatabase', [$domainName, $database]);
    }

    /**
     * Modify a database from a web hosting package.
     *
     * @param string                    $domainName Domain name to modify the database from
     * @param \TransIP\Model\Db $database   Database to modify
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function modifyDatabase($domainName, $database)
    {
        return $this->call(self::SERVICE, 'modifyDatabase', [$domainName, $database]);
    }

    /**
     * Set a password for a database from a web hosting package.
     *
     * @param string                    $domainName Domain name to set the database password for
     * @param \TransIP\Model\Db $database   Database to set the password for
     * @param string                    $password   Password to set
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function setDatabasePassword($domainName, $database, $password)
    {
        return $this->call(self::SERVICE, 'setDatabasePassword', [$domainName, $database, $password]);
    }

    /**
     * Delete a database from a web hosting package.
     *
     * @param string $domainName Domain name to delete the database from
     * @param string $database   Database to delete
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function deleteDatabase($domainName, $database)
    {
        return $this->call(self::SERVICE, 'deleteDatabase', [$domainName, $database]);
    }

    /**
     * Create a sub domain for a web hosting package.
     *
     * @param string                           $domainName $domainName Domain name to create the sub domain for
     * @param \TransIP\Model\SubDomain $subDomain  Sub domain to create
     *
     * @throws \SoapFault
     *
     * @return mixed
     */
    public function createSubDomain($domainName, $subDomain)
    {
        return $this->call(self::SERVICE, 'createSubdomain', [$domainName, $subDomain]);
    }

    /**
     * Delete a sub domain for a web hosting package.
     *
     * @param string                           $domainName $domainName Domain name to delete the sub domain from
     * @param \TransIP\Model\Subdomain $subDomain  Sub domain to delete
     *
     * @return mixed
     *
     * @throws\ SoapFault
     */
    public function deleteSubDomain($domainName, $subDomain)
    {
        return $this->call(self::SERVICE, 'deleteSubdomain', [$domainName, $subDomain]);
    }
}


<?php

namespace TransIP\Soap\Builder;

use TransIP\Soap\SoapClientFactory;

/**
 * @author Hidde Beydals <hello@hidde.co>
 */
abstract class SoapClientBuilder implements SoapClientBuilderInterface
{
    /**
     * @var \TransIP\Soap\SoapClient
     */
    protected $soapClient;

    /**
     * @var string
     */
    protected $wsdl;

    /**
     * {@inheritdoc}
     */
    public function setLogin($login)
    {
        $this->soapClient->setLogin($login);
    }

    /**
     * {@inheritdoc}
     */
    public function setMode($mode)
    {
        $this->soapClient->setMode($mode);
    }

    /**
     * {@inheritdoc}
     */
    public function setClientVersion($clientVersion)
    {
        $this->soapClient->setClientVersion($clientVersion);
    }

    /**
     * {@inheritdoc}
     */
    public function createWsdl($endpoint)
    {
        $this->wsdl = sprintf('https://%s'.$this->getWsdlPath(), $endpoint);
    }

    /**
     * {@inheritdoc}
     */
    public function createSoapClient()
    {
        $factory = new SoapClientFactory();
        $this->soapClient = $factory->make($this->wsdl, $this->getClassMap());
    }

    /**
     * {@inheritdoc}
     */
    public function getSoapClient()
    {
        return $this->soapClient;
    }

    /**
     * Get the Wsdl path.
     *
     * @return string
     */
    abstract protected function getWsdlPath();

    /**
     * Get the SOAP class map.
     *
     * @return array
     */
    abstract protected function getClassMap();
}


<?php

namespace RdnConsole\Factory\Controller;

use RdnConsole\Controller;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class Index implements FactoryInterface
{
	/**
	 * Create service
	 *
	 * @param ServiceLocatorInterface $controllers
	 * @return Controller\Index
	 */
	public function createService(ServiceLocatorInterface $controllers)
	{
		if ($controllers instanceof ServiceLocatorAwareInterface)
		{
			$services = $controllers->getServiceLocator();
		}
		else
		{
			$services = $controllers;
		}

		return new Controller\Index($services->get('RdnConsole\Application'));
	}
}


<?php

namespace RdnConsole\Factory\Command;

use RdnConsole\Command;
use Zend\ServiceManager\Config;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class CommandManager implements FactoryInterface
{
	/**
	 * Create service
	 *
	 * @param ServiceLocatorInterface $services
	 * @return Command\CommandManager
	 */
	public function createService(ServiceLocatorInterface $services)
	{
		$config = $services->get('Config');
		$config = new Config($config['rdn_console_commands']);

		$commands = new Command\CommandManager($config);
		$commands->setServiceLocator($services);

		return $commands;
	}
}


<?php

namespace RdnConsole\Factory;

use RdnConsole\Command\CommandInterface;
use Symfony\Component\Console;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class Application implements FactoryInterface
{
	/**
	 * Create service
	 *
	 * @param ServiceLocatorInterface $services
	 * @return Console\Application
	 */
	public function createService(ServiceLocatorInterface $services)
	{
		$app = new Console\Application;

		$config = $services->get('Config');
		$config = $config['rdn_console'];

		if (isset($config['application']['name']))
		{
			$app->setName($config['application']['name']);
		}
		if (isset($config['application']['version']))
		{
			$app->setVersion($config['application']['version']);
		}

		if (!empty($config['commands']))
		{
			$commands = $services->get('RdnConsole\Command\CommandManager');
			foreach ($config['commands'] as $name)
			{
				/** @var CommandInterface $command */
				$command = $commands->get($name);
				$app->add($command->getAdapter());
			}
		}

		return $app;
	}
}


<?php

namespace WordPress\Discovery;

/**
 * Site data from an API index.
 */
class Site {
	/**
	 * Data from the API index.
	 *
	 * @var stdClass
	 */
	protected $data;

	/**
	 * API index URL.
	 *
	 * @var string
	 */
	protected $index;

	/**
	 * Constructor.
	 *
	 * @param stdClass $data Data from the API index.
	 * @param string $index API index URL.
	 */
	public function __construct( $data, $index ) {
		$this->data = $data;
		$this->index = $index;
	}

	/**
	 * Get the name of a site.
	 *
	 * @return string
	 */
	public function getName() {
		return $this->data->name;
	}

	/**
	 * Get the description for a site.
	 *
	 * @return string
	 */
	public function getDescription() {
		return $this->data->description;
	}

	/**
	 * Get the URL for a site.
	 *
	 * @return string
	 */
	public function getURL() {
		return $this->data->url;
	}

	/**
	 * Get the index URL for the API.
	 *
	 * @return string
	 */
	public function getIndexURL() {
		return $this->index;
	}

	/**
	 * Get namespaces supported by the site.
	 *
	 * @return string[] List of namespaces supported by the site.
	 */
	public function getSupportedNamespaces() {
		if ( empty( $this->data->namespaces ) || ! is_array( $this->data->namespaces ) ) {
			return array();
		}

		return $this->data->namespaces;
	}

	/**
	 * Does the site support a namespace?
	 *
	 * @param string $namespace Namespace to check.
	 * @return bool True if supported by the site, false otherwise.
	 */
	public function supportsNamespace( $namespace ) {
		return in_array( $namespace, $this->getSupportedNamespaces() );
	}

	/**
	 * Get features supported by the site.
	 *
	 * @return array Map of authentication method => method-specific data.
	 */
	public function getSupportedAuthentication() {
		if ( empty( $this->data->authentication ) || empty( $this->data->authentication ) ) {
			return array();
		}

		return (array) $this->data->authentication;
	}

	/**
	 * Does the site support an authentication method?
	 *
	 * @param string $method Authentication method to check.
	 * @return bool True if supported by the site, false otherwise.
	 */
	public function supportsAuthentication( $method ) {
		return array_key_exists( $method, $this->getSupportedAuthentication() );
	}

	/**
	 * Get method-specific data for the given authentication method.
	 *
	 * @param string $method Authentication method to get data for.
	 * @return mixed Method-specific data if available, null if not supported.
	 */
	public function getAuthenticationData( $method ) {
		if ( ! $this->supportsAuthentication( $method ) ) {
			return null;
		}

		$authentication = $this->getSupportedAuthentication();
		return $authentication[ $method ];
	}
}


<?php

namespace Joli\Jane\OpenApi\Guesser\OpenApiSchema;

use Joli\Jane\Guesser\JsonSchema\SimpleTypeGuesser as BaseSimpleTypeGuesser;
use Joli\Jane\OpenApi\Model\Schema;

class SimpleTypeGuesser extends BaseSimpleTypeGuesser
{
    /**
     * {@inheritdoc}
     */
    public function supportObject($object)
    {
        return ($object instanceof Schema)
            &&
            in_array($object->getType(), $this->typesSupported)
            &&
            !in_array($object->getFormat(), $this->excludeFormat)
        ;
    }
}


<?php

namespace Joli\Jane\OpenApi\Guesser\OpenApiSchema;

use Joli\Jane\Guesser\ChainGuesserAwareInterface;
use Joli\Jane\Guesser\ChainGuesserAwareTrait;
use Joli\Jane\Guesser\ClassGuesserInterface;
use Joli\Jane\Guesser\GuesserInterface;
use Joli\Jane\OpenApi\Model\BodyParameter;
use Joli\Jane\OpenApi\Model\Operation;
use Joli\Jane\OpenApi\Model\PathItem;
use Joli\Jane\OpenApi\Model\Response;
use Joli\Jane\OpenApi\Model\OpenApi;
use Joli\Jane\Registry;

class OpenApiGuesser implements GuesserInterface, ClassGuesserInterface, ChainGuesserAwareInterface
{
    use ChainGuesserAwareTrait;

    /**
     * {@inheritDoc}
     */
    public function supportObject($object)
    {
        return ($object instanceof OpenApi);
    }

    /**
     * {@inheritDoc}
     *
     * @param OpenApi $object
     */
    public function guessClass($object, $name, $reference, Registry $registry)
    {
        if ($object->getDefinitions() !== null) {
            foreach ($object->getDefinitions() as $key => $definition) {
                $this->chainGuesser->guessClass($definition, $key, $reference . '/definitions/' . $key, $registry);
            }
        }

        if ($object->getPaths()) {
            foreach ($object->getPaths() as $pathName => $path) {
                if ($path instanceof PathItem) {
                    $this->getClassFromOperation($pathName . 'Delete', $path->getDelete(), $reference . '/' . $pathName . '/delete', $registry);
                    $this->getClassFromOperation($pathName . 'Get', $path->getGet(), $reference . '/' . $pathName . '/get', $registry);
                    $this->getClassFromOperation($pathName . 'Head', $path->getHead(), $reference . '/' . $pathName . '/head', $registry);
                    $this->getClassFromOperation($pathName . 'Options', $path->getOptions(), $reference . '/' . $pathName . '/options', $registry);
                    $this->getClassFromOperation($pathName . 'Patch', $path->getPatch(), $reference . '/' . $pathName . '/patch', $registry);
                    $this->getClassFromOperation($pathName . 'Post', $path->getPost(), $reference . '/' . $pathName . '/post', $registry);
                    $this->getClassFromOperation($pathName . 'Put', $path->getPut(), $reference . '/' . $pathName . '/put', $registry);

                    if ($path->getParameters()) {
                        foreach ($path->getParameters() as $key => $parameter) {
                            if ($parameter instanceof BodyParameter) {
                                $this->chainGuesser->guessClass($parameter->getSchema(), $pathName . 'Body' . $key, $reference . '/' . $pathName . '/parameters/' . $key,  $registry);
                            }
                        }
                    }
                }
            }
        }

        if ($object->getParameters()) {
            foreach ($object->getParameters() as $parameterName => $parameter) {
                if ($parameter instanceof BodyParameter) {
                    $this->chainGuesser->guessClass($parameter->getSchema(), $parameterName, $reference . '/parameters/' . $parameterName,  $registry);
                }
            }
        }
    }

    /**
     * Discover classes in operation
     *
     * @param $name
     * @param Operation $operation
     * @param string $reference
     * @param Registry $registry
     */
    protected function getClassFromOperation($name, Operation $operation = null, $reference, $registry)
    {
        if ($operation === null) {
            return;
        }

        if ($operation->getParameters()) {
            foreach ($operation->getParameters() as $key => $parameter) {
                if ($parameter instanceof BodyParameter) {
                    $this->chainGuesser->guessClass($parameter->getSchema(), $name . 'Body', $reference . '/parameters/' . $key,  $registry);
                }
            }
        }

        if ($operation->getResponses()) {
            foreach ($operation->getResponses() as $status => $response) {
                if ($response instanceof Response) {
                    $this->chainGuesser->guessClass($response->getSchema(), $name.'Response'.$status, $reference . '/responses/' . $status, $registry);
                }
            }
        }
    }
}


<?php

namespace Joli\Jane\OpenApi\Generator;

use Joli\Jane\Generator\Context\Context;
use Joli\Jane\Runtime\Reference;
use Joli\Jane\Reference\Resolver;
use Joli\Jane\OpenApi\Model\Schema;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
use PhpParser\Node\Scalar;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

trait OutputGeneratorTrait
{
    /**
     * @return DenormalizerInterface
     */
    abstract protected function getDenormalizer();

    /**
     * @param         $status
     * @param         $schema
     * @param Context $context
     *
     * @return [string, null|Stmt\If_]
     */
    protected function createResponseDenormalizationStatement($status, $schema, Context $context, $reference)
    {
        $jsonReference  = $reference;
        $array          = false;

        if ($schema instanceof Reference) {
            list($jsonReference, $schema) = $this->resolve($schema, Schema::class);
        }

        if ($schema instanceof Schema && $schema->getType() == "array") {
            $array = true;
            $jsonReference .= '/items';

            if ($schema->getItems() instanceof Reference) {
                list($jsonReference, ) = $this->resolve($schema->getItems(), Schema::class);
            }
        }

        $class = $context->getRegistry()->getClass($jsonReference);

        // Happens when reference resolve to a none object
        if ($class === null) {
            $returnType = 'null';
            $returnStmt = new Stmt\Return_(new Expr\ConstFetch(new Name('null')));
        } else {
            $class = $context->getRegistry()->getSchema($jsonReference)->getNamespace() . "\\Model\\" . $class->getName();

            if ($array) {
                $class .= "[]";
            }

            $returnType = "\\" . $class;
            $returnStmt = new Stmt\Return_(new Expr\MethodCall(
                new Expr\PropertyFetch(new Expr\Variable('this'), 'serializer'),
                'deserialize',
                [
                    new Arg(new Expr\Cast\String_(new Expr\MethodCall(new Expr\Variable('response'), 'getBody'))),
                    new Arg(new Scalar\String_($class)),
                    new Arg(new Scalar\String_('json'))
                ]
            ));
        }

        if ($status === 'default') {
            return [$returnType, $returnStmt];
        }

        return [$returnType, new Stmt\If_(
            new Expr\BinaryOp\Equal(
                new Scalar\String_($status),
                new Expr\MethodCall(new Expr\Variable('response'), 'getStatusCode')
            ),
            [
                'stmts' => [$returnStmt]
            ]
        )];
    }

    /**
     * @param Reference $reference
     * @param $class
     *
     * @return mixed
     */
    private function resolve(Reference $reference, $class)
    {
        $result    = $reference;

        do {
            $refString = (string) $reference->getMergedUri();
            $result = $result->resolve(function ($data) use($result, $class) {
                return $this->getDenormalizer()->denormalize($data, $class, 'json', [
                    'document-origin' => (string) $result->getMergedUri()->withFragment('')
                ]);
            });
        } while ($result instanceof Reference);

        return [$refString, $result];
    }
}


<?php

namespace Joli\Jane\OpenApi\Command;

use Joli\Jane\OpenApi\JaneOpenApi;
use Joli\Jane\Registry;
use Joli\Jane\Schema;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class GenerateCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    public function configure()
    {
        $this->setName('generate');
        $this->setDescription('Generate an api client: class, normalizers and resources given a specific Json OpenApi file');
        $this->addOption('config-file', 'c', InputOption::VALUE_OPTIONAL, 'File to use for Jane OpenAPI configuration');
        $this->addOption('reference', null, InputOption::VALUE_NONE, 'Use the JSON Reference specification in your generated library');
        $this->addOption('date-format', 'd', InputOption::VALUE_OPTIONAL, 'Date time format to use for date time field');
        $this->addArgument('openapi-file', InputArgument::OPTIONAL, 'Location of the OpenApi (Swagger) Schema file');
        $this->addArgument('namespace', InputArgument::OPTIONAL, 'Namespace prefix to use for generated files');
        $this->addArgument('directory', InputArgument::OPTIONAL, 'Directory where to generate files');
    }

    /**
     * {@inheritdoc}
     */
    public function execute(InputInterface $input, OutputInterface $output)
    {
        $options = [];

        $configFile = null;

        if (!$input->hasOption('config-file') && file_exists('.jane-openapi')) {
            $configFile = '.jane-openapi';
        } elseif($input->hasOption('config-file') && null !== $input->getOption('config-file')) {
            $configFile = $input->getOption('config-file');
        }

        if ($configFile) {
            $configFile = $input->getOption('config-file');

            if (!file_exists($configFile)) {
                throw new \RuntimeException(sprintf('Config file %s does not exist', $configFile));
            }

            $options = require $configFile;

            if (!is_array($options)) {
                throw new \RuntimeException(sprintf('Invalid config file specified or invalid return type in file %s', $configFile));
            }
        } else {
            if ($input->hasArgument('openapi-file') && null !== $input->getArgument('openapi-file')) {
                $options['openapi-file'] = $input->getArgument('openapi-file');
            }

            if ($input->hasArgument('namespace') && null !== $input->getArgument('namespace')) {
                $options['namespace'] = $input->getArgument('namespace');
            }

            if ($input->hasArgument('directory') && null !== $input->getArgument('directory')) {
                $options['directory'] = $input->getArgument('directory');
            }

            if ($input->hasOption('date-format') && null !== $input->getOption('date-format')) {
                $options['date-format'] = $input->getOption('date-format');
            }

            if ($input->hasOption('no-reference') && null !== $input->getOption('no-reference')) {
                $options['reference'] = $input->getOption('reference');
            }
        }

        $options = $this->resolveConfiguration($options);
        $registry = new Registry();

        if (array_key_exists('openapi-file', $options)) {
            $registry->addSchema($this->resolveSchema($options['openapi-file'], $options));
        } else {
            foreach ($options['mapping'] as $schema => $schemaOptions) {
                $registry->addSchema($this->resolveSchema($schema, $schemaOptions));
            }
        }

        $janeOpenApi = JaneOpenApi::build($options);
        $files       = $janeOpenApi->generate($registry);
        $janeOpenApi->printFiles($files, $registry);

        foreach ($files as $file) {
            $output->writeln(sprintf("Generate %s", $file->getFilename()));
        }
    }

    protected function resolveConfiguration(array $options = [])
    {
        $optionsResolver = new OptionsResolver();
        $optionsResolver->setDefaults([
            'reference' => false,
            'date-format' => \DateTime::RFC3339,
        ]);

        if (array_key_exists('openapi-file', $options)) {
            $optionsResolver->setRequired([
                'openapi-file',
                'namespace',
                'directory',
            ]);
        } else {
            $optionsResolver->setRequired([
                'mapping'
            ]);
        }

        return $optionsResolver->resolve($options);
    }

    protected function resolveSchema($schema, array $options = [])
    {
        $optionsResolver = new OptionsResolver();

        // To support old schema
        $optionsResolver->setDefined([
            'openapi-file',
            'reference',
            'date-format',
        ]);

        $optionsResolver->setRequired([
            'namespace',
            'directory',
        ]);

        $options = $optionsResolver->resolve($options);

        return new Schema($schema, $options['namespace'], $options['directory'], '');
    }
}


<?php

namespace Joli\Jane\OpenApi\Generator;

use Joli\Jane\Generator\Context\Context;
use Joli\Jane\OpenApi\Model\OpenApi;
use Joli\Jane\OpenApi\Naming\OperationNamingInterface;
use Joli\Jane\OpenApi\Operation\OperationManager;

use PhpParser\BuilderFactory;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt;

class ClientGenerator
{
    /**
     * @var \Joli\Jane\OpenApi\Operation\OperationManager
     */
    private $operationManager;

    /**
     * @var OperationGenerator
     */
    private $operationGenerator;

    /**
     * @var OperationNamingInterface
     */
    private $operationNaming;

    public function __construct(OperationManager $operationManager, OperationGenerator $operationGenerator, OperationNamingInterface $operationNaming)
    {
        $this->operationManager   = $operationManager;
        $this->operationGenerator = $operationGenerator;
        $this->operationNaming    = $operationNaming;
    }

    /**
     * Generate an ast node (which correspond to a class) for a OpenApi spec
     *
     * @param OpenApi $openApi
     * @param string  $namespace
     * @param Context $context
     * @param string  $reference
     * @param string  $suffix
     *
     * @return Node[]
     */
    public function generate(OpenApi $openApi, $namespace, Context $context, $reference, $suffix = 'Resource')
    {
        $operationsGrouped = $this->operationManager->buildOperationCollection($openApi, $reference);
        $nodes             = [];

        foreach ($operationsGrouped as $group => $operations) {
            $nodes[] = $this->generateClass($group, $operations, $namespace, $context, $suffix);
        }

        return $nodes;
    }

    protected function generateClass($group, $operations, $namespace, Context $context, $suffix = 'Resource')
    {
        $factory    = new BuilderFactory();
        $class      = $factory->class($group . $suffix);
        $class->extend('Resource');

        foreach ($operations as $operation) {
            $class->addStmt($this->operationGenerator->generate($this->operationNaming->generateFunctionName($operation), $operation, $context));
        }

        return $factory->namespace($namespace . "\\Resource")
            ->addStmt($factory->use('Joli\Jane\OpenApi\Runtime\Client\QueryParam'))
            ->addStmt($factory->use('Joli\Jane\OpenApi\Runtime\Client\Resource'))
            ->addStmt($class)
            ->getNode();
    }
}


<?php

namespace Joli\Jane\OpenApi\Generator\Parameter;

use Doctrine\Common\Inflector\Inflector;
use Joli\Jane\Generator\Context\Context;
use Joli\Jane\Runtime\Reference;
use Joli\Jane\Reference\Resolver;
use Joli\Jane\OpenApi\Model\BodyParameter;
use Joli\Jane\OpenApi\Model\Schema;
use PhpParser\Node;
use PhpParser\Parser;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

class BodyParameterGenerator extends ParameterGenerator
{
    /**
     * @var DenormalizerInterface
     */
    private $denormalizer;

    public function __construct(Parser $parser, DenormalizerInterface $denormalizer)
    {
        parent::__construct($parser);

        $this->denormalizer = $denormalizer;
    }

    /**
     * {@inheritDoc}
     *
     * @param $parameter BodyParameter
     */
    public function generateMethodParameter($parameter, Context $context, $reference)
    {
        $name = Inflector::camelize($parameter->getName());

        list($class, $array) = $this->getClass($parameter, $context, $reference);

        if (null === $array || true === $array) {
            if ($class == "array") {
                return new Node\Param($name, null, "array");
            }

            return new Node\Param($name);
        }

        return new Node\Param($name, null, $class);
    }

    /**
     * {@inheritDoc}
     *
     * @param $parameter BodyParameter
     */
    public function generateDocParameter($parameter, Context $context, $reference)
    {
        list($class, $array) = $this->getClass($parameter, $context, $reference);

        if (null === $class) {
            return sprintf('%s $%s %s', 'mixed', Inflector::camelize($parameter->getName()), $parameter->getDescription() ?: '');
        }

        return sprintf('%s $%s %s', $class, Inflector::camelize($parameter->getName()), $parameter->getDescription() ?: '');
    }

    /**
     * @param BodyParameter $parameter
     * @param Context $context
     *
     * @return array
     */
    protected function getClass(BodyParameter $parameter, Context $context, $reference)
    {
        $resolvedSchema = null;
        $jsonReference  = null;
        $array          = false;
        $schema         = $parameter->getSchema();

        if ($schema instanceof Reference) {
            list($jsonReference, $resolvedSchema) = $this->resolveSchema($schema, Schema::class);
        }

        if ($schema instanceof Schema && $schema->getType() == "array" && $schema->getItems() instanceof Reference) {
            list($jsonReference, $resolvedSchema) = $this->resolveSchema($schema->getItems(), Schema::class);
            $array          = true;
        }

        if ($resolvedSchema === null) {
            if ($context->getRegistry()->hasClass($reference)) {
                return ["\\" . $context->getRegistry()->getSchema($reference)->getNamespace() . "\\Model\\" . $context->getRegistry()->getClass($reference)->getName(), false];
            }

            return [$schema->getType(), null];
        }

        $class = $context->getRegistry()->getClass($jsonReference);

        // Happens when reference resolve to a none object
        if ($class === null) {
            return [$schema->getType(), null];
        }

        $class = "\\" . $context->getRegistry()->getSchema($jsonReference)->getNamespace() . "\\Model\\" . $class->getName();

        if ($array) {
            $class .= "[]";
        }

        return [$class, $array];
    }

    /**
     * @param Reference $reference
     * @param $class
     *
     * @return mixed
     */
    private function resolveSchema(Reference $reference, $class)
    {
        $result    = $reference;

        do {
            $refString = (string) $reference->getMergedUri();
            $result = $result->resolve(function ($data) use($result, $class) {
                return $this->denormalizer->denormalize($data, $class, 'json', [
                    'document-origin' => (string) $result->getMergedUri()->withFragment('')
                ]);
            });
        } while ($result instanceof Reference);

        return [$refString, $result];
    }
}


<?php

namespace Joli\Jane\OpenApi\Guesser\OpenApiSchema;

use Joli\Jane\Guesser\JsonSchema\ObjectGuesser;
use Joli\Jane\OpenApi\Model\Schema;

class SchemaGuesser extends ObjectGuesser
{
    /**
     * {@inheritDoc}
     */
    public function supportObject($object)
    {
        return (($object instanceof Schema) && ($object->getType() === 'object' || $object->getType() === null) && $object->getProperties() !== null);
    }

    /**
     * @return string
     */
    protected function getSchemaClass()
    {
        return Schema::class;
    }
}