The Rise of Contactless Payments:...
In recent years, contactless payments have surged in popularity, driven...
<?php declare(strict_types=1);
/*
* This file is part of sebastian/code-unit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\CodeUnit;
use function array_keys;
use function array_merge;
use function array_unique;
use function array_values;
use function class_exists;
use function explode;
use function function_exists;
use function interface_exists;
use function ksort;
use function method_exists;
use function sort;
use function sprintf;
use function str_replace;
use function strpos;
use function trait_exists;
use ReflectionClass;
use ReflectionFunction;
use ReflectionMethod;
final class Mapper
{
/**
* @psalm-return array<string,list<int>>
*/
public function codeUnitsToSourceLines(CodeUnitCollection $codeUnits): array
{
$result = [];
foreach ($codeUnits as $codeUnit) {
$sourceFileName = $codeUnit->sourceFileName();
if (!isset($result[$sourceFileName])) {
$result[$sourceFileName] = [];
}
$result[$sourceFileName] = array_merge($result[$sourceFileName], $codeUnit->sourceLines());
}
foreach (array_keys($result) as $sourceFileName) {
$result[$sourceFileName] = array_values(array_unique($result[$sourceFileName]));
sort($result[$sourceFileName]);
}
ksort($result);
return $result;
}
/**
* @throws InvalidCodeUnitException
* @throws ReflectionException
*/
public function stringToCodeUnits(string $unit): CodeUnitCollection
{
if (strpos($unit, '::') !== false) {
[$firstPart, $secondPart] = explode('::', $unit);
if (empty($firstPart) && $this->isUserDefinedFunction($secondPart)) {
return CodeUnitCollection::fromList(CodeUnit::forFunction($secondPart));
}
if ($this->isUserDefinedClass($firstPart)) {
if ($secondPart === '<public>') {
return $this->publicMethodsOfClass($firstPart);
}
if ($secondPart === '<!public>') {
return $this->protectedAndPrivateMethodsOfClass($firstPart);
}
if ($secondPart === '<protected>') {
return $this->protectedMethodsOfClass($firstPart);
}
if ($secondPart === '<!protected>') {
return $this->publicAndPrivateMethodsOfClass($firstPart);
}
if ($secondPart === '<private>') {
return $this->privateMethodsOfClass($firstPart);
}
if ($secondPart === '<!private>') {
return $this->publicAndProtectedMethodsOfClass($firstPart);
}
if ($this->isUserDefinedMethod($firstPart, $secondPart)) {
return CodeUnitCollection::fromList(CodeUnit::forClassMethod($firstPart, $secondPart));
}
}
if ($this->isUserDefinedInterface($firstPart)) {
return CodeUnitCollection::fromList(CodeUnit::forInterfaceMethod($firstPart, $secondPart));
}
if ($this->isUserDefinedTrait($firstPart)) {
return CodeUnitCollection::fromList(CodeUnit::forTraitMethod($firstPart, $secondPart));
}
} else {
if ($this->isUserDefinedClass($unit)) {
$units = [CodeUnit::forClass($unit)];
foreach ($this->reflectorForClass($unit)->getTraits() as $trait) {
if (!$trait->isUserDefined()) {
// @codeCoverageIgnoreStart
continue;
// @codeCoverageIgnoreEnd
}
$units[] = CodeUnit::forTrait($trait->getName());
}
return CodeUnitCollection::fromArray($units);
}
if ($this->isUserDefinedInterface($unit)) {
return CodeUnitCollection::fromList(CodeUnit::forInterface($unit));
}
if ($this->isUserDefinedTrait($unit)) {
return CodeUnitCollection::fromList(CodeUnit::forTrait($unit));
}
if ($this->isUserDefinedFunction($unit)) {
return CodeUnitCollection::fromList(CodeUnit::forFunction($unit));
}
$unit = str_replace('<extended>', '', $unit);
if ($this->isUserDefinedClass($unit)) {
return $this->classAndParentClassesAndTraits($unit);
}
}
throw new InvalidCodeUnitException(
sprintf(
'"%s" is not a valid code unit',
$unit
)
);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function publicMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function publicAndProtectedMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function publicAndPrivateMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function protectedMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function protectedAndPrivateMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function privateMethodsOfClass(string $className): CodeUnitCollection
{
return $this->methodsOfClass($className, ReflectionMethod::IS_PRIVATE);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function methodsOfClass(string $className, int $filter): CodeUnitCollection
{
$units = [];
foreach ($this->reflectorForClass($className)->getMethods($filter) as $method) {
if (!$method->isUserDefined()) {
continue;
}
$units[] = CodeUnit::forClassMethod($className, $method->getName());
}
return CodeUnitCollection::fromArray($units);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function classAndParentClassesAndTraits(string $className): CodeUnitCollection
{
$units = [CodeUnit::forClass($className)];
$reflector = $this->reflectorForClass($className);
foreach ($this->reflectorForClass($className)->getTraits() as $trait) {
if (!$trait->isUserDefined()) {
// @codeCoverageIgnoreStart
continue;
// @codeCoverageIgnoreEnd
}
$units[] = CodeUnit::forTrait($trait->getName());
}
while ($reflector = $reflector->getParentClass()) {
if (!$reflector->isUserDefined()) {
break;
}
$units[] = CodeUnit::forClass($reflector->getName());
foreach ($reflector->getTraits() as $trait) {
if (!$trait->isUserDefined()) {
// @codeCoverageIgnoreStart
continue;
// @codeCoverageIgnoreEnd
}
$units[] = CodeUnit::forTrait($trait->getName());
}
}
return CodeUnitCollection::fromArray($units);
}
/**
* @psalm-param class-string $className
*
* @throws ReflectionException
*/
private function reflectorForClass(string $className): ReflectionClass
{
try {
return new ReflectionClass($className);
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* @throws ReflectionException
*/
private function isUserDefinedFunction(string $functionName): bool
{
if (!function_exists($functionName)) {
return false;
}
try {
return (new ReflectionFunction($functionName))->isUserDefined();
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* @throws ReflectionException
*/
private function isUserDefinedClass(string $className): bool
{
if (!class_exists($className)) {
return false;
}
try {
return (new ReflectionClass($className))->isUserDefined();
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* @throws ReflectionException
*/
private function isUserDefinedInterface(string $interfaceName): bool
{
if (!interface_exists($interfaceName)) {
return false;
}
try {
return (new ReflectionClass($interfaceName))->isUserDefined();
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* @throws ReflectionException
*/
private function isUserDefinedTrait(string $traitName): bool
{
if (!trait_exists($traitName)) {
return false;
}
try {
return (new ReflectionClass($traitName))->isUserDefined();
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* @throws ReflectionException
*/
private function isUserDefinedMethod(string $className, string $methodName): bool
{
if (!class_exists($className)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
if (!method_exists($className, $methodName)) {
// @codeCoverageIgnoreStart
return false;
// @codeCoverageIgnoreEnd
}
try {
return (new ReflectionMethod($className, $methodName))->isUserDefined();
// @codeCoverageIgnoreStart
} catch (\ReflectionException $e) {
throw new ReflectionException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
}
Blog Section
Dive into our blog to explore the cutting-edge trends in digital payments and NFC technology. Stay updated on the innovations that are revolutionizing transactions, boosting security, and making payments quicker and more convenient. Learn how these advancements are shaping the future of financial interactions and driving the global transition towards a cashless world.
In recent years, contactless payments have surged in popularity, driven...
As digital transactions proliferate, ensuring robust payment security is more critical than ever. Two foundational...
Digital wallets have fundamentally transformed how we manage money, offering a streamlined, secure, and highly...