Added export contacts (vCard)

This commit is contained in:
RainLoop Team 2014-04-29 00:34:34 +04:00
parent c25b5bfef7
commit c248292f07
37 changed files with 489 additions and 237 deletions

View file

@ -565,6 +565,15 @@ class Http
return $bResult;
}
public function ServerNoCache()
{
@\header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
@\header('Last-Modified: '.\gmdate('D, d M Y H:i:s').' GMT');
@\header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
@\header('Cache-Control: post-check=0, pre-check=0', false);
@\header('Pragma: no-cache');
}
/**
* @param int $iStatus
*

View file

@ -6116,6 +6116,42 @@ class Actions
return $this->rawSmart(false);
}
/**
* @return bool
*/
public function RawContactsVcf()
{
$oAccount = $this->getAccountFromToken();
\header('Content-Type: text/directory; charset=UTF-8');
\header('Content-Disposition: attachment; filename="contacts.vcf"', true);
\header('Accept-Ranges: none', true);
\header('Content-Transfer-Encoding: binary');
$this->oHttp->ServerNoCache();
return $this->AddressBookProvider($oAccount)->IsActive() ?
$this->AddressBookProvider($oAccount)->Export($oAccount->ParentEmailHelper(), 'vcf') : false;
}
/**
* @return bool
*/
public function RawContactsCsv()
{
$oAccount = $this->getAccountFromToken();
\header('Content-Type: ext/csv; charset=UTF-8');
\header('Content-Disposition: attachment; filename="contacts.csv"', true);
\header('Accept-Ranges: none', true);
\header('Content-Transfer-Encoding: binary');
$this->oHttp->ServerNoCache();
return $this->AddressBookProvider($oAccount)->IsActive() ?
$this->AddressBookProvider($oAccount)->Export($oAccount->ParentEmailHelper(), 'csv') : false;
}
/**
* @return bool
*/

View file

@ -74,6 +74,17 @@ class AddressBook extends \RainLoop\Providers\AbstractProvider
{
return $this->IsActive() ? $this->oDriver->Sync($sEmail, $sUrl, $sUser, $sPassword) : false;
}
/**
* @param string $sEmail
* @param string $sType = 'vcf'
*
* @return bool
*/
public function Export($sEmail, $sType = 'vcf')
{
return $this->IsActive() ? $this->oDriver->Export($sEmail, $sType) : false;
}
/**
* @param string $sEmail

View file

@ -265,6 +265,25 @@ class Contact
return (string) $oVCard->serialize();
}
/**
* @todo
* @return string
*/
public function ToCsvHeader()
{
return '';
}
/**
* @todo
* @return string
*/
public function ToCsvLine()
{
$this->UpdateDependentValues();
return '';
}
/**
* @param mixed $oProp
* @param bool $bOldVersion

View file

@ -362,6 +362,57 @@ class PdoAddressBook
return true;
}
/**
* @param string $sEmail
* @param string $sType = 'vcf'
*
* @return bool
*/
public function Export($sEmail, $sType = 'vcf')
{
$this->SyncDatabase();
$iUserID = $this->getUserId($sEmail);
if (0 >= $iUserID)
{
return false;
}
$bVcf = 'vcf' === $sType;
$bCsvHeader = false;
$aDatabaseSyncData = $this->prepearDatabaseSyncData($iUserID);
if (\is_array($aDatabaseSyncData) && 0 < \count($aDatabaseSyncData))
{
foreach ($aDatabaseSyncData as $mData)
{
if ($mData && isset($mData['id_contact'], $mData['deleted']) && !$mData['deleted'])
{
$oContact = $this->GetContactByID($sEmail, $mData['id_contact']);
if ($oContact)
{
if ($bVcf)
{
echo $oContact->ToVCard();
}
else
{
if (!$bCsvHeader)
{
$bCsvHeader = true;
echo $oContact->ToCsvHeader();
}
echo $oContact->ToCsvLine();
}
}
}
}
}
return true;
}
/**
* @param string $sEmail
* @param \RainLoop\Providers\AddressBook\Classes\Contact $oContact

View file

@ -156,6 +156,7 @@ class Service
else
{
@header('Content-Type: text/html; charset=utf-8');
$this->oHttp->ServerNoCache();
$aData = $this->startUpData($bAdmin);

View file

@ -950,11 +950,7 @@ class ServiceActions
private function localAppData($bAdmin = false)
{
@\header('Content-Type: application/javascript; charset=utf-8');
@\header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
@\header('Last-Modified: '.\gmdate('D, d M Y H:i:s').' GMT');
@\header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
@\header('Cache-Control: post-check=0, pre-check=0', false);
@\header('Pragma: no-cache');
$this->oHttp->ServerNoCache();
$sAuthAccountHash = '';
if (!$bAdmin)

View file

@ -12,21 +12,36 @@
</a>
</div>
<div class="btn-group">
<a class="btn dropdown-toggle buttonMore" data-toggle="dropdown">
<div class="btn-group dropdown" data-bind="registrateBootstrapDropdown: true">
<a id="contacts-more-dropdown-id" class="btn dropdown-toggle buttonMore" href="#" tabindex="-1" data-toggle="dropdown">
<i data-bind="css: {'icon-list': !contacts.importing() && !contacts.syncing(),
'icon-spinner animated': contacts.importing() || contacts.syncing()}"></i>
</a>
<ul class="dropdown-menu g-ui-menu" role="menu">
<li class="e-item">
<a class="e-link" data-bind="initDom: importUploaderButton">
<ul class="dropdown-menu g-ui-menu" role="menu" aria-labelledby="contacts-more-dropdown-id">
<li class="e-item" role="presentation">
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="initDom: importUploaderButton">
<i data-bind="css: {'icon-list-add': !contacts.importing(), 'icon-spinner animated': contacts.importing}"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_IMPORT"></span>
</a>
</li>
<li class="e-item" data-bind="visible: enableContactsSync() && allowContactsSync()">
<a class="e-link" data-bind="command: syncCommand">
<!-- <li class="e-item" role="presentation" data-bind="visible: allowExport" >
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="click: exportCsv">
<i data-bind="css: {'icon-download': !contacts.exportingCsv(), 'icon-spinner animated': contacts.exportingCsv}"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_EXPORT_CSV"></span>
</a>
</li>-->
<li class="e-item" role="presentation" data-bind="visible: allowExport" >
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="click: exportVcf">
<i data-bind="css: {'icon-download': !contacts.exportingVcf(), 'icon-spinner animated': contacts.exportingVcf}"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_EXPORT_VCARD"></span>
</a>
</li>
<li class="divider" role="presentation" data-bind="visible: enableContactsSync() && allowContactsSync()"></li>
<li class="e-item" role="presentation" data-bind="visible: enableContactsSync() && allowContactsSync()">
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="command: syncCommand">
<i data-bind="css: {'icon-sync': !contacts.syncing(), 'icon-spinner animated': contacts.syncing}"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_SYNC"></span>