mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Resolve #931
This commit is contained in:
parent
58e1c2e535
commit
4145c87e55
3 changed files with 82 additions and 102 deletions
|
|
@ -133,9 +133,8 @@ trait Contacts
|
||||||
\ini_set('auto_detect_line_endings', '1');
|
\ini_set('auto_detect_line_endings', '1');
|
||||||
$mData = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
|
$mData = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
|
||||||
if ($mData) {
|
if ($mData) {
|
||||||
$sFileStart = \fread($mData, 20);
|
$sFileStart = \fread($mData, 128);
|
||||||
\rewind($mData);
|
\rewind($mData);
|
||||||
|
|
||||||
if (false !== $sFileStart) {
|
if (false !== $sFileStart) {
|
||||||
$sFileStart = \trim($sFileStart);
|
$sFileStart = \trim($sFileStart);
|
||||||
if (false !== \strpos($sFileStart, 'BEGIN:VCARD')) {
|
if (false !== \strpos($sFileStart, 'BEGIN:VCARD')) {
|
||||||
|
|
@ -254,65 +253,30 @@ trait Contacts
|
||||||
|
|
||||||
private function importContactsFromVcfFile(\RainLoop\Model\Account $oAccount, /*resource*/ $rFile): int
|
private function importContactsFromVcfFile(\RainLoop\Model\Account $oAccount, /*resource*/ $rFile): int
|
||||||
{
|
{
|
||||||
$iCount = 0;
|
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
||||||
if ($oAccount && \is_resource($rFile)) {
|
if (\is_resource($rFile) && $oAddressBookProvider && $oAddressBookProvider->IsActive()) {
|
||||||
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
$sFile = \stream_get_contents($rFile);
|
||||||
if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) {
|
if (\is_string($sFile) && 5 < \strlen($sFile)) {
|
||||||
$sFile = \stream_get_contents($rFile);
|
$this->Logger()->Write('Import contacts from vcf');
|
||||||
if (\is_resource($rFile)) {
|
return $oAddressBookProvider->ImportVcfFile($sFile);
|
||||||
\fclose($rFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_string($sFile) && 5 < \strlen($sFile)) {
|
|
||||||
$this->Logger()->Write('Import contacts from vcf');
|
|
||||||
$iCount = $oAddressBookProvider->ImportVcfFile($sFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
return $iCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function importContactsFromCsvFile(\RainLoop\Model\Account $oAccount, /*resource*/ $rFile, string $sFileStart): int
|
private function importContactsFromCsvFile(\RainLoop\Model\Account $oAccount, /*resource*/ $rFile, string $sFileStart): int
|
||||||
{
|
{
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
$aHeaders = null;
|
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
||||||
$aData = array();
|
if (\is_resource($rFile) && $oAddressBookProvider && $oAddressBookProvider->IsActive()) {
|
||||||
|
$this->oLogger->Write('Import contacts from csv');
|
||||||
if ($oAccount && \is_resource($rFile)) {
|
$sDelimiter = ((int)\strpos($sFileStart, ',') > (int)\strpos($sFileStart, ';')) ? ',' : ';';
|
||||||
$oAddressBookProvider = $this->AddressBookProvider($oAccount);
|
foreach (\RainLoop\Providers\AddressBook\Utils::CsvStreamToContacts($rFile, $sDelimiter) as $oContact) {
|
||||||
if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) {
|
if ($oAddressBookProvider->ContactSave($oContact)) {
|
||||||
$sDelimiter = ((int)\strpos($sFileStart, ',') > (int)\strpos($sFileStart, ';')) ? ',' : ';';
|
++$iCount;
|
||||||
|
|
||||||
\setlocale(LC_CTYPE, 'en_US.UTF-8');
|
|
||||||
while (false !== ($mRow = \fgetcsv($rFile, 5000, $sDelimiter, '"'))) {
|
|
||||||
if (null === $aHeaders) {
|
|
||||||
if (3 >= \count($mRow)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$aHeaders = $mRow;
|
|
||||||
|
|
||||||
foreach ($aHeaders as $iIndex => $sHeaderValue) {
|
|
||||||
$aHeaders[$iIndex] = \MailSo\Base\Utils::Utf8Clear($sHeaderValue);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$aNewItem = array();
|
|
||||||
foreach ($aHeaders as $iIndex => $sHeaderValue) {
|
|
||||||
$aNewItem[$sHeaderValue] = isset($mRow[$iIndex]) ? $mRow[$iIndex] : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$aData[] = $aNewItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\count($aData)) {
|
|
||||||
$this->oLogger->Write('Import contacts from csv');
|
|
||||||
$iCount = $oAddressBookProvider->ImportCsvArray($aData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $iCount;
|
return $iCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,19 +83,6 @@ class AddressBook extends AbstractProvider
|
||||||
return $this->IsActive() ? $this->oDriver->IncFrec($aEmails, $bCreateAuto) : false;
|
return $this->IsActive() ? $this->oDriver->IncFrec($aEmails, $bCreateAuto) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ImportCsvArray(array $aCsvData) : int
|
|
||||||
{
|
|
||||||
$iCount = 0;
|
|
||||||
if ($this->IsActive()) {
|
|
||||||
foreach (AddressBook\Utils::CsvArrayToContacts($aCsvData) as $oContact) {
|
|
||||||
if ($this->ContactSave($oContact)) {
|
|
||||||
++$iCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $iCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ImportVcfFile(string $sVcfData) : int
|
public function ImportVcfFile(string $sVcfData) : int
|
||||||
{
|
{
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
|
|
|
||||||
|
|
@ -22,20 +22,29 @@ class Utils
|
||||||
'namesuffix' => 4,
|
'namesuffix' => 4,
|
||||||
'shortname' => 'NICKNAME',
|
'shortname' => 'NICKNAME',
|
||||||
'nickname' => 'NICKNAME',
|
'nickname' => 'NICKNAME',
|
||||||
|
'birthday' => 'BDAY',
|
||||||
|
|
||||||
|
'mobile' => array('TEL', 'CELL'),
|
||||||
|
'mobilephone' => array('TEL', 'CELL'),
|
||||||
|
|
||||||
|
'businessemail' => array('EMAIL', 'WORK'),
|
||||||
|
'businessemail2' => array('EMAIL', 'WORK'),
|
||||||
|
'businessemail3' => array('EMAIL', 'WORK'),
|
||||||
'businessphone' => array('TEL', 'WORK'),
|
'businessphone' => array('TEL', 'WORK'),
|
||||||
'businessphone2' => array('TEL', 'WORK'),
|
'businessphone2' => array('TEL', 'WORK'),
|
||||||
'businessphone3' => array('TEL', 'WORK'),
|
'businessphone3' => array('TEL', 'WORK'),
|
||||||
|
'businessmobile' => array('TEL', 'WORK,CELL'),
|
||||||
|
'businessmobilephone' => array('TEL', 'WORK,CELL'),
|
||||||
|
'businessweb' => array('URL', 'WORK'),
|
||||||
|
'businesswebpage' => array('URL', 'WORK'),
|
||||||
|
'businesswebsite' => array('URL', 'WORK'),
|
||||||
'companyphone' => array('TEL', 'WORK'),
|
'companyphone' => array('TEL', 'WORK'),
|
||||||
'companymainphone' => array('TEL', 'WORK'),
|
'companymainphone' => array('TEL', 'WORK'),
|
||||||
|
|
||||||
|
'primaryphone' => array('TEL', 'PREF,HOME'),
|
||||||
'homephone' => array('TEL', 'HOME'),
|
'homephone' => array('TEL', 'HOME'),
|
||||||
'homephone2' => array('TEL', 'HOME'),
|
'homephone2' => array('TEL', 'HOME'),
|
||||||
'homephone3' => array('TEL', 'HOME'),
|
'homephone3' => array('TEL', 'HOME'),
|
||||||
'mobile' => array('TEL', 'CELL'),
|
|
||||||
'mobilephone' => array('TEL', 'CELL'),
|
|
||||||
'businessmobile' => array('TEL', 'WORK,CELL'),
|
|
||||||
'businessmobilephone' => array('TEL', 'WORK,CELL'),
|
|
||||||
'otherphone' => 'TEL',
|
|
||||||
'primaryphone' => array('TEL', 'PREF,HOME'),
|
|
||||||
'email' => array('EMAIL', 'HOME'),
|
'email' => array('EMAIL', 'HOME'),
|
||||||
'email2' => array('EMAIL', 'HOME'),
|
'email2' => array('EMAIL', 'HOME'),
|
||||||
'email3' => array('EMAIL', 'HOME'),
|
'email3' => array('EMAIL', 'HOME'),
|
||||||
|
|
@ -48,53 +57,73 @@ class Utils
|
||||||
'emailaddress' => array('EMAIL', 'HOME'),
|
'emailaddress' => array('EMAIL', 'HOME'),
|
||||||
'email2address' => array('EMAIL', 'HOME'),
|
'email2address' => array('EMAIL', 'HOME'),
|
||||||
'email3address' => array('EMAIL', 'HOME'),
|
'email3address' => array('EMAIL', 'HOME'),
|
||||||
'otheremail' => 'EMAIL',
|
|
||||||
'businessemail' => array('EMAIL', 'WORK'),
|
|
||||||
'businessemail2' => array('EMAIL', 'WORK'),
|
|
||||||
'businessemail3' => array('EMAIL', 'WORK'),
|
|
||||||
'personalemail' => array('EMAIL', 'HOME'),
|
'personalemail' => array('EMAIL', 'HOME'),
|
||||||
'personalemail2' => array('EMAIL', 'HOME'),
|
'personalemail2' => array('EMAIL', 'HOME'),
|
||||||
'personalemail3' => array('EMAIL', 'HOME'),
|
'personalemail3' => array('EMAIL', 'HOME'),
|
||||||
|
'personalwebsite' => array('URL', 'HOME'),
|
||||||
|
|
||||||
|
'otheremail' => 'EMAIL',
|
||||||
|
'otherphone' => 'TEL',
|
||||||
'notes' => 'NOTE',
|
'notes' => 'NOTE',
|
||||||
'web' => 'URL',
|
'web' => 'URL',
|
||||||
'businessweb' => array('URL', 'WORK'),
|
|
||||||
'webpage' => 'URL',
|
'webpage' => 'URL',
|
||||||
'businesswebpage' => array('URL', 'WORK'),
|
'website' => 'URL'
|
||||||
'website' => 'URL',
|
/*
|
||||||
'businesswebsite' => array('URL', 'WORK'),
|
TODO:
|
||||||
'personalwebsite' => 'URL',
|
'company' => '',
|
||||||
'birthday' => 'BDAY'
|
'department' => '',
|
||||||
|
'jobtitle' => '',
|
||||||
|
'officelocation' => '',
|
||||||
|
'homestreet' => '',
|
||||||
|
'homecity' => '',
|
||||||
|
'homestate' => '',
|
||||||
|
'homepostalcode' => '',
|
||||||
|
'homecountry' => '',
|
||||||
|
'businessstreet' => '',
|
||||||
|
'businesscity' => '',
|
||||||
|
'businessstate' => '',
|
||||||
|
'businesspostalcode' => '',
|
||||||
|
'businesscountry' => '',
|
||||||
|
*/
|
||||||
);
|
);
|
||||||
|
|
||||||
public static function CsvArrayToContacts(array $aCsvData) : iterable
|
public static function CsvStreamToContacts(/*resource*/ $rFile, string $sDelimiter) : iterable
|
||||||
{
|
{
|
||||||
foreach ($aCsvData as $aItem) {
|
\setlocale(LC_CTYPE, 'en_US.UTF-8');
|
||||||
|
|
||||||
|
$aHeaders = \fgetcsv($rFile, 5000, $sDelimiter, '"');
|
||||||
|
if (!$aHeaders || 3 >= \count($aHeaders)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach ($aHeaders as $iIndex => $sItemName) {
|
||||||
|
$sItemName = \MailSo\Base\Utils::Utf8Clear($sItemName);
|
||||||
|
$sItemName = \strtoupper(\trim(\preg_replace('/[\s\-]+/', '', $sItemName)));
|
||||||
|
if (!\array_key_exists($sItemName, \Sabre\VObject\Component\VCard::$propertyMap)) {
|
||||||
|
$sItemName = \strtolower($sItemName);
|
||||||
|
$sItemName = isset(static::$aMap[$sItemName]) ? static::$aMap[$sItemName] : null;
|
||||||
|
}
|
||||||
|
$aHeaders[$iIndex] = $sItemName;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (false !== ($mRow = \fgetcsv($rFile, 5000, $sDelimiter, '"'))) {
|
||||||
\MailSo\Base\Utils::ResetTimeLimit();
|
\MailSo\Base\Utils::ResetTimeLimit();
|
||||||
$iCount = 0;
|
$iCount = 0;
|
||||||
$oVCard = new \Sabre\VObject\Component\VCard;
|
$oVCard = new \Sabre\VObject\Component\VCard;
|
||||||
$aName = ['','','','',''];
|
$aName = ['','','','',''];
|
||||||
foreach ($aItem as $sItemName => $sItemValue) {
|
foreach ($mRow as $iIndex => $sItemValue) {
|
||||||
$sItemName = \strtoupper(\trim(\preg_replace('/[\s\-]+/', '', $sItemName)));
|
$sItemName = $aHeaders[$iIndex];
|
||||||
$sItemValue = \trim($sItemValue);
|
$sItemValue = \trim($sItemValue);
|
||||||
if (!empty($sItemName) && !empty($sItemValue)) {
|
if (isset($sItemName) && !empty($sItemValue)) {
|
||||||
if (\array_key_exists($sItemName, \Sabre\VObject\Component\VCard::$propertyMap)) {
|
$mType = \is_array($sItemName) ? $sItemName[0] : $sItemName;
|
||||||
$mData = $sItemName;
|
++$iCount;
|
||||||
|
if (\is_int($mType)) {
|
||||||
|
$aName[$mType] = $sItemValue;
|
||||||
|
} else if (\is_array($sItemName)) {
|
||||||
|
$oVCard->add($mType, $sItemValue, ['type' => $sItemName[1]]);
|
||||||
|
} else if ('FN' === $mType || 'NICKNAME' === $mType) {
|
||||||
|
$oVCard->$mType = $sItemValue;
|
||||||
} else {
|
} else {
|
||||||
$sItemName = \strtolower($sItemName);
|
$oVCard->add($mType, $sItemValue);
|
||||||
$mData = !empty($sItemName) && isset($aMap[$sItemName]) ? $aMap[$sItemName] : null;
|
|
||||||
}
|
|
||||||
if ($mData) {
|
|
||||||
$mType = \is_array($mData) ? $mData[0] : $mData;
|
|
||||||
++$iCount;
|
|
||||||
if (\is_int($mType)) {
|
|
||||||
$aName[$mType] = $sItemValue;
|
|
||||||
} else if (\is_array($mData)) {
|
|
||||||
$oVCard->add($mType, $sItemValue, ['type' => $mData[1]]);
|
|
||||||
} else if ('FN' === $mType || 'NICKNAME' === $mType) {
|
|
||||||
$oVCard->$mType = $sItemValue;
|
|
||||||
} else {
|
|
||||||
$oVCard->add($mType, $sItemValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue