diff --git a/application/Espo/Core/Mail/Importer.php b/application/Espo/Core/Mail/Importer.php
index d1da61023a..b22f99c0f7 100644
--- a/application/Espo/Core/Mail/Importer.php
+++ b/application/Espo/Core/Mail/Importer.php
@@ -64,16 +64,19 @@ class Importer
return $this->filtersMatcher;
}
- public function importMessage($message, $assignedUserId = null, $teamsIdList = [], $userIdList = [], $filterList = [], $fetchOnlyHeader = false, $folderData = null)
+ public function importMessage($message, $assignedUserId = null, $teamsIdList = [], $userIdList = [], $filterList = [], $fetchOnlyHeader = false, $folderData = null, $parserType = 'Zend')
{
try {
+ $parserClassName = '\\Espo\\Core\\Mail\\Parsers\\' . $parserType;
+ $parser = new $parserClassName($this->getEntityManager());
+
$email = $this->getEntityManager()->getEntity('Email');
$email->set('isBeingImported', true);
$subject = '';
- if (isset($message->subject)) {
- $subject = $message->subject;
+ if ($parser->checkMessageAttribute($message, 'subject')) {
+ $subject = $parser->getMessageAttribute($message, 'subject');
}
if (!empty($subject) && is_string($subject)) {
$subject = trim($subject);
@@ -98,17 +101,18 @@ class Importer
}
}
- $fromArr = $this->getAddressListFromMessage($message, 'from');
- if (isset($message->from)) {
- $email->set('fromString', $message->from);
- }
- if (isset($message->replyTo)) {
- $email->set('replyToString', $message->replyTo);
+ if ($parser->checkMessageAttribute($message, 'from')) {
+ $email->set('fromString', $parser->getMessageAttribute($message, 'from'));
}
- $toArr = $this->getAddressListFromMessage($message, 'to');
- $ccArr = $this->getAddressListFromMessage($message, 'cc');
- $replyToArr = $this->getAddressListFromMessage($message, 'replyTo');
+ if ($parser->checkMessageAttribute($message, 'replyTo')) {
+ $email->set('replyToString', $parser->getMessageAttribute($message, 'replyTo'));
+ }
+
+ $fromArr = $parser->getAddressListFromMessage($message, 'from');
+ $toArr = $parser->getAddressListFromMessage($message, 'to');
+ $ccArr = $parser->getAddressListFromMessage($message, 'cc');
+ $replyToArr = $parser->getAddressListFromMessage($message, 'replyTo');
$email->set('from', $fromArr[0]);
$email->set('to', implode(';', $toArr));
@@ -125,15 +129,14 @@ class Importer
return false;
}
- if (isset($message->messageId) && !empty($message->messageId)) {
- $messageId = $message->messageId;
- $messageId = str_replace('<<', '<', $messageId);
- $messageId = str_replace('>>', '>', $messageId);
+ if ($parser->checkMessageAttribute($message, 'messageId') && $parser->getMessageAttribute($message, 'messageId')) {
+ $messageId = $parser->getMessageMessageId($message);
+
$email->set('messageId', $messageId);
- if (isset($message->deliveredTo)) {
- $email->set('messageIdInternal', $message->messageId . '-' . $message->deliveredTo);
+ if ($parser->checkMessageAttribute($message, 'deliveredTo')) {
+ $email->set('messageIdInternal', $messageId . '-' . $parser->getMessageAttribute($message, 'deliveredTo'));
}
- if (stripos($message->messageId, '@espo-system') !== false) {
+ if (stripos($messageId, '@espo-system') !== false) {
return;
}
}
@@ -167,49 +170,29 @@ class Importer
return $duplicate;
}
- if (isset($message->date)) {
- $dt = new \DateTime($message->date);
- if ($dt) {
- $dateSent = $dt->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
- $email->set('dateSent', $dateSent);
- }
+ if ($parser->checkMessageAttribute($message, 'date')) {
+ try {
+ $dt = new \DateTime($parser->getMessageAttribute($message, 'date'));
+ if ($dt) {
+ $dateSent = $dt->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
+ $email->set('dateSent', $dateSent);
+ }
+ } catch (\Exception $e) {}
} else {
$email->set('dateSent', date('Y-m-d H:i:s'));
}
- if (isset($message->deliveryDate)) {
- $dt = new \DateTime($message->deliveryDate);
- if ($dt) {
- $deliveryDate = $dt->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
- $email->set('deliveryDate', $deliveryDate);
- }
+ if ($parser->checkMessageAttribute($message, 'deliveryDate')) {
+ try {
+ $dt = new \DateTime($parser->getMessageAttribute($message, 'deliveryDate'));
+ if ($dt) {
+ $deliveryDate = $dt->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
+ $email->set('deliveryDate', $deliveryDate);
+ }
+ } catch (\Exception $e) {}
}
- $inlineIds = array();
-
if (!$fetchOnlyHeader) {
- if ($message->isMultipart()) {
- foreach (new \RecursiveIteratorIterator($message) as $part) {
- $this->importPartDataToEmail($email, $part, $inlineIds);
- }
- } else {
- $this->importPartDataToEmail($email, $message, $inlineIds, 'text/plain');
- }
-
- if (!$email->get('body') && $email->get('bodyPlain')) {
- $email->set('body', $email->get('bodyPlain'));
- }
-
- $body = $email->get('body');
- if (!empty($body)) {
- foreach ($inlineIds as $cid => $attachmentId) {
- if (strpos($body, 'cid:' . $cid) !== false) {
- $body = str_replace('cid:' . $cid, '?entryPoint=attachment&id=' . $attachmentId, $body);
- } else {
- $email->addLinkMultipleId('attachments', $attachmentId);
- }
- }
- $email->set('body', $body);
- }
+ $parser->fetchContentParts($email, $message);
if ($this->getFiltersMatcher()->match($email, $filterList)) {
return false;
@@ -222,8 +205,9 @@ class Importer
$parentFound = false;
$replied = null;
- if (isset($message->inReplyTo) && !empty($message->inReplyTo)) {
- $arr = explode(' ', $message->inReplyTo);
+
+ if ($parser->checkMessageAttribute($message, 'inReplyTo') && $parser->getMessageAttribute($message, 'inReplyTo')) {
+ $arr = explode(' ', $parser->getMessageAttribute($message, 'inReplyTo'));
$inReplyTo = $arr[0];
$replied = $this->getEntityManager()->getRepository('Email')->where(array(
'messageId' => $inReplyTo
@@ -233,14 +217,17 @@ class Importer
}
}
- if (isset($message->references) && !empty($message->references)) {
- $arr = explode(' ', $message->references);
+ if ($parser->checkMessageAttribute($message, 'references') && $parser->getMessageAttribute($message, 'references')) {
+ $arr = explode(' ', $parser->getMessageAttribute($message, 'references'));
$reference = $arr[0];
$reference = str_replace(array('/', '@'), " ", trim($reference, '<>'));
$parentType = $parentId = null;
$emailSent = PHP_INT_MAX;
$number = null;
$n = sscanf($reference, '%s %s %d %d espo', $parentType, $parentId, $emailSent, $number);
+ if ($n != 4) {
+ $n = sscanf($reference, '%s %s %d %d espo-system', $parentType, $parentId, $emailSent, $number);
+ }
if ($n == 4 && $emailSent < time()) {
if (!empty($parentType) && !empty($parentId)) {
if ($parentType == 'Lead') {
@@ -354,243 +341,4 @@ class Importer
}
}
}
-
- protected function normilizeHeader($header)
- {
- if (is_a($header, 'ArrayIterator')) {
- return $header->current();
- } else {
- return $header;
- }
- }
-
- protected function getAddressListFromMessage($message, $type)
- {
- $addressList = array();
- if (isset($message->$type)) {
- $list = $this->normilizeHeader($message->getHeader($type))->getAddressList();
- foreach ($list as $address) {
- $addressList[] = $address->getEmail();
- }
- }
- return $addressList;
- }
-
- protected function importPartDataToEmail(\Espo\Entities\Email $email, $part, &$inlineIds = array(), $defaultContentType = null)
- {
- try {
- $type = null;
-
- if ($part->getHeaders() && isset($part->contentType)) {
- $type = strtok($part->contentType, ';');
- }
-
- $contentDisposition = false;
- if (isset($part->ContentDisposition)) {
- if (strpos(strtolower($part->ContentDisposition), 'attachment') === 0) {
- $contentDisposition = 'attachment';
- } else if (strpos(strtolower($part->ContentDisposition), 'inline') === 0) {
- $contentDisposition = 'inline';
- }
- } else if (isset($part->contentID)) {
- $contentDisposition = 'inline';
- }
-
- if (empty($type)) {
- if (!empty($defaultContentType)) {
- $type = $defaultContentType;
- } else {
- return;
- }
- }
-
- $encoding = null;
- $isAttachment = true;
- if ($type == 'text/plain' || $type == 'text/html') {
- if ($contentDisposition !== 'attachment') {
- $isAttachment = false;
- $content = $this->getContentFromPart($part);
- if ($type == 'text/plain') {
- $bodyPlain = '';
- if ($email->get('bodyPlain')) {
- $bodyPlain .= $email->get('bodyPlain') . "\n";
- }
- $bodyPlain .= $content;
- $email->set('bodyPlain', $bodyPlain);
- } else if ($type == 'text/html') {
- $body = '';
- if ($email->get('body')) {
- $body .= $email->get('body') . "
";
- }
- $body .= $content;
- $email->set('isHtml', true);
- $email->set('body', $body);
- }
- }
- }
-
- if ($isAttachment) {
- $content = $part->getContent();
- $disposition = null;
-
- $fileName = null;
- $contentId = null;
-
- if ($contentDisposition) {
- if ($contentDisposition === 'attachment') {
- $fileName = $this->fetchFileNameFromContentDisposition($part->ContentDisposition);
- if ($fileName) {
- $disposition = 'attachment';
- }
- } else if ($contentDisposition === 'inline') {
- if (isset($part->contentID)) {
- $contentId = trim($part->contentID, '<>');
- $fileName = $contentId;
- $disposition = 'inline';
- } else {
- // for iOS attachments
- if (empty($fileName)) {
- $fileName = $this->fetchFileNameFromContentDisposition($part->ContentDisposition);
- if ($fileName) {
- $disposition = 'attachment';
- }
- }
- }
- }
- }
-
- if (isset($part->contentTransferEncoding)) {
- $encoding = strtolower($this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'))->getTransferEncoding());
- }
-
- $attachment = $this->getEntityManager()->getEntity('Attachment');
- $attachment->set('name', $fileName);
- $attachment->set('type', $type);
-
- if ($disposition == 'inline') {
- $attachment->set('role', 'Inline Attachment');
- } else {
- $attachment->set('role', 'Attachment');
- }
-
- if ($encoding == 'base64') {
- $content = base64_decode($content);
- }
-
- $attachment->set('contents', $content);
-
- $this->getEntityManager()->saveEntity($attachment);
-
- if ($disposition == 'attachment') {
- $attachmentsIds = $email->get('attachmentsIds');
- $attachmentsIds[] = $attachment->id;
- $email->set('attachmentsIds', $attachmentsIds);
- } else if ($disposition == 'inline') {
- $inlineIds[$contentId] = $attachment->id;
- }
- }
- } catch (\Exception $e) {}
- }
-
- protected function decodeAttachmentFileName($fileName)
- {
- if ($fileName && stripos($fileName, "''") !== false) {
- list($encoding, $fileName) = explode("''", $fileName);
- $fileName = rawurldecode($fileName);
- if (strtoupper($encoding) !== 'UTF-8') {
- if ($encoding) {
- $fileName = mb_convert_encoding($fileName, 'UTF-8', $encoding);
- }
- }
- }
- return $fileName;
- }
-
- protected function fetchFileNameFromContentDisposition($contentDisposition)
- {
- $contentDisposition = preg_replace('/\\\\"/', "{{_!Q!U!O!T!E!_}}", $contentDisposition);
-
- $fileName = false;
- $m = array();
-
- if (preg_match('/filename="([^"]+)";?/i', $contentDisposition, $m)) {
- $fileName = $m[1];
- } else if (preg_match('/filename=([^";]+);?/i', $contentDisposition, $m)) {
- $fileName = $m[1];
- } else if (preg_match('/filename\*="([^"]+)";?/i', $contentDisposition, $m)) {
- $fileName = $m[1];
- $fileName = $this->decodeAttachmentFileName($fileName);
- } else if (preg_match('/filename\*=([^";]+);?/i', $contentDisposition, $m)) {
- $fileName = $m[1];
- $fileName = $this->decodeAttachmentFileName($fileName);
- } else {
- $fileName = '';
- foreach (['0', '1'] as $i) {
- if (preg_match('/filename\*'.$i.'[\*]?="([^"]+)";?/i', $contentDisposition, $m)) {
- $part = $m[1];
- $fileName .= $part;
- } else if (preg_match('/filename\*'.$i.'[\*]?=([^";]+);?/i', $contentDisposition, $m)) {
- $part = $m[1];
- $fileName .= $part;
- }
- }
-
- if ($fileName === '') {
- $fileName = null;
- } else {
- $fileName = $this->decodeAttachmentFileName($fileName);
- }
- }
-
- if ($fileName) {
- $fileName = str_replace('{{_!Q!U!O!T!E!_}}', '"', $fileName);
- }
-
- return $fileName;
- }
-
- protected function getContentFromPart($part)
- {
- if ($part instanceof \Zend\Mime\Part) {
- $content = $part->getRawContent();
- if (strtolower($part->charset) != 'utf-8') {
- $content = mb_convert_encoding($content, 'UTF-8', $part->charset);
- }
- } else {
- $content = $part->getContent();
-
- $encoding = null;
-
- if (isset($part->contentTransferEncoding)) {
- $cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
- $encoding = strtolower($cteHeader->getTransferEncoding());
- }
-
- if ($encoding == 'base64') {
- $content = base64_decode($content);
- }
-
- $charset = 'UTF-8';
-
- if (isset($part->contentType)) {
- $ctHeader = $this->normilizeHeader($part->getHeader('Content-Type'));
- $charsetParamValue = $ctHeader->getParameter('charset');
- if (!empty($charsetParamValue)) {
- $charset = strtoupper($charsetParamValue);
- }
- }
-
- if (isset($part->contentTransferEncoding)) {
- $cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
- if ($cteHeader->getTransferEncoding() == 'quoted-printable') {
- $content = quoted_printable_decode($content);
- }
- }
-
- if ($charset !== 'UTF-8') {
- $content = mb_convert_encoding($content, 'UTF-8', $charset);
- }
- }
- return $content;
- }
}
diff --git a/application/Espo/Core/Mail/Parsers/Zend.php b/application/Espo/Core/Mail/Parsers/Zend.php
new file mode 100644
index 0000000000..8bdffa36f9
--- /dev/null
+++ b/application/Espo/Core/Mail/Parsers/Zend.php
@@ -0,0 +1,338 @@
+entityManager = $entityManager;
+ }
+
+ public function getEntityManager()
+ {
+ return $this->entityManager;
+ }
+
+ public function checkMessageAttribute($message, $attribute)
+ {
+ return isset($message->$attribute);
+ }
+
+ public function getMessageAttribute($message, $attribute)
+ {
+ if (!isset($message->$attribute)) return null;
+
+ return $message->$attribute;
+ }
+
+ public function getMessageMessageId($message)
+ {
+ if (!isset($message->messageId)) return null;
+
+ $messageId = $message->messageId;
+ $messageId = str_replace('<<', '<', $messageId);
+ $messageId = str_replace('>>', '>', $messageId);
+
+ return $messageId;
+ }
+
+ public function getAddressListFromMessage($message, $type)
+ {
+ $addressList = array();
+ if (isset($message->$type)) {
+ $list = $this->normilizeHeader($message->getHeader($type))->getAddressList();
+ foreach ($list as $address) {
+ $addressList[] = $address->getEmail();
+ }
+ }
+ return $addressList;
+ }
+
+ public function fetchContentParts(\Espo\Entities\Email $email, $message)
+ {
+ $inlineIds = array();
+
+ if ($message->isMultipart()) {
+ foreach (new \RecursiveIteratorIterator($message) as $part) {
+ $this->importPartDataToEmail($email, $part, $inlineIds);
+ }
+ } else {
+ $this->importPartDataToEmail($email, $message, $inlineIds, 'text/plain');
+ }
+
+ if (!$email->get('body') && $email->get('bodyPlain')) {
+ $email->set('body', $email->get('bodyPlain'));
+ }
+
+ $body = $email->get('body');
+ if (!empty($body)) {
+ foreach ($inlineIds as $cid => $attachmentId) {
+ if (strpos($body, 'cid:' . $cid) !== false) {
+ $body = str_replace('cid:' . $cid, '?entryPoint=attachment&id=' . $attachmentId, $body);
+ } else {
+ $email->addLinkMultipleId('attachments', $attachmentId);
+ }
+ }
+ $email->set('body', $body);
+ }
+ }
+
+ protected function importPartDataToEmail(\Espo\Entities\Email $email, $part, &$inlineIds = array(), $defaultContentType = null)
+ {
+ try {
+ $type = null;
+
+ if ($part->getHeaders() && isset($part->contentType)) {
+ $type = strtok($part->contentType, ';');
+ }
+
+ $contentDisposition = false;
+ if (isset($part->ContentDisposition)) {
+ if (strpos(strtolower($part->ContentDisposition), 'attachment') === 0) {
+ $contentDisposition = 'attachment';
+ } else if (strpos(strtolower($part->ContentDisposition), 'inline') === 0) {
+ $contentDisposition = 'inline';
+ }
+ } else if (isset($part->contentID)) {
+ $contentDisposition = 'inline';
+ }
+
+ if (empty($type)) {
+ if (!empty($defaultContentType)) {
+ $type = $defaultContentType;
+ } else {
+ return;
+ }
+ }
+
+ $encoding = null;
+ $isAttachment = true;
+ if ($type == 'text/plain' || $type == 'text/html') {
+ if ($contentDisposition !== 'attachment') {
+ $isAttachment = false;
+ $content = $this->getContentFromPart($part);
+ if ($type == 'text/plain') {
+ $bodyPlain = '';
+ if ($email->get('bodyPlain')) {
+ $bodyPlain .= $email->get('bodyPlain') . "\n";
+ }
+ $bodyPlain .= $content;
+ $email->set('bodyPlain', $bodyPlain);
+ } else if ($type == 'text/html') {
+ $body = '';
+ if ($email->get('body')) {
+ $body .= $email->get('body') . "
";
+ }
+ $body .= $content;
+ $email->set('isHtml', true);
+ $email->set('body', $body);
+ }
+ }
+ }
+
+ if ($isAttachment) {
+ $content = $part->getContent();
+ $disposition = null;
+
+ $fileName = null;
+ $contentId = null;
+
+ if ($contentDisposition) {
+ if ($contentDisposition === 'attachment') {
+ $fileName = $this->fetchFileNameFromContentDisposition($part->ContentDisposition);
+ if ($fileName) {
+ $disposition = 'attachment';
+ }
+ } else if ($contentDisposition === 'inline') {
+ if (isset($part->contentID)) {
+ $contentId = trim($part->contentID, '<>');
+ $fileName = $contentId;
+ $disposition = 'inline';
+ } else {
+ // for iOS attachments
+ if (empty($fileName)) {
+ $fileName = $this->fetchFileNameFromContentDisposition($part->ContentDisposition);
+ if ($fileName) {
+ $disposition = 'attachment';
+ }
+ }
+ }
+ }
+ }
+
+ if (isset($part->contentTransferEncoding)) {
+ $encoding = strtolower($this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'))->getTransferEncoding());
+ }
+
+ $attachment = $this->getEntityManager()->getEntity('Attachment');
+ $attachment->set('name', $fileName);
+ $attachment->set('type', $type);
+
+ if ($disposition == 'inline') {
+ $attachment->set('role', 'Inline Attachment');
+ } else {
+ $attachment->set('role', 'Attachment');
+ }
+
+ if ($encoding == 'base64') {
+ $content = base64_decode($content);
+ }
+
+ $attachment->set('contents', $content);
+
+ $this->getEntityManager()->saveEntity($attachment);
+
+ if ($disposition == 'attachment') {
+ $attachmentsIds = $email->get('attachmentsIds');
+ $attachmentsIds[] = $attachment->id;
+ $email->set('attachmentsIds', $attachmentsIds);
+ } else if ($disposition == 'inline') {
+ $inlineIds[$contentId] = $attachment->id;
+ }
+ }
+ } catch (\Exception $e) {}
+ }
+
+ protected function getContentFromPart($part)
+ {
+ if ($part instanceof \Zend\Mime\Part) {
+ $content = $part->getRawContent();
+ if (strtolower($part->charset) != 'utf-8') {
+ $content = mb_convert_encoding($content, 'UTF-8', $part->charset);
+ }
+ } else {
+ $content = $part->getContent();
+
+ $encoding = null;
+
+ if (isset($part->contentTransferEncoding)) {
+ $cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
+ $encoding = strtolower($cteHeader->getTransferEncoding());
+ }
+
+ if ($encoding == 'base64') {
+ $content = base64_decode($content);
+ }
+
+ $charset = 'UTF-8';
+
+ if (isset($part->contentType)) {
+ $ctHeader = $this->normilizeHeader($part->getHeader('Content-Type'));
+ $charsetParamValue = $ctHeader->getParameter('charset');
+ if (!empty($charsetParamValue)) {
+ $charset = strtoupper($charsetParamValue);
+ }
+ }
+
+ if (isset($part->contentTransferEncoding)) {
+ $cteHeader = $this->normilizeHeader($part->getHeader('Content-Transfer-Encoding'));
+ if ($cteHeader->getTransferEncoding() == 'quoted-printable') {
+ $content = quoted_printable_decode($content);
+ }
+ }
+
+ if ($charset !== 'UTF-8') {
+ $content = mb_convert_encoding($content, 'UTF-8', $charset);
+ }
+ }
+ return $content;
+ }
+
+ protected function normilizeHeader($header)
+ {
+ if (is_a($header, 'ArrayIterator')) {
+ return $header->current();
+ } else {
+ return $header;
+ }
+ }
+
+ protected function fetchFileNameFromContentDisposition($contentDisposition)
+ {
+ $contentDisposition = preg_replace('/\\\\"/', "{{_!Q!U!O!T!E!_}}", $contentDisposition);
+
+ $fileName = false;
+ $m = array();
+
+ if (preg_match('/filename="([^"]+)";?/i', $contentDisposition, $m)) {
+ $fileName = $m[1];
+ } else if (preg_match('/filename=([^";]+);?/i', $contentDisposition, $m)) {
+ $fileName = $m[1];
+ } else if (preg_match('/filename\*="([^"]+)";?/i', $contentDisposition, $m)) {
+ $fileName = $m[1];
+ $fileName = $this->decodeAttachmentFileName($fileName);
+ } else if (preg_match('/filename\*=([^";]+);?/i', $contentDisposition, $m)) {
+ $fileName = $m[1];
+ $fileName = $this->decodeAttachmentFileName($fileName);
+ } else {
+ $fileName = '';
+ foreach (['0', '1'] as $i) {
+ if (preg_match('/filename\*'.$i.'[\*]?="([^"]+)";?/i', $contentDisposition, $m)) {
+ $part = $m[1];
+ $fileName .= $part;
+ } else if (preg_match('/filename\*'.$i.'[\*]?=([^";]+);?/i', $contentDisposition, $m)) {
+ $part = $m[1];
+ $fileName .= $part;
+ }
+ }
+
+ if ($fileName === '') {
+ $fileName = null;
+ } else {
+ $fileName = $this->decodeAttachmentFileName($fileName);
+ }
+ }
+
+ if ($fileName) {
+ $fileName = str_replace('{{_!Q!U!O!T!E!_}}', '"', $fileName);
+ }
+
+ return $fileName;
+ }
+
+ protected function decodeAttachmentFileName($fileName)
+ {
+ if ($fileName && stripos($fileName, "''") !== false) {
+ list($encoding, $fileName) = explode("''", $fileName);
+ $fileName = rawurldecode($fileName);
+ if (strtoupper($encoding) !== 'UTF-8') {
+ if ($encoding) {
+ $fileName = mb_convert_encoding($fileName, 'UTF-8', $encoding);
+ }
+ }
+ }
+ return $fileName;
+ }
+
+}
+
diff --git a/application/Espo/Modules/Crm/Controllers/Lead.php b/application/Espo/Modules/Crm/Controllers/Lead.php
index 02324e424f..22b40c1627 100644
--- a/application/Espo/Modules/Crm/Controllers/Lead.php
+++ b/application/Espo/Modules/Crm/Controllers/Lead.php
@@ -34,14 +34,11 @@ use \Espo\Core\Exceptions\BadRequest;
class Lead extends \Espo\Core\Controllers\Record
{
- public function actionConvert($params, $data, $request)
+ public function postActionConvert($params, $data, $request)
{
if (empty($data['id'])) {
throw new BadRequest();
}
- if (!$request->isPost()) {
- throw new BadRequest();
- }
$entity = $this->getRecordService()->convert($data['id'], $data['records']);
if (!empty($entity)) {
@@ -49,4 +46,13 @@ class Lead extends \Espo\Core\Controllers\Record
}
throw new Error();
}
+
+ public function postActionGetConvertAttributes($params, $data, $request)
+ {
+ if (empty($data['id'])) {
+ throw new BadRequest();
+ }
+
+ return $this->getRecordService()->getConvertAttributes($data['id']);
+ }
}
diff --git a/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php b/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php
index 3a0feed98e..e510f955a8 100644
--- a/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php
+++ b/application/Espo/Modules/Crm/EntryPoints/CampaignTrackOpened.php
@@ -90,7 +90,7 @@ class CampaignTrackOpened extends \Espo\Core\EntryPoints\Base
imagefill($img, 0, 0, $color);
imagepng($img);
- imagecolordeallocate($background);
+ imagecolordeallocate($color);
imagedestroy($img);
}
}
diff --git a/application/Espo/Modules/Crm/Repositories/Meeting.php b/application/Espo/Modules/Crm/Repositories/Meeting.php
index 385417f0a1..bcac81af50 100644
--- a/application/Espo/Modules/Crm/Repositories/Meeting.php
+++ b/application/Espo/Modules/Crm/Repositories/Meeting.php
@@ -30,6 +30,7 @@
namespace Espo\Modules\Crm\Repositories;
use Espo\ORM\Entity;
+use Espo\Core\Utils\Util;
class Meeting extends \Espo\Core\ORM\Repositories\RDB
{
@@ -210,7 +211,7 @@ class Meeting extends \Espo\Core\ORM\Repositories\RDB
$remindAt->sub(new \DateInterval('PT' . $seconds . 'S'));
foreach ($userIdList as $userId) {
- $id = uniqid(true);
+ $id = Util::generateId();
$sql = "
INSERT
diff --git a/application/Espo/Modules/Crm/Resources/i18n/en_US/Account.json b/application/Espo/Modules/Crm/Resources/i18n/en_US/Account.json
index c6be76bb79..a4fed37fc4 100644
--- a/application/Espo/Modules/Crm/Resources/i18n/en_US/Account.json
+++ b/application/Espo/Modules/Crm/Resources/i18n/en_US/Account.json
@@ -59,6 +59,7 @@
"Insurance": "Insurance",
"Legal": "Legal",
"Manufacturing": "Manufacturing",
+ "Marketing": "Marketing",
"Publishing": "Publishing",
"Real Estate": "Real Estate",
"Service": "Service",
diff --git a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Account.json b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Account.json
index e04c511362..01d6f5ff2d 100644
--- a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Account.json
+++ b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Account.json
@@ -45,6 +45,7 @@
"Insurance",
"Legal",
"Manufacturing",
+ "Marketing",
"Publishing",
"Real Estate",
"Service",
diff --git a/application/Espo/Modules/Crm/Services/Activities.php b/application/Espo/Modules/Crm/Services/Activities.php
index 15f35e9b1b..47c05afd6e 100644
--- a/application/Espo/Modules/Crm/Services/Activities.php
+++ b/application/Espo/Modules/Crm/Services/Activities.php
@@ -1101,22 +1101,39 @@ class Activities extends \Espo\Core\Services\Base
$sth = $pdo->prepare($sql);
$sth->execute();
- $rows = $sth->fetchAll(PDO::FETCH_ASSOC);
+ $rowList = $sth->fetchAll(PDO::FETCH_ASSOC);
$result = array();
- foreach ($rows as $row) {
- $entity = $this->getEntityManager()->getEntity($row['entityType'], $row['entityId']);
+ foreach ($rowList as $row) {
+ $reminderId = $row['id'];
+ $entityType = $row['entityType'];
+ $entityId = $row['entityId'];
+
+
+ $entity = $this->getEntityManager()->getEntity($entityType, $entityId);
$data = null;
+
if ($entity) {
+ if ($entityType === 'Meeting' || $entityType === 'Call') {
+ $entity->loadLinkMultipleField('users', array('status' => 'acceptanceStatus'));
+ $status = $entity->getLinkMultipleColumn('users', 'status', $userId);
+ if ($status === 'Declined') {
+ $this->removeReminder($reminderId);
+ continue;
+ }
+ }
+
$data = array(
'id' => $entity->id,
- 'entityType' => $row['entityType'],
+ 'entityType' => $entityType,
'dateStart' => $entity->get('dateStart'),
'name' => $entity->get('name')
);
+ } else {
+ continue;
}
$result[] = array(
- 'id' => $row['id'],
+ 'id' => $reminderId,
'data' => $data
);
diff --git a/application/Espo/Modules/Crm/Services/Lead.php b/application/Espo/Modules/Crm/Services/Lead.php
index d6ebf83ba5..c66985f7cb 100644
--- a/application/Espo/Modules/Crm/Services/Lead.php
+++ b/application/Espo/Modules/Crm/Services/Lead.php
@@ -36,6 +36,18 @@ use \Espo\ORM\Entity;
class Lead extends \Espo\Services\Record
{
+
+ protected function init()
+ {
+ parent::init();
+ $this->addDependency('container');
+ }
+
+ protected function getFieldManager()
+ {
+ return $this->getInjection('container')->get('fieldManager');
+ }
+
protected function getDuplicateWhereClause(Entity $entity, $data = array())
{
$data = array(
@@ -100,6 +112,105 @@ class Lead extends \Espo\Services\Record
}
}
+ public function getConvertAttributes($id)
+ {
+ $lead = $this->getEntity($id);
+
+ if (!$this->getAcl()->check($lead, 'read')) {
+ throw new Forbidden();
+ }
+
+ $data = array();
+
+ $entityList = $this->getMetadata()->get('entityDefs.Lead.convertEntityList', []);
+
+ $ignoreAttributeList = ['createdAt', 'modifiedAt', 'modifiedById', 'modifiedByName', 'createdById', 'createdByName'];
+
+ $convertFieldsDefs = $this->getMetadata()->get('entityDefs.Lead.convertFields', array());
+
+ foreach ($entityList as $entityType) {
+ if (!$this->getAcl()->checkScope($entityType, 'edit')) continue;
+
+ $attributes = array();
+
+ $target = $this->getEntityManager()->getEntity($entityType);
+
+ $fieldMap = array();
+
+ $fieldList = array_keys($this->getMetadata()->get('entityDefs.Lead.fields', array()));
+ foreach ($fieldList as $field) {
+ if (!$this->getMetadata()->get('entityDefs.'.$entityType.'.fields.' . $field)) continue;
+ if (
+ $this->getMetadata()->get(['entityDefs', $entityType, 'fields', $field, 'type'])
+ !==
+ $this->getMetadata()->get(['entityDefs', 'Lead', 'fields', $field, 'type'])
+ ) continue;
+
+ $fieldMap[$field] = $field;
+ }
+ if (array_key_exists($entityType, $convertFieldsDefs)) {
+ foreach ($convertFieldsDefs[$entityType] as $field => $leadField) {
+ $fieldMap[$field] = $leadField;
+ }
+ }
+
+ foreach ($fieldMap as $field => $leadField) {
+ $type = $this->getMetadata()->get(['entityDefs', 'Lead', 'fields', $field, 'type']);
+
+
+ if (in_array($type, ['file', 'image'])) {
+ $attachment = $lead->get($field);
+ if ($attachment) {
+ $attachment = $this->getEntityManager()->getRepository('Attachment')->getCopiedAttachment($attachment);
+ $idAttribute = $field . 'Id';
+ $nameAttribute = $field . 'Name';
+ if ($attachment) {
+ $attributes[$idAttribute] = $attachment->id;
+ $attributes[$nameAttribute] = $attachment->get('name');
+ }
+ }
+ continue;
+ } else if (in_array($type, ['attachmentMultiple'])) {
+ $attachmentList = $lead->get($field);
+ if (count($attachmentList)) {
+ $idList = [];
+ $nameHash = (object) [];
+ $typeHash = (object) [];
+ foreach ($attachmentList as $attachment) {
+ $attachment = $this->getEntityManager()->getRepository('Attachment')->getCopiedAttachment($attachment);
+ if ($attachment) {
+ $idList[] = $attachment->id;
+ $nameHash->{$attachment->id} = $attachment->get('name');
+ $typeHash->{$attachment->id} = $attachment->get('type');
+ }
+ }
+ $attributes[$field . 'Ids'] = $idList;
+ $attributes[$field . 'Names'] = $nameHash;
+ $attributes[$field . 'Types'] = $typeHash;
+ }
+ continue;
+ }
+
+ $leadAttributeList = $this->getFieldManager()->getAttributeList('Lead', $leadField);
+ $attributeList = $this->getFieldManager()->getAttributeList($entityType, $field);
+
+ foreach ($attributeList as $i => $attribute) {
+ if (in_array($attribute, $ignoreAttributeList)) continue;
+
+ $leadAttribute = $leadAttributeList[$i];
+ if (!$lead->has($leadAttribute)) continue;
+
+ $attributes[$attribute] = $lead->get($leadAttribute);
+ }
+ }
+
+ $data[$entityType] = $attributes;
+
+ }
+
+ return $data;
+ }
+
public function convert($id, $recordsData)
{
$lead = $this->getEntity($id);
diff --git a/application/Espo/ORM/EntityFactory.php b/application/Espo/ORM/EntityFactory.php
index 25d7c2decc..8dc1612111 100644
--- a/application/Espo/ORM/EntityFactory.php
+++ b/application/Espo/ORM/EntityFactory.php
@@ -43,10 +43,13 @@ class EntityFactory
public function create($name)
{
$className = $this->entityManager->normalizeEntityName($name);
- $defs = $this->metadata->get($name);
if (!class_exists($className)) {
return null;
}
+ $defs = $this->metadata->get($name);
+ if (is_null($defs)) {
+ return null;
+ }
$entity = new $className($defs, $this->entityManager);
return $entity;
}
diff --git a/application/Espo/ORM/Metadata.php b/application/Espo/ORM/Metadata.php
index b8aa4d1257..7cd7e8e51c 100644
--- a/application/Espo/ORM/Metadata.php
+++ b/application/Espo/ORM/Metadata.php
@@ -38,11 +38,11 @@ class Metadata
$this->data = $data;
}
- public function get($entityName)
+ public function get($entityType)
{
- return $this->data[$entityName];
+ if (!array_key_exists($entityType, $this->data)) {
+ return null;
+ }
+ return $this->data[$entityType];
}
-
}
-
-
diff --git a/application/Espo/ORM/Repositories/RDB.php b/application/Espo/ORM/Repositories/RDB.php
index 818f24a758..ebca5bcaaf 100644
--- a/application/Espo/ORM/Repositories/RDB.php
+++ b/application/Espo/ORM/Repositories/RDB.php
@@ -104,16 +104,17 @@ class RDB extends \Espo\ORM\Repository
protected function getEntityById($id)
{
+ $entity = $this->entityFactory->create($this->entityType);
+
+ if (!$entity) return null;
+
$params = array();
$this->handleSelectParams($params);
-
- $entity = $this->entityFactory->create($this->entityType);
- if ($entity) {
- if ($this->getMapper()->selectById($entity, $id, $params)) {
- $entity->setAsFetched();
- return $entity;
- }
+ if ($this->getMapper()->selectById($entity, $id, $params)) {
+ $entity->setAsFetched();
+ return $entity;
}
+
return null;
}
diff --git a/application/Espo/Repositories/Email.php b/application/Espo/Repositories/Email.php
index 4f6cf87521..34d80259fd 100644
--- a/application/Espo/Repositories/Email.php
+++ b/application/Espo/Repositories/Email.php
@@ -149,6 +149,9 @@ class Email extends \Espo\Core\ORM\Repositories\RDB
$idHash = (object) [];
foreach ($addressList as $address) {
$p = $this->getEntityManager()->getRepository('EmailAddress')->getEntityByAddress($address);
+ if (!$p) {
+ $p = $this->getEntityManager()->getRepository('InboundEmail')->where(array('emailAddress' => $address))->findOne();
+ }
if ($p) {
$nameHash->$address = $p->get('name');
$typeHash->$address = $p->getEntityName();
diff --git a/application/Espo/Resources/metadata/app/acl.json b/application/Espo/Resources/metadata/app/acl.json
index 448dd5543d..f0f6a1b55e 100644
--- a/application/Espo/Resources/metadata/app/acl.json
+++ b/application/Espo/Resources/metadata/app/acl.json
@@ -76,7 +76,7 @@
"fieldLevel": {
},
"assignmentPermission": "all",
- "userPermission": "no",
+ "userPermission": "all",
"portalPermission": "no"
},
"scopeLevelTypesDefaults": {
diff --git a/application/Espo/SelectManagers/Email.php b/application/Espo/SelectManagers/Email.php
index 21c99b32cf..f4a3f4bb10 100644
--- a/application/Espo/SelectManagers/Email.php
+++ b/application/Espo/SelectManagers/Email.php
@@ -119,10 +119,24 @@ class Email extends \Espo\Core\SelectManagers\Base
}
$d = array(
'usersMiddle.inTrash=' => false,
- 'usersMiddle.folderId' => null
+ 'usersMiddle.folderId' => null,
+ array(
+ 'status' => ['Archived', 'Sent']
+ )
);
if (!empty($idList)) {
$d['fromEmailAddressId!='] = $idList;
+ $d[] = array(
+ 'OR' => array(
+ 'status' => 'Archived',
+ 'createdById!=' => $this->getUser()->id
+ )
+ );
+ } else {
+ $d[] = array(
+ 'status' => 'Archived',
+ 'createdById!=' => $this->getUser()->id
+ );
}
$result['whereClause'][] = $d;
@@ -151,6 +165,9 @@ class Email extends \Espo\Core\SelectManagers\Base
'createdById' => $this->getUser()->id
)
),
+ array(
+ 'status!=' => 'Draft'
+ ),
'usersMiddle.inTrash=' => false
);
}
diff --git a/application/Espo/Services/Email.php b/application/Espo/Services/Email.php
index 3347bf66ae..982e35ebb7 100644
--- a/application/Espo/Services/Email.php
+++ b/application/Espo/Services/Email.php
@@ -586,7 +586,7 @@ class Email extends Record
$searchByEmailAddress = false;
if (!empty($params['where']) && is_array($params['where'])) {
foreach ($params['where'] as $i => $p) {
- if (!empty($p['field']) && $p['field'] == 'emailAddress') {
+ if (!empty($p['attribute']) && $p['attribute'] == 'emailAddress') {
$searchByEmailAddress = true;
$emailAddress = $p['value'];
unset($params['where'][$i]);
diff --git a/application/Espo/Services/EmailAddress.php b/application/Espo/Services/EmailAddress.php
index e88aa4ddfe..65abc84a27 100644
--- a/application/Espo/Services/EmailAddress.php
+++ b/application/Espo/Services/EmailAddress.php
@@ -177,13 +177,13 @@ class EmailAddress extends Record
{
$result = [];
+ $this->findInAddressBookUsers($query, $limit, $result);
if ($this->getAcl()->checkScope('Contact')) {
$this->findInAddressBookByEntityType($query, $limit, 'Contact', $result);
}
if ($this->getAcl()->checkScope('Lead')) {
$this->findInAddressBookByEntityType($query, $limit, 'Lead', $result);
}
- $this->findInAddressBookUsers($query, $limit, $result);
if ($this->getAcl()->checkScope('Account')) {
$this->findInAddressBookByEntityType($query, $limit, 'Account', $result);
}
diff --git a/application/Espo/Services/EmailNotification.php b/application/Espo/Services/EmailNotification.php
index 7c055c938c..f04a40e22a 100644
--- a/application/Espo/Services/EmailNotification.php
+++ b/application/Espo/Services/EmailNotification.php
@@ -133,7 +133,9 @@ class EmailNotification extends \Espo\Core\Services\Base
'body' => $body,
'isHtml' => true,
'to' => $emailAddress,
- 'isSystem' => true
+ 'isSystem' => true,
+ 'parentId' => $entity->id,
+ 'parentType' => $entity->getEntityType()
));
try {
$this->getMailSender()->send($email);
@@ -429,6 +431,13 @@ class EmailNotification extends \Espo\Core\Services\Base
'to' => $emailAddress,
'isSystem' => true
));
+ if ($parentId && $parentType) {
+ $email->set(array(
+ 'parentId' => $parentId,
+ 'parentType' => $parentType
+ ));
+ }
+
try {
$this->getMailSender()->send($email);
} catch (\Exception $e) {
@@ -517,6 +526,12 @@ class EmailNotification extends \Espo\Core\Services\Base
'to' => $emailAddress,
'isSystem' => true
));
+ if ($parentId && $parentType) {
+ $email->set(array(
+ 'parentId' => $parentId,
+ 'parentType' => $parentType
+ ));
+ }
try {
$this->getMailSender()->send($email);
} catch (\Exception $e) {
@@ -576,8 +591,11 @@ class EmailNotification extends \Espo\Core\Services\Base
'body' => $body,
'isHtml' => true,
'to' => $emailAddress,
- 'isSystem' => true
+ 'isSystem' => true,
+ 'parentId' => $parentId,
+ 'parentType' => $parentType
));
+
try {
$this->getMailSender()->send($email);
} catch (\Exception $e) {
diff --git a/application/Espo/Services/Import.php b/application/Espo/Services/Import.php
index ead09c2280..5024def9da 100644
--- a/application/Espo/Services/Import.php
+++ b/application/Espo/Services/Import.php
@@ -417,6 +417,9 @@ class Import extends \Espo\Services\Record
foreach ($importFieldList as $i => $field) {
if (!empty($field)) {
+ if (!array_key_exists($i, $row)) {
+ continue;
+ }
$value = $row[$i];
if ($field == 'id') {
if ($params['action'] == 'create') {
diff --git a/application/Espo/Services/User.php b/application/Espo/Services/User.php
index 52d288e401..18d285f68f 100644
--- a/application/Espo/Services/User.php
+++ b/application/Espo/Services/User.php
@@ -32,6 +32,7 @@ namespace Espo\Services;
use \Espo\Core\Exceptions\Forbidden;
use \Espo\Core\Exceptions\Error;
use \Espo\Core\Exceptions\NotFound;
+use Espo\Core\Utils\Util;
use \Espo\ORM\Entity;
@@ -153,7 +154,7 @@ class User extends Record
throw new Forbidden();
}
- $requestId = uniqid();
+ $requestId = Util::generateId();
$passwordChangeRequest = $this->getEntityManager()->getEntity('PasswordChangeRequest');
$passwordChangeRequest->set(array(
diff --git a/client/modules/crm/src/views/dashlets/calendar.js b/client/modules/crm/src/views/dashlets/calendar.js
index 219fe59548..486f8d5680 100644
--- a/client/modules/crm/src/views/dashlets/calendar.js
+++ b/client/modules/crm/src/views/dashlets/calendar.js
@@ -38,7 +38,7 @@ Espo.define('crm:views/dashlets/calendar', 'views/dashlets/abstract/base', funct
init: function () {
Dep.prototype.init.call(this);
- this.optionsFields['enabledScopeList'].options = this.getMetadata().get('clientDefs.Calendar.scopeList') || this.optionsFields['enabledScopeList'].options;
+ this.optionsFields['enabledScopeList'].options = this.getConfig().get('calendarEntityList') || [];
},
afterRender: function () {
diff --git a/client/modules/crm/src/views/lead/convert.js b/client/modules/crm/src/views/lead/convert.js
index 2683afc780..0697b24cc3 100644
--- a/client/modules/crm/src/views/lead/convert.js
+++ b/client/modules/crm/src/views/lead/convert.js
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
-Espo.define('crm:views/lead/convert', 'View', function (Dep) {
+Espo.define('crm:views/lead/convert', 'view', function (Dep) {
return Dep.extend({
@@ -90,42 +90,34 @@ Espo.define('crm:views/lead/convert', 'View', function (Dep) {
var attributeList = this.getFieldManager().getEntityAttributes(this.model.name);
var ignoreAttributeList = ['createdAt', 'modifiedAt', 'modifiedById', 'modifiedByName', 'createdById', 'createdByName'];
- scopeList.forEach(function (scope) {
- this.getModelFactory().create(scope, function (model) {
- model.populateDefaults();
+ if (scopeList.length) {
+ this.ajaxPostRequest('Lead/action/getConvertAttributes', {
+ id: this.model.id
+ }).done(function (data) {
+ scopeList.forEach(function (scope) {
+ this.getModelFactory().create(scope, function (model) {
+ model.populateDefaults();
- this.getFieldManager().getEntityAttributes(model.name).forEach(function (attr) {
- if (~attributeList.indexOf(attr) && !~ignoreAttributeList.indexOf(attr)) {
- model.set(attr, this.model.get(attr), {silent: true});
- }
+ model.set(data[scope] || {}, {silent: true});
+
+ this.createView(scope, 'views/record/edit', {
+ model: model,
+ el: '#main .edit-container-' + Espo.Utils.toDom(scope),
+ buttonsPosition: false,
+ layoutName: 'detailConvert',
+ exit: function () {},
+ }, function (view) {
+ i++;
+ if (i == scopeList.length) {
+ this.wait(false);
+ this.notify(false);
+ }
+ }, this);
+
+ }, this);
}, this);
-
- for (var field in this.model.defs.convertFields[scope]) {
- var leadField = this.model.defs.convertFields[scope][field];
- var leadAttrs = this.getFieldManager().getAttributes(this.model.getFieldParam(leadField, 'type'), leadField);
- var attrs = this.getFieldManager().getAttributes(model.getFieldParam(field, 'type'), field);
-
- attrs.forEach(function (attr, i) {
- var leadAttr = leadAttrs[i];
- model.set(attr, this.model.get(leadAttr));
- }.bind(this));
- }
-
- this.createView(scope, 'Record.Edit', {
- model: model,
- el: '#main .edit-container-' + Espo.Utils.toDom(scope),
- buttonsPosition: false,
- layoutName: 'detailConvert',
- exit: function () {},
- }, function (view) {
- i++;
- if (i == scopeList.length) {
- this.wait(false);
- this.notify(false);
- }
- }.bind(this));
- }, this);
- }, this);
+ }.bind(this));
+ }
if (scopeList.length == 0) {
this.wait(false);
diff --git a/client/res/templates/fields/email/search.tpl b/client/res/templates/fields/email/search.tpl
deleted file mode 100644
index 8e41d53c13..0000000000
--- a/client/res/templates/fields/email/search.tpl
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/client/res/templates/fields/phone/search.tpl b/client/res/templates/fields/phone/search.tpl
deleted file mode 100644
index 8e41d53c13..0000000000
--- a/client/res/templates/fields/phone/search.tpl
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/client/res/templates/fields/text/search.tpl b/client/res/templates/fields/text/search.tpl
index 20f56dea71..7141323b65 100644
--- a/client/res/templates/fields/text/search.tpl
+++ b/client/res/templates/fields/text/search.tpl
@@ -1,6 +1,6 @@
diff --git a/client/res/templates/fields/varchar/search.tpl b/client/res/templates/fields/varchar/search.tpl
index 20f56dea71..7141323b65 100644
--- a/client/res/templates/fields/varchar/search.tpl
+++ b/client/res/templates/fields/varchar/search.tpl
@@ -1,6 +1,6 @@
diff --git a/client/src/views/fields/email.js b/client/src/views/fields/email.js
index cbbd616a2b..3f5ce8f711 100644
--- a/client/src/views/fields/email.js
+++ b/client/src/views/fields/email.js
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
-Espo.define('views/fields/email', 'views/fields/base', function (Dep) {
+Espo.define('views/fields/email', 'views/fields/varchar', function (Dep) {
return Dep.extend({
@@ -38,11 +38,8 @@ Espo.define('views/fields/email', 'views/fields/base', function (Dep) {
listTemplate: 'fields/email/list',
- searchTemplate: 'fields/email/search',
-
validations: ['required', 'emailData'],
-
validateEmailData: function () {
var data = this.model.get(this.dataFieldName);
if (data && data.length) {
@@ -370,23 +367,8 @@ Espo.define('views/fields/email', 'views/fields/base', function (Dep) {
}
return data;
- },
-
- fetchSearch: function () {
- var value = this.$element.val() || null;
- if (value) {
- if (typeof value.trim === 'function') {
- value = value.trim();
- }
- var data = {
- type: 'like',
- value: value + '%',
- valueText: value
- };
- return data;
- }
- return false;
}
+
});
});
diff --git a/client/src/views/fields/phone.js b/client/src/views/fields/phone.js
index 63a1c5547d..6bb75320f7 100644
--- a/client/src/views/fields/phone.js
+++ b/client/src/views/fields/phone.js
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
-Espo.define('views/fields/phone', 'views/fields/base', function (Dep) {
+Espo.define('views/fields/phone', 'views/fields/varchar', function (Dep) {
return Dep.extend({
@@ -38,8 +38,6 @@ Espo.define('views/fields/phone', 'views/fields/base', function (Dep) {
listTemplate: 'fields/phone/list',
- searchTemplate: 'fields/phone/search',
-
validations: ['required'],
validateRequired: function () {
@@ -263,20 +261,8 @@ Espo.define('views/fields/phone', 'views/fields/base', function (Dep) {
}
return data;
- },
+ }
- fetchSearch: function () {
- var value = this.$element.val().trim() || null;
- if (value) {
- var data = {
- type: 'like',
- value: value + '%',
- valueText: value
- };
- return data;
- }
- return false;
- },
});
});
diff --git a/client/src/views/fields/text.js b/client/src/views/fields/text.js
index d6aeaa8106..079323494c 100644
--- a/client/src/views/fields/text.js
+++ b/client/src/views/fields/text.js
@@ -48,6 +48,8 @@ Espo.define('views/fields/text', 'views/fields/base', function (Dep) {
rowsDefault: 4,
+ searchTypeList: ['startsWith', 'contains', 'equals', 'isEmpty', 'isNotEmpty'],
+
events: {
'click a[data-action="seeMoreText"]': function (e) {
this.seeMoreText = true;
@@ -62,7 +64,6 @@ Espo.define('views/fields/text', 'views/fields/base', function (Dep) {
},
setupSearch: function () {
- this.searchParams.typeOptions = ['startsWith', 'contains', 'equals', 'isEmpty', 'isNotEmpty'];
this.events = _.extend({
'change select.search-type': function (e) {
var type = $(e.currentTarget).val();
@@ -192,6 +193,10 @@ Espo.define('views/fields/text', 'views/fields/base', function (Dep) {
}
}
return false;
+ },
+
+ getSearchType: function () {
+ return this.searchParams.typeFront || this.searchParams.type;
}
});
diff --git a/client/src/views/fields/varchar.js b/client/src/views/fields/varchar.js
index 6ef017de9f..712032a0b3 100644
--- a/client/src/views/fields/varchar.js
+++ b/client/src/views/fields/varchar.js
@@ -34,8 +34,9 @@ Espo.define('views/fields/varchar', 'views/fields/base', function (Dep) {
searchTemplate: 'fields/varchar/search',
+ searchTypeList: ['startsWith', 'endsWith', 'contains', 'equals', 'like', 'isEmpty', 'isNotEmpty'],
+
setupSearch: function () {
- this.searchParams.typeOptions = ['startsWith', 'endsWith', 'contains', 'equals', 'like', 'isEmpty', 'isNotEmpty'];
this.events = _.extend({
'change select.search-type': function (e) {
var type = $(e.currentTarget).val();
@@ -131,6 +132,10 @@ Espo.define('views/fields/varchar', 'views/fields/base', function (Dep) {
}
}
return false;
+ },
+
+ getSearchType: function () {
+ return this.searchParams.typeFront || this.searchParams.type;
}
});
diff --git a/tests/integration/Espo/Email/SearchByEmailAddressTest.php b/tests/integration/Espo/Email/SearchByEmailAddressTest.php
new file mode 100644
index 0000000000..0c7615e8ab
--- /dev/null
+++ b/tests/integration/Espo/Email/SearchByEmailAddressTest.php
@@ -0,0 +1,59 @@
+getContainer()->get('entityManager');
+
+ $email = $entityManager->getEntity('Email');
+ $email->set('from', 'test@test.com');
+ $email->set('status', 'Archived');
+ $entityManager->saveEntity($email);
+
+ $emailService = $this->getApplication()->getContainer()->get('serviceFactory')->create('Email');
+
+ $result = $emailService->findEntities(array(
+ 'where' => array(
+ array(
+ 'type' => 'equals',
+ 'attribute' => 'emailAddress',
+ 'value' => 'test@test.com'
+ )
+ )
+ ));
+
+ $this->assertArrayHasKey('collection', $result);
+ $this->assertEquals(1, count($result['collection']));
+ }
+}