Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
<?php
namespace Mautic\SmsBundle\Helper;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
use Mautic\CoreBundle\Helper\PhoneNumberHelper;
use Mautic\LeadBundle\Entity\LeadRepository;
use Mautic\SmsBundle\Exception\NumberNotFoundException;
class ContactHelper
{
public function __construct(
private LeadRepository $leadRepository,
private Connection $connection,
private PhoneNumberHelper $phoneNumberHelper,
) {
}
/**
* @param string $number
*
* @throws NumberNotFoundException
*/
public function findContactsByNumber($number): ArrayCollection
{
// Who knows what the number was originally formatted as so let's try a few
$searchForNumbers = $this->phoneNumberHelper->getFormattedNumberList($number);
$qb = $this->connection->createQueryBuilder();
$foundContacts = $qb->select('l.id')
->from(MAUTIC_TABLE_PREFIX.'leads', 'l')
->where(
$qb->expr()->or(
'l.mobile IN (:numbers)',
'l.phone IN (:numbers)'
)
)
->setParameter('numbers', $searchForNumbers, ArrayParameterType::STRING)
->executeQuery()
->fetchAllAssociative();
$ids = array_column($foundContacts, 'id');
if (0 === count($ids)) {
throw new NumberNotFoundException($number);
}
$collection = new ArrayCollection();
/** @var Lead[] $contacts */
$contacts = $this->leadRepository->getEntities(['ids' => $ids]);
foreach ($contacts as $contact) {
$collection->set($contact->getId(), $contact);
}
return $collection;
}
}

View File

@@ -0,0 +1,90 @@
<?php
namespace Mautic\SmsBundle\Helper;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Tracker\ContactTracker;
use Mautic\SmsBundle\Callback\CallbackInterface;
use Mautic\SmsBundle\Event\ReplyEvent;
use Mautic\SmsBundle\Exception\NumberNotFoundException;
use Mautic\SmsBundle\SmsEvents;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ReplyHelper
{
public function __construct(
private EventDispatcherInterface $eventDispatcher,
private LoggerInterface $logger,
private ContactTracker $contactTracker,
) {
}
/**
* @param string $pattern
* @param string $replyBody
*/
public static function matches($pattern, $replyBody): bool
{
return fnmatch($pattern, $replyBody, FNM_CASEFOLD);
}
/**
* @return Response
*
* @throws \Exception
*/
public function handleRequest(CallbackInterface $handler, Request $request)
{
// Set the default response
$response = new Response();
try {
$message = $handler->getMessage($request);
$contacts = $handler->getContacts($request);
$this->logger->debug(sprintf('SMS REPLY: Processing message "%s"', $message));
$this->logger->debug(sprintf('SMS REPLY: Found IDs %s', implode(',', $contacts->getKeys())));
foreach ($contacts as $contact) {
// Set the contact for campaign decisions
$this->contactTracker->setSystemContact($contact);
$eventResponse = $this->dispatchReplyEvent($contact, $message);
if ($eventResponse instanceof Response) {
// Last one wins
$response = $eventResponse;
}
}
} catch (BadRequestHttpException) {
return new Response('invalid request', 400);
} catch (NotFoundHttpException) {
return new Response('', 404);
} catch (NumberNotFoundException $exception) {
$this->logger->debug(
sprintf(
'%s: %s was not found. The message sent was "%s"',
$handler->getTransportName(),
$exception->getNumber(),
!empty($message) ? $message : 'unknown'
)
);
}
return $response;
}
private function dispatchReplyEvent(Lead $contact, string $message): ?Response
{
$replyEvent = new ReplyEvent($contact, trim($message));
$this->eventDispatcher->dispatch($replyEvent, SmsEvents::ON_REPLY);
return $replyEvent->getResponse();
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace Mautic\SmsBundle\Helper;
use Doctrine\ORM\EntityManager;
use libphonenumber\PhoneNumberFormat;
use Mautic\CoreBundle\Helper\CoreParametersHelper;
use Mautic\CoreBundle\Helper\PhoneNumberHelper;
use Mautic\LeadBundle\Entity\DoNotContact as DoNotContactEntity;
use Mautic\LeadBundle\Entity\LeadRepository;
use Mautic\LeadBundle\Model\DoNotContact;
use Mautic\LeadBundle\Model\LeadModel;
use Mautic\PluginBundle\Helper\IntegrationHelper;
use Mautic\SmsBundle\Form\Type\ConfigType;
use Mautic\SmsBundle\Model\SmsModel;
class SmsHelper
{
public function __construct(
protected EntityManager $em,
protected LeadModel $leadModel,
protected PhoneNumberHelper $phoneNumberHelper,
protected SmsModel $smsModel,
protected IntegrationHelper $integrationHelper,
private DoNotContact $doNotContact,
private CoreParametersHelper $coreParametersHelper,
) {
}
public function unsubscribe($number)
{
$number = $this->phoneNumberHelper->format($number, PhoneNumberFormat::E164);
/** @var LeadRepository $repo */
$repo = $this->em->getRepository(\Mautic\LeadBundle\Entity\Lead::class);
$args = [
'filter' => [
'force' => [
[
'column' => 'mobile',
'expr' => 'eq',
'value' => $number,
],
],
],
];
$leads = $repo->getEntities($args);
if (!empty($leads)) {
$lead = array_shift($leads);
} else {
// Try to find the lead based on the given phone number
$args['filter']['force'][0]['column'] = 'phone';
$leads = $repo->getEntities($args);
if (!empty($leads)) {
$lead = array_shift($leads);
} else {
return false;
}
}
return $this->doNotContact->addDncForContact($lead->getId(), 'sms', DoNotContactEntity::UNSUBSCRIBED);
}
public function getDisableTrackableUrls(): bool
{
return $this->coreParametersHelper->get(ConfigType::SMS_DISABLE_TRACKABLE_URLS);
}
}