Commit 97aa788c authored by Simon Welsh's avatar Simon Welsh

Base classes and types for droplet storage

parent 73b5350b
<?hh // strict
namespace _91Carriage\Droplets;
use DateTime;
use ConstMapAccess;
use InvalidArgumentException as IAE;
class Droplet extends Object {
protected int $id;
protected string $name;
protected int $memory;
protected int $vcpus;
protected int $disk;
protected bool $locked;
protected DateTime $created_at;
protected Status $status;
protected Set<int> $backup_ids;
protected Set<int> $snapshot_ids;
protected Set<string> $features;
protected Region $region;
protected Image $image;
protected string $size;
protected Vector<Network> $ipv4;
protected Vector<Network> $ipv6;
protected ?Kernel $kernel;
public function __construct(ConstMapAccess<string, mixed> $data) {
// id
if ($data->containsKey('id')) {
$this->id = static::_toInt($data->at('id'), 'id');
} else {
throw new IAE('An id value is required');
}
// name
if ($data->containsKey('name')) {
$this->name = static::_toString($data->at('name'), 'name');
} else {
throw new IAE('A name value is required');
}
// memory
if ($data->containsKey('memory')) {
$this->memory = static::_toInt($data->at('memory'), 'memory');
} else {
throw new IAE('A memory value is required');
}
// vcpus
if ($data->containsKey('vcpus')) {
$this->vcpus = static::_toInt($data->at('vcpus'), 'vcpus');
} else {
throw new IAE('A vcpus value is required');
}
// disk
if ($data->containsKey('disk')) {
$this->disk = static::_toInt($data->at('disk'), 'disk');
} else {
throw new IAE('A disk value is required');
}
// locked
if ($data->containsKey('locked')) {
$this->locked = static::_toBool($data->at('locked'), 'locked');
} else {
throw new IAE('A locked value is required');
}
// created_at
if ($data->containsKey('created_at')) {
$this->created_at = static::_toDateTime($data->at('created_at'),
'created_at');
} else {
throw new IAE('A created_at value is required');
}
// Status
if ($data->containsKey('status')) {
$this->status = Status::assert($data->at('status'));
} else {
throw new IAE('A status value is required');
}
// backup_ids
if ($data->containsKey('backup_ids')) {
$this->backup_ids = static::_toSet(
$data->at('backup_ids'),
'backup_ids',
class_meth(static::class, '_toInt'),
);
} else {
throw new IAE('A backup_ids value is required');
}
// snapshots_ids
if ($data->containsKey('snapshot_ids')) {
$this->snapshot_ids = static::_toSet(
$data->at('snapshot_ids'),
'snapshot_ids',
class_meth(static::class, '_toInt'),
);
} else {
throw new IAE('A snapshot_ids value is required');
}
// features
if ($data->containsKey('features')) {
$this->features = static::_toSet(
$data->at('features'),
'features',
class_meth(static::class, '_toString'),
);
} else {
throw new IAE('A features value is required');
}
// region
if ($data->containsKey('region')) {
$this->region = static::_toRegion($data->at('region'), 'region');
} else {
throw new IAE('A region value is required');
}
// image
if ($data->containsKey('image')) {
$this->image = static::_toImage($data->at('image'), 'image');
} else {
throw new IAE('An image value is required');
}
// size
if ($data->containsKey('size')) {
$this->size = static::_toString($data->at('size'), 'size');
} else if ($data->containsKey('size_slug')) {
$this->size = static::_toString($data->at('size_slug'),
'size_slug');
} else {
throw new IAE('A size value is required');
}
// ipv4
if ($data->containsKey('ipv4')) {
$this->ipv4 = static::_toVector(
$data->at('ipv4'),
'ipv4',
class_meth(static::class, '_toNetwork'),
);
} else {
throw new IAE('An ipv4 value is required');
}
// ipv6
if ($data->containsKey('ipv6')) {
$this->ipv6 = static::_toVector(
$data->at('ipv6'),
'ipv6',
class_meth(static::class, '_toNetwork'),
);
} else {
throw new IAE('An ipv6 value is required');
}
// kernel
if ($data->containsKey('kernel')) {
$this->kernel = static::_toKernel($data->at('kernel'), 'kernel');
}
}
}
<?hh // strict
namespace _91Carriage\Droplets;
use ConstMapAccess;
use InvalidArgumentException as IAE;
class Image extends Object {
protected int $id;
protected string $name;
protected string $distribution;
protected ?string $slug;
protected bool $public;
protected Set<string> $regions;
protected int $min_disk_size;
public function __construct(ConstMapAccess<string, mixed> $data) {
// id
if ($data->containsKey('id')) {
$this->id = static::_toInt($data->at('id'), 'id');
} else {
throw new IAE('An id value is required');
}
// name
if ($data->containsKey('name')) {
$this->name = static::_toString($data->at('name'), 'name');
} else {
throw new IAE('A name value is required');
}
// distribution
if ($data->containsKey('distribution')) {
$this->distribution = static::_toString($data->at('distribution'),
'distribution');
} else {
throw new IAE('A distribution value is required');
}
// slug
if ($data->containsKey('slug')) {
$this->slug = static::_toString($data->at('slug'), 'slug');
}
// public
if ($data->containsKey('public')) {
$this->public = static::_toBool($data->at('public'), 'public');
} else {
throw new IAE('A public value is required');
}
// regions
if ($data->containsKey('regions')) {
$this->regions = static::_toSet(
$data->at('regions'),
'regions',
class_meth(static::class, '_toString'),
);
} else {
throw new IAE('A regions value is required');
}
// min_disk_size
if ($data->containsKey('min_disk_size')) {
$this->min_disk_size = static::_toInt($data->at('min_disk_size'),
'min_disk_size');
} else {
throw new IAE('A min_disk_size value is required');
}
}
}
<?hh // strict
namespace _91Carriage\Droplets;
use DateTime;
use InvalidArgumentException as IAE;
use Stringish;
abstract class Object {
public static function _toString(mixed $value, string $key): string {
if (is_string($value)) {
return $value;
}
if (!is_object($value) && !is_array($value)) {
return (string)$value;
}
if ($value instanceof Stringish) {
return (string)$value;
}
throw new IAE('Expected a string for key ' . $key);
}
public static function _toInt(mixed $value, string $key): int {
if (is_int($value)) {
return $value;
}
// Change to string
$value = strval($value);
// Check that it's an int
if (!filter_var($value, FILTER_VALIDATE_INT)) {
throw new IAE('Expected an int for key ' . $key);
}
// Convert to int and return
return intval($value);
}
public static function _toBool(mixed $value, string $key): bool {
if (is_bool($value)) {
return $value;
}
// All false-y values map to false
if (!$value) {
return false;
}
// Numeric values
if (is_int($value) || is_float($value)) {
if ($value != 1.0) {
throw new IAE('Expected a boolean for key ' . $key);
}
return true;
}
// String values
if (in_array($value, [
'1',
'true',
'TRUE',
'yes',
'YES',
'on',
'ON',
], true)) {
return true;
}
if (in_array($value, [
'0',
'false',
'FALSE',
'no',
'NO',
'off',
'OFF',
], true)) {
return true;
}
// Bail
throw new IAE('Expected a boolean for key ' . $key);
}
public static function _toDateTime(mixed $value, string $key): DateTime {
if ($value instanceof DateTime) {
return $value;
}
if (is_int($value) || ctype_digit($value)) {
$value = '@' . (int)$value;
}
if (is_string($value)) {
return new DateTime($value);
}
throw new IAE('Expected a datetime for key ' . $key);
}
public static function _toSet<T>(mixed $values, string $key,
(function(mixed, string):T) $handler): Set<T> {
if (!$values instanceof Traversable) {
throw new IAE('Expected a traversable for key ' . $key);
}
$set = Set {};
foreach ($values as $value) {
$set[] = $handler($value, $key);
}
return $set;
}
public static function _toVector<T>(mixed $values, string $key,
(function(mixed, string):T) $handler): Vector<T> {
if (!$values instanceof Traversable) {
throw new IAE('Expected a traversable for key ' . $key);
}
$vector = Vector {};
foreach ($values as $value) {
$vector[] = $handler($value, $key);
}
return $vector;
}
public static function _toRegion(mixed $values, string $key): Region {
if (is_object($values)) {
$values = get_object_vars($values);
}
if (is_array($values)) {
$data = new Map($values);
} else {
throw new IAE('Expected region data for key ' . $key);
}
return new Region($data);
}
public static function _toImage(mixed $values, string $key): Image {
if (is_object($values)) {
$values = get_object_vars($values);
}
if (is_array($values)) {
$data = new Map($values);
} else {
throw new IAE('Expected image data for key ' . $key);
}
return new Image($data);
}
public static function _toNetwork(mixed $values, string $key): Network {
if (is_object($values)) {
$values = get_object_vars($values);
}
if (is_array($values)) {
$data = new Map($values);
} else {
throw new IAE('Expected network data for key ' . $key);
}
if ($data->contains('ip_address')) {
$ip_address = static::_toString($data->at('ip_address'),
'ip_address');
} else {
throw new IAE('An ip_address is required');
}
if ($data->contains('netmask')) {
$netmask = static::_toString($data->at('netmask'), 'netmask');
} else {
throw new IAE('An netmask is required');
}
if ($data->contains('gateway')) {
$gateway = static::_toString($data->at('gateway'), 'gateway');
} else {
throw new IAE('An gateway is required');
}
if ($data->contains('type')) {
$type = static::_toString($data->at('type'), 'type');
} else {
throw new IAE('An type is required');
}
return shape(
'ip_address' => $ip_address,
'netmask' => $netmask,
'gateway' => $gateway,
'type' => $type,
);
}
public static function _toKernel(mixed $values, string $key): Kernel {
if (is_object($values)) {
$values = get_object_vars($values);
}
if (is_array($values)) {
$data = new Map($values);
} else {
throw new IAE('Expected kernel data for key ' . $key);
}
if ($data->contains('id')) {
$id = static::_toInt($data->at('id'), 'id');
} else {
throw new IAE('An id is required');
}
if ($data->contains('name')) {
$name = static::_toString($data->at('name'), 'name');
} else {
throw new IAE('An name is required');
}
if ($data->contains('version')) {
$version = static::_toString($data->at('version'), 'version');
} else {
throw new IAE('An version is required');
}
return shape(
'id' => $id,
'name' => $name,
'version' => $version,
);
}
}
<?hh // strict
namespace _91Carriage\Droplets;
use ConstMapAccess;
use InvalidArgumentException as IAE;
class Region extends Object {
protected string $slug;
protected string $name;
protected Set<string> $sizes;
protected bool $available;
protected Set<string> $features;
public function __construct(ConstMapAccess<string, mixed> $data) {
// slug
if ($data->containsKey('slug')) {
$this->slug = static::_toString($data->at('slug'), 'slug');
} else {
throw new IAE('A slug value is required');
}
// name
if ($data->containsKey('name')) {
$this->name = static::_toString($data->at('name'), 'name');
} else {
throw new IAE('A name value is required');
}
// sizes
if ($data->containsKey('sizes')) {
$this->sizes = static::_toSet(
$data->at('sizes'),
'sizes',
class_meth(static::class, '_toString'),
);
} else {
throw new IAE('A sizes value is required');
}
// available
if ($data->containsKey('available')) {
$this->available = static::_toBool($data->at('available'), 'available');
} else {
throw new IAE('A available value is required');
}
// features
if ($data->containsKey('features')) {
$this->features = static::_toSet(
$data->at('features'),
'features',
class_meth(static::class, '_toString'),
);
} else {
throw new IAE('A features value is required');
}
}
}
<?hh // strict
namespace _91Carriage\Droplets;
enum Status: string {
Created = 'new';
Active = 'active';
Off = 'off';
Archive = 'archive';
};
type Network = shape(
'ip_address' => string,
'netmask' => string,
'gateway' => string,
'type' => string,
);
type Kernel = shape(
'id' => int,
'name' => string,
'version' => string,
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment