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,232 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
use Mautic\CoreBundle\Entity\CacheInvalidateInterface;
use Mautic\CoreBundle\Entity\CommonEntity;
class Integration extends CommonEntity implements CacheInvalidateInterface
{
public const CACHE_NAMESPACE = 'IntegrationSettings';
/**
* @var int
*/
private $id;
/**
* @var Plugin|null
*/
private $plugin;
/**
* @var string
*/
private $name;
/**
* @var bool
*/
private $isPublished = false;
/**
* @var array
*/
private $supportedFeatures = [];
/**
* @var array
*/
private $apiKeys = [];
/**
* @var array
*/
private $featureSettings = [];
public static function loadMetadata(ORM\ClassMetadata $metadata): void
{
$builder = new ClassMetadataBuilder($metadata);
$builder->setTable('plugin_integration_settings')
->setCustomRepositoryClass(IntegrationRepository::class);
$builder->createField('id', 'integer')
->makePrimaryKey()
->generatedValue()
->build();
$builder->createManyToOne('plugin', 'Plugin')
->inversedBy('integrations')
->addJoinColumn('plugin_id', 'id', true, false, 'CASCADE')
->build();
$builder->addField('name', 'string');
$builder->createField('isPublished', 'boolean')
->columnName('is_published')
->build();
$builder->createField('supportedFeatures', 'array')
->columnName('supported_features')
->nullable()
->build();
$builder->createField('apiKeys', 'array')
->columnName('api_keys')
->build();
$builder->createField('featureSettings', 'array')
->columnName('feature_settings')
->nullable()
->build();
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return Plugin|null
*/
public function getPlugin()
{
return $this->plugin;
}
/**
* @param mixed $plugin
*
* @return Integration
*/
public function setPlugin($plugin)
{
$this->plugin = $plugin;
return $this;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @param mixed $name
*
* @return Integration
*/
public function setName($name)
{
$this->isChanged('name', $name);
$this->name = $name;
return $this;
}
/**
* @return mixed
*/
public function getIsPublished()
{
return $this->isPublished;
}
/**
* @param mixed $isPublished
*
* @return Integration
*/
public function setIsPublished($isPublished)
{
$this->isChanged('isPublished', $isPublished);
$this->isPublished = $isPublished;
return $this;
}
public function isPublished(): bool
{
return $this->isPublished;
}
/**
* @return mixed
*/
public function getSupportedFeatures()
{
return $this->supportedFeatures;
}
/**
* @param mixed $supportedFeatures
*
* @return Integration
*/
public function setSupportedFeatures($supportedFeatures)
{
$this->isChanged('supportedFeatures', $supportedFeatures);
$this->supportedFeatures = $supportedFeatures;
return $this;
}
/**
* @return mixed
*/
public function getApiKeys()
{
return $this->apiKeys;
}
/**
* @param mixed $apiKeys
*
* @return Integration
*/
public function setApiKeys($apiKeys)
{
$this->apiKeys = $apiKeys;
return $this;
}
/**
* @return mixed
*/
public function getFeatureSettings()
{
return $this->featureSettings;
}
/**
* @param mixed $featureSettings
*
* @return Integration
*/
public function setFeatureSettings($featureSettings)
{
$this->isChanged('featureSettings', $featureSettings);
$this->featureSettings = $featureSettings;
return $this;
}
public function getCacheNamespacesToDelete(): array
{
return [self::CACHE_NAMESPACE];
}
}

View File

@@ -0,0 +1,272 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
use Mautic\CoreBundle\Entity\CommonEntity;
class IntegrationEntity extends CommonEntity
{
/**
* @var int
*/
private $id;
/**
* @var string|null
*/
private $integration;
/**
* @var string|null
*/
private $integrationEntity;
/**
* @var string|null
*/
private $integrationEntityId;
/**
* @var \DateTimeInterface
*/
private $dateAdded;
/**
* @var \DateTimeInterface
*/
private $lastSyncDate;
/**
* @var string|null
*/
private $internalEntity;
/**
* @var int|null
*/
private $internalEntityId;
/**
* @var array
*/
private $internal;
public function __construct()
{
$this->internal = new ArrayCollection();
}
public static function loadMetadata(ORM\ClassMetadata $metadata): void
{
$builder = new ClassMetadataBuilder($metadata);
$builder->setTable('integration_entity')
->setCustomRepositoryClass(IntegrationEntityRepository::class)
->addIndex(['integration', 'integration_entity', 'integration_entity_id'], 'integration_external_entity')
->addIndex(['integration', 'internal_entity', 'internal_entity_id'], 'integration_internal_entity')
->addIndex(['integration', 'internal_entity', 'integration_entity'], 'integration_entity_match')
->addIndex(['integration', 'last_sync_date'], 'integration_last_sync_date')
->addIndex(['internal_entity_id', 'integration_entity_id', 'internal_entity', 'integration_entity'], 'internal_integration_entity');
$builder->addId();
$builder->addDateAdded();
$builder->addNullableField('integration', 'string');
$builder->createField('integrationEntity', 'string')
->columnName('integration_entity')
->nullable()
->build();
$builder->createField('integrationEntityId', 'string')
->columnName('integration_entity_id')
->nullable()
->build();
$builder->createField('internalEntity', 'string')
->columnName('internal_entity')
->nullable()
->build();
$builder->createField('internalEntityId', 'integer')
->columnName('internal_entity_id')
->nullable()
->build();
$builder->createField('lastSyncDate', 'datetime')
->columnName('last_sync_date')
->nullable()
->build();
$builder->addNullableField('internal', 'array');
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getIntegration()
{
return $this->integration;
}
/**
* @param string $integration
*
* @return IntegrationEntity
*/
public function setIntegration($integration)
{
$this->integration = $integration;
return $this;
}
/**
* @return string
*/
public function getIntegrationEntity()
{
return $this->integrationEntity;
}
/**
* @param string $integrationEntity
*
* @return IntegrationEntity
*/
public function setIntegrationEntity($integrationEntity)
{
$this->integrationEntity = $integrationEntity;
return $this;
}
/**
* @return string
*/
public function getIntegrationEntityId()
{
return $this->integrationEntityId;
}
/**
* @param string $integrationEntityId
*
* @return IntegrationEntity
*/
public function setIntegrationEntityId($integrationEntityId)
{
$this->integrationEntityId = $integrationEntityId;
return $this;
}
/**
* @return \DateTimeInterface
*/
public function getDateAdded()
{
return $this->dateAdded;
}
/**
* @param \DateTime $dateAdded
*
* @return IntegrationEntity
*/
public function setDateAdded($dateAdded)
{
$this->dateAdded = $dateAdded;
return $this;
}
/**
* @return \DateTimeInterface
*/
public function getLastSyncDate()
{
return $this->lastSyncDate;
}
/**
* @param \DateTime $lastSyncDate
*
* @return IntegrationEntity
*/
public function setLastSyncDate($lastSyncDate)
{
$this->lastSyncDate = $lastSyncDate;
return $this;
}
/**
* @return string
*/
public function getInternalEntity()
{
return $this->internalEntity;
}
/**
* @param string $internalEntity
*
* @return IntegrationEntity
*/
public function setInternalEntity($internalEntity)
{
$this->internalEntity = $internalEntity;
return $this;
}
/**
* @return int
*/
public function getInternalEntityId()
{
return $this->internalEntityId;
}
/**
* @param int $internalEntityId
*
* @return IntegrationEntity
*/
public function setInternalEntityId($internalEntityId)
{
$this->internalEntityId = $internalEntityId;
return $this;
}
/**
* @return array
*/
public function getInternal()
{
return $this->internal;
}
/**
* @param array $internal
*
* @return IntegrationEntity
*/
public function setInternal($internal)
{
$this->internal = $internal;
return $this;
}
}

View File

@@ -0,0 +1,539 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Query\Expression\CompositeExpression;
use Mautic\CoreBundle\Entity\CommonRepository;
/**
* @extends CommonRepository<IntegrationEntity>
*/
class IntegrationEntityRepository extends CommonRepository
{
/**
* @param array<int>|int|null $internalEntityIds
* @param mixed $startDate
* @param mixed $endDate
* @param bool $push
* @param int $start
* @param int $limit
* @param int|string|array<int|string>|null $integrationEntityIds
*/
public function getIntegrationsEntityId(
$integration,
$integrationEntity,
$internalEntity,
$internalEntityIds = null,
$startDate = null,
$endDate = null,
$push = false,
$start = 0,
$limit = 0,
$integrationEntityIds = null,
): array {
$q = $this->_em->getConnection()->createQueryBuilder()
->select('DISTINCT(i.integration_entity_id), i.id, i.internal_entity_id, i.integration_entity, i.internal_entity')
->from(MAUTIC_TABLE_PREFIX.'integration_entity', 'i');
$q->where('i.integration = :integration')
->andWhere('i.internal_entity = :internalEntity')
->setParameter('integration', $integration)
->setParameter('internalEntity', $internalEntity);
if ($integrationEntity) {
$q->andWhere('i.integration_entity = :integrationEntity')
->setParameter('integrationEntity', $integrationEntity);
}
if ('lead' === $internalEntity) {
$joinCondition = $q->expr()->and(
$q->expr()->eq('l.id', 'i.internal_entity_id')
);
if ($push) {
$joinCondition->with(
$q->expr()->gte('l.last_active', ':startDate')
);
$q->setParameter('startDate', $startDate);
}
$q->join('i', MAUTIC_TABLE_PREFIX.'leads', 'l', $joinCondition);
}
if ($internalEntityIds) {
if (is_array($internalEntityIds)) {
$q->andWhere('i.internal_entity_id in (:internalEntityIds)')
->setParameter('internalEntityIds', $internalEntityIds, ArrayParameterType::STRING);
} else {
$q->andWhere('i.internal_entity_id = :internalEntityId')
->setParameter('internalEntityId', $internalEntityIds);
}
}
if ($startDate and !$push) {
$q->andWhere('i.last_sync_date >= :startDate')
->setParameter('startDate', $startDate);
}
if ($endDate and !$push) {
$q->andWhere('i.last_sync_date <= :endDate')
->setParameter('endDate', $endDate);
}
if ($integrationEntityIds) {
if (is_array($integrationEntityIds)) {
$q->andWhere('i.integration_entity_id in (:integrationEntityIds)')
->setParameter('integrationEntityIds', $integrationEntityIds, ArrayParameterType::STRING);
} else {
$q->andWhere('i.integration_entity_id = :integrationEntityId')
->setParameter('integrationEntityId', $integrationEntityIds);
}
}
if ($start) {
$q->setFirstResult((int) $start);
}
if ($limit) {
$q->setMaxResults((int) $limit);
}
return $q->executeQuery()->fetchAllAssociative();
}
/**
* @return array
*/
public function getIntegrationEntity($integration, $integrationEntity, $internalEntity, $internalEntityId, $leadFields = null)
{
$q = $this->_em->getConnection()->createQueryBuilder()
->from(MAUTIC_TABLE_PREFIX.'integration_entity', 'i')
->join('i', MAUTIC_TABLE_PREFIX.'leads', 'l', 'l.id = i.internal_entity_id');
$q->select('i.integration_entity_id, i.integration_entity, i.id, i.internal_entity_id');
if ($leadFields) {
$q->addSelect($leadFields);
}
$q->where(
$q->expr()->and(
$q->expr()->eq('i.integration', ':integration'),
$q->expr()->eq('i.internal_entity', ':internalEntity'),
$q->expr()->eq('i.integration_entity', ':integrationEntity'),
$q->expr()->eq('i.internal_entity_id', (int) $internalEntityId)
)
)
->setParameter('integration', $integration)
->setParameter('internalEntity', $internalEntity)
->setParameter('integrationEntity', $integrationEntity)
->setMaxResults(1);
$results = $q->executeQuery()->fetchAllAssociative();
return ($results) ? $results[0] : null;
}
/**
* @return IntegrationEntity[]
*/
public function getIntegrationEntities($integration, $integrationEntity, $internalEntity, $internalEntityIds)
{
$q = $this->createQueryBuilder('i', 'i.internalEntityId');
$q->where(
$q->expr()->andX(
$q->expr()->eq('i.integration', ':integration'),
$q->expr()->eq('i.internalEntity', ':internalEntity'),
$q->expr()->eq('i.integrationEntity', ':integrationEntity'),
$q->expr()->in('i.internalEntityId', ':internalEntityIds')
)
)
->setParameter('integration', $integration)
->setParameter('internalEntity', $internalEntity)
->setParameter('integrationEntity', $integrationEntity)
->setParameter('internalEntityIds', $internalEntityIds);
return $q->getQuery()->getResult();
}
/**
* @param int $limit
* @param array|string $integrationEntity
* @param array $excludeIntegrationIds
*
* @return mixed[]
*/
public function findLeadsToUpdate(
$integration,
$internalEntity,
$leadFields,
$limit = 25,
$fromDate = null,
$toDate = null,
$integrationEntity = ['Contact', 'Lead'],
$excludeIntegrationIds = [],
): array {
if ('company' == $internalEntity) {
$joinTable = 'companies';
} else {
$joinTable = 'leads';
}
$q = $this->_em->getConnection()->createQueryBuilder()
->from(MAUTIC_TABLE_PREFIX.'integration_entity', 'i')
->join('i', MAUTIC_TABLE_PREFIX.$joinTable, 'l', 'l.id = i.internal_entity_id');
if (false === $limit) {
$q->select('count(i.integration_entity_id) as total');
if ($integrationEntity) {
$q->addSelect('i.integration_entity');
}
} else {
$q->select('i.integration_entity_id, i.integration_entity, i.id, i.internal_entity_id,'.$leadFields);
}
$q->where('i.integration = :integration');
if ($integrationEntity) {
if (!is_array($integrationEntity)) {
$integrationEntity = [$integrationEntity];
}
$sub = null;
foreach ($integrationEntity as $key => $entity) {
if (null === $sub) {
$sub = CompositeExpression::or($q->expr()->eq('i.integration_entity', ':entity'.$key));
$q->setParameter('entity'.$key, $entity);
continue;
}
$sub->with($q->expr()->eq('i.integration_entity', ':entity'.$key));
$q->setParameter('entity'.$key, $entity);
}
$q->andWhere($sub);
}
$q->andWhere('i.internal_entity = :internalEntity')
->setParameter('integration', $integration)
->setParameter('internalEntity', $internalEntity);
if (!empty($excludeIntegrationIds)) {
$q->andWhere(
$q->expr()->notIn(
'i.integration_entity_id',
array_map(
fn ($x): string => "'".$x."'",
$excludeIntegrationIds
)
)
);
}
$q->andWhere(
$q->expr()->and(
$q->expr()->isNotNull('i.integration_entity_id'),
$q->expr()->or(
$q->expr()->and(
$q->expr()->isNotNull('i.last_sync_date'),
$q->expr()->gt('l.date_modified', 'i.last_sync_date')
),
$q->expr()->and(
$q->expr()->isNull('i.last_sync_date'),
$q->expr()->isNotNull('l.date_modified'),
$q->expr()->gt('l.date_modified', 'l.date_added')
)
)
)
);
if ('lead' == $internalEntity) {
$q->andWhere(
$q->expr()->and($q->expr()->isNotNull('l.email')));
} else {
$q->andWhere(
$q->expr()->and($q->expr()->isNotNull('l.companyname')));
}
if ($fromDate) {
if ($toDate) {
$q->andWhere(
$q->expr()->comparison('l.date_modified', 'BETWEEN', ':dateFrom and :dateTo')
)
->setParameter('dateFrom', $fromDate)
->setParameter('dateTo', $toDate);
} else {
$q->andWhere(
$q->expr()->gte('l.date_modified', ':dateFrom')
)
->setParameter('dateFrom', $fromDate);
}
} elseif ($toDate) {
$q->andWhere(
$q->expr()->lte('l.date_modified', ':dateTo')
)
->setParameter('dateTo', $toDate);
}
// Group by email to prevent duplicates from affecting this
if (false === $limit and $integrationEntity) {
$q->groupBy('i.integration_entity')->having('total');
}
if ($limit) {
$q->setMaxResults($limit);
}
$results = $q->executeQuery()->fetchAllAssociative();
$leads = [];
if ($integrationEntity) {
foreach ($integrationEntity as $entity) {
$leads[$entity] = (false === $limit) ? 0 : [];
}
}
foreach ($results as $result) {
if ($integrationEntity) {
if (false === $limit) {
$leads[$result['integration_entity']] = (int) $result['total'];
} else {
$leads[$result['integration_entity']][$result['internal_entity_id']] = $result;
}
} else {
$leads[$result['internal_entity_id']] = $result['internal_entity_id'];
}
}
return $leads;
}
/**
* @param int $limit
*
* @return array|int
*/
public function findLeadsToCreate($integration, $leadFields, $limit = 25, $fromDate = null, $toDate = null, $internalEntity = 'lead')
{
if ('company' == $internalEntity) {
$joinTable = 'companies';
} else {
$joinTable = 'leads';
}
$q = $this->_em->getConnection()->createQueryBuilder()
->from(MAUTIC_TABLE_PREFIX.$joinTable, 'l');
if (false === $limit) {
$q->select('count(*) as total');
} else {
$q->select('l.id as internal_entity_id,'.$leadFields);
}
if ('company' == $internalEntity) {
$q->where('not exists (select null from '.MAUTIC_TABLE_PREFIX
.'integration_entity i where i.integration = :integration and i.internal_entity LIKE "'.$internalEntity.'%" and i.internal_entity_id = l.id)')
->setParameter('integration', $integration);
} else {
$q->where('l.date_identified is not null')
->andWhere(
'not exists (select null from '.MAUTIC_TABLE_PREFIX
.'integration_entity i where i.integration = :integration and i.internal_entity LIKE "'.$internalEntity.'%" and i.internal_entity_id = l.id)'
)
->setParameter('integration', $integration);
}
if ('company' == $internalEntity) {
$q->andWhere('l.companyname is not null');
} else {
$q->andWhere('l.email is not null');
}
if ($limit) {
$q->setMaxResults($limit);
}
if ($fromDate) {
if ($toDate) {
$q->andWhere(
$q->expr()->or(
$q->expr()->and(
$q->expr()->isNotNull('l.date_modified'),
$q->expr()->comparison('l.date_modified', 'BETWEEN', ':dateFrom and :dateTo')
),
$q->expr()->and(
$q->expr()->isNull('l.date_modified'),
$q->expr()->comparison('l.date_added', 'BETWEEN', ':dateFrom and :dateTo')
)
)
)
->setParameter('dateFrom', $fromDate)
->setParameter('dateTo', $toDate);
} else {
$q->andWhere(
$q->expr()->or(
$q->expr()->and(
$q->expr()->isNotNull('l.date_modified'),
$q->expr()->gte('l.date_modified', ':dateFrom')
),
$q->expr()->and(
$q->expr()->isNull('l.date_modified'),
$q->expr()->gte('l.date_added', ':dateFrom')
)
)
)
->setParameter('dateFrom', $fromDate);
}
} elseif ($toDate) {
$q->andWhere(
$q->expr()->or(
$q->expr()->and(
$q->expr()->isNotNull('l.date_modified'),
$q->expr()->lte('l.date_modified', ':dateTo')
),
$q->expr()->and(
$q->expr()->isNull('l.date_modified'),
$q->expr()->lte('l.date_added', ':dateTo')
)
)
)
->setParameter('dateTo', $toDate);
}
$results = $q->executeQuery()->fetchAllAssociative();
if (false === $limit) {
return (int) $results[0]['total'];
}
$leads = [];
foreach ($results as $result) {
$leads[$result['internal_entity_id']] = $result;
}
return $leads;
}
/**
* @return int
*/
public function getIntegrationEntityCount($leadId, $integration = null, $integrationEntity = null, $internalEntity = null)
{
return $this->getIntegrationEntityByLead($leadId, $integration, $integrationEntity, $internalEntity, false);
}
/**
* @param int|bool $limit
*
* @return array|int
*/
public function getIntegrationEntityByLead($leadId, $integration = null, $integrationEntity = null, $internalEntity = null, $limit = 100)
{
$q = $this->_em->getConnection()->createQueryBuilder()
->from(MAUTIC_TABLE_PREFIX.'integration_entity', 'i');
if (false === $limit) {
$q->select('count(*) as total');
} else {
$q->select('i.integration, i.integration_entity, i.integration_entity_id, i.date_added, i.last_sync_date, i.internal');
}
$q->where('i.internal not like \'%error%\' and i.integration_entity_id is not null');
$q->orderBy('i.last_sync_date', 'DESC');
if (empty($integration)) {
// get list of published integrations
$pq = $this->_em->getConnection()->createQueryBuilder()
->select('p.name')
->from(MAUTIC_TABLE_PREFIX.'plugin_integration_settings', 'p')
->where('p.is_published = 1');
$rows = $pq->executeQuery()->fetchAllAssociative();
$plugins = array_map(static fn ($i): string => "'{$i['name']}'", $rows);
if (count($plugins) > 0) {
$q->andWhere($q->expr()->in('i.integration', $plugins));
} else {
return [];
}
} else {
$q->andWhere($q->expr()->eq('i.integration', ':integration'));
$q->setParameter('integration', $integration);
}
$q->andWhere(
$q->expr()->and(
"i.internal_entity='lead'",
$q->expr()->eq('i.internal_entity_id', ':internalEntityId')
)
);
$q->setParameter('internalEntityId', $leadId);
if (!empty($internalEntity)) {
$q->andWhere($q->expr()->eq('i.internalEntity', ':internalEntity'));
$q->setParameter('internalEntity', $internalEntity);
}
if (!empty($integrationEntity)) {
$q->andWhere($q->expr()->eq('i.integrationEntity', ':integrationEntity'));
$q->setParameter('integrationEntity', $integrationEntity);
}
$results = $q->executeQuery()->fetchAllAssociative();
if (false === $limit && count($results) > 0) {
return (int) $results[0]['total'];
}
return $results;
}
public function markAsDeleted(array $integrationIds, $integration, $internalEntityType): void
{
$q = $this->_em->getConnection()->createQueryBuilder();
$q->update(MAUTIC_TABLE_PREFIX.'integration_entity')
->set('internal_entity', ':entity')
->where(
$q->expr()->and(
$q->expr()->eq('integration', ':integration'),
$q->expr()->in('integration_entity_id', array_map([$q->expr(), 'literal'], $integrationIds))
)
)
->setParameter('integration', $integration)
->setParameter('entity', $internalEntityType.'-deleted')
->executeStatement();
}
public function findLeadsToDelete($internalEntity, $leadId): void
{
$q = $this->_em->getConnection()->createQueryBuilder()
->delete(MAUTIC_TABLE_PREFIX.'integration_entity')
->from(MAUTIC_TABLE_PREFIX.'integration_entity');
$q->where('internal_entity_id = :leadId')
->andWhere($q->expr()->like('internal_entity', ':internalEntity'))
->setParameter('leadId', $leadId)
->setParameter('internalEntity', $internalEntity)
->executeStatement();
}
public function updateErrorLeads($internalEntity, $leadId): void
{
$q = $this->_em->getConnection()->createQueryBuilder()
->update(MAUTIC_TABLE_PREFIX.'integration_entity')
->set('internal_entity', ':lead')->setParameter('lead', 'lead');
$q->where('internal_entity_id = :leadId')
->andWhere($q->expr()->isNotNull('integration_entity_id'))
->andWhere($q->expr()->eq('internal_entity', ':internalEntity'))
->setParameter('leadId', $leadId)
->setParameter('internalEntity', $internalEntity)
->executeStatement();
$z = $this->_em->getConnection()->createQueryBuilder()
->delete(MAUTIC_TABLE_PREFIX.'integration_entity')
->from(MAUTIC_TABLE_PREFIX.'integration_entity');
$z->where('internal_entity_id = :leadId')
->andWhere($q->expr()->isNull('integration_entity_id'))
->andWhere($q->expr()->like('internal_entity', ':internalEntity'))
->setParameter('leadId', $leadId)
->setParameter('internalEntity', $internalEntity)
->executeStatement();
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Doctrine\ORM\Query;
use Mautic\CoreBundle\Cache\ResultCacheHelper;
use Mautic\CoreBundle\Cache\ResultCacheOptions;
use Mautic\CoreBundle\Entity\CommonRepository;
/**
* @extends CommonRepository<Integration>
*/
class IntegrationRepository extends CommonRepository
{
/**
* @return mixed[]
*/
public function getIntegrations(): array
{
$query = $this->createQueryBuilder('i')
->join('i.plugin', 'p')
->getQuery();
$this->enableCache($query);
$services = $query->getResult();
$results = [];
foreach ($services as $s) {
$results[$s->getName()] = $s;
}
return $results;
}
/**
* Get core (no plugin) integrations.
*
* @return mixed[]
*/
public function getCoreIntegrations(): array
{
$query = $this->createQueryBuilder('i')
->getQuery();
$this->enableCache($query);
$services = $query->getResult();
$results = [];
foreach ($services as $s) {
$results[$s->getName()] = $s;
}
return $results;
}
public function findOneByName(string $name): ?Integration
{
$query = $this->createQueryBuilder('i')
->where('i.name = :name')
->setParameter('name', $name)
->setMaxResults(1)
->getQuery();
$this->enableCache($query);
return $query->getOneOrNullResult();
}
private function enableCache(Query $query): void
{
ResultCacheHelper::enableOrmQueryCache($query, new ResultCacheOptions(Integration::CACHE_NAMESPACE));
}
}

View File

@@ -0,0 +1,272 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
use Mautic\CoreBundle\Entity\CacheInvalidateInterface;
use Mautic\CoreBundle\Entity\CommonEntity;
class Plugin extends CommonEntity implements CacheInvalidateInterface
{
public const DESCRIPTION_DELIMITER_REGEX = "/\R---\R/";
public const CACHE_NAMESPACE = 'Plugin';
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var string|null
*/
private $description;
/**
* @var string
*/
private $primaryDescription;
/**
* @var string
*/
private $secondaryDescription;
/**
* @var bool
*/
private $isMissing = false;
/**
* @var string
*/
private $bundle;
/**
* @var string|null
*/
private $version;
/**
* @var string|null
*/
private $author;
/**
* @var ArrayCollection<int, Integration>
*/
private $integrations;
public function __construct()
{
$this->integrations = new ArrayCollection();
}
public static function loadMetadata(ORM\ClassMetadata $metadata): void
{
$builder = new ClassMetadataBuilder($metadata);
$builder->setTable('plugins')
->setCustomRepositoryClass(PluginRepository::class)
->addUniqueConstraint(['bundle'], 'unique_bundle');
$builder->addIdColumns();
$builder->createField('isMissing', 'boolean')
->columnName('is_missing')
->build();
$builder->createField('bundle', 'string')
->length(50)
->build();
$builder->createField('version', 'string')
->nullable()
->build();
$builder->createField('author', 'string')
->nullable()
->build();
$builder->createOneToMany('integrations', 'Integration')
->setIndexBy('id')
->mappedBy('plugin')
->fetchExtraLazy()
->build();
}
public function __clone()
{
$this->id = null;
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name.
*
* @param string $name
*
* @return Plugin
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $bundle
*/
public function setBundle($bundle): void
{
$this->bundle = $bundle;
}
/**
* @return string
*/
public function getBundle()
{
return $this->bundle;
}
/**
* @return mixed
*/
public function getIntegrations()
{
return $this->integrations;
}
/**
* @return mixed
*/
public function getDescription()
{
return $this->description;
}
/**
* @param mixed $description
*/
public function setDescription($description): void
{
$this->description = $description;
$this->splitDescriptions();
}
/**
* @return string|null
*/
public function getPrimaryDescription()
{
return $this->primaryDescription ?: $this->description;
}
public function hasSecondaryDescription(): bool
{
return $this->description && preg_match(self::DESCRIPTION_DELIMITER_REGEX, $this->description) >= 1;
}
/**
* @return string|null
*/
public function getSecondaryDescription()
{
return $this->secondaryDescription;
}
/**
* @return mixed
*/
public function getVersion()
{
return $this->version;
}
/**
* @param mixed $version
*/
public function setVersion($version): void
{
$this->version = $version;
}
/**
* @return mixed
*/
public function getIsMissing()
{
return $this->isMissing;
}
/**
* @param mixed $isMissing
*/
public function setIsMissing($isMissing): void
{
$this->isMissing = $isMissing;
}
/**
* @return mixed
*/
public function getAuthor()
{
return $this->author;
}
/**
* @param mixed $author
*/
public function setAuthor($author): void
{
$this->author = $author;
}
/**
* Splits description into primary and secondary.
*/
public function splitDescriptions(): void
{
if ($this->hasSecondaryDescription()) {
$parts = preg_split(self::DESCRIPTION_DELIMITER_REGEX, $this->description);
$this->primaryDescription = trim($parts[0]);
$this->secondaryDescription = trim($parts[1]);
}
}
public function getCacheNamespacesToDelete(): array
{
return [
self::CACHE_NAMESPACE,
Integration::CACHE_NAMESPACE,
];
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace Mautic\PluginBundle\Entity;
use Mautic\CoreBundle\Entity\CommonRepository;
/**
* @extends CommonRepository<Plugin>
*/
class PluginRepository extends CommonRepository
{
/**
* Find an addon record by bundle name.
*
* @param string $bundle
*
* @return mixed
*
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function findByBundle($bundle)
{
$q = $this->createQueryBuilder($this->getTableAlias());
$q->where($q->expr()->eq('p.bundle', ':bundle'))
->setParameter('bundle', $bundle);
return $q->getQuery()->getOneOrNullResult();
}
public function getEntities(array $args = [])
{
$q = $this->_em->createQueryBuilder();
$q->select($this->getTableAlias())
->from(Plugin::class, $this->getTableAlias(), (!empty($args['index'])) ? $this->getTableAlias().'.'.$args['index'] : $this->getTableAlias().'.id');
$args['qb'] = $q;
$args['ignore_paginator'] = true;
return parent::getEntities($args);
}
protected function getDefaultOrder(): array
{
return [
['p.name', 'ASC'],
];
}
public function getTableAlias(): string
{
return 'p';
}
}