/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\UuidIdentifier', null, $field->getName()); if ($field->hasClassName()) { Assertion::isInstanceOf($value, $field->getClassName(), null, $field->getName()); } }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var BigNumber $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\BigNumber', null, $field->getName()); Assertion::true(!$value->isNegative(), sprintf('Field [%s] cannot be negative.', $field->getName()), $field->getName()); Assertion::true($value->isLessThanOrEqualTo('18446744073709551615'), sprintf('Field [%s] cannot be greater than [18446744073709551615].', $field->getName()), $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var BigNumber $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\BigNumber', null, $field->getName()); Assertion::true($value->isGreaterThanOrEqualTo('-9223372036854775808'), sprintf('Field [%s] cannot be less than [-9223372036854775808].', $field->getName()), $field->getName()); Assertion::true($value->isLessThanOrEqualTo('9223372036854775807'), sprintf('Field [%s] cannot be greater than [9223372036854775807].', $field->getName()), $field->getName()); }
/** * {@inheritdoc} * * @return Message */ public function deserialize($data, array $options = []) { /** @var Message $message */ $message = unserialize($data); Assertion::isInstanceOf($message, 'Gdbots\\Pbj\\Message'); return $message; }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var Enum $value */ Assertion::isInstanceOf($value, 'Gdbots\\Common\\Enum', null, $field->getName()); Assertion::isInstanceOf($value, $field->getClassName(), null, $field->getName()); Assertion::integer($value->getValue(), null, $field->getName()); Assertion::range($value->getValue(), $this->getMin(), $this->getMax(), null, $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::integer($value, null, $field->getName()); $intMin = $this->getMin(); $intMax = $this->getMax(); $min = NumberUtils::bound($field->getMin(), $intMin, $intMax); $max = NumberUtils::bound($field->getMax(), $intMin, $intMax); Assertion::range($value, $min, $max, null, $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::string($value, null, $field->getName()); // intentionally using strlen to get byte length, not mb_strlen $length = strlen($value); $minLength = $field->getMinLength(); $maxLength = NumberUtils::bound($field->getMaxLength(), $minLength, $this->getMaxBytes()); $okay = $length >= $minLength && $length <= $maxLength; Assertion::true($okay, sprintf('Field [%s] must be between [%d] and [%d] bytes, [%d] bytes given.', $field->getName(), $minLength, $maxLength, $length), $field->getName()); }
/** * @param string $name * @param DynamicFieldKind $kind * @param mixed $value */ private function __construct($name, DynamicFieldKind $kind, $value) { Assertion::betweenLength($name, 1, 127); Assertion::regex($name, self::VALID_NAME_PATTERN, sprintf('DynamicField name [%s] must match pattern [%s].', $name, self::VALID_NAME_PATTERN)); $this->name = $name; $this->kind = $kind->getValue(); $field = self::createField($this->kind); $this->value = $field->getType()->decode($value, $field); $field->guardValue($this->value); }
/** * todo: review random failures from YamlSerializer on $id when no tag is present. * * @param SchemaCurie $curie * @param string $id * @param string $tag The tag will be automatically fixed to a slug-formatted-string. * @throws \Exception */ public function __construct(SchemaCurie $curie, $id, $tag = null) { $this->curie = $curie; $this->id = trim((string) $id) ?: 'null'; Assertion::regex($this->id, '/^[\\w\\/\\.:-]+$/', null, 'MessageRef.id'); if (null !== $tag) { $this->tag = strtolower(preg_replace('/[^\\w\\.-]/', '-', $tag)) ?: null; } if ($this->curie->isMixin()) { throw new LogicException('Mixins cannot be used in a MessageRef.'); } }
/** * {@inheritdoc} */ public function guard($value, Field $field) { parent::guard($value, $field); if ($pattern = $field->getPattern()) { Assertion::regex($value, $pattern, null, $field->getName()); } switch ($field->getFormat()->getValue()) { case Format::UNKNOWN: break; case Format::DATE: Assertion::regex($value, '/^\\d{4}-\\d{2}-\\d{2}$/', null, $field->getName()); break; case Format::DATE_TIME: Assertion::true(DateUtils::isValidISO8601Date($value), sprintf('Field [%s] must be a valid ISO8601 date-time. Format must match one of [%s], [%s] or [%s].', $field->getName(), DateUtils::ISO8601_ZULU, DateUtils::ISO8601, \DateTime::ISO8601), $field->getName()); break; case Format::SLUG: Assertion::regex($value, '/^([\\w\\/-]|[\\w-][\\w\\/-]*[\\w-])$/', null, $field->getName()); break; case Format::EMAIL: Assertion::email($value, null, $field->getName()); break; case Format::HASHTAG: Assertion::true(HashtagUtils::isValid($value), sprintf('Field [%s] must be a valid hashtag. @see HashtagUtils::isValid', $field->getName()), $field->getName()); break; case Format::IPV4: case Format::IPV6: /* * todo: need separate assertion for ipv4 and ipv6 */ Assertion::url('http://' . $value, sprintf('Field [%s] must be a valid [%s].', $field->getName(), $field->getFormat()->getValue()), $field->getName()); break; case Format::HOSTNAME: case Format::URI: case Format::URL: /* * fixme: need better handling for HOSTNAME, URI and URL... assertion library just has one "url" handling * but we really need separate ones for each of these formats. right now we're just prefixing * the value with a http so it looks like a url. this won't work for thinks like mailto: * urn:, etc. */ if (false === strpos($value, 'http')) { $value = 'http://' . $value; } Assertion::url($value, sprintf('Field [%s] must be a valid [%s].', $field->getName(), $field->getFormat()->getValue()), $field->getName()); break; case Format::UUID: Assertion::uuid($value, null, $field->getName()); break; default: break; } }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var Identifier $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\Identifier', null, $field->getName()); Assertion::isInstanceOf($value, $field->getClassName(), null, $field->getName()); $v = $value->toString(); //Assertion::string($v, null, $field->getName()); // intentionally using strlen to get byte length, not mb_strlen $length = strlen($v); $maxBytes = $this->getMaxBytes(); $okay = $length > 0 && $length <= $maxBytes; Assertion::true($okay, sprintf('Field [%s] must be between [1] and [%d] bytes, [%d] bytes given.', $field->getName(), $maxBytes, $length), $field->getName()); }
/** * @param string $curie * @return SchemaCurie * @throws InvalidSchemaCurie */ public static function fromString($curie) { if (isset(self::$instances[$curie])) { return self::$instances[$curie]; } $okay = strlen($curie) < 146; Assertion::true($okay, 'SchemaCurie cannot be greater than 145 chars.', 'curie'); if (!preg_match(self::VALID_PATTERN, $curie, $matches)) { throw new InvalidSchemaCurie(sprintf('SchemaCurie [%s] is invalid. It must match the pattern [%s].', $curie, self::VALID_PATTERN)); } self::$instances[$curie] = new self($matches[1], $matches[2], $matches[3], $matches[4]); return self::$instances[$curie]; }
/** * @param SchemaId|string $id * @param string $className * @param Field[] $fields * @param Mixin[] $mixins */ public function __construct($id, $className, array $fields = [], array $mixins = []) { Assertion::classExists($className, null, 'className'); Assertion::allIsInstanceOf($fields, 'Gdbots\\Pbj\\Field', null, 'fields'); Assertion::allIsInstanceOf($mixins, 'Gdbots\\Pbj\\Mixin', null, 'mixins'); $this->id = $id instanceof SchemaId ? $id : SchemaId::fromString($id); $this->className = $className; $this->classShortName = ClassUtils::getShortName($this->className); $this->addField(FieldBuilder::create(self::PBJ_FIELD_NAME, Type\StringType::create())->required()->pattern(SchemaId::VALID_PATTERN)->withDefault($this->id->toString())->build()); foreach ($mixins as $mixin) { $this->addMixin($mixin); } foreach ($fields as $field) { $this->addField($field); } $this->mixinIds = array_keys($this->mixins); $this->mixinCuries = array_keys($this->mixinsByCurie); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var Message $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\Message', null, $field->getName()); Assertion::isInstanceOf($value, $field->getClassName(), null, $field->getName()); if (!$field->hasAnyOfClassNames()) { return; } $classNames = $field->getAnyOfClassNames(); if (empty($classNames)) { // means it can be "any message" return; } foreach ($classNames as $className) { if ($value instanceof $className) { return; } } Assertion::true(false, sprintf('Field [%s] must be an instance of at least one of: %s.', $field->getName(), implode(',', $classNames)), $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var Microtime $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\Microtime', null, $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var GeoPoint $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\WellKnown\\GeoPoint', null, $field->getName()); }
/** * @param string $schemaId * @return SchemaId * @throws InvalidSchemaId */ public static function fromString($schemaId) { if (isset(self::$instances[$schemaId])) { return self::$instances[$schemaId]; } $okay = strlen($schemaId) < 151; Assertion::true($okay, 'Schema id cannot be greater than 150 chars.', 'schemaId'); if (!preg_match(self::VALID_PATTERN, $schemaId, $matches)) { throw new InvalidSchemaId(sprintf('Schema id [%s] is invalid. It must match the pattern [%s].', $schemaId, self::VALID_PATTERN)); } self::$instances[$schemaId] = new self($matches[1], $matches[2], $matches[3], $matches[4], $matches[5]); return self::$instances[$schemaId]; }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var MessageRef $value */ Assertion::isInstanceOf($value, 'Gdbots\\Pbj\\MessageRef', null, $field->getName()); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::integer($value, null, $field->getName()); Assertion::true(DateUtils::isValidTimestamp($value), sprintf('Field [%s] value [%d] is not a valid unix timestamp.', $field->getName(), $value), $field->getName()); }
/** * @param mixed $value * @throws AssertionFailed * @throws \Exception */ public function guardValue($value) { if ($this->required) { Assertion::notNull($value, sprintf('Field [%s] is required and cannot be null.', $this->name)); } if (null !== $value) { $this->type->guard($value, $this); } if (null !== $this->assertion) { call_user_func($this->assertion, $value, $this); } }
/** * @param string $accountId * @throws \InvalidArgumentException */ protected function __construct($accountId) { Assertion::regex($accountId, '/^[A-Za-z0-9]+$/'); parent::__construct($accountId); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::boolean($value, null, $field->getName()); }
/** * {@inheritdoc} * @return static */ public final function removeFromMap($fieldName, $key) { $this->guardFrozenMessage(); $field = static::schema()->getField($fieldName); Assertion::true($field->isAMap(), sprintf('Field [%s] must be a map.', $fieldName), $fieldName); unset($this->data[$fieldName][$key]); if (empty($this->data[$fieldName])) { $this->clearedFields[$fieldName] = true; } return $this; }
/** * {@inheritdoc} */ public function guard($value, Field $field) { Assertion::choice($value, [0, 1, 2], null, $field->getName()); }
/** * @param array $data * @return Message * * @throws \Exception * @throws GdbotsPbjException */ private function doDeserialize(array $data) { $schemaId = SchemaId::fromString((string) $data[Schema::PBJ_FIELD_NAME]); $className = MessageResolver::resolveId($schemaId); /** @var Message $message */ $message = new $className(); Assertion::isInstanceOf($message, 'Gdbots\\Pbj\\Message'); if ($message::schema()->getCurieMajor() !== $schemaId->getCurieMajor()) { throw new InvalidResolvedSchema($message::schema(), $schemaId, $className); } $schema = $message::schema(); foreach ($data as $fieldName => $value) { if (!$schema->hasField($fieldName)) { continue; } if (null === $value) { $message->clear($fieldName); continue; } $field = $schema->getField($fieldName); $type = $field->getType(); switch ($field->getRule()->getValue()) { case FieldRule::A_SINGLE_VALUE: $message->set($fieldName, $type->decode($value, $field, $this)); break; case FieldRule::A_SET: case FieldRule::A_LIST: Assertion::isArray($value, sprintf('Field [%s] must be an array.', $fieldName), $fieldName); $values = []; foreach ($value as $v) { $values[] = $type->decode($v, $field, $this); } if ($field->isASet()) { $message->addToSet($fieldName, $values); } else { $message->addToList($fieldName, $values); } break; case FieldRule::A_MAP: Assertion::true(ArrayUtils::isAssoc($value), sprintf('Field [%s] must be an associative array.', $fieldName), $fieldName); foreach ($value as $k => $v) { $message->addToMap($fieldName, $k, $type->decode($v, $field, $this)); } break; default: break; } } return $message->set(Schema::PBJ_FIELD_NAME, $schema->getId()->toString())->populateDefaults(); }
/** * {@inheritdoc} */ public function guard($value, Field $field) { /** @var \DateTime $value */ Assertion::isInstanceOf($value, 'DateTime', null, $field->getName()); }
/** * @param array $data * @return Message * * @throws \Exception * @throws GdbotsPbjException */ private function doUnmarshal(array $data) { Assertion::keyIsset($data['M'], Schema::PBJ_FIELD_NAME, sprintf('[%s::%s] Array provided must contain the [%s] key.', get_called_class(), __FUNCTION__, Schema::PBJ_FIELD_NAME)); $schemaId = SchemaId::fromString((string) $data['M'][Schema::PBJ_FIELD_NAME]['S']); $className = MessageResolver::resolveId($schemaId); /** @var Message $message */ $message = new $className(); Assertion::isInstanceOf($message, 'Gdbots\\Pbj\\Message'); if ($message::schema()->getCurieMajor() !== $schemaId->getCurieMajor()) { throw new InvalidResolvedSchema($message::schema(), $schemaId, $className); } $schema = $message::schema(); foreach ($data['M'] as $fieldName => $dynamoValue) { if (!$schema->hasField($fieldName)) { continue; } $dynamoType = key($dynamoValue); $value = current($dynamoValue); if ('NULL' === $dynamoType) { $message->clear($fieldName); continue; } $field = $schema->getField($fieldName); $type = $field->getType(); switch ($field->getRule()->getValue()) { case FieldRule::A_SINGLE_VALUE: $message->set($fieldName, $type->decode($value, $field, $this)); break; case FieldRule::A_SET: case FieldRule::A_LIST: $values = []; if ('L' === $dynamoType) { foreach ($value as $v) { $values[] = $type->decode(isset($v['M']) ? $v['M'] : current($v), $field, $this); } } else { foreach ($value as $v) { $values[] = $type->decode($v, $field, $this); } } if ($field->isASet()) { $message->addToSet($fieldName, $values); } else { $message->addToList($fieldName, $values); } break; case FieldRule::A_MAP: foreach ($value as $k => $v) { $message->addToMap($fieldName, $k, $type->decode(current($v), $field, $this)); } break; default: break; } } return $message->set(Schema::PBJ_FIELD_NAME, $schema->getId()->toString())->populateDefaults(); }