Esempio n. 1
0
 /**
  * @param SchemaId|string $id
  * @param array           $parameters
  */
 public function __construct($id, array $parameters = [])
 {
     $this->id = $id instanceof SchemaId ? $id : SchemaId::fromString($id);
     foreach ($parameters as $key => $value) {
         $classProperty = lcfirst(StringUtils::toCamelFromSlug($key));
         // existing properties
         if (property_exists(get_called_class(), $classProperty)) {
             switch ($classProperty) {
                 case 'isMixin':
                 case 'isLatestVersion':
                 case 'deprecated':
                     $value = (bool) $value;
                     break;
                 case 'fields':
                     $fields = [];
                     /** @var FieldDescriptor $field */
                     foreach ($value as $field) {
                         $fields[$field->getName()] = $field;
                     }
                     $value = $fields;
                     break;
                 case 'mixins':
                     $mixins = [];
                     /** @var SchemaDescriptor $mixin */
                     foreach ($value as $mixin) {
                         $mixins[$mixin->getId()->getCurieWithMajorRev()] = $mixin;
                     }
                     $value = $mixins;
                     break;
             }
             $this->{$classProperty} = $value;
         }
     }
 }
Esempio n. 2
0
 /**
  * @param Schema $schema
  * @param \stdClass $rootObject
  * @param string $path
  * @return array
  */
 protected function mapSchema(Schema $schema, \stdClass $rootObject, $path = null)
 {
     $map = [];
     foreach ($schema->getFields() as $field) {
         $fieldName = $field->getName();
         $type = $field->getType();
         $fieldPath = empty($path) ? $fieldName : $path . '.' . $fieldName;
         if ($fieldName === Schema::PBJ_FIELD_NAME) {
             $map[$fieldName] = ['type' => 'string', 'index' => 'not_analyzed', 'include_in_all' => false];
             continue;
         }
         $method = 'map' . ucfirst(StringUtils::toCamelFromSlug($type->getTypeValue()));
         if ($field->isAMap()) {
             $templateName = str_replace('-', '_', SlugUtils::create($fieldPath . '-template'));
             if (is_callable([$this, $method])) {
                 $rootObject->dynamic_templates[] = [$templateName => ['path_match' => $fieldPath . '.*', 'mapping' => $this->{$method}($field, $rootObject, $fieldPath)]];
             } else {
                 $rootObject->dynamic_templates[] = [$templateName => ['path_match' => $fieldPath . '.*', 'mapping' => $this->applyAnalyzer($this->types[$type->getTypeValue()], $field, $rootObject, $path)]];
             }
         } else {
             if (is_callable([$this, $method])) {
                 $map[$fieldName] = $this->{$method}($field, $rootObject, $fieldPath);
             } else {
                 $map[$fieldName] = $this->applyAnalyzer($this->types[$type->getTypeValue()], $field, $rootObject, $path);
             }
         }
     }
     return $map;
 }
Esempio n. 3
0
 /**
  * {@inheritdoc}
  */
 public function validate(SchemaDescriptor $a, SchemaDescriptor $b)
 {
     $fa = array_merge($a->getInheritedFields(), $a->getFields());
     $fb = array_merge($b->getInheritedFields(), $b->getFields());
     /** @var \Gdbots\Pbjc\FieldDescriptor $field */
     /** @var \Gdbots\Pbjc\FieldDescriptor[] $fb */
     foreach ($fa as $name => $field) {
         if (!isset($fb[$name])) {
             continue;
         }
         $method = 'get' . StringUtils::toCamelFromSnake($this->attribute);
         if (!method_exists($field, $method)) {
             $method = 'is' . StringUtils::toCamelFromSnake($this->attribute);
             if (!method_exists($field, $method)) {
                 throw new \RuntimeException(sprintf('Invalid FieldDescriptor attribute "%s"', $this->attribute));
             }
         }
         if ($field->{$method}() != $fb[$name]->{$method}()) {
             $value = $field->{$method}();
             if ($value instanceof Enum) {
                 $value = $value->__toString();
             }
             if ($value instanceof Type) {
                 $value = $value->getTypeName()->__toString();
             }
             if ($value === true) {
                 $value = 'true';
             }
             if ($value === false) {
                 $value = 'false';
             }
             throw new ValidatorException(sprintf('The schema "%s" field "%s" should be of %s "%s".', $b, $name, $this->attribute, $value));
         }
     }
 }
Esempio n. 4
0
 /**
  * @param mixed $value
  * @param string Field $field
  * @param string $message
  */
 public function __construct($value, Field $field, $message = null)
 {
     $this->value = $value;
     $this->field = $field;
     $message = sprintf('Failed to encode [%s] for field [%s].  Detail: %s', is_scalar($this->value) ? $this->value : StringUtils::varToString($this->value), $this->field->getName(), $message);
     parent::__construct($message);
 }
Esempio n. 5
0
 /**
  * @param string $slug
  * @throws InvalidArgumentException
  */
 protected function __construct($slug)
 {
     if (!is_string($slug)) {
         throw new InvalidArgumentException(sprintf('String expected but got [%s].', StringUtils::varToString($slug)));
     }
     if (!SlugUtils::isValid($slug, true) || !SlugUtils::containsDate($slug)) {
         throw new InvalidArgumentException(sprintf('The value [%s] is not a valid dated slug.', $slug));
     }
     $this->slug = $slug;
 }
Esempio n. 6
0
 /**
  * @param string $string
  * @throws InvalidArgumentException
  */
 protected function __construct($string)
 {
     if (!is_string($string)) {
         throw new InvalidArgumentException(sprintf('String expected but got [%s].', StringUtils::varToString($string)));
     }
     $this->string = trim((string) $string);
     if (empty($this->string)) {
         throw new InvalidArgumentException('String cannot be empty.');
     }
 }
Esempio n. 7
0
 /**
  * @return static
  */
 public static final function create()
 {
     $type = get_called_class();
     if (!isset(self::$instances[$type])) {
         $a = explode('\\', $type);
         $typeName = StringUtils::toSlugFromCamel(str_replace('Type', '', end($a)));
         self::$instances[$type] = new static(TypeName::create($typeName));
     }
     return self::$instances[$type];
 }
Esempio n. 8
0
 /**
  * @param string $slug
  * @throws \InvalidArgumentException
  */
 protected function __construct($slug)
 {
     @trigger_error(sprintf('"%s" is deprecated.  Use "Gdbots\\Pbj\\WellKnown\\DatedSlugIdentifier" from "gdbots/pbj" 1.1.x or later instead.', __CLASS__), E_USER_DEPRECATED);
     if (!is_string($slug)) {
         throw new \InvalidArgumentException(sprintf('String expected but got [%s].', StringUtils::varToString($slug)));
     }
     if (!SlugUtils::isValid($slug, true) || !SlugUtils::containsDate($slug)) {
         throw new \InvalidArgumentException(sprintf('The value [%s] is not a valid dated slug.', $slug));
     }
     $this->slug = $slug;
 }
Esempio n. 9
0
 /**
  * @param SchemaDescriptor $schema
  * @param string           $filename
  * @param string           $directory
  * @param bool             $isLatest
  *
  * @return string
  */
 protected function getSchemaTarget(SchemaDescriptor $schema, $filename, $directory = null, $isLatest = false)
 {
     $filename = str_replace(['{vendor}', '{package}', '{category}', '{version}', '{major}'], [$schema->getId()->getVendor(), $schema->getId()->getPackage(), $schema->getId()->getCategory(), $schema->getId()->getVersion()->toString(), $schema->getId()->getVersion()->getMajor()], $filename);
     if ($directory === null) {
         $directory = sprintf('%s/%s/%s', StringUtils::toCamelFromSlug($schema->getId()->getVendor()), StringUtils::toCamelFromSlug($schema->getId()->getPackage()), StringUtils::toCamelFromSlug($schema->getId()->getCategory()));
     }
     if ($directory) {
         $directory .= '/';
     }
     return sprintf('%s/%s%s%s', $this->compileOptions->getOutput(), $directory, $filename, $this->extension);
 }
Esempio n. 10
0
 /**
  * @param string $string
  * @throws \InvalidArgumentException
  */
 protected function __construct($string)
 {
     @trigger_error(sprintf('"%s" is deprecated.  Use "Gdbots\\Pbj\\WellKnown\\StringIdentifier" from "gdbots/pbj" 1.1.x or later instead.', __CLASS__), E_USER_DEPRECATED);
     if (!is_string($string)) {
         throw new \InvalidArgumentException(sprintf('String expected but got [%s].', StringUtils::varToString($string)));
     }
     $this->string = trim((string) $string);
     if (empty($this->string)) {
         throw new \InvalidArgumentException('String cannot be empty.');
     }
 }
Esempio n. 11
0
 /**
  * @param SchemaDescriptor $schema
  * @param bool             $majorRev
  * @param string           $baseClassName
  * @param bool             $withAs
  *
  * @return string
  */
 public function getClassName(SchemaDescriptor $schema, $majorRev = false, $baseClassName = null, $withAs = false)
 {
     $className = StringUtils::toCamelFromSlug($schema->getId()->getMessage());
     if ($majorRev) {
         $className = sprintf('%sV%d', StringUtils::toCamelFromSlug($schema->getId()->getMessage()), $schema->getId()->getVersion()->getMajor());
     }
     if ($baseClassName == $className) {
         $classNameBase = sprintf('%s%s%s', StringUtils::toCamelFromSlug($schema->getId()->getVendor()), StringUtils::toCamelFromSlug($schema->getId()->getPackage()), $className);
         if ($withAs) {
             $className = sprintf('%s as %s', $className, $classNameBase);
         } else {
             $className = $classNameBase;
         }
     }
     return $className;
 }
Esempio n. 12
0
 /**
  * @param string $name
  * @param array  $parameters
  *
  * @throws \InvalidArgumentException
  */
 public function __construct($name, array $parameters)
 {
     if (!$name || strlen($name) > 127 || preg_match(self::VALID_NAME_PATTERN, $name) === false) {
         throw new \InvalidArgumentException(sprintf('Field [%s] must match pattern [%s] with less than 127 characters.', $name, self::VALID_NAME_PATTERN));
     }
     foreach ($parameters as $key => $value) {
         $classProperty = lcfirst(StringUtils::toCamelFromSlug($key));
         // existing properties
         if (property_exists(get_called_class(), $classProperty)) {
             switch ($classProperty) {
                 case 'name':
                 case 'languages':
                     continue 2;
                 case 'type':
                     /** @var \Gdbots\Pbjc\Type\Type $class */
                     $class = sprintf('\\Gdbots\\Pbjc\\Type\\%sType', StringUtils::toCamelFromSlug($parameters['type']));
                     $value = $class::create();
                     break;
                 case 'rule':
                     if (null !== $value && in_array($value, FieldRule::values())) {
                         $value = FieldRule::create($value);
                     }
                     break;
                 case 'format':
                     if (null !== $value && in_array($value, Format::values())) {
                         $value = Format::create($value);
                     }
                     break;
                 case 'required':
                 case 'useTypeDefault':
                 case 'overridable':
                 case 'deprecated':
                     $value = (bool) $value;
                     break;
                 case 'min':
                 case 'max':
                 case 'minLength':
                 case 'maxLength':
                 case 'precision':
                 case 'scale':
                     $value = (int) $value;
                     break;
             }
             $this->{$classProperty} = $value;
         } elseif (substr($key, -8) == '-options') {
             $language = substr($key, 0, -8);
             // remove "-options"
             if (is_array($value)) {
                 $value = new LanguageBag($value);
             }
             $this->getLanguages()->set($language, $value);
         }
     }
     $this->name = $name;
     $this->applyDefaults();
     $this->applyFieldRule();
     $this->applyStringOptions();
     $this->applyNumericOptions();
 }
Esempio n. 13
0
 /**
  * @param string $slug
  *
  * @return string
  */
 public function toCamelFromSlug($slug)
 {
     return StringUtils::toCamelFromSlug($slug);
 }
Esempio n. 14
0
 /**
  * {@inheritdoc}
  */
 public function generateManifest(array $schemas)
 {
     $messages = [];
     if (!($filename = $this->compileOptions->getManifest())) {
         return;
     }
     // extract previous schemas
     if (file_exists($filename)) {
         $content = file_get_contents($filename);
         if (preg_match_all('/\'([a-z0-9-]+:[a-z0-9\\.-]+:[a-z0-9-]+?:[a-z0-9-]+(:v[0-9]+)?)\' => \'(.*)\'/', $content, $matches) !== false) {
             foreach ($matches[1] as $key => $value) {
                 $messages[$value] = $matches[3][$key];
             }
         }
     }
     // merge with selected schemas (only non-mixin schema's)
     /** @var SchemaDescriptor $schema */
     foreach ($schemas as $schema) {
         if ($schema->isMixinSchema()) {
             continue;
         }
         if (!array_key_exists($schema->getId()->getCurie(), $messages)) {
             $messages[$schema->getId()->getCurie()] = sprintf('%s\\%sV%d', $schema->getLanguage('php')->get('namespace'), StringUtils::toCamelFromSlug($schema->getId()->getMessage()), $schema->getId()->getVersion()->getMajor());
         }
         if (SchemaStore::hasOtherSchemaMajorRev($schema->getId())) {
             /** @var SchemaDescriptor $s */
             foreach (SchemaStore::getOtherSchemaMajorRev($schema->getId()) as $s) {
                 if (!array_key_exists($s->getId()->getCurieWithMajorRev(), $messages)) {
                     $messages[$s->getId()->getCurieWithMajorRev()] = sprintf('%s\\%sV%d', $s->getLanguage('php')->get('namespace'), StringUtils::toCamelFromSlug($s->getId()->getMessage()), $s->getId()->getVersion()->getMajor());
                 }
             }
         }
     }
     // delete invalid schemas
     foreach ($messages as $key => $value) {
         if (!SchemaStore::getSchemaById($key, true)) {
             unset($messages[$key]);
         }
     }
     $response = new GeneratorResponse();
     $response->addFile($this->renderFile('manifest.twig', $filename, ['messages' => $messages]));
     return $response;
 }
Esempio n. 15
0
 /**
  * Generates and writes files for each schema.
  *
  * @param string         $language
  * @param CompileOptions $options
  *
  * @throws \InvalidArgumentException
  */
 public function run($language, CompileOptions $options)
 {
     $namespaces = $options->getNamespaces();
     if (!$namespaces || count($namespaces) === 0) {
         throw new \InvalidArgumentException('Missing "namespaces" options.');
     }
     if (!is_array($namespaces)) {
         $namespaces = [$namespaces];
     }
     foreach ($namespaces as $namespace) {
         if (!preg_match('/^([a-z0-9-]+):([a-z0-9\\.-]+)$/', $namespace)) {
             throw new \InvalidArgumentException(sprintf('The namespace "%s" must follow "vendor:package" format.', $namespace));
         }
     }
     if (!$options->getOutput()) {
         throw new \InvalidArgumentException('Missing "output" directory options.');
     }
     $class = sprintf('\\Gdbots\\Pbjc\\Generator\\%sGenerator', StringUtils::toCamelFromSlug($language));
     /** @var \Gdbots\Pbjc\Generator\Generator $generator */
     $generator = new $class($options);
     $outputFiles = [];
     /** @var EnumDescriptor $enum */
     foreach (SchemaStore::getEnums() as $enum) {
         if (!$options->getIncludeAll() && !in_array($enum->getId()->getNamespace(), $namespaces)) {
             continue;
         }
         /** @var $response \Gdbots\Pbjc\Generator\GeneratorResponse */
         if ($response = $generator->generateEnum($enum)) {
             $outputFiles = array_merge($outputFiles, $response->getFiles());
         }
     }
     /** @var SchemaDescriptor $schema */
     foreach (SchemaStore::getSchemas() as $schema) {
         if (!$options->getIncludeAll() && !in_array($schema->getId()->getNamespace(), $namespaces)) {
             continue;
         }
         /** @var $response \Gdbots\Pbjc\Generator\GeneratorResponse */
         if ($response = $generator->generateSchema($schema)) {
             $outputFiles = array_merge($outputFiles, $response->getFiles());
         }
     }
     if ($options->getManifest()) {
         /** @var $response \Gdbots\Pbjc\Generator\GeneratorResponse */
         if ($response = $generator->generateManifest(SchemaStore::getSchemas())) {
             $outputFiles = array_merge($outputFiles, $response->getFiles());
         }
     }
     if ($callback = $options->getCallback()) {
         foreach ($outputFiles as $outputFile) {
             call_user_func($callback, $outputFile);
         }
     }
 }
Esempio n. 16
0
 public function testAddInvalidTypeToMap()
 {
     // todo: refactor, this test is weird and confusing
     $shouldWork = MapsMessage::create();
     $shouldFail = clone $shouldWork;
     /*
      * some int types won't fail because they're all ints of course, just different ranges.
      * e.g. an Int is also all other unsigned ints (except BigInt but that's a class so we're fine)
      */
     $allInts = ['TinyInt', 'SmallInt', 'MediumInt', 'Int', 'SignedTinyInt', 'SignedSmallInt', 'SignedMediumInt', 'SignedInt', 'Timestamp'];
     $allStrings = ['Binary', 'Blob', 'MediumBlob', 'MediumText', 'String', 'Text'];
     foreach ($shouldWork::getAllTypes() as $type => $class) {
         foreach ($this->getTypeValues() as $k => $v) {
             $thrown = false;
             if ($type == $k) {
                 if (is_array($v)) {
                     $shouldWork->addToMap($type, 'test1', $v[0]);
                     $shouldWork->addToMap($type, 'test2', $v[1]);
                 } else {
                     $shouldWork->addToMap($type, 'test1', $v);
                 }
                 continue;
             }
             try {
                 if (is_array($v)) {
                     $shouldFail->addToMap($type, 'test1', $v[0]);
                     $shouldFail->addToMap($type, 'test2', $v[1]);
                 } else {
                     $shouldFail->addToMap($type, 'test1', $v);
                 }
                 switch ($type) {
                     case 'Binary':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'Blob':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'Decimal':
                         if (in_array($k, ['Float'])) {
                             continue 2;
                         }
                         break;
                     case 'Date':
                         if (in_array($k, ['DateTime'])) {
                             continue 2;
                         }
                         break;
                     case 'DateTime':
                         if (in_array($k, ['Date'])) {
                             continue 2;
                         }
                         break;
                     case 'Float':
                         if (in_array($k, ['Decimal'])) {
                             continue 2;
                         }
                         break;
                     case 'Identifier':
                         if (in_array($k, ['TimeUuid', 'Uuid'])) {
                             continue 2;
                         }
                         break;
                     case 'MediumBlob':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'MediumText':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'String':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'Text':
                         if (in_array($k, $allStrings)) {
                             continue 2;
                         }
                         break;
                     case 'Timestamp':
                         if (in_array($k, $allInts)) {
                             continue 2;
                         }
                         break;
                     case 'Uuid':
                         if (in_array($k, ['Identifier', 'TimeUuid'])) {
                             continue 2;
                         }
                         break;
                     default:
                 }
                 if (false !== strpos($type, 'Int') && in_array($k, $allInts)) {
                     continue;
                 }
             } catch (\Exception $e) {
                 $thrown = true;
             }
             if (!$thrown) {
                 if (is_array($v)) {
                     $this->fail(sprintf('[%s] accepted an invalid/mismatched [%s] value', $type, StringUtils::varToString($v[0])));
                     $this->fail(sprintf('[%s] accepted an invalid/mismatched [%s] value', $type, StringUtils::varToString($v[1])));
                 } else {
                     $this->fail(sprintf('[%s] accepted an invalid/mismatched [%s] value', $type, StringUtils::varToString($v)));
                 }
             }
         }
     }
     //echo json_encode($shouldWork, JSON_PRETTY_PRINT);
 }