Newer
Older
<?php
/**
* Copyright Maarch since 2008 under licence GPLv3.
* See LICENCE.txt file at the root folder for more details.
* This file is part of Maarch software.
*/
/**
* @brief Contact Controller
* @author dev@maarch.org
*/
use AcknowledgementReceipt\models\AcknowledgementReceiptModel;
use Attachment\models\AttachmentModel;
use Contact\models\ContactCustomFieldListModel;

Florian Azizian
committed
use Contact\models\ContactGroupModel;
use Contact\models\ContactParameterModel;
use Entity\models\EntityModel;
use Group\controllers\PrivilegeController;
use History\controllers\HistoryController;
use MessageExchange\controllers\AnnuaryController;
use Parameter\models\ParameterModel;
use Resource\controllers\ResController;
use Resource\models\ResModel;
use Resource\models\ResourceContactModel;
use Slim\Http\Request;
use Slim\Http\Response;
use SrcCore\controllers\AutoCompleteController;
use SrcCore\models\CoreConfigModel;
Guillaume Heurtier
committed
use SrcCore\models\DatabaseModel;
use User\models\UserModel;
const MAPPING_FIELDS = [
'civility' => 'civility',
'firstname' => 'firstname',
'lastname' => 'lastname',
'company' => 'company',
'department' => 'department',
'function' => 'function',
'addressNumber' => 'address_number',
'addressStreet' => 'address_street',
'addressAdditional1' => 'address_additional1',
'addressAdditional2' => 'address_additional2',
'addressPostcode' => 'address_postcode',
'addressTown' => 'address_town',
'addressCountry' => 'address_country',
'email' => 'email',
'phone' => 'phone',
'notes' => 'notes'
];
public function get(Request $request, Response $response)
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
$queryParams = $request->getQueryParams();
$queryParams['offset'] = (empty($queryParams['offset']) || !is_numeric($queryParams['offset']) ? 0 : (int)$queryParams['offset']);
$queryParams['limit'] = (empty($queryParams['limit']) || !is_numeric($queryParams['limit']) ? 25 : (int)$queryParams['limit']);
$order = !in_array($queryParams['order'], ['asc', 'desc']) ? '' : $queryParams['order'];
$orderBy = !in_array($queryParams['orderBy'], ['firstname', 'lastname', 'company']) ? ['id'] : ["{$queryParams['orderBy']} {$order}", 'id'];
if (!empty($queryParams['search'])) {
$fields = ['firstname', 'lastname', 'company', 'address_number', 'address_street', 'address_additional1', 'address_additional2', 'address_postcode', 'address_town', 'address_country'];
$fieldsNumber = count($fields);
$fields = AutoCompleteController::getUnsensitiveFieldsForRequest(['fields' => $fields]);
$requestData = AutoCompleteController::getDataForRequest([
'search' => $queryParams['search'],
'fields' => $fields,
'where' => [],
'data' => [],
'fieldsNumber' => $fieldsNumber
]);
}
$contacts = ContactModel::get([
'select' => [
'id', 'firstname', 'lastname', 'company', 'address_number as "addressNumber"', 'address_street as "addressStreet"',
'address_additional1 as "addressAdditional1"', 'address_additional2 as "addressAdditional2"', 'address_postcode as "addressPostcode"',
'address_town as "addressTown"', 'address_country as "addressCountry"', 'enabled', 'count(1) OVER()'
],
'where' => $requestData['where'] ?? null,
'data' => $requestData['data'] ?? null,
'offset' => $queryParams['offset'],
'limit' => $queryParams['limit']
]);
if (empty($contacts)) {
return $response->withJson(['contacts' => $contacts, 'count' => $count]);
}
$contactIds = array_column($contacts, 'id');
$contactsUsed = ContactController::isContactUsed(['ids' => $contactIds]);
foreach ($contacts as $key => $contact) {
unset($contacts[$key]['count']);
$filling = ContactController::getFillingRate(['contactId' => $contact['id']]);
$contacts[$key]['isUsed'] = $contactsUsed[$contact['id']];
$contacts[$key]['filling'] = $filling;
if ($queryParams['orderBy'] == 'filling') {
usort($contacts, function ($a, $b) {
return $a['filling']['rate'] <=> $b['filling']['rate'];
});
if ($queryParams['order'] == 'desc') {
$contacts = array_reverse($contacts);
}
}
return $response->withJson(['contacts' => $contacts, 'count' => $count]);
public function create(Request $request, Response $response)
{
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'create_contacts', 'userId' => $GLOBALS['id']])
&& !PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
$control = ContactController::controlContact(['body' => $body]);
if (!empty($control['errors'])) {
return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
if (!empty($body['email'])) {
$contact = ContactModel::get(['select' => ['id'], 'where' => ['email = ?'], 'data' => [$body['email']]]);
if (!empty($contact[0]['id'])) {
return $response->withJson(['id' => $contact[0]['id']]);
}
if (!empty($body['communicationMeans'])) {
if (filter_var($body['communicationMeans'], FILTER_VALIDATE_EMAIL)) {
$body['communicationMeans'] = ['email' => $body['communicationMeans']];
} elseif (filter_var($body['communicationMeans'], FILTER_VALIDATE_URL)) {
$body['communicationMeans'] = ['url' => $body['communicationMeans']];
} else {
return $response->withStatus(400)->withJson(['errors' => _COMMUNICATION_MEANS_VALIDATOR]);
$annuaryReturn = ContactController::addContactToM2MAnnuary(['body' => $body]);
$body = $annuaryReturn['body'];
if (!empty($body['externalId']) && is_array($body['externalId'])) {
$externalId = json_encode($body['externalId']);
} else {
$externalId = '{}';
}
if (!empty($body['customFields'])) {
foreach ($body['customFields'] as $key => $value) {
$customField = ContactCustomFieldListModel::getById(['id' => $key, 'select' => ['type']]);
if ($customField['type'] == 'date') {
$date = new \DateTime($value);
$value = $date->format('Y-m-d');
$body['customFields'][$key] = $value;
}
}
}
$id = ContactModel::create([
'civility' => $body['civility'] ?? null,
'firstname' => $body['firstname'] ?? null,
'lastname' => $body['lastname'] ?? null,
'company' => $body['company'] ?? null,
'department' => $body['department'] ?? null,
'function' => $body['function'] ?? null,
'address_number' => $body['addressNumber'] ?? null,
'address_street' => $body['addressStreet'] ?? null,
'address_additional1' => $body['addressAdditional1'] ?? null,
'address_additional2' => $body['addressAdditional2'] ?? null,
'address_postcode' => $body['addressPostcode'] ?? null,
'address_town' => $body['addressTown'] ?? null,
'address_country' => $body['addressCountry'] ?? null,
'email' => $body['email'] ?? null,
'phone' => $body['phone'] ?? null,
'communication_means' => !empty($body['communicationMeans']) ? json_encode($body['communicationMeans']) : null,
'notes' => $body['notes'] ?? null,
'creator' => $GLOBALS['id'],
'enabled' => 'true',
'custom_fields' => !empty($body['customFields']) ? json_encode($body['customFields']) : null,
$historyInfoContact = '';
if (!empty($body['firstname']) || !empty($body['lastname'])) {
$historyInfoContact .= $body['firstname'] . ' ' . $body['lastname'];
}
if (!empty($historyInfoContact) && !empty($body['company'])) {
$historyInfoContact .= ' (' . $body['company'] . ')';
} else {
$historyInfoContact .= $body['company'];
}
HistoryController::add([
'tableName' => 'contacts',
'recordId' => $id,
'eventType' => 'ADD',
'info' => _CONTACT_CREATION . " : " . trim($historyInfoContact),
'moduleId' => 'contact',
'eventId' => 'contactCreation',
]);
return $response->withJson(['id' => $id, 'warning' => $annuaryReturn['warning']]);
public function getById(Request $request, Response $response, array $args)
{
if (!Validator::intVal()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$rawContact = ContactModel::getById(['id' => $args['id'], 'select' => ['*']]);
if (empty($rawContact)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
$contact = [
'id' => $rawContact['id'],
'civility' => null,
'firstname' => $rawContact['firstname'],
'lastname' => $rawContact['lastname'],
'company' => $rawContact['company'],
'department' => $rawContact['department'],
'function' => $rawContact['function'],
'addressNumber' => $rawContact['address_number'],
'addressStreet' => $rawContact['address_street'],
'addressAdditional1' => $rawContact['address_additional1'],
'addressAdditional2' => $rawContact['address_additional2'],
'addressPostcode' => $rawContact['address_postcode'],
'addressTown' => $rawContact['address_town'],
'addressCountry' => $rawContact['address_country'],
'email' => $rawContact['email'],
'phone' => $rawContact['phone'],
'notes' => $rawContact['notes'],
'creator' => $rawContact['creator'],
'creatorLabel' => UserModel::getLabelledUserById(['id' => $rawContact['creator']]),
'enabled' => $rawContact['enabled'],
'creationDate' => $rawContact['creation_date'],
'modificationDate' => $rawContact['modification_date'],
'customFields' => !empty($rawContact['custom_fields']) ? json_decode($rawContact['custom_fields'], true) : null,
'externalId' => json_decode($rawContact['external_id'], true)
];
if (!empty($rawContact['civility'])) {
$civilities = ContactModel::getCivilities();
$contact['civility'] = [
'id' => $rawContact['civility'],
'label' => $civilities[$rawContact['civility']]['label'],
'abbreviation' => $civilities[$rawContact['civility']]['abbreviation']
];
}
if (!empty($rawContact['communication_means'])) {
$communicationMeans = json_decode($rawContact['communication_means'], true);
$contact['communicationMeans'] = $communicationMeans['url'] ?? $communicationMeans['email'];
}
$filling = ContactController::getFillingRate(['contactId' => $rawContact['id']]);
$contact['fillingRate'] = empty($filling) ? null : $filling;
public function update(Request $request, Response $response, array $args)
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'update_contacts', 'userId' => $GLOBALS['id']])
&& !PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
if (!Validator::intVal()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$body = $request->getParsedBody();
$control = ContactController::controlContact(['body' => $body]);
if (!empty($control['errors'])) {
return $response->withStatus(400)->withJson(['errors' => $control['errors']]);
}
$contact = ContactModel::getById(['id' => $args['id'], 'select' => [1]]);
if (empty($contact)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
}
if (!empty($body['communicationMeans'])) {
if (filter_var($body['communicationMeans'], FILTER_VALIDATE_EMAIL)) {
$body['communicationMeans'] = ['email' => $body['communicationMeans']];
} elseif (filter_var($body['communicationMeans'], FILTER_VALIDATE_URL)) {
$body['communicationMeans'] = ['url' => $body['communicationMeans']];
}
}
$annuaryReturn = ContactController::addContactToM2MAnnuary(['body' => $body]);
$body = $annuaryReturn['body'];
if (!empty($body['externalId']) && is_array($body['externalId'])) {
$externalId = json_encode($body['externalId']);
} else {
$externalId = '{}';
}
ContactModel::update([
'set' => [
'civility' => $body['civility'] ?? null,
'firstname' => $body['firstname'] ?? null,
'lastname' => $body['lastname'] ?? null,
'company' => $body['company'] ?? null,
'department' => $body['department'] ?? null,
'function' => $body['function'] ?? null,
'address_number' => $body['addressNumber'] ?? null,
'address_street' => $body['addressStreet'] ?? null,
'address_additional1' => $body['addressAdditional1'] ?? null,
'address_additional2' => $body['addressAdditional2'] ?? null,
'address_postcode' => $body['addressPostcode'] ?? null,
'address_town' => $body['addressTown'] ?? null,
'address_country' => $body['addressCountry'] ?? null,
'email' => $body['email'] ?? null,
'phone' => $body['phone'] ?? null,
'communication_means' => !empty($body['communicationMeans']) ? json_encode($body['communicationMeans']) : null,
'notes' => $body['notes'] ?? null,
'modification_date' => 'CURRENT_TIMESTAMP',
'custom_fields' => !empty($body['customFields']) ? json_encode($body['customFields']) : null,
'external_id' => $externalId
],
'where' => ['id = ?'],
'data' => [$args['id']]
]);
$historyInfoContact = '';
if (!empty($body['firstname']) || !empty($body['lastname'])) {
$historyInfoContact .= $body['firstname'] . ' ' . $body['lastname'];
}
if (!empty($historyInfoContact) && !empty($body['company'])) {
$historyInfoContact .= ' (' . $body['company'] . ')';
} else {
$historyInfoContact .= $body['company'];
}
HistoryController::add([
'tableName' => 'contacts',
'recordId' => $args['id'],
'eventType' => 'UP',
'info' => _CONTACT_MODIFICATION . " : " . trim($historyInfoContact),
'moduleId' => 'contact',
'eventId' => 'contactModification',
]);
if (!empty($annuaryReturn['warning'])) {
return $response->withJson(['warning' => $annuaryReturn['warning']]);
}
public function addContactToM2MAnnuary($args = [])
{
$warning = '';
$body = $args['body'];
if (!empty($body['externalId']['m2m']) && !empty($body['company']) && empty($body['externalId']['m2m_annuary_id'])) {
if (empty($body['company']) || (empty($body['communicationMeans']['email']) && empty($body['communicationMeans']['url'])) || empty($body['department'])) {
$control = AnnuaryController::getAnnuaries();
if (!empty($control['annuaries'])) {
$warning = _CANNOT_SYNCHRONIZE_M2M_ANNUARY;
}
} else {
$annuaryInfo = AnnuaryController::addContact([
'ouName' => $body['company'],
'communicationValue' => $body['communicationMeans']['email'] ?? $body['communicationMeans']['url'],
'serviceName' => $body['department'],
'm2mId' => $body['externalId']['m2m']
]);
if (!empty($annuaryInfo['errors'])) {
$warning = $annuaryInfo['errors'];
} else {
$body['externalId']['m2m_annuary_id'] = $annuaryInfo['entryUUID'];
}
}
}
return ['body' => $body, 'warning' => $warning];
}
public function updateActivation(Request $request, Response $response, array $args)
{
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
if (!Validator::intVal()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$contact = ContactModel::getById(['id' => $args['id'], 'select' => [1]]);
if (empty($contact)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
}
$body = $request->getParsedBody();
ContactModel::update([
'set' => ['enabled' => empty($body['enabled']) ? 'false' : 'true'],
'where' => ['id = ?'],
'data' => [$args['id']]
]);
return $response->withStatus(204);
}
public function delete(Request $request, Response $response, array $args)
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
if (!Validator::intVal()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$contact = ContactModel::getById(['id' => $args['id'], 'select' => ['lastname', 'firstname', 'company']]);
if (empty($contact)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
}
$queryParams = $request->getQueryParams();
if (!empty($queryParams['redirect'])) {
if (!Validator::intVal()->validate($queryParams['redirect'])) {
return $response->withStatus(400)->withJson(['errors' => 'Query param redirect is not an integer']);
} elseif ($queryParams['redirect'] == $args['id']) {
return $response->withStatus(400)->withJson(['errors' => 'Cannot redirect to contact you are deleting']);
}
$contactRedirect = ContactModel::getById(['id' => $queryParams['redirect'], 'select' => [1]]);
if (empty($contactRedirect)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
}
$resourcesContacts = ResourceContactModel::get([
'select' => ['res_id', 'mode'],
'where' => ['item_id = ?', "type = 'contact'"],
'data' => [$args['id']]
]);
ResourceContactModel::update([
'set' => ['item_id' => $queryParams['redirect']],
'where' => ['item_id = ?', 'type = ?'],
'data' => [$args['id'], 'contact']
]);
// Delete duplicates if needed
$toDelete = [];
foreach ($resourcesContacts as $resourcesContact) {
$resContact = ResourceContactModel::get([
'select' => ['id'],
'where' => ['res_id = ?', 'item_id = ?', 'mode = ?', "type = 'contact'"],
'data' => [$resourcesContact['res_id'], $queryParams['redirect'], $resourcesContact['mode']],
'orderBy' => ['id desc']
]);
if (count($resContact) > 1) {
$toDelete[] = $resContact[0]['id'];
}
}
if (!empty($toDelete)) {
ResourceContactModel::delete([
'where' => ['id in (?)'],
'data' => [$toDelete]
]);
}
AcknowledgementReceiptModel::update([
'set' => ['contact_id' => $queryParams['redirect']],
'where' => ['contact_id = ?'],
'data' => [$args['id']]
]);
AttachmentModel::update([
'set' => ['recipient_id' => $queryParams['redirect']],
'where' => ['recipient_id = ?', "recipient_type = 'contact'"],
'data' => [$args['id']]
]);
}
AttachmentModel::update([
'set' => ['recipient_id' => null, 'recipient_type' => null],
'where' => ['recipient_id = ?', "recipient_type = 'contact'"],
'data' => [$args['id']]
]);
ResourceContactModel::delete([
'where' => ['item_id = ?', "type = 'contact'"],
]);
ContactModel::delete([
'where' => ['id = ?'],
'data' => [$args['id']]
]);

Florian Azizian
committed
ContactGroupModel::deleteByContactId(['contactId' => $args['id']]);
$historyInfoContact = '';
if (!empty($contact['firstname']) || !empty($contact['lastname'])) {
$historyInfoContact .= $contact['firstname'] . ' ' . $contact['lastname'];
if (!empty($historyInfoContact) && !empty($contact['company'])) {
$historyInfoContact .= ' (' . $contact['company'] . ')';
} else {
$historyInfoContact .= $contact['company'];
}
HistoryController::add([
'tableName' => 'contacts',
'recordId' => $args['id'],
'eventType' => 'DEL',
'info' => _CONTACT_SUPPRESSION . " : " . trim($historyInfoContact),
'moduleId' => 'contact',
'eventId' => 'contactSuppression',
]);
public function getContactsParameters(Request $request, Response $response)
{
$contactsFilling = ContactFillingModel::get();
$contactParameters = ContactParameterModel::get([
'select' => ['*'],
'orderBy' => ['identifier=\'civility\' desc, identifier=\'firstname\' desc, identifier=\'lastname\' desc, identifier=\'company\' desc, identifier=\'department\' desc,
identifier=\'function\' desc, identifier=\'address_number\' desc, identifier=\'address_street\' desc, identifier=\'address_additional1\' desc, identifier=\'address_additional2\' desc,
identifier=\'address_postcode\' desc, identifier=\'address_town\' desc, identifier=\'address_country\' desc, identifier=\'email\' desc, identifier=\'phone\' desc']
]);
foreach ($contactParameters as $key => $parameter) {
if (strpos($parameter['identifier'], 'contactCustomField_') !== false) {
$contactCustomId = str_replace("contactCustomField_", "", $parameter['identifier']);
$customField = ContactCustomFieldListModel::getById(['select' => ['label'], 'id' => $contactCustomId]);
$contactParameters[$key]['label'] = $customField['label'];
} else {
$contactParameters[$key]['label'] = null;
}
}
Guillaume Heurtier
committed
$loadedXml = CoreConfigModel::getXmlLoaded(['path' => 'apps/maarch_entreprise/xml/m2m_config.xml']);
$annuaryEnabled = true;
if (!$loadedXml) {
$annuaryEnabled = false;
}
if (empty($loadedXml->annuaries) || $loadedXml->annuaries->enabled == 'false') {
$annuaryEnabled = false;
}
return $response->withJson(['contactsFilling' => $contactsFilling, 'contactsParameters' => $contactParameters, 'annuaryEnabled' => $annuaryEnabled]);
public function updateContactsParameters(Request $request, Response $response)
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
$data = $request->getParams();
$check = Validator::arrayType()->validate($data['contactsParameters']);
$check = $check && Validator::arrayType()->validate($data['contactsFilling']);
$check = $check && Validator::boolType()->validate($data['contactsFilling']['enable']);
$check = $check && Validator::intVal()->notEmpty()->validate($data['contactsFilling']['first_threshold']) && $data['contactsFilling']['first_threshold'] > 0 && $data['contactsFilling']['first_threshold'] < 99;
$check = $check && Validator::intVal()->notEmpty()->validate($data['contactsFilling']['second_threshold']) && $data['contactsFilling']['second_threshold'] > 1 && $data['contactsFilling']['second_threshold'] < 100;
$check = $check && $data['contactsFilling']['first_threshold'] < $data['contactsFilling']['second_threshold'];
if (!$check) {
return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
}
foreach ($data['contactsParameters'] as $contactParameter) {
unset($contactParameter['label']);
ContactParameterModel::update([
'set' => [
'mandatory' => empty($contactParameter['mandatory']) ? 'false' : 'true',
'filling' => empty($contactParameter['filling']) ? 'false' : 'true',
'searchable' => empty($contactParameter['searchable']) ? 'false' : 'true',
'displayable' => empty($contactParameter['displayable']) ? 'false' : 'true',
],
'where' => ['id = ?'],
'data' => [$contactParameter['id']]
]);
}
ContactFillingModel::update($data['contactsFilling']);
return $response->withJson(['success' => 'success']);
}
public function getByResId(Request $request, Response $response, array $args)
if (!Validator::intVal()->validate($args['resId']) || !ResController::hasRightByResId(['resId' => [$args['resId']], 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Document out of perimeter']);
}
$resource = ResModel::getById(['select' => ['res_id'], 'resId' => $args['resId']]);
if (empty($resource)) {
return $response->withStatus(404)->withJson(['errors' => 'Document does not exist']);
}
$queryParams = $request->getQueryParams();
$contacts = [];
if ($queryParams['type'] == 'senders') {
$contacts = ContactController::getParsedContacts(['resId' => $resource['res_id'], 'mode' => 'sender']);
} elseif ($queryParams['type'] == 'recipients') {
$contacts = ContactController::getParsedContacts(['resId' => $resource['res_id'], 'mode' => 'recipient']);
}
return $response->withJson(['contacts' => $contacts]);
}
public function getLightFormattedContact(Request $request, Response $response, array $args)
{
if (!Validator::intVal()->notEmpty()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Query params id is not an integer']);
}
if ($args['type'] == 'contact') {
$contact = ContactModel::getById([
'select' => [
'firstname', 'lastname', 'company', 'address_number as "addressNumber"', 'address_street as "addressStreet"',
'address_postcode as "addressPostcode"', 'address_town as "addressTown"', 'address_country as "addressCountry"'],
'id' => $args['id']
]);
} elseif ($args['type'] == 'user') {
$contact = UserModel::getById(['id' => $args['id'], 'select' => ['firstname', 'lastname']]);
} elseif ($args['type'] == 'entity') {
$contact = EntityModel::getById(['id' => $args['id'], 'select' => ['entity_label as label']]);
}
if (empty($contact)) {
return $response->withStatus(400)->withJson(['errors' => 'Contact does not exist']);
}
return $response->withJson(['contact' => $contact]);
}
public function getCivilities(Request $request, Response $response)
{
$civilities = ContactModel::getCivilities();
return $response->withJson(['civilities' => $civilities]);
}
public static function getFillingRate(array $aArgs)
{
ValidatorModel::notEmpty($aArgs, ['contactId']);
ValidatorModel::intVal($aArgs, ['contactId']);
$contactsFilling = ContactFillingModel::get();
$contactsParameters = ContactParameterModel::get(['select' => ['identifier'], 'where' => ['filling = ?'], 'data' => ['true']]);
if ($contactsFilling['enable'] && !empty($contactsParameters)) {
$contactRaw = ContactModel::getById([
'select' => [
'civility', 'firstname', 'lastname', 'company', 'department', 'function', 'address_number as "addressNumber"', 'address_street as "addressStreet"',
'address_additional1 as "addressAdditional1"', 'address_additional2 as "addressAdditional2"', 'address_postcode as "addressPostcode"',
'address_town as "addressTown"', 'address_country as "addressCountry"', 'email', 'phone', 'custom_fields'
],
'id' => $aArgs['contactId']
]);
$customFields = json_decode($contactRaw['custom_fields'], true);
foreach ($contactsParameters as $ratingColumn) {
if (strpos($ratingColumn['identifier'], 'contactCustomField_') !== false && !empty($customFields[str_replace("contactCustomField_", "", $ratingColumn['identifier'])])) {
$percent++;
} elseif (!empty($contactRaw[$ratingColumn['identifier']])) {
$percent = $percent * 100 / count($contactsParameters);
if ($percent <= $contactsFilling['first_threshold']) {
$thresholdLevel = 'first';
} elseif ($percent <= $contactsFilling['second_threshold']) {
$thresholdLevel = 'second';
$thresholdLevel = 'third';
return ['rate' => round($percent, 2), 'thresholdLevel' => $thresholdLevel];
public static function getContactAfnor(array $args)
{
$afnorAddress = ['Afnor',
'',
'',
'',
'',
'',
''
];
if (!empty($args['company'])) {
$afnorAddress[1] = trim(substr($args['company'], 0, 38));
// Ligne 2
if (!empty($args['civility']) || !empty($args['firstname']) || !empty($args['lastname'])) {
$afnorAddress[2] = ContactController::controlLengthNameAfnor([
'civility' => $args['civility'],
'fullName' => $args['firstname'].' '.$args['lastname'],
'strMaxLength' => 38
]);
$afnorAddress[2] = trim($afnorAddress[2]);
if (!empty($args['address_additional1'])) {
$afnorAddress[3] = trim(substr($args['address_additional1'], 0, 38));
if (!empty($args['address_number'])) {
$args['address_number'] = TextFormatModel::normalize(['string' => $args['address_number']]);
$args['address_number'] = preg_replace('/[^\w]/s', ' ', $args['address_number']);
$args['address_number'] = strtoupper($args['address_number']);
if (!empty($args['address_street'])) {
$args['address_street'] = TextFormatModel::normalize(['string' => $args['address_street']]);
$args['address_street'] = preg_replace('/[^\w]/s', ' ', $args['address_street']);
$args['address_street'] = strtoupper($args['address_street']);
$afnorAddress[4] = trim(substr($args['address_number'].' '.$args['address_street'], 0, 38));
if (!empty($args['address_additional2'])) {
$afnorAddress[5] = trim(substr($args['address_additional2'], 0, 38));
$args['address_postcode'] = strtoupper($args['address_postcode']);
$args['address_town'] = strtoupper($args['address_town']);
$afnorAddress[6] = trim(substr($args['address_postcode'].' '.$args['address_town'], 0, 38));
public static function controlLengthNameAfnor(array $args)
if (strlen($args['civility'].' '.$args['fullName']) > $args['strMaxLength']) {
$args['civility'] = $aCivility[$args['civility']]['abbreviation'];
$args['civility'] = $aCivility[$args['civility']]['label'];
return substr($args['civility'].' '.$args['fullName'], 0, $args['strMaxLength']);
public function getAvailableDepartments(Request $request, Response $response)
$customId = CoreConfigModel::getCustomId();

Alex ORLUC
committed
$referentialDirectory = 'referential/ban/indexes';
if (is_dir("custom/{$customId}/".$referentialDirectory)) {
$customFilesDepartments = scandir("custom/{$customId}/".$referentialDirectory);
if (is_dir($referentialDirectory)) {
$filesDepartments = scandir($referentialDirectory);
$departments = [];
if (!empty($customFilesDepartments)) {
foreach ($customFilesDepartments as $value) {

Alex ORLUC
committed
if ($value != '.' && $value != '..' && is_writable("custom/{$customId}/".$referentialDirectory.'/'.$value)) {
if (!empty($filesDepartments)) {
foreach ($filesDepartments as $value) {

Alex ORLUC
committed
if ($value != '.' && $value != '..' && !in_array($value, $departments) && is_writable($referentialDirectory.'/'.$value)) {
if (empty($departments)) {
return $response->withJson(['departments' => []]);
sort($departments, SORT_NUMERIC);
$defaultDepartment = ParameterModel::getById(['id' => 'defaultDepartment', 'select' => ['param_value_int']]);
return $response->withJson(['departments' => $departments, 'default' => empty($defaultDepartment['param_value_int']) ? null : $defaultDepartment['param_value_int']]);
public function getDuplicatedContacts(Request $request, Response $response)
{
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
$queryParams = $request->getQueryParams();
Guillaume Heurtier
committed
// [fieldNameInFront] => field_name_in_db
$allowedFields = [
'firstname' => 'firstname',
'lastname' => 'lastname',
'company' => 'company',
'addressNumber' => 'address_number',
'addressStreet' => 'address_street',
'addressAdditional1' => 'address_additional1',
'addressAdditional2' => 'address_additional2',
'addressPostcode' => 'address_postcode',
'addressTown' => 'address_town',
'addressCountry' => 'address_country',
'department' => 'department',
'function' => 'function',
'email' => 'email',
'phone' => 'phone'
];
if (!Validator::arrayType()->notEmpty()->validate($queryParams['criteria'])) {
return $response->withStatus(400)->withJson(['errors' => 'criteria is empty or not an array']);
}
$contactCustoms = ContactCustomFieldListModel::get(['select' => ['id']]);
$contactCustoms = array_column($contactCustoms, 'id');
Guillaume Heurtier
committed
$allowedFieldsKeys = array_keys($allowedFields);
foreach ($queryParams['criteria'] as $criterion) {
if (strpos($criterion, 'contactCustomField_') !== false) {
$customId = explode('_', $criterion)[1];
if (!in_array($customId, $contactCustoms)) {
return $response->withStatus(400)->withJson(['errors' => 'Custom criteria does not exist']);
}
} else {
if (!in_array($criterion, $allowedFieldsKeys)) {
return $response->withStatus(400)->withJson(['errors' => 'criteria does not exist']);
}
Guillaume Heurtier
committed
// Construct the query to get all duplicates on criteria
$criteria = [];
$order = [];
foreach ($queryParams['criteria'] as $criterion) {
if (strpos($criterion, 'contactCustomField_') !== false) {
if (!in_array('custom_fields', $order)) {
$order[] = 'custom_fields';
}
$customId = explode('_', $criterion)[1];
$criteria[] = "replace(lower(translate(custom_fields->>'" . $customId . "', 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûýýþÿŔŕ',
'aaaaaaaceeeeiiiidnoooooouuuuybsaaaaaaaceeeeiiiidnoooooouuuyybyRr') ), ' ', '')";
} else {
$order[] = $allowedFields[$criterion];
$criteria[] = "replace(lower(translate(" . $allowedFields[$criterion] . ", 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûýýþÿŔŕ',
Guillaume Heurtier
committed
'aaaaaaaceeeeiiiidnoooooouuuuybsaaaaaaaceeeeiiiidnoooooouuuyybyRr') ), ' ', '')";
Guillaume Heurtier
committed
}
$fields = ['distinct(id)', 'enabled', 'dense_rank() over (order by ' . implode(',', $criteria) . ') duplicate_id', 'custom_fields'];
foreach ($allowedFields as $field) {
$fields[] = $field;
}
$where = [];
Guillaume Heurtier
committed
foreach ($criteria as $criterion) {
$subQuery = "SELECT " . $criterion . ' as field FROM contacts c GROUP BY field HAVING count(*) > 1';
Guillaume Heurtier
committed
$where[] = $criterion . " in (" . $subQuery . ") ";
}
Guillaume Heurtier
committed
$duplicatesQuery = "SELECT " . implode(', ', $fields) . ' FROM contacts WHERE ' . implode(' AND ', $where);
// Create a query that will have the number of duplicates for each duplicate group
// this is needed to avoid getting result that only appears once in the result list (and the function dense_rank cannot be used in group by)
$duplicatesCountQuery = 'SELECT duplicate_id, count(*) as duplicate_count FROM (' . $duplicatesQuery . ') as duplicates_id group by duplicate_id';
$fields = ['distinct(id)', 'count(*) over () as total', 'duplicates_info.duplicate_id', 'enabled', 'custom_fields'];
Guillaume Heurtier
committed
foreach ($allowedFields as $field) {
$fields[] = $field;
Guillaume Heurtier
committed
// Get all the duplicates
$duplicates = DatabaseModel::select([
'select' => $fields,
'table' => ['( ' . $duplicatesQuery . ') as duplicates_info, (' . $duplicatesCountQuery . ') as duplicates_ids'],
'where' => ['duplicates_ids.duplicate_id = duplicates_info.duplicate_id', 'duplicate_count > 1'],
'order_by' => $order,
'limit' => 500
Guillaume Heurtier
committed
if (empty($duplicates)) {
Guillaume Heurtier
committed
return $response->withJson(['returnedCount' => 0, 'realCount' => 0, 'contacts' => []]);
Guillaume Heurtier
committed
}
$contactIds = array_column($duplicates, 'id');
$contactsUsed = ContactController::isContactUsed(['ids' => $contactIds]);
$contacts = [];
foreach ($duplicates as $key => $contact) {
unset($duplicates[$key]['count']);
$filling = ContactController::getFillingRate(['contactId' => $contact['id']]);
$contacts[] = [
'duplicateId' => $contact['duplicate_id'],
'id' => $contact['id'],
'firstname' => $contact['firstname'],
'lastname' => $contact['lastname'],
'company' => $contact['company'],
'addressNumber' => $contact['address_number'],
'addressStreet' => $contact['address_street'],
'addressAdditional1' => $contact['address_additional1'],
'addressAdditional2' => $contact['address_additional2'],
'addressPostcode' => $contact['address_postcode'],
'addressTown' => $contact['address_town'],
'addressCountry' => $contact['address_country'],
'enabled' => $contact['enabled'],
Guillaume Heurtier
committed
'function' => $contact['function'],
'department' => $contact['department'],
'email' => $contact['email'],
'phone' => $contact['phone'],
'isUsed' => $contactsUsed[$contact['id']],
'filling' => $filling,
'customFields' => !empty($contact['custom_fields']) ? json_decode($contact['custom_fields'], true) : null,
];
}
Guillaume Heurtier
committed
$count = $duplicates[0]['total'];
Guillaume Heurtier
committed
return $response->withJson(['returnedCount' => count($contacts), 'realCount' => $count, 'contacts' => $contacts]);
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
public function mergeContacts(Request $request, Response $response, array $args)
{
if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_contacts', 'userId' => $GLOBALS['id']])) {
return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
}
if (!Validator::intVal()->validate($args['id'])) {
return $response->withStatus(400)->withJson(['errors' => 'Route id is not an integer']);
}
$body = $request->getParsedBody();
if (!Validator::arrayType()->notEmpty()->validate($body['duplicates'])) {
return $response->withStatus(400)->withJson(['errors' => 'Body duplicates is empty or not an array']);
}
$fields = ['firstname', 'lastname', 'company', 'address_number', 'address_street', 'address_additional1', 'address_additional2',
'address_postcode', 'address_town', 'address_country', 'department', 'function', 'email', 'phone'];
$master = ContactModel::getById([
'select' => $fields,
'id' => $args['id']
]);
if (empty($master)) {
return $response->withStatus(400)->withJson(['errors' => 'master does not exist']);
}
$duplicates = ContactModel::get([
'select' => $fields,
'where' => ['id in (?)'],
'data' => [$body['duplicates']]
]);
if (count($duplicates) != count($body['duplicates'])) {
return $response->withStatus(400)->withJson(['errors' => 'duplicates do not exist']);
}
$set = [];
foreach ($fields as $field) {
if (empty($master[$field])) {
foreach ($duplicates as $duplicate) {
if (!empty($duplicate[$field])) {
$set[$field] = $duplicate[$field];