Skip to content

Commit df15676

Browse files
committed
PhpMd
1 parent 77bf428 commit df15676

32 files changed

+927
-328
lines changed

config/PHPMD/rules.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
<!-- rules from the "naming" rule set -->
5252
<rule ref="rulesets/naming.xml/ShortVariable">
5353
<properties>
54-
<property name="exceptions" value="id,ip,cc"/>
54+
<property name="exceptions" value="id,ip,cc,io"/>
5555
</properties>
5656
</rule>
5757
<rule ref="rulesets/naming.xml/LongVariable">

config/services/providers.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ services:
22
PhpList\Core\Domain\Subscription\Service\Provider\SubscriberProvider:
33
autowire: true
44
autoconfigure: true
5+
6+
PhpList\Core\Domain\Messaging\Service\Provider\BounceActionProvider:
7+
autowire: true
8+
autoconfigure: true

config/services/services.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,15 @@ services:
9595
PhpList\Core\Domain\Messaging\Service\MessageParser:
9696
autowire: true
9797
autoconfigure: true
98+
99+
_instanceof:
100+
PhpList\Core\Domain\Messaging\Service\Handler\BounceActionHandlerInterface:
101+
tags:
102+
- { name: 'phplist.bounce_action_handler' }
103+
104+
PhpList\Core\Domain\Messaging\Service\Handler\:
105+
resource: '../../src/Domain/Messaging/Service/Handler/*Handler.php'
106+
107+
PhpList\Core\Domain\Messaging\Service\BounceActionResolver:
108+
arguments:
109+
- !tagged_iterator { tag: 'phplist.bounce_action_handler', default_index_method: 'supports' }

src/Domain/Common/SystemInfoCollector.php

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpList\Core\Domain\Common;
66

77
use Symfony\Component\HttpFoundation\RequestStack;
8+
use Symfony\Component\HttpFoundation\Request;
89

910
class SystemInfoCollector
1011
{
@@ -25,31 +26,20 @@ public function __construct(
2526

2627
/**
2728
* Return key=>value pairs (already sanitized for safe logging/HTML display).
28-
*
29+
* @SuppressWarnings(PHPMD.StaticAccess)
2930
* @return array<string,string>
3031
*/
3132
public function collect(): array
3233
{
33-
$request = $this->requestStack->getCurrentRequest();
34-
34+
$request = $this->requestStack->getCurrentRequest() ?? Request::createFromGlobals();
3535
$data = [];
36+
$headers = $request->headers;
3637

37-
if ($request) {
38-
$headers = $request->headers;
39-
40-
$data['HTTP_USER_AGENT'] = (string) $headers->get('User-Agent', '');
41-
$data['HTTP_REFERER'] = (string) $headers->get('Referer', '');
42-
$data['HTTP_X_FORWARDED_FOR'] = (string) $headers->get('X-Forwarded-For', '');
43-
$data['REQUEST_URI'] = $request->getRequestUri();
44-
$data['REMOTE_ADDR'] = $request->getClientIp() ?? '';
45-
} else {
46-
$server = $_SERVER;
47-
$data['HTTP_USER_AGENT'] = (string) ($server['HTTP_USER_AGENT'] ?? '');
48-
$data['HTTP_REFERER'] = (string) ($server['HTTP_REFERER'] ?? '');
49-
$data['HTTP_X_FORWARDED_FOR'] = (string) ($server['HTTP_X_FORWARDED_FOR'] ?? '');
50-
$data['REQUEST_URI'] = (string) ($server['REQUEST_URI'] ?? '');
51-
$data['REMOTE_ADDR'] = (string) ($server['REMOTE_ADDR'] ?? '');
52-
}
38+
$data['HTTP_USER_AGENT'] = (string) $headers->get('User-Agent', '');
39+
$data['HTTP_REFERER'] = (string) $headers->get('Referer', '');
40+
$data['HTTP_X_FORWARDED_FOR'] = (string) $headers->get('X-Forwarded-For', '');
41+
$data['REQUEST_URI'] = $request->getRequestUri();
42+
$data['REMOTE_ADDR'] = $request->getClientIp() ?? '';
5343

5444
$keys = $this->configuredKeys ?: $this->defaultKeys;
5545

src/Domain/Messaging/Command/ProcessBouncesCommand.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,31 @@ public function __construct(
3737
/** @var iterable<BounceProtocolProcessor> */
3838
private readonly iterable $protocolProcessors,
3939
private readonly AdvancedBounceRulesProcessor $advancedRulesProcessor,
40-
private readonly UnidentifiedBounceReprocessor $unidentifiedBounceReprocessor,
40+
private readonly UnidentifiedBounceReprocessor $unidentifiedReprocessor,
4141
private readonly ConsecutiveBounceHandler $consecutiveBounceHandler,
4242
) {
4343
parent::__construct();
4444
}
4545

4646
protected function execute(InputInterface $input, OutputInterface $output): int
4747
{
48-
$io = new SymfonyStyle($input, $output);
48+
$inputOutput = new SymfonyStyle($input, $output);
4949

5050
if (!function_exists('imap_open')) {
51-
$io->note('PHP IMAP extension not available. Falling back to Webklex IMAP where applicable.');
51+
$inputOutput->note('PHP IMAP extension not available. Falling back to Webklex IMAP where applicable.');
5252
}
5353

5454
$force = (bool)$input->getOption('force');
5555
$lock = $this->lockService->acquirePageLock('bounce_processor', $force);
5656

5757
if (!$lock) {
58-
$io->warning('Another bounce processing is already running. Aborting.');
58+
$inputOutput->warning('Another bounce processing is already running. Aborting.');
5959

6060
return Command::SUCCESS;
6161
}
6262

6363
try {
64-
$io->title('Processing bounces');
64+
$inputOutput->title('Processing bounces');
6565
$protocol = (string)$input->getOption('protocol');
6666

6767
$downloadReport = '';
@@ -75,23 +75,23 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7575
}
7676

7777
if ($processor === null) {
78-
$io->error('Unsupported protocol: '.$protocol);
78+
$inputOutput->error('Unsupported protocol: '.$protocol);
7979

8080
return Command::FAILURE;
8181
}
8282

83-
$downloadReport .= $processor->process($input, $io);
84-
$this->unidentifiedBounceReprocessor->process($io);
85-
$this->advancedRulesProcessor->process($io, (int)$input->getOption('rules-batch-size'));
86-
$this->consecutiveBounceHandler->handle($io);
83+
$downloadReport .= $processor->process($input, $inputOutput);
84+
$this->unidentifiedReprocessor->process($inputOutput);
85+
$this->advancedRulesProcessor->process($inputOutput, (int)$input->getOption('rules-batch-size'));
86+
$this->consecutiveBounceHandler->handle($inputOutput);
8787

8888
$this->logger->info('Bounce processing completed', ['downloadReport' => $downloadReport]);
89-
$io->success('Bounce processing completed.');
89+
$inputOutput->success('Bounce processing completed.');
9090

9191
return Command::SUCCESS;
9292
} catch (Exception $e) {
9393
$this->logger->error('Bounce processing failed', ['exception' => $e]);
94-
$io->error('Error: '.$e->getMessage());
94+
$inputOutput->error('Error: '.$e->getMessage());
9595

9696
return Command::FAILURE;
9797
} finally {

src/Domain/Messaging/Repository/UserMessageBounceRepository.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ public function getCountByMessageId(int $messageId): int
2828

2929
public function existsByMessageIdAndUserId(int $messageId, int $subscriberId): bool
3030
{
31-
$qb = $this->createQueryBuilder('umb')
31+
return (bool) $this->createQueryBuilder('umb')
3232
->select('1')
3333
->where('umb.messageId = :messageId')
3434
->andWhere('umb.userId = :userId')
3535
->setParameter('messageId', $messageId)
3636
->setParameter('userId', $subscriberId)
37-
->setMaxResults(1);
38-
39-
return (bool) $qb->getQuery()->getOneOrNullResult();
37+
->setMaxResults(1)
38+
->getQuery()
39+
->getOneOrNullResult();
4040
}
4141

4242
/**
@@ -66,7 +66,7 @@ public function getPaginatedWithJoinNoRelation(int $fromId, int $limit): array
6666
*/
6767
public function getUserMessageHistoryWithBounces(Subscriber $subscriber): array
6868
{
69-
$qb = $this->getEntityManager()
69+
return $this->getEntityManager()
7070
->createQueryBuilder()
7171
->select('um', 'umb', 'b')
7272
->from(UserMessage::class, 'um')
@@ -86,8 +86,8 @@ public function getUserMessageHistoryWithBounces(Subscriber $subscriber): array
8686
->andWhere('um.status = :status')
8787
->setParameter('userId', $subscriber->getId())
8888
->setParameter('status', 'sent')
89-
->orderBy('um.entered', 'DESC');
90-
91-
return $qb->getQuery()->getResult();
89+
->orderBy('um.entered', 'DESC')
90+
->getQuery()
91+
->getResult();
9292
}
9393
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpList\Core\Domain\Messaging\Service;
6+
7+
use PhpList\Core\Domain\Messaging\Service\Handler\BounceActionHandlerInterface;
8+
use RuntimeException;
9+
10+
class BounceActionResolver
11+
{
12+
/** @var BounceActionHandlerInterface[] */
13+
private array $handlers = [];
14+
15+
/** @var array<string, BounceActionHandlerInterface> */
16+
private array $cache = [];
17+
18+
/**
19+
* @param iterable<BounceActionHandlerInterface> $handlers
20+
*/
21+
public function __construct(iterable $handlers)
22+
{
23+
foreach ($handlers as $handler) {
24+
$this->handlers[] = $handler;
25+
}
26+
}
27+
28+
public function has(string $action): bool
29+
{
30+
return isset($this->cache[$action]) || $this->find($action) !== null;
31+
}
32+
33+
public function resolve(string $action): BounceActionHandlerInterface
34+
{
35+
if (isset($this->cache[$action])) {
36+
return $this->cache[$action];
37+
}
38+
39+
$handler = $this->find($action);
40+
if ($handler === null) {
41+
throw new RuntimeException(sprintf('No handler found for action "%s".', $action));
42+
}
43+
44+
return $this->cache[$action] = $handler;
45+
}
46+
47+
/** Convenience: resolve + execute */
48+
public function handle(string $action, array $context): void
49+
{
50+
$this->resolve($action)->handle($context);
51+
}
52+
53+
private function find(string $action): ?BounceActionHandlerInterface
54+
{
55+
foreach ($this->handlers as $handler) {
56+
if ($handler->supports($action)) {
57+
return $handler;
58+
}
59+
}
60+
return null;
61+
}
62+
}

src/Domain/Messaging/Service/BounceProcessingServiceInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88

99
interface BounceProcessingServiceInterface
1010
{
11-
public function processMailbox(SymfonyStyle $io, string $mailbox, int $max, bool $testMode): string;
11+
public function processMailbox(SymfonyStyle $inputOutput, string $mailbox, int $max, bool $testMode): string;
1212
}

0 commit comments

Comments
 (0)