diff --git a/src/AttributeGenerator/ConfigurationAttributeGenerator.php b/src/AttributeGenerator/ConfigurationAttributeGenerator.php index e06c2dfb..64f73851 100644 --- a/src/AttributeGenerator/ConfigurationAttributeGenerator.php +++ b/src/AttributeGenerator/ConfigurationAttributeGenerator.php @@ -25,8 +25,10 @@ public function generateClassAttributes(Class_ $class): array { $typeAttributes = $this->config['types'][$class->name()]['attributes'] ?? [[]]; $vocabAttributes = [[]]; + if ($class instanceof SchemaClass) { - $vocabAttributes = $this->config['vocabularies'][$class->resource()->getGraph()->getUri()]['attributes'] ?? [[]]; + $graphUri = (null !== $class->resource()->getGraph()) ? $class->resource()->getGraph()->getUri() : null; + $vocabAttributes = $this->config['vocabularies'][$graphUri]['attributes'] ?? [[]]; } $getAttributesNames = static fn (array $config) => $config === [[]] diff --git a/src/CardinalitiesExtractor.php b/src/CardinalitiesExtractor.php index 343b0ee4..799362f7 100644 --- a/src/CardinalitiesExtractor.php +++ b/src/CardinalitiesExtractor.php @@ -13,8 +13,8 @@ namespace ApiPlatform\SchemaGenerator; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; /** * Extracts cardinalities from the OWL definition, from GoodRelations or from Schema.org's comments. @@ -104,7 +104,7 @@ private function extractForProperty(RdfResource $property): string return self::CARDINALITY_UNKNOWN; } - $fromGoodRelations = $this->goodRelationsBridge->extractCardinality($localName); + $fromGoodRelations = $this->goodRelationsBridge->extractCardinality($property->localId()); if (false !== $fromGoodRelations) { return $fromGoodRelations; } diff --git a/src/ClassMutator/AnnotationsAppender.php b/src/ClassMutator/AnnotationsAppender.php index fc074e65..22753f3e 100644 --- a/src/ClassMutator/AnnotationsAppender.php +++ b/src/ClassMutator/AnnotationsAppender.php @@ -16,7 +16,7 @@ use ApiPlatform\SchemaGenerator\AnnotationGenerator\AnnotationGeneratorInterface; use ApiPlatform\SchemaGenerator\Model\Class_; use ApiPlatform\SchemaGenerator\Model\Use_; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class AnnotationsAppender implements ClassMutatorInterface { diff --git a/src/ClassMutator/ClassPropertiesAppender.php b/src/ClassMutator/ClassPropertiesAppender.php index 988d135c..b34fcd76 100644 --- a/src/ClassMutator/ClassPropertiesAppender.php +++ b/src/ClassMutator/ClassPropertiesAppender.php @@ -16,8 +16,8 @@ use ApiPlatform\SchemaGenerator\Model\Class_; use ApiPlatform\SchemaGenerator\PropertyGenerator\PropertyGeneratorInterface; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use Psr\Log\LoggerAwareTrait; final class ClassPropertiesAppender implements ClassMutatorInterface diff --git a/src/Command/ExtractCardinalitiesCommand.php b/src/Command/ExtractCardinalitiesCommand.php index 7701f729..fbb6c971 100644 --- a/src/Command/ExtractCardinalitiesCommand.php +++ b/src/Command/ExtractCardinalitiesCommand.php @@ -15,8 +15,8 @@ use ApiPlatform\SchemaGenerator\CardinalitiesExtractor; use ApiPlatform\SchemaGenerator\GoodRelationsBridge; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/src/Schema/ClassMutator/EnumClassMutator.php b/src/Schema/ClassMutator/EnumClassMutator.php index eb0ef2df..a37e447b 100644 --- a/src/Schema/ClassMutator/EnumClassMutator.php +++ b/src/Schema/ClassMutator/EnumClassMutator.php @@ -17,7 +17,7 @@ use ApiPlatform\SchemaGenerator\Model\Class_; use ApiPlatform\SchemaGenerator\PhpTypeConverterInterface; use ApiPlatform\SchemaGenerator\Schema\Model\Constant as SchemaConstant; -use EasyRdf\Graph as RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; final class EnumClassMutator extends BaseEnumClassMutator { diff --git a/src/Schema/Generator.php b/src/Schema/Generator.php index 81b84a0e..93fbbc1d 100644 --- a/src/Schema/Generator.php +++ b/src/Schema/Generator.php @@ -18,9 +18,9 @@ use ApiPlatform\SchemaGenerator\GoodRelationsBridge; use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Printer; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; use ApiPlatform\SchemaGenerator\TwigBuilder; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; use Symfony\Component\Console\Logger\ConsoleLogger; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; diff --git a/src/Schema/Model/Class_.php b/src/Schema/Model/Class_.php index 6d6a49b7..6921e928 100644 --- a/src/Schema/Model/Class_.php +++ b/src/Schema/Model/Class_.php @@ -14,7 +14,7 @@ namespace ApiPlatform\SchemaGenerator\Schema\Model; use ApiPlatform\SchemaGenerator\Model\Class_ as BaseClass_; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class Class_ extends BaseClass_ { diff --git a/src/Schema/Model/Constant.php b/src/Schema/Model/Constant.php index f173157b..584cf870 100644 --- a/src/Schema/Model/Constant.php +++ b/src/Schema/Model/Constant.php @@ -14,7 +14,7 @@ namespace ApiPlatform\SchemaGenerator\Schema\Model; use ApiPlatform\SchemaGenerator\Model\Constant as BaseConstant; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class Constant extends BaseConstant { diff --git a/src/Schema/Model/Property.php b/src/Schema/Model/Property.php index 4c9a49f4..dc374f35 100644 --- a/src/Schema/Model/Property.php +++ b/src/Schema/Model/Property.php @@ -14,7 +14,7 @@ namespace ApiPlatform\SchemaGenerator\Schema\Model; use ApiPlatform\SchemaGenerator\Model\Property as BaseProperty; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class Property extends BaseProperty { diff --git a/src/Schema/PropertyGenerator/IdPropertyGenerator.php b/src/Schema/PropertyGenerator/IdPropertyGenerator.php index 00413794..aff2de20 100644 --- a/src/Schema/PropertyGenerator/IdPropertyGenerator.php +++ b/src/Schema/PropertyGenerator/IdPropertyGenerator.php @@ -19,7 +19,7 @@ use ApiPlatform\SchemaGenerator\PropertyGenerator\IdPropertyGeneratorInterface; use ApiPlatform\SchemaGenerator\Schema\Model\Property as SchemaProperty; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class IdPropertyGenerator implements IdPropertyGeneratorInterface { diff --git a/src/Schema/PropertyGenerator/PropertyGenerator.php b/src/Schema/PropertyGenerator/PropertyGenerator.php index 47e2634b..e22f47db 100644 --- a/src/Schema/PropertyGenerator/PropertyGenerator.php +++ b/src/Schema/PropertyGenerator/PropertyGenerator.php @@ -23,8 +23,8 @@ use ApiPlatform\SchemaGenerator\PropertyGenerator\PropertyGeneratorInterface; use ApiPlatform\SchemaGenerator\Schema\Model\Property as SchemaProperty; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\Schema\TypeConverter; -use EasyRdf\Resource as RdfResource; use Psr\Log\LoggerAwareTrait; final class PropertyGenerator implements PropertyGeneratorInterface diff --git a/src/Schema/Rdf/RdfGraph.php b/src/Schema/Rdf/RdfGraph.php new file mode 100644 index 00000000..0fd3eef2 --- /dev/null +++ b/src/Schema/Rdf/RdfGraph.php @@ -0,0 +1,251 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\SchemaGenerator\Schema\Rdf; + +use EasyRdf\Graph as EasyRdfGraph; + +/** + * This class is a wrapper around the EasyRdf\Graph class. It allows the Schema + * Generator to get RdfResource objects instead of EasyRdf\Resource ones when required. + * + * @author d3fk::Angatar + */ +class RdfGraph +{ + private EasyRdfGraph $graph; + + /** + * Constructor, creates the RdfGraph decorating a freshly created or given + * EasyRdf\Graph with the capability to return/use RdfResource instead of EasyRdf\Resource. + */ + final public function __construct(string $uri = null, string $data = null, string $format = null, EasyRdfGraph $graph = null) + { + $this->graph = $graph ?? new EasyRdfGraph($uri, $data, $format); + } + + /** + * Returns the corresponding EasyRdf\Graph. + */ + public function getEasyGraph(): EasyRdfGraph + { + return $this->graph; + } + + /** + * Passes any call for an absent method to the contained EasyRdf\Graph, ensuring + * that it returns a Schema Generator's RdfResource in place of any EasyRdf\Resource. + * + * @param array $arguments + * + * @return mixed depending on the method called + */ + #[\ReturnTypeWillChange] + public function __call(string $methodName, array $arguments) + { + $arguments = RdfResource::fromRdftoEasyRdfResources($arguments); + $callback = [$this->graph, $methodName]; + if (\is_callable($callback)) { + return RdfResource::wrapEasyRdfResource(\call_user_func_array($callback, $arguments)); + } + throw new \Exception('Method not found'); + } + + /** + * Gets all the resources for a property of a resource and ensures that each + * EasyRdf\Resource matched is returned as wrapped in an RdfResource. + * + * @return array + */ + public function allResources(string $resource, string $property): array + { + $resource = RdfResource::fromRdftoEasyRdfResource($resource); + + return RdfResource::wrapEasyRdfResources($this->graph->allResources($resource, $property)); + } + + /** + * Gets all values for a property path and ensures that each EasyRdf\Resource + * matched is returned as wrapped in an RdfResource. + * + * @return array + */ + public function all(string $resource, string $propertyPath, string $type = null, string $lang = null): array + { + $resource = RdfResource::fromRdftoEasyRdfResource($resource); + + return RdfResource::wrapEasyRdfResources($this->graph->all($resource, $propertyPath, $type, $lang)); + } + + /** + * Gets all the resources in the graph of a certain type and ensures that + * each EasyRdf\Resource matched is returned as wrapped in an RdfResource. + * + * @return array + */ + public function allOfType(string $type): array + { + return RdfResource::wrapEasyRdfResources($this->graph->allOfType($type)); + } + + /** + * Gets the resource types of the graph as list of RdfResource. + * + * @param string|null $resource + * + * @return RdfResource[] + */ + public function typesAsResources($resource = null): array + { + $resource = RdfResource::fromRdftoEasyRdfResource($resource); + + return RdfResource::wrapEasyRdfResources($this->graph->typesAsResources($resource)); + } + + /** + * Gets an associative array of all the resources stored in the graph as + * RdfResources. The keys of the array is the URI of the related RdfResource. + * + * @return RdfResource[] + */ + public function resources(): array + { + return RdfResource::wrapEasyRdfResources($this->graph->resources()); + } + + /** + * Get an array of RdfResources matching a certain property and optional value. + * + * @param string $property the property to check + * @param mixed $value optional, the value of the propery to check for + * + * @return RdfResource[] + */ + public function resourcesMatching($property, $value = null): array + { + return RdfResource::wrapEasyRdfResources($this->graph->resourcesMatching($property, $value)); + } + + /** + * Turns any provided EasyRdf\Graph into an RdfGraph. + */ + public static function fromEasyRdf(EasyRdfGraph $graph): self + { + $rdfGraph = new static(null, null, null, $graph); + + return $rdfGraph; + } + + /** + * Ensures that any EasyRdf\Graph provided by reference will be wrapped in + * an RdfGraph. + * + * @param EasyRdfGraph|RdfGraph &$graph + */ + public static function ensureGraphClass(&$graph): void + { + $graph = ($graph instanceof EasyRdfGraph) ? self::fromEasyRdf($graph) : $graph; + } + + /** + * Ensures that each EasyRdf\Graph, in an array of Graphs passed by reference, + * is wrapped in an RdfGraph. + * + * @param array &$graphs + */ + public static function ensureGraphsClass(array &$graphs): void + { + array_walk($graphs, self::class.'::ensureGraphClass'); + } + + /** + * Statically creates a new RdfGraph and loads RDF data from the provided URI. + */ + public static function newAndLoad(string $uri, string $format = null): self + { + $graph = new self($uri); + $graph->load($uri, $format); + + return $graph; + } + + public function __toString(): string + { + return $this->graph->__toString(); + } + + public function __isset(string $name): bool + { + return $this->graph->__isset($name); + } + + public function __set(string $name, string $value): void + { + $this->graph->__set($name, $value); + } + + public function __get(string $name): ?string + { + return $this->graph->__get($name); + } + + public function __unset(string $name): void + { + $this->graph->__unset($name); + } + + // The following Methods are not required but avoid PHPStan special cases of + // class Reflection without implementing extensions; see __call() + + /** + * Get the URI of the EasyRdf\Graph. + */ + public function getUri(): ?string + { + return $this->graph->getUri(); + } + + /** Get or create a resource stored in a graph. + * + * If the resource did not previously exist, then a new resource will + * be created. + * + * If URI is null, then the URI of the graph is used. + * + * @param string $uri The URI of the resource + * @param mixed $types RDF type of a new resource (e.g. foaf:Person) + */ + public function resource($uri = null, $types = []): RdfResource + { + return RdfResource::wrapEasyRdfResource($this->graph->resource($uri, $types)); + } + + public function load(string $uri = null, string $format = null): int + { + return $this->graph->load($uri, $format); + } + + /** + * Parse a file containing RDF data into the graph object. + * + * @param string $filename The path of the file to load + * @param string $format Optional format of the file + * @param string $uri The URI of the file to load + * + * @return int The number of triples added to the graph + */ + public function parseFile($filename, $format = null, $uri = null): int + { + return $this->graph->parseFile($filename, $format, $uri); + } +} diff --git a/src/Schema/Rdf/RdfResource.php b/src/Schema/Rdf/RdfResource.php new file mode 100644 index 00000000..5985c481 --- /dev/null +++ b/src/Schema/Rdf/RdfResource.php @@ -0,0 +1,535 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\SchemaGenerator\Schema\Rdf; + +use ApiPlatform\SchemaGenerator\SchemaGeneratorConfigurationHolder as Config; +use EasyRdf\Graph as EasyRdfGraph; +use EasyRdf\Resource as EasyRdfResource; + +use function Symfony\Component\String\u; + +/** + * This class is a wrapper around the EasyRdf\Resource class. It allows the + * Schema Generator to use the labels for the resources names instead of the + * default "ID/local names"(URI fragment ID), if the option is choosen in config. + * This capability impacts the PHP class names and API resource names accordingly. + * + * @implements \ArrayAccess + * + * @author d3fk::Angatar + */ +class RdfResource implements \ArrayAccess +{ + private EasyRdfResource $resource; + private ?string $resourceName = null; + private ?string $language = null; + private ?string $namingConvention = null; + private bool $useLabel = false; + + /** + * Constructor, creates the RdfResource decorating a freshly created + * or given EasyRdf\Resource with new resource naming capabilities. + * + * @param EasyRdfGraph|RdfGraph|null $graph + */ + final public function __construct(?string $uri, $graph = null, EasyRdfResource $resource = null) + { + $graph = ($graph instanceof RdfGraph) ? $graph->getEasyGraph() : $graph; + $this->resource = $resource ?? new EasyRdfResource($uri, $graph); + $this->defineResourceName(); // line only added to satisfy existing test conditions in ClassPropertiesAppenderTest::testInvoke + } + + /** + * Returns the resourceName or trigger to define one according to the config. + */ + public function localName(): ?string + { + if (!isset($this->resourceName)) { + $this->defineResourceName(); + } + + return $this->resourceName; + } + + /** + * Defines the resource name according to the config file (ID/localName or Label). + */ + private function defineResourceName(): void + { + $this->applyNamingConfig(); + $this->updateResourceName(); + } + + /** + * Applies the naming configuration from the config file to the object. + */ + public function applyNamingConfig(): void + { + $graphUri = (null !== $this->getGraph()) ? $this->getGraph()->getUri() : null; + // Uses label only if asked in config and the resource is part of a graph + if ($this->hasGraph() + && ((Config::$config['nameAllFromLabels'] ?? false) + || (Config::$config['vocabularies'][$graphUri]['nameAllFromLabels'] ?? false) + || (Config::$config['types'][$this->localId()]['nameFromLabel'] ?? false) + ) + ) { + $this->useLabel = true; + + $this->language = Config::$config['types'][$this->localId()]['language'] + ?? (Config::$config['vocabularies'][$graphUri]['language'] + ?? (Config::$config['language'] ?? $this->language)); + + $this->namingConvention = Config::$config['types'][$this->localId()]['namingConvention'] + ?? (Config::$config['vocabularies'][$graphUri]['namingConvention'] + ?? (Config::$config['namingConvention'] ?? $this->namingConvention)); + } else { + $this->useLabel = false; + } + } + + /** + * Updates the resource name according to language and naming convention + * defined in the object. Using URI fragment ID (local ID/Name) by default. + */ + public function updateResourceName(): void + { + if ($this->useLabel) { + $resourceName = $this->labelAsName($this->language, $this->namingConvention) ?? $this->localId(); + // If it's a Class or a Wikidata/Wikibase Item, we need to start with + // a capital letter as the name is used for the PHP Class & API resource + $this->resourceName = (\in_array($this->type(), ['owl:Class', 'rdfs:Class', 'wikibase:Item', 'wd:Item'], true)) ? ucfirst($resourceName) : $resourceName; + } else { + $this->resourceName = $this->localId(); + } + } + + /** + * Sets wether or not this Resource makes use of the label for defining its name. + */ + public function setUseLabel(bool $useLabel): void + { + $this->useLabel = $useLabel; + } + + /** + * Gets wether or not this Resource makes use of the label for defining its name. + */ + public function getUseLabel(): bool + { + return $this->useLabel; + } + + /** + * Sets the resource name. + */ + public function setResourceName(?string $resourceName): void + { + $this->resourceName = $resourceName; + } + + /** + * Gets the resource name defined. + */ + public function getResourceName(): ?string + { + return $this->resourceName; + } + + /** + * Gets the EasyRdf\Resource composing this Schema Generator's RdfResource. + */ + public function getEasyResource(): EasyRdfResource + { + return $this->resource; + } + + /** + * Resets the resource's parameters related to naming behavior. + */ + public function resetResourceNamingBehavior(): void + { + $this->useLabel = false; + $this->language = null; + $this->namingConvention = null; + $this->resourceName = null; + } + + /** + * Gets the Identifier of the resource from the URI fragment identifier. + */ + public function localId(): string + { + // Replaces EasyRdf\Resource->localName() that may return void on v1.1.1 (PHPStan) + if (preg_match('|([^#:/]+)$|', $this->getUri(), $matches)) { + return $matches[1]; + } + + return ''; + } + + /** + * Returns the label of the resource in the given language with given style + * or make use of the default label if none exists in the defined language. + */ + private function labelAsName(?string $language, string $namingConvention = null): ?string + { + // English is the default language, forseeing graphs with several ones. + $language = $language ?: 'en'; + + $defaultLabel = $this->resource->label(null); + $label = $this->resource->label($language) ?? $defaultLabel; + + if ('snake case' === $namingConvention) { + return isset($label) ? u($label->__toString())->snake()->__toString() : null; + } + + // default is camel case style as with schema.org + return isset($label) ? u($label->__toString())->camel()->__toString() : null; + } + + /** + * Gets the graph related to this resource as a Schema Generator's RdfGraph. + */ + public function getGraph(): ?RdfGraph + { + return ($this->hasGraph()) ? RdfGraph::fromEasyRdf($this->resource->getGraph()) : null; + } + + /** + * Get the URI of the EasyRdf\Resource. + */ + public function getUri(): string + { + return $this->resource->getUri(); + } + + /** + * Returns true if the current RdfResource belongs to a graph. + */ + protected function hasGraph(): bool + { + return null !== $this->resource->getGraph(); + } + + /** + * Sets the current resource's prefered language (e.g. 'en'). + */ + public function setResourceLanguage(?string $language): void + { + $this->language = $language; + } + + /** + * Gets the prefered language set for the resource. + */ + public function getResourceLanguage(): ?string + { + return $this->language; + } + + /** + * Sets the current resource naming convention to use when naming entities + * from labels (i.e. "snake case" or "camel case"). + */ + public function setNamingConvention(?string $namingConvention): void + { + $this->namingConvention = $namingConvention; + } + + /** + * Gets the naming convention set for the resource. + */ + public function getNamingConvention(): ?string + { + return $this->namingConvention; + } + + /** + * Gets all values for a property and ensures that each EasyRdf\Resource + * matched is returned as wrapped in an RdfResource. + * + * @param mixed $property The name of the property + * + * @return array + */ + public function all($property, string $type = null, string $lang = null): array + { + $property = self::fromRdftoEasyRdfResource($property); + + return self::wrapEasyRdfResources($this->resource->all($property, $type, $lang)); + } + + /** + * Gets all the resources for a property of this resource and ensures that + * each EasyRdf\Resource matched is returned as wrapped in an RdfResource. + * + * @return RdfResource[] + */ + public function allResources(string $property): array + { + $property = self::fromRdftoEasyRdfResource($property); + + return self::wrapEasyRdfResources($this->resource->allResources($property)); + } + + /** + * Gets a list of types for a resource, as an array of schema generator's RdfResources. + * + * @return RdfResource[] + */ + public function typesAsResources(): array + { + return self::wrapEasyRdfResources($this->resource->typesAsResources()); + } + + /** + * Wrapps a given EasyRdf\Resource in the returned RdfResource. + */ + public static function fromEasyRdf(EasyRdfResource $resource): self + { + $rdfResource = new static(null, null, $resource); + + return $rdfResource; + } + + /** + * Turns any EasyRdf\Resource, provided by reference, into an RdfResource. + * Any form of resource is accepted but only EasyRdf\Resources are impacted. + * + * @param mixed &$resource mixed resource types + */ + public static function ensureResourceClass(&$resource): void + { + $resource = ($resource instanceof EasyRdfResource) ? self::fromEasyRdf($resource) : $resource; + } + + /** + * Ensures each EasyRdf\resource in the array of resources passed by reference + * is turned into an RdfResource wrapping the EasyRdf\Resource. + * + * @param array &$resources + */ + public static function ensureResourcesClass(array &$resources): void + { + array_walk($resources, self::class.'::ensureResourceClass'); + } + + /** + * Extends the capabilities of any EasyRdf\Resource provided by turning it + * into an RdfResource. + * + * @param mixed $resource mixed resource types + * + * @return mixed $resource mixed but EasyRdf\Resource is wrapped into an RdfResource + */ + public static function wrapEasyRdfResource($resource) + { + $resource = ($resource instanceof EasyRdfResource) ? self::fromEasyRdf($resource) : $resource; + + return $resource; + } + + /** + * Extends the capabilities of each EasyRdf\resource in the array provided + * by wrapping it in an RdfResource. + * + * @param array $resources + * + * @return array + */ + public static function wrapEasyRdfResources(array $resources): array + { + array_walk($resources, self::class.'::ensureResourceClass'); + + return $resources; + } + + /** + * Returns the corresponding EasyRdf\Resource for any RdfResource provided. + * + * @param mixed $resource mixed resource types + * + * @return mixed $resource mixed but any RdfResource will return its contained EasyRdf\resource + */ + public static function fromRdftoEasyRdfResource($resource) + { + $resource = ($resource instanceof self) ? $resource->getEasyResource() : $resource; + + return $resource; + } + + /** + * Ensures that all RdfResources provided in an array are returned in that + * array as EasyRdf\Resource class Type. + * + * @param array $resources + * + * @return array + */ + public static function fromRdftoEasyRdfResources(array $resources): array + { + array_walk($resources, self::class.'::ensureEasyResourceClass'); + + return $resources; + } + + /** + * Ensures that any RdfResource provided by reference will be an EasyRdf\Resource. + * + * @param mixed $resource mixed resource types + */ + public static function ensureEasyResourceClass(&$resource): void + { + $resource = ($resource instanceof self) ? $resource->getEasyResource() : $resource; + } + + /** + * Passes any call for an absent method to the contained EasyRdf\Resource, + * ensuring that it returns an RdfResource in place of a simple EasyRdf\Resource. + * + * @param array $arguments + * + * @return mixed depending on the method called + */ + #[\ReturnTypeWillChange] + public function __call(string $methodName, array $arguments) + { + $arguments = self::fromRdftoEasyRdfResources($arguments); + $callback = [$this->resource, $methodName]; + if (\is_callable($callback)) { + return self::wrapEasyRdfResource(\call_user_func_array($callback, $arguments)); + } + throw new \Exception('Method not found'); + } + + public function __toString(): string + { + return $this->resource->__toString(); + } + + public function __isset(string $name): bool + { + return $this->resource->__isset($name); + } + + public function __set(string $name, string $value): void + { + $this->resource->__set($name, $value); + } + + public function __get(string $name): ?string + { + return $this->resource->__get($name); + } + + public function __unset(string $name): void + { + $this->resource->__unset($name); + } + + /** + * Array Access Interface: Check whether an offset exists. + * + * @param mixed $offset an offset to check for + */ + public function offsetExists($offset): bool + { + return $this->resource->offsetExists($offset); + } + + /** + * Array Access Interface: perform get at using array syntax. + * + * @return mixed can return all value types + */ + #[\ReturnTypeWillChange] + public function offsetGet($offset) + { + return $this->resource->offsetGet($offset); + } + + /** + * Array Access Interface: perform set at using array syntax. + */ + public function offsetSet($offset, $value): void + { + $this->resource->offsetSet($offset, $value); + } + + /** + * Array Access Interface: perform unset at using array syntax. + */ + public function offsetUnset($offset): void + { + $this->resource->offsetUnset($offset); + } + + // The following Methods are not required but avoid PHPStan special cases of + // class Reflection without implementing extensions; see __call() + + public function isA(string $type): bool + { + return $this->resource->isA($type); + } + + public function isBNode(): bool + { + return $this->resource->isBNode(); + } + + /** Get a single value for a property. + * + * @param mixed $property The name of the property (e.g. foaf:name) + * @param mixed $type The type of value to filter by (e.g. literal or resource) + * @param string $lang The language to filter by (e.g. en) + * + * @return mixed A value associated with the property + */ + public function get($property, $type = null, $lang = null) + { + $property = self::fromRdftoEasyRdfResource($property); + $type = self::fromRdftoEasyRdfResource($type); + + return self::wrapEasyRdfResource($this->resource->get($property, $type, $lang)); + } + + /** Check to see if a property exists for this resource. + * + * @param string $property The name of the property (e.g. foaf:name) + * @param mixed $value An optional value of the property + * + * @return bool true if value the property exists + */ + public function hasProperty($property, $value = null): bool + { + return $this->resource->hasProperty($property, $value); + } + + /** Add values to for a property of the resource. + * + * @param mixed $property The property name + * @param mixed $value The value for the property + * + * @return int The number of values added (1 or 0) + */ + public function add($property, $value): int + { + return $this->resource->add($property, $value); + } + + public function type(): ?string + { + return $this->resource->type(); + } +} diff --git a/src/Schema/TypeConverter.php b/src/Schema/TypeConverter.php index cc8f4382..744f840f 100644 --- a/src/Schema/TypeConverter.php +++ b/src/Schema/TypeConverter.php @@ -13,7 +13,7 @@ namespace ApiPlatform\SchemaGenerator\Schema; -use EasyRdf\Resource as RdfResource; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; final class TypeConverter { diff --git a/src/SchemaGeneratorConfiguration.php b/src/SchemaGeneratorConfiguration.php index 3195e7a1..8acb60c9 100644 --- a/src/SchemaGeneratorConfiguration.php +++ b/src/SchemaGeneratorConfiguration.php @@ -86,6 +86,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarNode('uri')->info('RDF vocabulary to use')->example('https://schema.org/version/latest/schemaorg-current-https.rdf')->end() ->scalarNode('format')->defaultNull()->info('RDF vocabulary format')->example('rdfxml')->end() ->booleanNode('allTypes')->defaultNull()->info('Generate all types for this vocabulary, even if an explicit configuration exists. If allTypes is enabled globally, it can be disabled for this particular vocabulary')->end() + ->booleanNode('nameAllFromLabels')->defaultFalse()->info('Make use of the label information when possible to define all entities names in this vocabulary?')->end() + ->scalarNode('language')->defaultNull()->info('The language to use, with this vocabulary, among the labels when used as entities names, e.g., en')->end() + ->scalarNode('namingConvention')->defaultNull()->info('The naming convention to use, with this vocabulary, when naming entities from their labels; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase')->end() ->append($attributesNode()) ->end() ->end() @@ -173,6 +176,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarPrototype()->end() ->end() ->booleanNode('allTypes')->defaultFalse()->info('Generate all types, even if an explicit configuration exists')->end() + ->booleanNode('nameAllFromLabels')->defaultFalse()->info('Make use of the label information when possible to define all entities names?')->end() + ->scalarNode('language')->defaultNull()->info('The language to use among the labels when used as entities names, e.g., en')->end() + ->scalarNode('namingConvention')->defaultNull()->info('The naming convention to use when naming entities from their labels; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase')->end() ->booleanNode('resolveTypes')->defaultFalse()->info('If a type is present in a vocabulary but not explicitly imported (types) or if the vocabulary is not totally imported (allTypes), it will be generated')->end() ->arrayNode('types') ->beforeNormalization() @@ -193,6 +199,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->scalarNode('vocabularyNamespace')->defaultNull()->info('Namespace of the vocabulary of this type (defaults to the global "vocabularyNamespace" entry)')->example('http://www.w3.org/ns/activitystreams#')->end() ->booleanNode('abstract')->defaultNull()->info('Is the class abstract? (null to guess)')->end() ->booleanNode('embeddable')->defaultFalse()->info('Is the class embeddable?')->end() + ->booleanNode('nameFromLabel')->defaultFalse()->info('Make use of the label if possible to define this type entity name?')->end() + ->scalarNode('language')->defaultNull()->info('The language to use among the labels when used as entity name for the current type, e.g., en')->end() + ->scalarNode('namingConvention')->defaultNull()->info('The naming convention to use when naming entities from the labels related to the current type; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase')->end() ->arrayNode('namespaces') ->addDefaultsIfNotSet() ->info('Type namespaces') diff --git a/src/SchemaGeneratorConfigurationHolder.php b/src/SchemaGeneratorConfigurationHolder.php new file mode 100644 index 00000000..5085d05c --- /dev/null +++ b/src/SchemaGeneratorConfigurationHolder.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\SchemaGenerator; + +/** + * Holder of static configuration for the current run of Schema Generator. + * + * @author d3fk::Angatar + */ +class SchemaGeneratorConfigurationHolder +{ + /** + * @var array + */ + public static array $config = []; + + /** + * Sets the static configuration. + * + * @param array $config + */ + public static function set(array $config): void + { + self::$config = $config; + } + + /** + * Gets the static configuration set. + * + * @return array $config + */ + public static function get(): array + { + return self::$config; + } + + /** + * Returns true if the configuration was set and is ready to be used. + */ + public static function isReady(): bool + { + if (empty(self::$config)) { + return false; + } + + return true; + } + + /** + * Flushes any stored configuration. + */ + public static function reset(): void + { + self::$config = []; + } +} diff --git a/src/TypesGenerator.php b/src/TypesGenerator.php index 7547dc47..cee7a0ea 100644 --- a/src/TypesGenerator.php +++ b/src/TypesGenerator.php @@ -28,12 +28,13 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Property as SchemaProperty; use ApiPlatform\SchemaGenerator\Schema\PropertyGenerator\IdPropertyGenerator; use ApiPlatform\SchemaGenerator\Schema\PropertyGenerator\PropertyGenerator; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\Schema\TypeConverter; +use ApiPlatform\SchemaGenerator\SchemaGeneratorConfigurationHolder as Config; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; -use EasyRdf\Graph as RdfGraph; use EasyRdf\RdfNamespace; -use EasyRdf\Resource as RdfResource; use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerInterface; use Symfony\Component\String\Inflector\InflectorInterface; @@ -108,6 +109,10 @@ public function generate(array $graphs, array $config): array throw new \InvalidArgumentException('At least one graph must be injected.'); } + // From here, we also make the config easily accessible as a static + // information in a dedicated holder class. + Config::set($config); + [$typeNamesToGenerate, $types] = $this->defineTypesToGenerate($graphs, $config); $classes = []; @@ -452,7 +457,8 @@ private function defineTypesToGenerate(array $graphs, array $config): array } $typeName = $this->phpTypeConverter->escapeIdentifier($type->localName()); - if (!($config['types'][$typeName]['exclude'] ?? false)) { + $typeId = $type->localId(); + if (!($config['types'][$typeId]['exclude'] ?? false)) { if ($config['resolveTypes'] || $vocabAllTypes) { $allTypes[$typeName] = $type; } @@ -464,7 +470,7 @@ private function defineTypesToGenerate(array $graphs, array $config): array } } - foreach ($config['types'] as $typeName => $typeConfig) { + foreach ($config['types'] as $typeId => $typeConfig) { if ($typeConfig['exclude']) { continue; } @@ -474,20 +480,21 @@ private function defineTypesToGenerate(array $graphs, array $config): array foreach ($graphs as $graph) { $resources = $graph->resources(); - $typeIri = $vocabularyNamespace.$typeName; + $typeIri = $vocabularyNamespace.$typeId; if (isset($resources[$typeIri])) { $resource = $graph->resource($typeIri); break; } } - $typeName = $this->phpTypeConverter->escapeIdentifier($typeName); if ($resource) { + $typeName = $this->phpTypeConverter->escapeIdentifier($resource->localName() ?? ''); $allTypes[$typeName] = $resource; if (!\in_array($typeName, $typeNamesToGenerate, true)) { $typeNamesToGenerate[] = $typeName; } } else { + $typeName = $this->phpTypeConverter->escapeIdentifier($typeId); $this->logger ? $this->logger->warning('Type "{typeName}" cannot be found. Using "{guessFrom}" type to generate entity.', ['typeName' => $typeName, 'guessFrom' => $typeConfig['guessFrom']]) : null; if (isset($graph)) { $type = $graph->resource($vocabularyNamespace.$typeConfig['guessFrom']); diff --git a/tests/AnnotationGenerator/PhpDocAnnotationGeneratorTest.php b/tests/AnnotationGenerator/PhpDocAnnotationGeneratorTest.php index 85545a24..10c7b39b 100644 --- a/tests/AnnotationGenerator/PhpDocAnnotationGeneratorTest.php +++ b/tests/AnnotationGenerator/PhpDocAnnotationGeneratorTest.php @@ -22,9 +22,9 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property as SchemaProperty; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\String\Inflector\EnglishInflector; diff --git a/tests/AttributeGenerator/ApiPlatformCoreAttributeGeneratorTest.php b/tests/AttributeGenerator/ApiPlatformCoreAttributeGeneratorTest.php index c2a4e637..385a0a93 100644 --- a/tests/AttributeGenerator/ApiPlatformCoreAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/ApiPlatformCoreAttributeGeneratorTest.php @@ -29,9 +29,9 @@ use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use Nette\PhpGenerator\Literal; use PHPUnit\Framework\TestCase; use Symfony\Component\String\Inflector\EnglishInflector; diff --git a/tests/AttributeGenerator/ConfigurationAttributeGeneratorTest.php b/tests/AttributeGenerator/ConfigurationAttributeGeneratorTest.php index 1eb03797..4c70f6d7 100644 --- a/tests/AttributeGenerator/ConfigurationAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/ConfigurationAttributeGeneratorTest.php @@ -19,9 +19,9 @@ use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use PHPUnit\Framework\TestCase; use Symfony\Component\String\Inflector\EnglishInflector; diff --git a/tests/AttributeGenerator/ConstraintAttributeGeneratorTest.php b/tests/AttributeGenerator/ConstraintAttributeGeneratorTest.php index 9f4d2e6f..ca1a3c21 100644 --- a/tests/AttributeGenerator/ConstraintAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/ConstraintAttributeGeneratorTest.php @@ -21,9 +21,9 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use Nette\PhpGenerator\Literal; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; diff --git a/tests/AttributeGenerator/DoctrineMongoDBAttributeGeneratorTest.php b/tests/AttributeGenerator/DoctrineMongoDBAttributeGeneratorTest.php index 42dcc0e9..c5aaa131 100644 --- a/tests/AttributeGenerator/DoctrineMongoDBAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/DoctrineMongoDBAttributeGeneratorTest.php @@ -21,10 +21,10 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use Nette\PhpGenerator\Literal; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; diff --git a/tests/AttributeGenerator/DoctrineOrmAssociationOverrideAttributeGeneratorTest.php b/tests/AttributeGenerator/DoctrineOrmAssociationOverrideAttributeGeneratorTest.php index 072cc266..2cb50353 100644 --- a/tests/AttributeGenerator/DoctrineOrmAssociationOverrideAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/DoctrineOrmAssociationOverrideAttributeGeneratorTest.php @@ -18,9 +18,9 @@ use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use Nette\PhpGenerator\Literal; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; diff --git a/tests/AttributeGenerator/DoctrineOrmAttributeGeneratorTest.php b/tests/AttributeGenerator/DoctrineOrmAttributeGeneratorTest.php index a8a11942..2abdb1fe 100644 --- a/tests/AttributeGenerator/DoctrineOrmAttributeGeneratorTest.php +++ b/tests/AttributeGenerator/DoctrineOrmAttributeGeneratorTest.php @@ -21,10 +21,10 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use Nette\PhpGenerator\Literal; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; diff --git a/tests/ClassMutator/ClassParentMutatorTest.php b/tests/ClassMutator/ClassParentMutatorTest.php index 2d12ab7f..8bce0f48 100644 --- a/tests/ClassMutator/ClassParentMutatorTest.php +++ b/tests/ClassMutator/ClassParentMutatorTest.php @@ -17,9 +17,9 @@ use ApiPlatform\SchemaGenerator\Model\Use_; use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; diff --git a/tests/ClassMutator/ClassPropertiesAppenderTest.php b/tests/ClassMutator/ClassPropertiesAppenderTest.php index 8cbe5003..aa514fe6 100644 --- a/tests/ClassMutator/ClassPropertiesAppenderTest.php +++ b/tests/ClassMutator/ClassPropertiesAppenderTest.php @@ -21,10 +21,10 @@ use ApiPlatform\SchemaGenerator\Schema\Model\Property; use ApiPlatform\SchemaGenerator\Schema\Model\Type\PrimitiveType as SchemaPrimitiveType; use ApiPlatform\SchemaGenerator\Schema\PropertyGenerator\PropertyGenerator as SchemaPropertyGenerator; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\Schema\TypeConverter; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; use Prophecy\Prophecy\ObjectProphecy; diff --git a/tests/Command/DumpConfigurationTest.php b/tests/Command/DumpConfigurationTest.php index feec7860..26a0ca2e 100644 --- a/tests/Command/DumpConfigurationTest.php +++ b/tests/Command/DumpConfigurationTest.php @@ -46,6 +46,15 @@ public function testDumpConfiguration(): void # Generate all types for this vocabulary, even if an explicit configuration exists. If allTypes is enabled globally, it can be disabled for this particular vocabulary allTypes: null + # Make use of the label information when possible to define all entities names in this vocabulary? + nameAllFromLabels: false + + # The language to use, with this vocabulary, among the labels when used as entities names, e.g., en + language: null + + # The naming convention to use, with this vocabulary, when naming entities from their labels; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase + namingConvention: null + # Attributes (merged with generated attributes) attributes: [] @@ -164,6 +173,15 @@ interface: App\Model # Example: App\Model # Generate all types, even if an explicit configuration exists allTypes: false + # Make use of the label information when possible to define all entities names? + nameAllFromLabels: false + + # The language to use among the labels when used as entities names, e.g., en + language: null + + # The naming convention to use when naming entities from their labels; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase + namingConvention: null + # If a type is present in a vocabulary but not explicitly imported (types) or if the vocabulary is not totally imported (allTypes), it will be generated resolveTypes: false @@ -185,6 +203,15 @@ interface: App\Model # Example: App\Model # Is the class embeddable? embeddable: false + # Make use of the label if possible to define this type entity name? + nameFromLabel: false + + # The language to use among the labels when used as entity name for the current type, e.g., en + language: null + + # The naming convention to use when naming entities from the labels related to the current type; the default value is camel case (possible values are "snake case" or "camel case"), classes have first charater in uppercase + namingConvention: null + # Type namespaces namespaces: diff --git a/tests/Schema/Model/ClassTest.php b/tests/Schema/Model/ClassTest.php index 1cbcb963..c26b4a03 100644 --- a/tests/Schema/Model/ClassTest.php +++ b/tests/Schema/Model/ClassTest.php @@ -17,9 +17,9 @@ use ApiPlatform\SchemaGenerator\Model\Use_; use ApiPlatform\SchemaGenerator\Schema\Model\Class_ as SchemaClass; use ApiPlatform\SchemaGenerator\Schema\Model\Property as SchemaProperty; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; -use EasyRdf\Graph as RdfGraph; -use EasyRdf\Resource as RdfResource; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Definition\Processor; use Symfony\Component\String\Inflector\EnglishInflector; diff --git a/tests/Schema/Rdf/RdfGraphTest.php b/tests/Schema/Rdf/RdfGraphTest.php new file mode 100644 index 00000000..9b7d7181 --- /dev/null +++ b/tests/Schema/Rdf/RdfGraphTest.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\SchemaGenerator\Tests\Schema\Rdf; + +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; +use EasyRdf\Graph as EasyRdfGraph; +use PHPUnit\Framework\TestCase; + +/** + * @author d3fk::Angatar + */ +class RdfGraphTest extends TestCase +{ + private static array $testvalues; + private RdfGraph $graph; + + public static function setUpBeforeClass(): void + { + self::$testvalues = [ + 'graphUri' => 'https://raw.githubusercontent.com/w3c/dxwg/gh-pages/dcat/rdf/dcat3.rdf', + 'graphFormat' => 'rdfxml', + 'vocabularyNamespace' => 'http://www.w3.org/ns/dcat#', + 'resourceUri' => 'http://www.w3.org/ns/dcat#DataService', + 'resourceType' => 'owl:Class', + 'property' => 'rdfs:range', + 'newBnodeType' => 'foaf:Project', + 'newResourcePropertyName' => 'rdf:test', + ]; + } + + protected function setUp(): void + { + $this->graph = new RdfGraph(self::$testvalues['graphUri']); + } + + public function testResource(): void + { + $resource = $this->graph->resource(self::$testvalues['resourceUri'], [self::$testvalues['resourceType']]); + $this->assertInstanceOf(RdfResource::class, $resource); + } + + public function testNewBnode(): void + { + $bnode = $this->graph->newBnode(self::$testvalues['newBnodeType']); + $this->assertInstanceOf(RdfResource::class, $bnode); + } + + public function testGet(): void + { + $bnode = $this->graph->newBnode(self::$testvalues['newBnodeType']); + $this->graph->addResource(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName'], $bnode); + $resource = $this->graph->get(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName'], 'resource'); + $this->assertInstanceOf(RdfResource::class, $resource); + } + + public function testGetResource(): void + { + $bnode = $this->graph->newBnode(self::$testvalues['newBnodeType']); + $this->graph->addResource(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName'], $bnode); + $resource = $this->graph->getResource(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName']); + $this->assertInstanceOf(RdfResource::class, $resource); + } + + public function testTypeAsResource(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resource = $this->graph->typeAsResource(self::$testvalues['resourceUri']); + $this->assertInstanceOf(RdfResource::class, $resource); + } + + public function testPrimaryTopic(): void + { + $bnode = $this->graph->newBnode(self::$testvalues['newBnodeType']); + $this->graph->addResource(self::$testvalues['resourceUri'], 'foaf:primaryTopic', $bnode); + $resource = $this->graph->primaryTopic(self::$testvalues['resourceUri']); + $this->assertInstanceOf(RdfResource::class, $resource); + } + + public function testAll(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resources = $this->graph->all(self::$testvalues['resourceType'], '^rdf:type'); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testAllOfType(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resources = $this->graph->allOfType(self::$testvalues['resourceType']); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testTypesAsResources(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resources = $this->graph->typesAsResources(self::$testvalues['resourceUri']); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testResources(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resources = $this->graph->resources(); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testResourcesMatching(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $resources = $this->graph->resourcesMatching(self::$testvalues['property']); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testAllResources(): void + { + $this->graph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $this->graph->addResource(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName'], 'http://example.com/thing'); + $this->graph->addResource(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName'], '_:bnode1'); + $resources = $this->graph->allResources(self::$testvalues['resourceUri'], self::$testvalues['newResourcePropertyName']); + $this->assertNotEmpty($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testFromEasyRdf(): void + { + $easyRdfGraph = new EasyRdfGraph(self::$testvalues['graphUri']); + $easyRdfGraph->load(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $rdfGraph = RdfGraph::fromEasyRdf($easyRdfGraph); + $this->assertInstanceOf(RdfGraph::class, $rdfGraph); + $this->assertEquals($easyRdfGraph->serialise('rdfxml'), $rdfGraph->serialise('rdfxml')); + } + + public function testEnsureGraphClass(): void + { + $rdfGraph = new EasyRdfGraph(self::$testvalues['graphUri']); + RdfGraph::ensureGraphClass($rdfGraph); + $this->assertInstanceOf(RdfGraph::class, $rdfGraph); + } + + public function testEnsureGraphsClass(): void + { + $graphs = []; + $rdfGraph = new EasyRdfGraph(self::$testvalues['graphUri']); + $graphs[] = $rdfGraph; + $graphs[] = $rdfGraph; + $graphs[] = $this->graph; + + RdfGraph::ensureGraphsClass($graphs); + foreach ($graphs as $graph) { + $this->assertInstanceOf(RdfGraph::class, $graph); + } + } + + public function testNewAndLoad(): void + { + $newLoadedGraph = RdfGraph::newAndLoad(self::$testvalues['graphUri'], self::$testvalues['graphFormat']); + $this->assertInstanceOf(RdfGraph::class, $newLoadedGraph); + } +} diff --git a/tests/Schema/Rdf/RdfResourceTest.php b/tests/Schema/Rdf/RdfResourceTest.php new file mode 100644 index 00000000..204efb0d --- /dev/null +++ b/tests/Schema/Rdf/RdfResourceTest.php @@ -0,0 +1,466 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\SchemaGenerator\Tests\Schema\Rdf; + +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfResource; +use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; +use ApiPlatform\SchemaGenerator\SchemaGeneratorConfigurationHolder as Config; +use EasyRdf\Graph as EasyRdfGraph; +use EasyRdf\RdfNamespace; +use EasyRdf\Resource as EasyRdfResource; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Definition\Processor; + +use function Symfony\Component\String\u; + +/** + * @author d3fk::Angatar + */ +class RdfResourceTest extends TestCase +{ + private static array $testGroups; + private static Processor $processor; + + public static function setUpBeforeClass(): void + { + self::$processor = new Processor(); + $testGroups = [ + [ + 'graphUri' => 'https://ontobee.org/ontology/rdf/NCIT?iri=http://purl.obolibrary.org/obo/NCIT_C94196', + 'graphFormat' => 'rdfxml', + 'resourceUri' => 'http://purl.obolibrary.org/obo/NCIT_C94196', + 'vocabularyNamespace' => 'http://purl.obolibrary.org/obo/', + 'label' => 'Virus-neutralizing Antibody', + 'id' => 'NCIT_C94196', + 'spanishLabel' => 'Virus-neutralizing Antibody', + ], + [ + 'graphUri' => 'https://raw.githubusercontent.com/w3c/dxwg/gh-pages/dcat/rdf/dcat3.rdf', + 'graphFormat' => 'rdfxml', + 'resourceUri' => 'http://www.w3.org/ns/dcat#DataService', + 'vocabularyNamespace' => 'http://www.w3.org/ns/dcat#', + 'label' => 'Data service', + 'id' => 'DataService', + 'spanishLabel' => 'Servicio de datos', + ], + [ + 'graphUri' => 'http://www.wikidata.org/entity/Q115634351.rdf', + 'graphFormat' => 'rdfxml', + 'resourceUri' => 'http://www.wikidata.org/entity/Q115634351', + 'vocabularyNamespace' => 'http://www.wikidata.org/entity/', + 'label' => 'laboratory freezer', + 'id' => 'Q115634351', + 'spanishLabel' => 'congelador de laboratorio', + ], + ]; + + // set namespaces to work with wikidata + RdfNamespace::set('wikibase', 'http://wikiba.se/ontology#'); + RdfNamespace::set('wd', 'http://www.wikidata.org/entity/'); + + foreach ($testGroups as &$testValues) { + $testValues['snakeLabel'] = u($testValues['label'])->snake()->__toString(); + $testValues['camelLabel'] = u($testValues['label'])->camel()->__toString(); + $testValues['snakeClassLabel'] = ucfirst($testValues['snakeLabel']); + $testValues['camelClassLabel'] = ucfirst($testValues['camelLabel']); + $testValues['snakeSpanishLabel'] = u($testValues['spanishLabel'])->snake()->__toString(); + $testValues['camelSpanishLabel'] = u($testValues['spanishLabel'])->camel()->__toString(); + $testValues['snakeSpanishClassLabel'] = ucfirst($testValues['snakeSpanishLabel']); + + $testValues['graph'] = RdfGraph::newAndLoad($testValues['graphUri'], $testValues['graphFormat']); + } + + self::$testGroups = $testGroups; + } + + protected function setUp(): void + { + Config::reset(); + } + + public function testLocalNameWithConfig(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getSingleTypeRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['snakeClassLabel'], $resource->localName()); + + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceGeneralNamingConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['camelClassLabel'], $resource->localName()); + + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['snakeClassLabel'], $resource->localName()); + + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourcePreferedLanguageConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['snakeSpanishClassLabel'], $resource->localName()); + + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localName()); + + // no config reset occured Config::$config is still set + $resource = new RdfResource($testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localName()); + + $resource = new RdfResource($testValues['resourceUri']); + $this->assertEquals($testValues['id'], $resource->localName()); + } + } + + public function testLocalNameWithoutConfig(): void + { + foreach (self::$testGroups as $testValues) { + $resource = new RdfResource($testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localName()); + + $resource = new RdfResource($testValues['resourceUri']); + $this->assertEquals($testValues['id'], $resource->localName()); + } + } + + public function testLocalNameConfigOvewrittenBySetters() + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localName()); + $resource->setResourceName('test'); + $this->assertEquals('test', $resource->localName()); + $resource->setResourceName(null); + $this->assertEquals($testValues['id'], $resource->localName()); + $resource->setResourceName(null); + $resource->setUseLabel(true); + $resource->updateResourceName(); + $this->assertEquals($testValues['camelClassLabel'], $resource->localName()); + $resource->setNamingConvention('snake case'); + $resource->updateResourceName(); + $this->assertEquals($testValues['snakeClassLabel'], $resource->localName()); + $resource->setResourceLanguage('es'); + $resource->updateResourceName(); + $this->assertEquals($testValues['snakeSpanishClassLabel'], $resource->localName()); + $resource->setResourceLanguage('en'); + $resource->updateResourceName(); + $this->assertEquals($testValues['snakeClassLabel'], $resource->localName()); + } + } + + public function testApplyNamingConfig(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->setUseLabel(true); + $resource->applyNamingConfig(); + $this->assertFalse($resource->getUseLabel()); + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertTrue($resource->getUseLabel()); + $resource->setUseLabel(false); + $resource->applyNamingConfig(); + $this->assertTrue($resource->getUseLabel()); + } + } + + public function testSetResourceName(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->setResourceName('test'); + $this->assertEquals('test', $resource->getResourceName()); + } + } + + public function testUpdateResourceName(): void + { + foreach (self::$testGroups as $testValues) { + $resource = new RdfResource($testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localName()); + $resource->setUseLabel(true); + $resource->updateResourceName(); + $this->assertEquals($testValues['camelClassLabel'], $resource->getResourceName()); + } + } + + public function testResetResourceNamingBehavior(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + + $resource->resetResourceNamingBehavior(); + $this->assertNull($resource->getResourceName()); + + $resource->updateResourceName(); + $this->assertEquals($testValues['id'], $resource->localName()); + } + } + + public function testLocalId(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $this->assertEquals($testValues['id'], $resource->localId()); + } + } + + public function testLabelAsName(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resourceMethod = self::getMethod('labelAsName'); + $this->assertEquals($testValues['camelLabel'], $resourceMethod->invokeArgs($resource, ['', ''])); + $this->assertEquals($testValues['snakeLabel'], $resourceMethod->invokeArgs($resource, ['en', 'snake case'])); + $this->assertEquals($testValues['camelSpanishLabel'], $resourceMethod->invokeArgs($resource, ['es', 'camel case'])); + } + } + + public function testGetGraph(): void + { + foreach (self::$testGroups as $testValues) { + $resource = new RdfResource($testValues['resourceUri']); + $this->assertNull($resource->getGraph()); + $resource = new RdfResource($testValues['resourceUri'], $testValues['graph']); + $this->assertInstanceOf(RdfGraph::class, $resource->getGraph()); + $resource = new RdfResource($testValues['resourceUri'], new EasyRdfGraph($testValues['graphUri'])); + $this->assertInstanceOf(RdfGraph::class, $resource->getGraph()); + } + } + + public function testAll(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getAllTypesRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->addResource('rdf:test', 'Simple Test1'); + $resource->addResource('rdf:test', 'Simple Test2'); + $prop = $testValues['graph']->resource('http://www.w3.org/1999/02/22-rdf-syntax-ns#test'); + $all = $resource->all($prop); + $this->assertNotEmpty($all); + foreach ($all as $propResource) { + $this->assertInstanceOf(RdfResource::class, $propResource); + } + } + } + + public function testAllResources(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->addResource('rdf:test', 'Resource Test'); + $resources = $resource->allResources('rdf:test'); + $this->assertNotEmpty($resources); + foreach ($resources as $relatedResource) { + $this->assertInstanceOf(RdfResource::class, $relatedResource); + } + } + } + + public function testTypesAsResources(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resources = $resource->typesAsResources(); + $this->assertNotEmpty($resources); + foreach ($resources as $typeResource) { + $this->assertInstanceOf(RdfResource::class, $typeResource); + } + } + } + + public function testTypeAsResource(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $typeResource = $resource->typeAsResource(); + $this->assertNotNull($typeResource); + $this->assertInstanceOf(RdfResource::class, $typeResource); + } + } + + public function testGet(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->addResource('rdf:test', 'Testing get function'); + $prop = $testValues['graph']->resource('http://www.w3.org/1999/02/22-rdf-syntax-ns#test'); + $getPropertyResource = $resource->get($prop); + $this->assertNotNull($getPropertyResource); + $this->assertInstanceOf(RdfResource::class, $getPropertyResource); + } + } + + public function testGetResource(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->addResource('rdf:test', 'Testing getRersource function'); + $prop = $testValues['graph']->resource('http://www.w3.org/1999/02/22-rdf-syntax-ns#test'); + $getPropertyResource = $resource->getResource($prop); + $this->assertNotNull($getPropertyResource); + $this->assertInstanceOf(RdfResource::class, $getPropertyResource); + } + } + + public function testPrimaryTopic(): void + { + foreach (self::$testGroups as $testValues) { + $resource = $this->createConfiguredRdfResource($this->getDefaultRdfResourceConfig($testValues), $testValues['resourceUri'], $testValues['graph']); + $resource->addResource('foaf:primaryTopic', 'Testing Resource primary Topic'); + $primaryTopic = $resource->primaryTopic(); + $this->assertInstanceOf(RdfResource::class, $primaryTopic); + } + } + + public function testFromEasyRdf(): void + { + foreach (self::$testGroups as $testValues) { + $easyRdfResource = new EasyRdfResource($testValues['resourceUri']); + $rdfResource = RdfResource::fromEasyRdf($easyRdfResource); + $this->assertInstanceOf(RdfResource::class, $rdfResource); + } + } + + public function testFromEasyRdfWithGraph(): void + { + foreach (self::$testGroups as $testValues) { + $easyRdfResource = new EasyRdfResource($testValues['resourceUri'], $testValues['graph']->getEasyGraph()); + $rdfResource = RdfResource::fromEasyRdf($easyRdfResource); + $this->assertInstanceOf(RdfResource::class, $rdfResource); + } + } + + public function testEnsureResourceClass(): void + { + foreach (self::$testGroups as $testValues) { + $rdfResourceToCast = new EasyRdfResource($testValues['resourceUri'], $testValues['graph']->getEasyGraph()); + RdfResource::ensureResourceClass($rdfResourceToCast); + $this->assertInstanceOf(RdfResource::class, $rdfResourceToCast); + } + } + + public function testEnsureResourcesClass(): void + { + $resources = []; + $easyRdfResource = new EasyRdfResource(self::$testGroups[0]['resourceUri'], self::$testGroups[0]['graph']->getEasyGraph()); + $resources[] = $easyRdfResource; + $resources[] = $easyRdfResource; + $resources[] = new RdfResource(self::$testGroups[0]['resourceUri'], self::$testGroups[0]['graph']); + + RdfResource::ensureResourcesClass($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + public function testWrapEasyRdfResource(): void + { + $resourceToDecorate = new EasyRdfResource(self::$testGroups[0]['resourceUri'], self::$testGroups[0]['graph']->getEasyGraph()); + $decoratedResource = RdfResource::wrapEasyRdfResource($resourceToDecorate); + $this->assertInstanceOf(RdfResource::class, $decoratedResource); + } + + public function testWrapEasyRdfResources(): void + { + $resources = []; + $easyRdfResource = new EasyRdfResource(self::$testGroups[0]['resourceUri'], self::$testGroups[0]['graph']->getEasyGraph()); + $resources[] = $easyRdfResource; + $resources[] = $easyRdfResource; + $resources[] = new RdfResource(self::$testGroups[0]['resourceUri'], self::$testGroups[0]['graph']); + + $resources = RdfResource::wrapEasyRdfResources($resources); + foreach ($resources as $resource) { + $this->assertInstanceOf(RdfResource::class, $resource); + } + } + + private function processConfiguration(array $config): array + { + return self::$processor->processConfiguration(new SchemaGeneratorConfiguration(), [$config]); + } + + private function setResourceConfiguration(array $processedConfiguration): void + { + Config::set($processedConfiguration); + } + + private function createConfiguredRdfResource(array $config, string $resouceUri, RdfGraph $graph): RdfResource + { + $processedConfiguration = $this->processConfiguration($config); + $this->setResourceConfiguration($processedConfiguration); + + return new RdfResource($resouceUri, $graph); + } + + private function getSingleTypeRdfResourceConfig(array $testValues): array + { + return [ + 'vocabularies' => [ + ['uri' => $testValues['graphUri'], 'allTypes' => false], + ], + 'types' => [ + $testValues['id'] => [ + 'nameFromLabel' => true, + 'namingConvention' => 'snake case', + 'vocabularyNamespace' => $testValues['vocabularyNamespace'], + ], + ], + ]; + } + + private function getAllTypesRdfResourceGeneralNamingConfig(array $testValues): array + { + return [ + 'vocabularies' => [ + ['uri' => $testValues['graphUri'], 'allTypes' => true], + ], + 'nameAllFromLabels' => true, + 'namingConvention' => 'camel case', + ]; + } + + private function getAllTypesRdfResourceConfig(array $testValues): array + { + return [ + 'vocabularies' => [ + ['uri' => $testValues['graphUri'], 'allTypes' => true, 'nameAllFromLabels' => true, 'namingConvention' => 'snake case'], + ], + ]; + } + + private function getAllTypesRdfResourcePreferedLanguageConfig(array $testValues): array + { + return [ + 'vocabularies' => [ + ['uri' => $testValues['graphUri'], 'allTypes' => true, 'nameAllFromLabels' => true, 'namingConvention' => 'snake case', 'language' => 'es'], + ], + ]; + } + + private function getDefaultRdfResourceConfig(array $testValues): array + { + return [ + 'vocabularies' => [ + ['uri' => $testValues['graphUri']], + ], + ]; + } + + /** + * Get private/protected method from a class for testing. + * + * @param string $name method name + */ + protected static function getMethod($name): \ReflectionMethod + { + $class = new \ReflectionClass(RdfResource::class); + $method = $class->getMethod($name); + $method->setAccessible(true); + + return $method; + } +} diff --git a/tests/TypesGeneratorTest.php b/tests/TypesGeneratorTest.php index beb07316..c199bfe5 100644 --- a/tests/TypesGeneratorTest.php +++ b/tests/TypesGeneratorTest.php @@ -18,9 +18,9 @@ use ApiPlatform\SchemaGenerator\GoodRelationsBridge; use ApiPlatform\SchemaGenerator\PhpTypeConverter; use ApiPlatform\SchemaGenerator\Printer; +use ApiPlatform\SchemaGenerator\Schema\Rdf\RdfGraph; use ApiPlatform\SchemaGenerator\SchemaGeneratorConfiguration; use ApiPlatform\SchemaGenerator\TypesGenerator; -use EasyRdf\Graph as RdfGraph; use EasyRdf\RdfNamespace; use PHPUnit\Framework\TestCase; use Prophecy\Argument;