OpenXE/classes/Modules/Pipedrive/Scheduler/PipedrivePullPersonsTask.php

306 lines
10 KiB
PHP
Raw Normal View History

2021-05-21 08:49:41 +02:00
<?php
declare(strict_types=1);
namespace Xentral\Modules\Pipedrive\Scheduler;
use Xentral\Components\Database\Database;
use ArrayObject;
use Xentral\Components\Database\Exception\EscapingException;
use Xentral\Modules\Pipedrive\Exception\PipedriveConfigurationException;
use Xentral\Modules\Pipedrive\Exception\PipedriveEventException;
use Xentral\Modules\Pipedrive\Exception\PipedriveMetaException;
use Xentral\Modules\Pipedrive\Exception\PipedrivePersonServiceException;
use Xentral\Modules\Pipedrive\Gateway\PipedriveContactGateway;
use Xentral\Modules\Pipedrive\Service\PipedriveConfigurationService;
use Xentral\Modules\Pipedrive\Service\PipedriveEventService;
use Xentral\Modules\Pipedrive\Service\PipedriveMetaReaderService;
use Xentral\Modules\Pipedrive\Service\PipedriveMetaWriterService;
use Xentral\Modules\Pipedrive\Service\PipedrivePersonService;
final class PipedrivePullPersonsTask implements PipedriveSchedulerTaskInterface
{
/** @var PipedrivePersonService $contactService */
private $contactService;
/** @var Database $db */
private $db;
/** @var PipedriveMetaWriterService $metaWriterService */
private $metaWriterService;
/** @var PipedriveContactGateway $gateway */
private $gateway;
/** @var PipedriveConfigurationService $configuration */
private $configuration;
/** @var PipedriveEventService $eventService */
private $eventService;
/** @var PipedriveMetaReaderService $metaReaderService */
private $metaReaderService;
/**
* @param PipedrivePersonService $contactService
* @param Database $db
* @param PipedriveMetaWriterService $metaService
* @param PipedriveContactGateway $gateway
* @param PipedriveConfigurationService $configuration
* @param PipedriveEventService $eventService
* @param PipedriveMetaReaderService $metaReaderService
*/
public function __construct(
PipedrivePersonService $contactService,
Database $db,
PipedriveMetaWriterService $metaService,
PipedriveContactGateway $gateway,
PipedriveConfigurationService $configuration,
PipedriveEventService $eventService,
PipedriveMetaReaderService $metaReaderService
) {
$this->db = $db;
$this->contactService = $contactService;
$this->metaWriterService = $metaService;
$this->gateway = $gateway;
$this->configuration = $configuration;
$this->eventService = $eventService;
$this->metaReaderService = $metaReaderService;
}
/**
* @param array $option
* @param string|null $type
* @param bool $recursiveMode
*
* @throws EscapingException
* @throws PipedriveConfigurationException
* @throws PipedriveEventException
* @throws PipedriveMetaException
* @throws PipedrivePersonServiceException
*
* @return void
*/
public function execute(array $option = [], ?string $type = null, bool $recursiveMode = false): void
{
$settings = $this->configuration->getSettings();
if ($settings['pd_sync_addresses'] !== true) {
return;
}
$type = $type ?? 'pipedrive_recently_updated';
if (empty($recursiveMode) && $this->db->fetchValue(
'SELECT COUNT(id) FROM `pipedrive_contacts` WHERE `hidden` = 0'
) > 0) {
$type = $type === 'all' ? 'pipedrive_recently_updated' : $type;
}
$ret = $this->pull($type, $option);
if (!empty($ret['has_more'])) {
$this->execute($option, $type, true);
}
}
/**
* @return void
*/
public function cleanup(): void
{
}
/**
* @param string $type
* @param array $options
*
* @throws EscapingException
* @throws PipedriveConfigurationException
* @throws PipedriveEventException
* @throws PipedriveMetaException
* @throws PipedrivePersonServiceException
*
* @return array
*/
protected function pull(string $type = 'pipedrive_recently_updated', array $options = []): array
{
$response = $this->contactService->pullPersons($type, $options);
if ($response->getStatusCode() !== 200) {
return [];
}
$persons = $response->getData();
$pagination = $response->getPagination();
$metaFile = sprintf('%s.json', $type);
$metaOption = $this->metaReaderService->readFromFile($metaFile);
$hasMore = is_array($pagination) && array_key_exists(
'more_items_in_collection',
$pagination
) ? $pagination['more_items_in_collection'] : false;
$startOffset = 0;
if (empty($metaOption)) {
$timeOffset = '1970-01-01 23:59:59';
$this->metaWriterService->save($metaFile, ['timeOffset' => date('Y-m-d H:i:s')]);
} elseif (array_key_exists('has_more', $options) && $options['has_more'] === true) {
$timeOffset = $options['previous_timeOffset'] ?? '1970-01-01 23:59:59';
$startOffset += 100;
} else {
$timeOffset = $metaOption['timeOffset'];
}
if (is_array($persons) && count($persons) > 0) {
foreach ($persons as $contact) {
$contactData = $contact['data'];
$contactId = $contact['id'];
if ($this->gateway->getMappingByPipedriveId($contactId)) {
// UPDATE
$this->updateXTContact($contactData);
} else {
$this->addXTContact($contactData);
}
}
}
if (!empty($metaOption) && !array_key_exists('previous_timeOffset', $metaOption)) {
$this->metaWriterService->save($metaFile, ['timeOffset' => date('Y-m-d H:i:s')]);
}
return [
'has_more' => $hasMore,
'previous_timeOffset' => $timeOffset,
'startOffset' => $startOffset,
];
}
/**
* @param array $contact
*
* @throws PipedriveConfigurationException
* @throws PipedriveMetaException
* @throws EscapingException
* @throws PipedriveEventException
*
* @return void
*/
private function addXTContact(array $contact): void
{
$internalContact = $this->configuration->formatAddressByResponse($contact);
if (!$internalContact) {
return;
}
$paramValues = array_map(
function ($value) {
if (empty($value)) {
return "''";
}
return is_string($value) ? $this->db->escapeString($value) : $value;
},
array_values($internalContact)
);
$placeHolders = implode(',', array_fill(0, count($paramValues), '%s'));
$insertSql = sprintf(
'INSERT INTO `adresse` (%s) VALUES(%s)',
implode(',', array_keys($internalContact)),
vsprintf($placeHolders, $paramValues)
);
$this->db->perform($insertSql);
if ($addressId = $this->db->lastInsertId()) {
$this->db->perform(
'INSERT INTO `pipedrive_contacts`
(`pd_contact_id`, `created_at`, `address_id`) VALUES (:id, NOW(), :aid)',
['id' => (int)$contact['id'], 'aid' => $addressId]
);
$personName = !empty($internalContact['email'])? $internalContact['email'] : $internalContact['name'];
$eventMsg = sprintf(
'Neuen Kontakt (<a href="/index.php?module=adresse&action=edit&id=%d">%s</a>) hinzugef&uuml;gt.',
$addressId,
$personName
);
$this->eventService->add($eventMsg);
// ADD to group
$this->configuration->addContactToGroup($addressId);
}
}
/**
* @param array $contact
*
* @throws PipedriveConfigurationException
* @throws PipedriveEventException
*
* @return void
*/
private function updateXTContact(array $contact): void
{
$internalContact = $this->configuration->formatAddressByResponse($contact);
if (!$internalContact) {
return;
}
$excludeVars = ['lead', 'typ', 'sprache', 'waehrung', 'kundenfreigabe'];
foreach ($excludeVars as $excludeVar) {
unset($internalContact[$excludeVar]);
}
if ($hPdContact = $this->gateway->getMappingByPipedriveId($contact['id'])) {
$asPlaceHolders = array_map(
static function ($val) {
return vsprintf('%s=:%s', [$val, $val]);
},
array_keys($internalContact)
);
$placeHolders = implode(',', $asPlaceHolders);
$affected = $this->db->fetchAffected(
'UPDATE `adresse` SET ' . $placeHolders . ' WHERE `id` = ' . $hPdContact['address_id'],
$internalContact
);
if ($affected > 0) {
$personName = !empty($internalContact['email'])? $internalContact['email'] : $internalContact['name'];
$eventMsg = sprintf(
'Kontakt (<a href="/index.php?module=adresse&action=edit&id=%d">%s</a>) ge&auml;ndert.',
$hPdContact['address_id'],
$personName
);
$this->eventService->add($eventMsg);
}
}
}
/**
* @param ArrayObject $data
*
* @throws PipedriveConfigurationException
*
* @return void
*/
public function beforeScheduleAction(ArrayObject $data): void
{
if (empty($this->configuration->tryGetConfiguration('pipedrive_settings'))) {
return;
}
try {
$leadsFields = $this->configuration->matchSelectedAddressFreeField();
} catch (PipedriveConfigurationException $exception) {
return;
}
if (empty($leadsFields)) {
return;
}
}
/**
* @param ArrayObject $data
*
* @return void
*/
public function afterScheduleAction(ArrayObject $data): void
{
}
}