<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Routing\Loader;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Loader\LoaderResolverInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Routing\Annotation\Route as RouteAnnotation;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* AnnotationClassLoader loads routing information from a PHP class and its methods.
*
* You need to define an implementation for the configureRoute() method. Most of the
* time, this method should define some PHP callable to be called for the route
* (a controller in MVC speak).
*
* The @Route annotation can be set on the class (for global parameters),
* and on each method.
*
* The @Route annotation main value is the route path. The annotation also
* recognizes several parameters: requirements, options, defaults, schemes,
* methods, host, and name. The name parameter is mandatory.
* Here is an example of how you should be able to use it:
* /**
* * @Route("/Blog")
* * /
* class Blog
* {
* /**
* * @Route("/", name="blog_index")
* * /
* public function index()
* {
* }
* /**
* * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"})
* * /
* public function show()
* {
* }
* }
*
* On PHP 8, the annotation class can be used as an attribute as well:
* #[Route('/Blog')]
* class Blog
* {
* #[Route('/', name: 'blog_index')]
* public function index()
* {
* }
* #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])]
* public function show()
* {
* }
* }
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Alexander M. Turek <me@derrabus.de>
*/
abstract class AnnotationClassLoader implements LoaderInterface
{
protected $reader;
protected $env;
/**
* @var string
*/
protected $routeAnnotationClass = RouteAnnotation::class;
/**
* @var int
*/
protected $defaultRouteIndex = 0;
public function __construct(Reader $reader = null, string $env = null)
{
$this->reader = $reader;
$this->env = $env;
}
/**
* Sets the annotation class to read route properties from.
*/
public function setRouteAnnotationClass(string $class)
{
$this->routeAnnotationClass = $class;
}
/**
* Loads from annotations from a class.
*
* @throws \InvalidArgumentException When route can't be parsed
*/
public function load(mixed $class, string $type = null): RouteCollection
{
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
}
$class = new \ReflectionClass($class);
if ($class->isAbstract()) {
throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName()));
}
$globals = $this->getGlobals($class);
$collection = new RouteCollection();
$collection->addResource(new FileResource($class->getFileName()));
if ($globals['env'] && $this->env !== $globals['env']) {
return $collection;
}
foreach ($class->getMethods() as $method) {
$this->defaultRouteIndex = 0;
foreach ($this->getAnnotations($method) as $annot) {
$this->addRoute($collection, $annot, $globals, $class, $method);
}
}
if (0 === $collection->count() && $class->hasMethod('__invoke')) {
$globals = $this->resetGlobals();
foreach ($this->getAnnotations($class) as $annot) {
$this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke'));
}
}
return $collection;
}
/**
* @param RouteAnnotation $annot or an object that exposes a similar interface
*/
protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method)
{
if ($annot->getEnv() && $annot->getEnv() !== $this->env) {
return;
}
$name = $annot->getName();
if (null === $name) {
$name = $this->getDefaultRouteName($class, $method);
}
$name = $globals['name'].$name;
$requirements = $annot->getRequirements();
foreach ($requirements as $placeholder => $requirement) {
if (\is_int($placeholder)) {
throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()));
}
}
$defaults = array_replace($globals['defaults'], $annot->getDefaults());
$requirements = array_replace($globals['requirements'], $requirements);
$options = array_replace($globals['options'], $annot->getOptions());
$schemes = array_merge($globals['schemes'], $annot->getSchemes());
$methods = array_merge($globals['methods'], $annot->getMethods());
$host = $annot->getHost();
if (null === $host) {
$host = $globals['host'];
}
$condition = $annot->getCondition() ?? $globals['condition'];
$priority = $annot->getPriority() ?? $globals['priority'];
$path = $annot->getLocalizedPaths() ?: $annot->getPath();
$prefix = $globals['localized_paths'] ?: $globals['path'];
$paths = [];
if (\is_array($path)) {
if (!\is_array($prefix)) {
foreach ($path as $locale => $localePath) {
$paths[$locale] = $prefix.$localePath;
}
} elseif ($missing = array_diff_key($prefix, $path)) {
throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing))));
} else {
foreach ($path as $locale => $localePath) {
if (!isset($prefix[$locale])) {
throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name));
}
$paths[$locale] = $prefix[$locale].$localePath;
}
}
} elseif (\is_array($prefix)) {
foreach ($prefix as $locale => $localePrefix) {
$paths[$locale] = $localePrefix.$path;
}
} else {
$paths[] = $prefix.$path;
}
foreach ($method->getParameters() as $param) {
if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) {
continue;
}
foreach ($paths as $locale => $path) {
if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) {
$defaults[$param->name] = $param->getDefaultValue();
break;
}
}
}
foreach ($paths as $locale => $path) {
$route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
$this->configureRoute($route, $class, $method, $annot);
if (0 !== $locale) {
$route->setDefault('_locale', $locale);
$route->setRequirement('_locale', preg_quote($locale));
$route->setDefault('_canonical_route', $name);
$collection->add($name.'.'.$locale, $route, $priority);
} else {
$collection->add($name, $route, $priority);
}
}
}
/**
* {@inheritdoc}
*/
public function supports(mixed $resource, string $type = null): bool
{
return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type);
}
/**
* {@inheritdoc}
*/
public function setResolver(LoaderResolverInterface $resolver)
{
}
/**
* {@inheritdoc}
*/
public function getResolver(): LoaderResolverInterface
{
}
/**
* Gets the default route name for a class method.
*
* @return string
*/
protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
{
$name = str_replace('\\', '_', $class->name).'_'.$method->name;
$name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name);
if ($this->defaultRouteIndex > 0) {
$name .= '_'.$this->defaultRouteIndex;
}
++$this->defaultRouteIndex;
return $name;
}
protected function getGlobals(\ReflectionClass $class)
{
$globals = $this->resetGlobals();
$annot = null;
if ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null) {
$annot = $attribute->newInstance();
}
if (!$annot && $this->reader) {
$annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass);
}
if ($annot) {
if (null !== $annot->getName()) {
$globals['name'] = $annot->getName();
}
if (null !== $annot->getPath()) {
$globals['path'] = $annot->getPath();
}
$globals['localized_paths'] = $annot->getLocalizedPaths();
if (null !== $annot->getRequirements()) {
$globals['requirements'] = $annot->getRequirements();
}
if (null !== $annot->getOptions()) {
$globals['options'] = $annot->getOptions();
}
if (null !== $annot->getDefaults()) {
$globals['defaults'] = $annot->getDefaults();
}
if (null !== $annot->getSchemes()) {
$globals['schemes'] = $annot->getSchemes();
}
if (null !== $annot->getMethods()) {
$globals['methods'] = $annot->getMethods();
}
if (null !== $annot->getHost()) {
$globals['host'] = $annot->getHost();
}
if (null !== $annot->getCondition()) {
$globals['condition'] = $annot->getCondition();
}
$globals['priority'] = $annot->getPriority() ?? 0;
$globals['env'] = $annot->getEnv();
foreach ($globals['requirements'] as $placeholder => $requirement) {
if (\is_int($placeholder)) {
throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()));
}
}
}
return $globals;
}
private function resetGlobals(): array
{
return [
'path' => null,
'localized_paths' => [],
'requirements' => [],
'options' => [],
'defaults' => [],
'schemes' => [],
'methods' => [],
'host' => '',
'condition' => '',
'name' => '',
'priority' => 0,
'env' => null,
];
}
protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition)
{
return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
}
abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot);
/**
* @param \ReflectionClass|\ReflectionMethod $reflection
*
* @return iterable<int, RouteAnnotation>
*/
private function getAnnotations(object $reflection): iterable
{
foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
yield $attribute->newInstance();
}
if (!$this->reader) {
return;
}
$anntotations = $reflection instanceof \ReflectionClass
? $this->reader->getClassAnnotations($reflection)
: $this->reader->getMethodAnnotations($reflection);
foreach ($anntotations as $annotation) {
if ($annotation instanceof $this->routeAnnotationClass) {
yield $annotation;
}
}
}
}
At NFC Pay, we strive to provide a seamless and satisfactory experience with our services. This Refund Policy outlines the circumstances under which refunds may be issued for transactions made through our platform. Please read this policy carefully to understand your rights regarding refunds.
1. Eligibility for Refunds
Refunds may be considered under the following circumstances:
2. Non-Refundable Situations
Refunds will generally not be issued in the following situations:
3. Refund Process
To request a refund, please follow these steps:
4. Refund Exceptions
Certain transactions may be subject to specific terms and conditions, including non-refundable fees or charges. Please review the terms associated with each transaction carefully, as some fees may not be eligible for refunds.
5. Modifications to the Refund Policy
NFC Pay reserves the right to modify this Refund Policy at any time. Changes will be communicated through updates on our website and app, and the effective date will be updated accordingly. We encourage you to review this policy periodically to stay informed about our refund practices.
By using NFC Pay, you agree to this Refund Policy and understand the terms under which refunds may be issued. Our goal is to ensure a fair and transparent refund process, providing you with confidence and peace of mind when using our services.