Skip to content
This repository has been archived by the owner on Jan 20, 2024. It is now read-only.

V3.0 #113

Closed
wants to merge 26 commits into from
Closed

V3.0 #113

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4dc7787
DataTypes added from RAML1.0
Feb 3, 2017
ec7c517
Possible to include named traits; Check if protocol is not empty it A…
Feb 4, 2017
90c28b6
Finished implementation of RAML 1.0 processing functions
InfopactMLoos Feb 14, 2017
c5293f4
Added explicit parameter check
InfopactMLoos Feb 14, 2017
025dbc1
Enabled error & warning to exception conversion in phpunit
InfopactMLoos Feb 16, 2017
60e4ab5
Added raml 1.0 datatypes and implemented parsing
InfopactMLoos Feb 28, 2017
c44f2ac
Added JSON & XML types
InfopactMLoos Mar 1, 2017
b0dbb6e
Added validation of types
InfopactMLoos Mar 1, 2017
91e62ea
Added notice and todo for 1.0 spec to README
InfopactMLoos Mar 2, 2017
f7fce9a
Added extra checks and more fine-tuning to spec
InfopactMLoos Mar 2, 2017
093d4ba
Added method for retrieving parsed RAML in array form
InfopactMLoos Mar 13, 2017
3f682ec
Added traits & resourcetype parsing to array method
InfopactMLoos Mar 27, 2017
5b0e014
Refactored namespace Types to Type
InfopactMLoos Apr 6, 2017
bbac707
Implemented type validator class based on schema validator
InfopactMLoos Apr 6, 2017
b2ad193
Updated/fixed tests
InfopactMLoos Apr 6, 2017
c0e10f7
Fixed and optimized type validations
InfopactMLoos Apr 12, 2017
122516e
Fix: missing adding of previous validation errors
InfopactMLoos Apr 12, 2017
2a9aa0e
Fix: null type should be nil type
InfopactMLoos Apr 12, 2017
135b521
Improved validation error message
InfopactMLoos Apr 12, 2017
0133c21
Moved raml type name to class name mapping to corresponding classes
InfopactMLoos Apr 13, 2017
c60161f
Fixed datetime constants
InfopactMLoos Apr 13, 2017
b4fd5d2
Set todo
InfopactMLoos Apr 13, 2017
67c765c
Fix: forgot variable after refactoring
InfopactMLoos Apr 13, 2017
96d4916
Added deprecation comments to old schema validators
InfopactMLoos Apr 13, 2017
d7cdcd0
Fixed incomplete optional shorthand parsing
InfopactMLoos Apr 13, 2017
3e74f20
Fixed unit tests
InfopactMLoos Apr 13, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# PHP RAML Parser

## **!!Attention!!** this is a work-in-progress of the RAML 1.0 specification, for RAML 0.8 see the [master branch](https://github.com/alecsammon/php-raml-parser/tree/master)

### Still TODO:
- [User defined facets](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#user-defined-facets)
- Full implementation of [type expressions](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#type-expressions)
- The shorthand array and the union type have been implemented
- Bi-dimensional array and the array-union combination have **NOT** been implemented yet.
- [Multiple inheritance](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#multiple-inheritance)
- [Annotations](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#annotations)
- [Libraries](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#libraries)
- [Overlays and Extensions](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#overlays-and-extensions)
- [Improved Security Schemes](https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#security-schemes)

## Original documentation

Parses a RAML file into a PHP object.

[![Build Status](https://travis-ci.org/alecsammon/php-raml-parser.svg?branch=master)](https://travis-ci.org/alecsammon/php-raml-parser)
Expand Down
4 changes: 2 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
colors="true"
convertErrorsToExceptions="false"
convertNoticesToExceptions="false"
convertWarningsToExceptions="false"
convertWarningsToExceptions="true"
convertErrorsToExceptions="true"
stopOnFailure="false"
bootstrap="vendor/autoload.php"
verbose="true"
Expand Down
169 changes: 159 additions & 10 deletions src/ApiDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
use Raml\Exception\BadParameter\ResourceNotFoundException;
use Raml\Exception\BadParameter\InvalidSchemaDefinitionException;
use Raml\Exception\BadParameter\InvalidProtocolException;
use Raml\Exception\MutuallyExclusiveElementsException;

use Raml\Utility\StringTransformer;

use Raml\Type\UnionType;
use Raml\Type\ArrayType;
use Raml\Type\ObjectType;
use Raml\Type\JsonType;
use Raml\Type\XmlType;
use Raml\Type\LazyProxyType;

/**
* The API Definition
Expand All @@ -21,6 +31,7 @@ class ApiDefinition implements ArrayInstantiationInterface
{
const PROTOCOL_HTTP = 'HTTP';
const PROTOCOL_HTTPS = 'HTTPS';
const ROOT_ELEMENT_NAME = '__ROOT_ELEMENT__';

// ---

Expand All @@ -42,6 +53,13 @@ class ApiDefinition implements ArrayInstantiationInterface
*/
private $version;

/**
* Raml version
*
* @var string
*/
private $ramlVersion;

/**
* The Base URL (optional for development, required in production)
*
Expand Down Expand Up @@ -90,6 +108,7 @@ class ApiDefinition implements ArrayInstantiationInterface
/**
* The schemas the API supplies defined in the root (optional)
*
* @deprecated Replaced by types element.
* @see http://raml.org/spec.html#schemas
*
* @var array[]
Expand Down Expand Up @@ -133,6 +152,15 @@ class ApiDefinition implements ArrayInstantiationInterface
*/
private $securedBy = [];

/**
* A list of data types
*
* @link https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md/#raml-data-types
*
* @var \Raml\TypeCollection
*/
private $types = [];

// ---

/**
Expand All @@ -143,6 +171,9 @@ class ApiDefinition implements ArrayInstantiationInterface
public function __construct($title)
{
$this->title = $title;
$this->types = TypeCollection::getInstance();
// since the TypeCollection is a singleton, we need to clear it for every parse
$this->types->clear();
}

/**
Expand All @@ -158,6 +189,7 @@ public function __construct($title)
* protocols: ?array
* defaultMediaType: ?string
* schemas: ?array
* types: ?array
* securitySchemes: ?array
* documentation: ?array
* /*
Expand All @@ -171,7 +203,6 @@ public static function createFromArray($title, array $data = [])

// --


if (isset($data['version'])) {
$apiDefinition->setVersion($data['version']);
}
Expand Down Expand Up @@ -207,12 +238,6 @@ public static function createFromArray($title, array $data = [])
$apiDefinition->setDefaultMediaType($data['defaultMediaType']);
}

if (isset($data['schemas'])) {
foreach ($data['schemas'] as $name => $schema) {
$apiDefinition->addSchemaCollection($name, $schema);
}
}

if (isset($data['securitySchemes'])) {
foreach ($data['securitySchemes'] as $name => $securityScheme) {
$apiDefinition->addSecurityScheme(SecurityScheme::createFromArray($name, $securityScheme));
Expand All @@ -235,6 +260,20 @@ public static function createFromArray($title, array $data = [])
}
}

if (isset($data['schemas']) && isset($data['types'])) {
throw new MutuallyExclusiveElementsException();
}

if (isset($data['schemas']) || isset($data['types'])) {
$types = isset($data['schemas']) ? $data['schemas'] : $data['types'];
foreach ($types as $name => $definition) {
$apiDefinition->addType(ApiDefinition::determineType($name, $definition));
}
}

// resolve type inheritance
$apiDefinition->getTypes()->applyInheritance();

// ---

foreach ($data as $resourceName => $resource) {
Expand Down Expand Up @@ -401,7 +440,10 @@ public function setBaseUrl($baseUrl)
$this->baseUrl = $baseUrl;

if (!$this->protocols) {
$this->protocols = [strtoupper(parse_url($this->baseUrl, PHP_URL_SCHEME))];
$protocol = strtoupper(parse_url($this->baseUrl, PHP_URL_SCHEME));
if (!empty($protocol)) {
$this->protocols = [$protocol];
}
}
}

Expand Down Expand Up @@ -503,16 +545,18 @@ public function setDefaultMediaType($defaultMediaType)
// --

/**
* @deprecated Use types instead!
* Get the schemas defined in the root of the API
*
* @return array[]
*/
public function getSchemaCollections()
{
return $this->schemaCollections;
return $this->types;
}

/**
* @deprecated Use types instead!
* Add an schema
*
* @param string $collectionName
Expand All @@ -528,6 +572,7 @@ public function addSchemaCollection($collectionName, $schemas)
}

/**
* @deprecated Use types instead!
* Add a new schema to a collection
*
* @param string $collectionName
Expand Down Expand Up @@ -568,6 +613,110 @@ public function addDocumentation($title, $documentation)
$this->documentationList[$title] = $documentation;
}

/**
* Determines the right Type and returns a type instance
*
* @param string $name Name of type.
* @param array $definition Definition of type.
* @param \Raml\TypeCollection|null $typeCollection Type collection object.
*
* @return Raml\TypeInterface Returns a (best) matched type object.
* @throws \Exception Thrown when no type is defined.
**/
public static function determineType($name, $definition)
{
if (is_string($definition)) {
$definition = ['type' => $definition];
} elseif (is_array($definition)) {
if (!isset($definition['type'])) {
$definition['type'] = isset($definition['properties']) ? 'object' : 'string';
}
} elseif ($definition instanceof \stdClass) {
return JsonType::createFromArray('schema', $definition);
} else {
throw new \Exception('Invalid datatype for $definition parameter.');
}
if (is_object($name)) {
throw new \Exception(var_export($name, true));
}


if (strpos($definition['type'], '?') !== false ||
$pos = strpos($name, '?') !== false) {
// shorthand for required = false
$definition['required'] = isset($definition['required']) ? $definition['required'] : false;
}

// check if we can find a more appropriate Type subclass
$straightForwardTypes = [
\Raml\Type\TimeOnlyType::TYPE_NAME => 'Raml\Type\TimeOnlyType',
\Raml\Type\DateTimeType::TYPE_NAME => 'Raml\Type\DateTimeType',
\Raml\Type\DateTimeOnlyType::TYPE_NAME => 'Raml\Type\DateTimeOnlyType',
\Raml\Type\DateOnlyType::TYPE_NAME => 'Raml\Type\DateOnlyType',
\Raml\Type\NumberType::TYPE_NAME => 'Raml\Type\NumberType',
\Raml\Type\IntegerType::TYPE_NAME => 'Raml\Type\IntegerType',
\Raml\Type\BooleanType::TYPE_NAME => 'Raml\Type\BooleanType',
\Raml\Type\StringType::TYPE_NAME => 'Raml\Type\StringType',
\Raml\Type\NilType::TYPE_NAME => 'Raml\Type\NilType',
\Raml\Type\FileType::TYPE_NAME => 'Raml\Type\FileType',
\Raml\Type\ArrayType::TYPE_NAME => 'Raml\Type\ArrayType',
\Raml\Type\ObjectType::TYPE_NAME => 'Raml\Type\ObjectType',
];

$type = $definition['type'];

if (in_array($type, array_keys($straightForwardTypes))) {
return forward_static_call_array([$straightForwardTypes[$type],'createFromArray'], [$name, $definition]);
}

if (!in_array($type, ['','any'])) {
// if $type contains a '|' we can savely assume it's a combination of types (union)
if (strpos($type, '|') !== false) {
return UnionType::createFromArray($name, $definition);
}
// if $type contains a '[]' it means we have an array with a item restriction
if (strpos($type, '[]') !== false) {
return ArrayType::createFromArray($name, $definition);
}
// is it a XML schema?
if (substr(ltrim($type), 0, 1) === '<') {
return XmlType::createFromArray(self::ROOT_ELEMENT_NAME, $definition);
}
// is it a JSON schema?
if (substr(ltrim($type), 0, 1) === '{') {
return JsonType::createFromArray(self::ROOT_ELEMENT_NAME, $definition);
}

// no? then no standard type found so this must be a reference to a custom defined type.
// since the actual definition can be defined later then when it is referenced,
// we create a proxy object for lazy loading when it is needed
return LazyProxyType::createFromArray($name, $definition);
}

// No subclass found, let's use base class
return Type::createFromArray($name, $definition);
}

/**
* Add data type
*
* @param \Raml\TypeInterface $type
*/
public function addType(TypeInterface $type)
{
$this->types->add($type);
}

/**
* Get all data types defined in the root of the API
*
* @return \Raml\TypeCollection
*/
public function getTypes()
{
return $this->types;
}

// --

/**
Expand Down Expand Up @@ -595,7 +744,7 @@ public function addResource(Resource $resource)
/**
* Get a security scheme by it's name
*
* @param $schemeName
* @param string $schemeName
*
* @return SecurityScheme
*/
Expand Down
Loading