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,520 @@
<?php
namespace MauticPlugin\MauticClearbitBundle\Controller;
use Mautic\FormBundle\Controller\FormController;
use Mautic\LeadBundle\Entity\Company;
use Mautic\LeadBundle\Entity\Lead;
use MauticPlugin\MauticClearbitBundle\Form\Type\BatchLookupType;
use MauticPlugin\MauticClearbitBundle\Form\Type\LookupType;
use MauticPlugin\MauticClearbitBundle\Helper\LookupHelper;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class ClearbitController extends FormController
{
/**
* @param string $objectId
*
* @return JsonResponse
*
* @throws \InvalidArgumentException
*/
public function lookupPersonAction(Request $request, LookupHelper $lookupHelper, $objectId = '')
{
if ('POST' === $request->getMethod()) {
$data = $request->request->all()['clearbit_lookup'] ?? [];
$objectId = $data['objectId'];
}
/** @var \Mautic\LeadBundle\Model\LeadModel $model */
$model = $this->getModel('lead');
$lead = $model->getEntity($objectId);
if (!$this->security->hasEntityAccess(
'lead:leads:editown',
'lead:leads:editother',
$lead->getPermissionUser()
)
) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.forbidden'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
if ('GET' === $request->getMethod()) {
$route = $this->generateUrl(
'mautic_plugin_clearbit_action',
[
'objectAction' => 'lookupPerson',
]
);
return $this->delegateView(
[
'viewParameters' => [
'form' => $this->createForm(
LookupType::class,
[
'objectId' => $objectId,
],
[
'action' => $route,
]
)->createView(),
'lookupItem' => $lead->getEmail(),
],
'contentTemplate' => '@MauticClearbit/Clearbit/lookup.html.twig',
'passthroughVars' => [
'activeLink' => '#mautic_contact_index',
'mauticContent' => 'lead',
'route' => $route,
],
]
);
} else {
if ('POST' === $request->getMethod()) {
try {
$lookupHelper->lookupContact($lead, array_key_exists('notify', $data));
$this->addFlashMessage(
'mautic.lead.batch_leads_affected',
[
'%count%' => 1,
]
);
} catch (\Exception $ex) {
$this->addFlashMessage(
$ex->getMessage(),
[],
'error'
);
}
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
return new Response('Bad Request', 400);
}
/**
* @return JsonResponse
*
* @throws \InvalidArgumentException
*/
public function batchLookupPersonAction(Request $request, LookupHelper $lookupHelper)
{
/** @var \Mautic\LeadBundle\Model\LeadModel $model */
$model = $this->getModel('lead');
if ('GET' === $request->getMethod()) {
$data = $request->query->all()['clearbit_batch_lookup'] ?? [];
} else {
$data = $request->request->all()['clearbit_batch_lookup'] ?? [];
}
$entities = [];
if (array_key_exists('ids', $data)) {
$ids = $data['ids'];
if (!is_array($ids)) {
$ids = json_decode($ids, true);
}
if (is_array($ids) && count($ids)) {
$entities = $model->getEntities(
[
'filter' => [
'force' => [
[
'column' => 'l.id',
'expr' => 'in',
'value' => $ids,
],
],
],
'ignore_paginator' => true,
]
);
}
}
$lookupEmails = [];
if ($count = count($entities)) {
/** @var Lead $lead */
foreach ($entities as $lead) {
if ($this->security->hasEntityAccess(
'lead:leads:editown',
'lead:leads:editother',
$lead->getPermissionUser()
)
&& $lead->getEmail()
) {
$lookupEmails[$lead->getId()] = $lead->getEmail();
}
}
$count = count($lookupEmails);
}
if (0 === $count) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.empty'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
} else {
if ($count > 20) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.toomany'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
if ('GET' === $request->getMethod()) {
$route = $this->generateUrl(
'mautic_plugin_clearbit_action',
[
'objectAction' => 'batchLookupPerson',
]
);
return $this->delegateView(
[
'viewParameters' => [
'form' => $this->createForm(
BatchLookupType::class,
[],
[
'action' => $route,
]
)->createView(),
'lookupItems' => array_values($lookupEmails),
],
'contentTemplate' => '@MauticClearbit/Clearbit/batchLookup.html.twig',
'passthroughVars' => [
'activeLink' => '#mautic_contact_index',
'mauticContent' => 'leadBatch',
'route' => $route,
],
]
);
} else {
if ('POST' === $request->getMethod()) {
$notify = array_key_exists('notify', $data);
foreach ($lookupEmails as $id => $lookupEmail) {
if ($lead = $model->getEntity($id)) {
try {
$lookupHelper->lookupContact($lead, $notify);
} catch (\Exception $ex) {
$this->addFlashMessage(
$ex->getMessage(),
[],
'error'
);
--$count;
}
}
}
if ($count) {
$this->addFlashMessage(
'mautic.lead.batch_leads_affected',
[
'%count%' => $count,
]
);
}
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
return new Response('Bad Request', 400);
}
/***************** COMPANY ***********************/
/**
* @param string $objectId
*
* @return JsonResponse
*
* @throws \InvalidArgumentException
*/
public function lookupCompanyAction(Request $request, LookupHelper $lookupHelper, $objectId = '')
{
if ('POST' === $request->getMethod()) {
$data = $request->request->all()['clearbit_lookup'] ?? [];
$objectId = $data['objectId'];
}
/** @var \Mautic\LeadBundle\Model\CompanyModel $model */
$model = $this->getModel('lead.company');
/** @var Company $company */
$company = $model->getEntity($objectId);
if ('GET' === $request->getMethod()) {
$route = $this->generateUrl(
'mautic_plugin_clearbit_action',
[
'objectAction' => 'lookupCompany',
]
);
$website = $company->getFieldValue('companywebsite');
if (!$website) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.compempty'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
$parse = parse_url($website);
return $this->delegateView(
[
'viewParameters' => [
'form' => $this->createForm(
LookupType::class,
[
'objectId' => $objectId,
],
[
'action' => $route,
]
)->createView(),
'lookupItem' => $parse['host'],
],
'contentTemplate' => '@MauticClearbit/Clearbit/lookup.html.twig',
'passthroughVars' => [
'activeLink' => '#mautic_company_index',
'mauticContent' => 'company',
'route' => $route,
],
]
);
} else {
if ('POST' === $request->getMethod()) {
try {
$lookupHelper->lookupCompany($company, array_key_exists('notify', $data));
$this->addFlashMessage(
'mautic.company.batch_companies_affected',
[
'%count%' => 1,
]
);
} catch (\Exception $ex) {
$this->addFlashMessage(
$ex->getMessage(),
[],
'error'
);
}
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
return new Response('Bad Request', 400);
}
/**
* @return JsonResponse
*
* @throws \InvalidArgumentException
*/
public function batchLookupCompanyAction(Request $request, LookupHelper $lookupHelper)
{
/** @var \Mautic\LeadBundle\Model\CompanyModel $model */
$model = $this->getModel('lead.company');
if ('GET' === $request->getMethod()) {
$data = $request->query->all()['clearbit_batch_lookup'] ?? [];
} else {
$data = $request->request->all()['clearbit_batch_lookup'] ?? [];
}
$entities = [];
if (array_key_exists('ids', $data)) {
$ids = $data['ids'];
if (!is_array($ids)) {
$ids = json_decode($ids, true);
}
if (is_array($ids) && count($ids)) {
$entities = $model->getEntities(
[
'filter' => [
'force' => [
[
'column' => 'comp.id',
'expr' => 'in',
'value' => $ids,
],
],
],
'ignore_paginator' => true,
]
);
}
}
$lookupWebsites = [];
if ($count = count($entities)) {
/** @var Company $company */
foreach ($entities as $company) {
if ($company->getFieldValue('companywebsite')) {
$website = $company->getFieldValue('companywebsite');
$parse = parse_url($website);
if (!isset($parse['host'])) {
continue;
}
$lookupWebsites[$company->getId()] = $parse['host'];
}
}
$count = count($lookupWebsites);
}
if (0 === $count) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.compempty'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
} else {
if ($count > 20) {
$this->addFlashMessage(
$this->translator->trans('mautic.plugin.clearbit.comptoomany'),
[],
'error'
);
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
if ('GET' === $request->getMethod()) {
$route = $this->generateUrl(
'mautic_plugin_clearbit_action',
[
'objectAction' => 'batchLookupCompany',
]
);
return $this->delegateView(
[
'viewParameters' => [
'form' => $this->createForm(
BatchLookupType::class,
[],
[
'action' => $route,
]
)->createView(),
'lookupItems' => array_values($lookupWebsites),
],
'contentTemplate' => '@MauticClearbit/Clearbit/batchLookup.html.twig',
'passthroughVars' => [
'activeLink' => '#mautic_company_index',
'mauticContent' => 'companyBatch',
'route' => $route,
],
]
);
} else {
if ('POST' === $request->getMethod()) {
$notify = array_key_exists('notify', $data);
foreach ($lookupWebsites as $id => $lookupWebsite) {
if ($company = $model->getEntity($id)) {
try {
$lookupHelper->lookupCompany($company, $notify);
} catch (\Exception $ex) {
$this->addFlashMessage(
$ex->getMessage(),
[],
'error'
);
--$count;
}
}
}
if ($count) {
$this->addFlashMessage(
'mautic.company.batch_companies_affected',
[
'%count%' => $count,
]
);
}
return new JsonResponse(
[
'closeModal' => true,
'flashes' => $this->getFlashContent(),
]
);
}
}
return new Response('Bad Request', 400);
}
}

View File

@@ -0,0 +1,283 @@
<?php
namespace MauticPlugin\MauticClearbitBundle\Controller;
use Mautic\FormBundle\Controller\FormController;
use Mautic\LeadBundle\Entity\Company;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\UserBundle\Entity\User;
use Mautic\UserBundle\Model\UserModel;
use MauticPlugin\MauticClearbitBundle\Helper\LookupHelper;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class PublicController extends FormController
{
/**
* Write a notification.
*
* @param string $message Message of the notification
* @param string $header Header for message
* @param string $iconClass CSS class for the icon (e.g. ri-eye-line)
* @param User|null $user User object; defaults to current user
*/
public function addNewNotification($message, $header, $iconClass, User $user): void
{
/** @var \Mautic\CoreBundle\Model\NotificationModel $notificationModel */
$notificationModel = $this->getModel('core.notification');
$notificationModel->addNotification($message, 'FullContact', false, $header, $iconClass, null, $user);
}
/**
* @throws \InvalidArgumentException
*/
public function callbackAction(Request $request, LoggerInterface $mauticLogger, LookupHelper $lookupHelper): Response
{
if (!$request->request->has('body') || !$request->request->has('id')
|| !$request->request->has('type')
|| !$request->request->has('status')
|| 200 !== $request->request->get('status')
) {
$mauticLogger->log('error', 'ERROR on Clearbit callback: Malformed request variables: '.json_encode($request->request->all(), JSON_PRETTY_PRINT));
return new Response('ERROR');
}
/** @var array $result */
$result = $request->request->all()['body'] ?? [];
$oid = $request->request->get('id');
$validatedRequest = $lookupHelper->validateRequest($oid, $request->request->get('type'));
if (!$validatedRequest || !is_array($result)) {
$mauticLogger->log('error', 'ERROR on Clearbit callback: Wrong body or id in request: id='.$oid.' body='.json_encode($result, JSON_PRETTY_PRINT));
return new Response('ERROR');
}
$notify = $validatedRequest['notify'];
try {
if ('person' === $request->request->get('type')) {
/** @var \Mautic\LeadBundle\Model\LeadModel $model */
$model = $this->getModel('lead');
/** @var Lead $lead */
$lead = $validatedRequest['entity'];
$currFields = $lead->getFields(true);
$mauticLogger->log('debug', 'CURRFIELDS: '.var_export($currFields, true));
$loc = [];
if (array_key_exists('geo', $result)) {
$loc = $result['geo'];
}
$data = [];
foreach ([
'facebook' => 'http://www.facebook.com/',
'linkedin' => 'http://www.linkedin.com/',
'twitter' => 'http://www.twitter.com/',
] as $p => $u) {
foreach ($result as $type => $socialProfile) {
if ($type === $p && empty($currFields[$p]['value'])) {
$data[$p] = (array_key_exists('handle', $socialProfile) && $socialProfile['handle']) ? $u.$socialProfile['handle'] : '';
break;
}
}
}
if (array_key_exists('name', $result)
&& array_key_exists(
'familyName',
$result['name']
)
&& empty($currFields['lastname']['value'])
) {
$data['lastname'] = $result['name']['familyName'];
}
if (array_key_exists('name', $result)
&& array_key_exists(
'givenName',
$result['name']
)
&& empty($currFields['firstname']['value'])
) {
$data['firstname'] = $result['name']['givenName'];
}
if (array_key_exists('site', $result) && empty($currFields['website']['value'])) {
$data['website'] = $result['site'];
}
if (array_key_exists('employment', $result)
&& array_key_exists(
'name',
$result['employment']
)
&& empty($currFields['company']['value'])
) {
$data['company'] = $result['employment']['name'];
}
if (array_key_exists('employment', $result)
&& array_key_exists(
'title',
$result['employment']
)
&& empty($currFields['position']['value'])
) {
$data['position'] = $result['employment']['title'];
}
if (array_key_exists('city', $loc) && empty($currFields['city']['value'])) {
$data['city'] = $loc['city'];
}
if (array_key_exists('state', $loc) && empty($currFields['state']['value'])) {
$data['state'] = $loc['state'];
}
if (array_key_exists('country', $loc) && empty($currFields['country']['value'])) {
$data['country'] = $loc['country'];
}
$mauticLogger->log('debug', 'SETTING FIELDS: '.print_r($data, true));
// Unset the nonce so that it's not used again
$socialCache = $lead->getSocialCache();
unset($socialCache['clearbit']['nonce']);
$lead->setSocialCache($socialCache);
$model->setFieldValues($lead, $data);
$model->saveEntity($lead);
if ($notify && (!isset($lead->imported) || !$lead->imported)) {
/** @var UserModel $userModel */
$userModel = $this->getModel('user');
if ($user = $userModel->getEntity($notify)) {
$this->addNewNotification(
sprintf($this->translator->trans('mautic.plugin.clearbit.contact_retrieved'), $lead->getEmail()),
'Clearbit Plugin',
'ri-search-line',
$user
);
}
}
} else {
/****************** COMPANY STUFF *********************/
if ('company' === $request->request->get('type')) {
/** @var \Mautic\LeadBundle\Model\CompanyModel $model */
$model = $this->getModel('lead.company');
/** @var Company $company */
$company = $validatedRequest['entity'];
$currFields = $company->getFields(true);
$loc = [];
if (array_key_exists('geo', $result)) {
$loc = $result['geo'];
}
$data = [];
if (array_key_exists('streetNumber', $loc)
&& array_key_exists(
'streetName',
$loc
)
&& empty($currFields['companyaddress1']['value'])
) {
$data['companyaddress1'] = $loc['streetNumber'].' '.$loc['streetName'];
}
if (array_key_exists('city', $loc) && empty($currFields['companycity']['value'])) {
$data['companycity'] = $loc['city'];
}
if (array_key_exists('metrics', $result)
&& array_key_exists(
'employees',
$result['metrics']
)
&& empty($currFields['companynumber_of_employees']['value'])
) {
$data['companynumber_of_employees'] = $result['metrics']['employees'];
}
if (array_key_exists('description', $result) && empty($currFields['companydescription']['value'])) {
$data['companydescription'] = $result['description'];
}
if (array_key_exists('phone', $result) && empty($currFields['companyphone']['value'])) {
$data['companyphone'] = $result['phone'];
}
if (array_key_exists('site', $result)
&& array_key_exists(
'emailAddresses',
$result['site']
)
&& count($result['site']['emailAddresses'])
&& empty($currFields['companyemail']['value'])
) {
$data['companyemail'] = $result['site']['emailAddresses'][0];
}
if (array_key_exists('country', $loc) && empty($currFields['companycountry']['value'])) {
$data['companycountry'] = $loc['country'];
}
if (array_key_exists('state', $loc) && empty($currFields['companystate']['value'])) {
$data['companystate'] = $loc['state'];
}
$mauticLogger->log('debug', 'SETTING FIELDS: '.print_r($data, true));
// Unset the nonce so that it's not used again
$socialCache = $company->getSocialCache();
unset($socialCache['clearbit']['nonce']);
$company->setSocialCache($socialCache);
$model->setFieldValues($company, $data);
$model->saveEntity($company);
if ($notify) {
/** @var UserModel $userModel */
$userModel = $this->getModel('user');
if ($user = $userModel->getEntity($notify)) {
$this->addNewNotification(
sprintf($this->translator->trans('mautic.plugin.clearbit.company_retrieved'), $company->getName()),
'Clearbit Plugin',
'ri-search-line',
$user
);
}
}
}
}
} catch (\Exception $ex) {
$mauticLogger->log('error', 'ERROR on Clearbit callback: '.$ex->getMessage());
try {
if ($notify) {
/** @var UserModel $userModel */
$userModel = $this->getModel('user');
if ($user = $userModel->getEntity($notify)) {
$this->addNewNotification(
sprintf(
$this->translator->trans('mautic.plugin.clearbit.unable'),
$ex->getMessage()
),
'Clearbit Plugin',
'ri-error-warning-line',
$user
);
}
}
} catch (\Exception $ex2) {
$mauticLogger->log('error', 'Clearbit: '.$ex2->getMessage());
}
}
return new Response('OK');
}
}