Skip to content

donatj/php-dnf-solver

Repository files navigation

PHP DNF Solver

Latest Stable Version License ci.yml Coverage Status

PHP DNF (Disjunctive Normal Form) Signature Compatibility Solver - see: https://wiki.php.net/rfc/dnf_types

Requirements

  • php: ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0

Installing

Install the latest version with:

composer require 'donatj/php-dnf-solver'

Examples

Example Parameter Satisfaction Check

<?php

namespace Examples;

use donatj\PhpDnfSolver\DNF;
use donatj\PhpDnfSolver\Types\UserDefinedType;

require __DIR__ . '/../vendor/autoload.php';

interface A {}
interface B {}
interface C {}
interface D {}

class Foo implements A, B {}
class Bar implements B, C {}
class Baz implements C, D {}

$qux = function ( A|(B&C) $aOrB ) : void {};

$quxParamType = (new \ReflectionFunction($qux))->getParameters()[0]->getType();

$quxDnf = DNF::getFromReflectionType($quxParamType);

var_dump($quxDnf->isSatisfiedBy(
	new UserDefinedType(Foo::class)
)); // true

var_dump($quxDnf->isSatisfiedBy(
	new UserDefinedType(Bar::class)
)); // true

var_dump($quxDnf->isSatisfiedBy(
	new UserDefinedType(Baz::class)
)); // false

Outputs:

bool(true)
bool(true)
bool(false)

Example DNF Building

<?php

namespace Examples;

use donatj\PhpDnfSolver\Types\AndClause;
use donatj\PhpDnfSolver\Types\BuiltInType;
use donatj\PhpDnfSolver\Types\OrClause;
use donatj\PhpDnfSolver\Types\UserDefinedType;

require __DIR__ . '/../vendor/autoload.php';

interface A {}
interface B {}
interface C {}

var_dump((new OrClause(
	new UserDefinedType(A::class),
	new UserDefinedType(B::class),
	new UserDefinedType(C::class)
))->dnf()); // A|B|C

var_dump((new OrClause(
	new UserDefinedType(A::class),
	new AndClause(
		new UserDefinedType(B::class),
		new UserDefinedType(C::class)
	)
))->dnf()); // A|(B&C)

var_dump((new OrClause(
	new AndClause(new UserDefinedType(A::class), new UserDefinedType(B::class)),
	new AndClause(
		new UserDefinedType(B::class),
		new UserDefinedType(C::class)
	),
	new BuiltInType('null'),
))->dnf()); // (A&B)|(B&C)|null

Outputs:

string(32) "Examples\A|Examples\B|Examples\C"
string(34) "Examples\A|(Examples\B&Examples\C)"
string(52) "(Examples\A&Examples\B)|(Examples\B&Examples\C)|null"

Documentation

Class: donatj\PhpDnfSolver\DNF

Method: DNF::getFromReflectionType

function getFromReflectionType(\ReflectionType $type) : \donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface

Helper to convert a ReflectionType into it's DNF representation

Example sources include
  • ReflectionFunctionAbstract::getParameters()[…]->getType()
  • ReflectionParameter::getType()
  • ReflectionMethod::getReturnType()
  • ReflectionProperty::getType()

Method: DNF::reflectionTypeSatisfiesReflectionType

function reflectionTypeSatisfiesReflectionType(\ReflectionType $satisfyingType, \ReflectionType $satisfiedType) : bool

Helper to quickly check if a ReflectionType satisfies another ReflectionType

Parameters:
  • \ReflectionType $satisfyingType - The type which must be satisfied (e.g. a parameter type)
  • \ReflectionType $satisfiedType - The type which must satisfy the other (e.g. a return type)

Method: DNF::getFromVarType

function getFromVarType(\ReflectionParameter|\ReflectionProperty $parameter) : \donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface|null

Helper to quickly get a DNF representation of a (ReflectionParameter or ReflectionProperty)'s return type


Method: DNF::getFromReturnType

function getFromReturnType(\ReflectionFunctionAbstract $func) : \donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface|null

Helper to quickly get a DNF representation of a ReflectionFunctionAbstract (ReflectionFunction /
ReflectionMethod)'s return type

Class: donatj\PhpDnfSolver\Exceptions\InvalidArgumentException

Class: donatj\PhpDnfSolver\Exceptions\LogicException

Class: donatj\PhpDnfSolver\Types\AndClause

Represents an "and clause" - a set of types which must all be satisfied - e.g. "A&B&C"

Method: AndClause->__construct

function __construct(\donatj\PhpDnfSolver\SingularDnfTypeInterface ...$types)
Parameters:
  • \donatj\PhpDnfSolver\SingularDnfTypeInterface $types - The list of types to be satisfied

Method: AndClause->dnf

function dnf() : string

Return the canonical string representation of the DNF representation of this type


Method: AndClause->isSatisfiedBy

function isSatisfiedBy(\donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface $value) : bool

Tests if this type is satisfied by the given type

For example, if this type is "A|(B&C)" and the given type matches just "A", this method returns true.
If the given type matches just "B", this method returns false.
If the given type matches "B&C", this method returns true.


Method: AndClause->count

function count() : int

Returns the number of types in this DNF type


Method: AndClause->getTypes

function getTypes() : array
Returns:
  • \donatj\PhpDnfSolver\SingularDnfTypeInterface[]

Class: donatj\PhpDnfSolver\Types\BuiltInType

Represents a "built in type" as defined by ReflectionNamedType::isBuiltin()

This includes:

  • int
  • float
  • string
  • bool
  • array
  • iterable

Method: BuiltInType->__construct

function __construct(string $name)
Parameters:
  • string $name - The name of the built-in type

Method: BuiltInType->dnf

function dnf() : string

Return the canonical string representation of the DNF representation of this type


Method: BuiltInType->getTypeName

function getTypeName() : string

Returns the fully qualified type name of this type


Method: BuiltInType->isSatisfiedBy

function isSatisfiedBy(\donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface $value) : bool

Tests if this type is satisfied by the given type

For example, if this type is "A|(B&C)" and the given type matches just "A", this method returns true.
If the given type matches just "B", this method returns false.
If the given type matches "B&C", this method returns true.


Method: BuiltInType->count

function count() : int

Always 1 for singular types

Returns the number of types in this DNF type

Class: donatj\PhpDnfSolver\Types\CallableType

Represents a "callable" type

This includes:

  • callable
  • Closure
  • Invokable classes

Method: CallableType->dnf

function dnf() : string

Return the canonical string representation of the DNF representation of this type


Method: CallableType->isSatisfiedBy

function isSatisfiedBy(\donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface $value) : bool

Tests if this type is satisfied by the given type

For example, if this type is "A|(B&C)" and the given type matches just "A", this method returns true.
If the given type matches just "B", this method returns false.
If the given type matches "B&C", this method returns true.


Method: CallableType->getTypeName

function getTypeName() : string

Returns the fully qualified type name of this type


Method: CallableType->count

function count() : int

Always 1 for singular types

Returns the number of types in this DNF type

Class: donatj\PhpDnfSolver\Types\OrClause

Represents a "or" clause - a set of types where any one of them must be satisfied - e.g. "A|B|(C&D)"

Method: OrClause->__construct

function __construct(\donatj\PhpDnfSolver\Types\AndClause|\donatj\PhpDnfSolver\SingularDnfTypeInterface ...$types)
Parameters:
  • \donatj\PhpDnfSolver\Types\AndClause | \donatj\PhpDnfSolver\SingularDnfTypeInterface $types - The list of types to be satisfied. Does not accept an OrClause as DNF defines that as invalid.

Method: OrClause->dnf

function dnf() : string

Return the canonical string representation of the DNF representation of this type


Method: OrClause->isSatisfiedBy

function isSatisfiedBy(\donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface $value) : bool

Tests if this type is satisfied by the given type

For example, if this type is "A|(B&C)" and the given type matches just "A", this method returns true.
If the given type matches just "B", this method returns false.
If the given type matches "B&C", this method returns true.


Method: OrClause->count

function count() : int

Returns the number of types in this DNF type


Method: OrClause->getTypes

function getTypes() : array
Returns:
  • \donatj\PhpDnfSolver\Types\AndClause[]

Class: donatj\PhpDnfSolver\Types\UserDefinedType

Represents a "user defined type" - a class, interface, or trait, etc.

<?php
namespace donatj\PhpDnfSolver\Types;

class UserDefinedType {
	public $className;
}

Method: UserDefinedType->__construct

function __construct(string $className)
Parameters:
  • class-string $className - The name of the class, interface, or trait to be satisfied

Throws: \donatj\PhpDnfSolver\Exceptions\InvalidArgumentException - if the user defined type does not exist after triggering registered autoloaders


Method: UserDefinedType->dnf

function dnf() : string

Return the canonical string representation of the DNF representation of this type


Method: UserDefinedType->getTypeName

function getTypeName() : string

Returns the fully qualified type name of this type

Returns:
  • class-string

Method: UserDefinedType->isSatisfiedBy

function isSatisfiedBy(\donatj\PhpDnfSolver\SingularDnfTypeInterface|\donatj\PhpDnfSolver\NestedDnfTypeInterface $value) : bool

Tests if this type is satisfied by the given type

For example, if this type is "A|(B&C)" and the given type matches just "A", this method returns true.
If the given type matches just "B", this method returns false.
If the given type matches "B&C", this method returns true.


Method: UserDefinedType->count

function count() : int

Always 1 for singular types

Returns the number of types in this DNF type

About

PHP DNF (Disjunctive Normal Form) Signature Compatibility Solver

Topics

Resources

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages