Commit 93897fb4 authored by Sebastian Kummer's avatar Sebastian Kummer

Merge pull request #447 in ZP/z-push from...

Merge pull request #447 in ZP/z-push from feature/ZP-1134-check-if-already-synchronized-folders to develop

* commit '8ff33644':
  ZP-1134 Check for 'secondarycontact' capability support to send additional contact folders, print capabilities in DEBUG level.
  ZP-1134 Fixed comments.
  ZP-1134 Set TypeReal on all SyncFolder that pass through ChangesMemoryWrapper from cache, fixed support for PHP 5.4 that does clone objects from the cache (requires some explicit setting), moved patching of folders from Synchronize() to ImportFolderChange() to update the cache correctly (requires following AddFolder() in PHP 5.4), introduced ChangesMemoryWrapper::SYNCHRONIZING flag to indicate to Config() if updates on folders should be performed (should e.g. no for FolderUpdate command), patch and re-export as new (ADD) secondary contact folders that were synchronized as standard (SYNC_FOLDER_TYPE_USER_CONTACT) before (ticket task).
  ZP-1134 Configured additional SyncFolder objects are now generated on demand - not in ZPush::CheckAdvancedConfig() anymore, uses DeviceManager->BuildSyncFolderObject() to build SyncFolder objects.
  ZP-1134 Added DeviceManager->IsKoeSupportingSecondaryContacts() to check if secondary contacts should be synchronized, renamed DeviceManager->getAdditionalSyncFolderObject() to DeviceManager->BuildSyncFolderObject() and made it public - nethod updates unpatched contact folders for correct processing by ChangesMemoryWrapper.
parents a2cc2877 8ff33644
...@@ -27,6 +27,7 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -27,6 +27,7 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
const CHANGE = 1; const CHANGE = 1;
const DELETION = 2; const DELETION = 2;
const SOFTDELETION = 3; const SOFTDELETION = 3;
const SYNCHRONIZING = 4;
private $changes; private $changes;
private $step; private $step;
...@@ -70,6 +71,13 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -70,6 +71,13 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
continue; continue;
} }
} }
// make sure, if the folder is already in cache, to set the TypeReal flag (if available)
$cacheFolder = $this->GetFolder($addFolder->serverid);
if (isset($cacheFolder->TypeReal)) {
$addFolder->TypeReal = $cacheFolder->TypeReal;
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ChangesMemoryWrapper->Config(): Set REAL foldertype for folder '%s' from cache: '%s'", $addFolder->displayname, $addFolder->TypeReal));
}
// add folder to the device - if folder is already on the device, nothing will happen // add folder to the device - if folder is already on the device, nothing will happen
$this->ImportFolderChange($addFolder); $this->ImportFolderChange($addFolder);
} }
...@@ -77,6 +85,15 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -77,6 +85,15 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
// look for folders which are currently on the device if there are now not to be synched anymore // look for folders which are currently on the device if there are now not to be synched anymore
$alreadyDeleted = $this->GetDeletedFolders(); $alreadyDeleted = $this->GetDeletedFolders();
foreach ($this->ExportFolders(true) as $sid => $folder) { foreach ($this->ExportFolders(true) as $sid => $folder) {
// check if previously synchronized secondary contact folders were patched for KOE - if no RealType is set they weren't
if ($flags == self::SYNCHRONIZING && ZPush::GetDeviceManager()->IsKoeSupportingSecondaryContacts() && $folder->type == SYNC_FOLDER_TYPE_USER_CONTACT && !isset($folder->TypeReal)) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ChangesMemoryWrapper->Config(): Identifided secondary contact folder '%s' that was not patched for KOE before. Re-adding it now.", $folder->displayname));
// we need to delete it from the hierarchy cache so it's exported as NEW (way to convince OL to add it)
$this->DelFolder($folder->serverid);
$folder->flags = SYNC_NEWMESSAGE;
$this->ImportFolderChange($folder);
}
// we are only looking at additional folders // we are only looking at additional folders
if (isset($folder->NoBackendFolder)) { if (isset($folder->NoBackendFolder)) {
// look if this folder is still in the list of additional folders and was not already deleted (e.g. missing permissions) // look if this folder is still in the list of additional folders and was not already deleted (e.g. missing permissions)
...@@ -205,9 +222,16 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -205,9 +222,16 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
$retFolder = false; $retFolder = false;
} }
// KOE ZP-907: When a secondary contact folder is patched (update type & change name) don't import it through the backend // KOE ZP-907: When a secondary contact folder is patched (update type & change name) don't import it through the backend
// This is a bit more permissive than ZPush::GetDeviceManager()->IsKoeSupportingSecondaryContacts() so that updates are always catched
// even if the feature was disabled in the meantime.
elseif ($folder->type == SYNC_FOLDER_TYPE_UNKNOWN && ZPush::GetDeviceManager()->IsKoe() && !Utils::IsFolderToBeProcessedByKoe($folder)) { elseif ($folder->type == SYNC_FOLDER_TYPE_UNKNOWN && ZPush::GetDeviceManager()->IsKoe() && !Utils::IsFolderToBeProcessedByKoe($folder)) {
ZLog::Write(LOGLEVEL_DEBUG, "ChangesMemoryWrapper->ImportFolderChange(): Rewrote folder type to real type, as KOE patched the folder"); ZLog::Write(LOGLEVEL_DEBUG, "ChangesMemoryWrapper->ImportFolderChange(): Rewrote folder type to real type, as KOE patched the folder");
$folder->type = $folder->TypeReal; // cacheFolder contains other properties that must be maintained
// so we continue using the cacheFolder, but rewrite the type and use the incoming displayname
$cacheFolder = $this->GetFolder($folder->serverid);
$cacheFolder->type = $cacheFolder->TypeReal;
$cacheFolder->displayname = $folder->displayname;
$folder = $cacheFolder;
$retFolder = $folder; $retFolder = $folder;
} }
// do regular folder update // do regular folder update
...@@ -254,6 +278,14 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -254,6 +278,14 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
return false; return false;
} }
// ZP-907: if we are ADDING a secondary contact folder and a compatible Outlook is connected, rewrite the type to SYNC_FOLDER_TYPE_UNKNOWN and mark the foldername
if (ZPush::GetDeviceManager()->IsKoeSupportingSecondaryContacts() && $folder->type == SYNC_FOLDER_TYPE_USER_CONTACT &&
(!$this->GetFolder($folder->serverid, true) || !$this->GetFolder($folder->serverid) || $this->GetFolder($folder->serverid)->type === SYNC_FOLDER_TYPE_UNKNOWN)
) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ChangesMemoryWrapper->ImportFolderChange(): Sending new folder '%s' as type SYNC_FOLDER_TYPE_UNKNOWN as Outlook is not able to handle secondary contact folders", $folder->displayname));
$folder = Utils::ChangeFolderToTypeUnknownForKoe($folder);
}
// load this change into memory // load this change into memory
$this->changes[] = array(self::CHANGE, $folder); $this->changes[] = array(self::CHANGE, $folder);
...@@ -342,16 +374,9 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx ...@@ -342,16 +374,9 @@ class ChangesMemoryWrapper extends HierarchyCache implements IImportChanges, IEx
$change = $this->changes[$this->step]; $change = $this->changes[$this->step];
if ($change[0] == self::CHANGE) { if ($change[0] == self::CHANGE) {
if (! $this->GetFolder($change[1]->serverid, true)) { if (! $this->GetFolder($change[1]->serverid, true))
$change[1]->flags = SYNC_NEWMESSAGE; $change[1]->flags = SYNC_NEWMESSAGE;
// ZP-907: if we are ADDING a secondary contact folder and Outlook is connected, rewrite the type to SYNC_FOLDER_TYPE_UNKNOWN and mark the foldername
// TODO: ZP-1124 this should only be done, if the feature is enabled and the KOE version supports this feature
if (defined('KOE_CAPABILITY_SECONDARYCONTACTS') && KOE_CAPABILITY_SECONDARYCONTACTS && $change[1]->type == SYNC_FOLDER_TYPE_USER_CONTACT && ZPush::GetDeviceManager()->IsKoe()) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("ChangesMemoryWrapper->Synchronize(): Synchronizing folder '%s' as type SYNC_FOLDER_TYPE_UNKNOWN as Outlook is not able to handle secondary contact folders", $change[1]->displayname));
$change[1] = Utils::ChangeFolderToTypeUnknownForKoe($change[1]);
}
}
$this->exportImporter->ImportFolderChange($change[1]); $this->exportImporter->ImportFolderChange($change[1]);
} }
// deletion // deletion
......
...@@ -95,6 +95,7 @@ class DeviceManager { ...@@ -95,6 +95,7 @@ class DeviceManager {
if ($this->IsKoe() && $this->device->GetKoeVersion() !== false) { if ($this->IsKoe() && $this->device->GetKoeVersion() !== false) {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KOE: %s / %s / %s", $this->device->GetKoeVersion(), $this->device->GetKoeBuild(), strftime("%Y-%m-%d %H:%M", $this->device->GetKoeBuildDate()))); ZLog::Write(LOGLEVEL_DEBUG, sprintf("KOE: %s / %s / %s", $this->device->GetKoeVersion(), $this->device->GetKoeBuild(), strftime("%Y-%m-%d %H:%M", $this->device->GetKoeBuildDate())));
ZLog::Write(LOGLEVEL_DEBUG, sprintf("KOE Capabilities: %s ", count($this->device->GetKoeCapabilities()) ? implode(',', $this->device->GetKoeCapabilities()) : 'unknown'));
} }
} }
...@@ -488,15 +489,7 @@ class DeviceManager { ...@@ -488,15 +489,7 @@ class DeviceManager {
ZLog::Write(LOGLEVEL_WARN, sprintf("DeviceManager->GetAdditionalUserSyncFolders(): Additional folder '%s' has no parentid. Please run 'z-push-admin -a fixstates' to fix this issue.", $df['name'])); ZLog::Write(LOGLEVEL_WARN, sprintf("DeviceManager->GetAdditionalUserSyncFolders(): Additional folder '%s' has no parentid. Please run 'z-push-admin -a fixstates' to fix this issue.", $df['name']));
} }
$folder = $this->getAdditionalSyncFolderObject($df['store'], $df['folderid'], $df['parentid'], $df['name'], $df['type'], $df['flags'], DeviceManager::FLD_ORIGIN_SHARED); $folder = $this->BuildSyncFolderObject($df['store'], $df['folderid'], $df['parentid'], $df['name'], $df['type'], $df['flags'], DeviceManager::FLD_ORIGIN_SHARED);
// adjust additional folders so it matches not yet processed KOE type UNKNOWN folders
$type = $this->device->GetFolderType($folder->serverid);
if (defined('KOE_CAPABILITY_SECONDARYCONTACTS') && KOE_CAPABILITY_SECONDARYCONTACTS && $type !== $folder->type && $type == SYNC_FOLDER_TYPE_UNKNOWN) {
ZLog::Write(LOGLEVEL_DEBUG, "DeviceManager->GetAdditionalUserSyncFolders(): Modifying additional folder so it matches an unprocessed KOE folder");
$folder = Utils::ChangeFolderToTypeUnknownForKoe($folder);
}
$folders[$folder->BackendId] = $folder; $folders[$folder->BackendId] = $folder;
} }
...@@ -504,7 +497,7 @@ class DeviceManager { ...@@ -504,7 +497,7 @@ class DeviceManager {
if (KOE_CAPABILITY_GAB && $this->IsKoe() && KOE_GAB_STORE != "" && KOE_GAB_NAME != "") { if (KOE_CAPABILITY_GAB && $this->IsKoe() && KOE_GAB_STORE != "" && KOE_GAB_NAME != "") {
// if KOE_GAB_FOLDERID is set, use it // if KOE_GAB_FOLDERID is set, use it
if (KOE_GAB_FOLDERID != "") { if (KOE_GAB_FOLDERID != "") {
$folder = $this->getAdditionalSyncFolderObject(KOE_GAB_STORE, KOE_GAB_FOLDERID, '0', KOE_GAB_NAME, SYNC_FOLDER_TYPE_USER_APPOINTMENT, 0, DeviceManager::FLD_ORIGIN_GAB); $folder = $this->BuildSyncFolderObject(KOE_GAB_STORE, KOE_GAB_FOLDERID, '0', KOE_GAB_NAME, SYNC_FOLDER_TYPE_USER_APPOINTMENT, 0, DeviceManager::FLD_ORIGIN_GAB);
$folders[$folder->BackendId] = $folder; $folders[$folder->BackendId] = $folder;
} }
else { else {
...@@ -521,7 +514,7 @@ class DeviceManager { ...@@ -521,7 +514,7 @@ class DeviceManager {
} }
if ($backendGabId) { if ($backendGabId) {
$folders[$backendGabId] = $this->getAdditionalSyncFolderObject(KOE_GAB_STORE, $backendGabId, '0', KOE_GAB_NAME, SYNC_FOLDER_TYPE_USER_APPOINTMENT, 0, DeviceManager::FLD_ORIGIN_GAB); $folders[$backendGabId] = $this->BuildSyncFolderObject(KOE_GAB_STORE, $backendGabId, '0', KOE_GAB_NAME, SYNC_FOLDER_TYPE_USER_APPOINTMENT, 0, DeviceManager::FLD_ORIGIN_GAB);
} }
} }
} }
...@@ -791,6 +784,17 @@ class DeviceManager { ...@@ -791,6 +784,17 @@ class DeviceManager {
return in_array($feature, $capabilities); return in_array($feature, $capabilities);
} }
/**
* Indicates if the connected device is Outlook + KOE and supports the
* secondary contact folder synchronization.
*
* @access public
* @return boolean
*/
public function IsKoeSupportingSecondaryContacts() {
return defined('KOE_CAPABILITY_SECONDARYCONTACTS') && KOE_CAPABILITY_SECONDARYCONTACTS && $this->IsKoe() && $this->HasKoeFeature('secondarycontacts');
}
/** /**
* Adds an Exceptions to the process tracking * Adds an Exceptions to the process tracking
* *
...@@ -1201,10 +1205,10 @@ class DeviceManager { ...@@ -1201,10 +1205,10 @@ class DeviceManager {
* @param int $flags * @param int $flags
* @param string $folderOrigin * @param string $folderOrigin
* *
* @access private * @access public
* @returns SyncFolder * @returns SyncFolder
*/ */
private function getAdditionalSyncFolderObject($store, $folderid, $parentid, $name, $type, $flags, $folderOrigin) { public function BuildSyncFolderObject($store, $folderid, $parentid, $name, $type, $flags, $folderOrigin) {
$folder = new SyncFolder(); $folder = new SyncFolder();
$folder->BackendId = $folderid; $folder->BackendId = $folderid;
$folder->serverid = $this->GetFolderIdForBackendId($folder->BackendId, true, $folderOrigin, $name); $folder->serverid = $this->GetFolderIdForBackendId($folder->BackendId, true, $folderOrigin, $name);
...@@ -1216,6 +1220,12 @@ class DeviceManager { ...@@ -1216,6 +1220,12 @@ class DeviceManager {
$folder->Store = $store; $folder->Store = $store;
$folder->Flags = $flags; $folder->Flags = $flags;
// adjust additional folders so it matches not yet processed KOE type UNKNOWN folders
$synctype = $this->device->GetFolderType($folder->serverid);
if ($this->IsKoeSupportingSecondaryContacts() && $synctype !== $folder->type && $synctype == SYNC_FOLDER_TYPE_UNKNOWN) {
ZLog::Write(LOGLEVEL_DEBUG, "DeviceManager->BuildSyncFolderObject(): Modifying additional folder so it matches an unprocessed KOE folder");
$folder = Utils::ChangeFolderToTypeUnknownForKoe($folder);
}
return $folder; return $folder;
} }
} }
...@@ -368,9 +368,7 @@ class ZPush { ...@@ -368,9 +368,7 @@ class ZPush {
if (isset($additionalFolders) && !is_array($additionalFolders)) if (isset($additionalFolders) && !is_array($additionalFolders))
ZLog::Write(LOGLEVEL_ERROR, "ZPush::CheckConfig() : The additional folders synchronization not available as array."); ZLog::Write(LOGLEVEL_ERROR, "ZPush::CheckConfig() : The additional folders synchronization not available as array.");
else { else {
self::$addSyncFolders = array(); // check configured data
// process configured data
foreach ($additionalFolders as $af) { foreach ($additionalFolders as $af) {
if (!is_array($af) || !isset($af['store']) || !isset($af['folderid']) || !isset($af['name']) || !isset($af['type'])) { if (!is_array($af) || !isset($af['store']) || !isset($af['folderid']) || !isset($af['name']) || !isset($af['type'])) {
...@@ -387,21 +385,8 @@ class ZPush { ...@@ -387,21 +385,8 @@ class ZPush {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPush::CheckConfig() : the type of the additional synchronization folder '%s is not permitted.", $af['name'])); ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPush::CheckConfig() : the type of the additional synchronization folder '%s is not permitted.", $af['name']));
continue; continue;
} }
// the data will be inizialized when used via self::getAddFolders()
$folder = new SyncFolder();
$folder->BackendId = $af['folderid'];
$folder->serverid = ZPush::GetDeviceManager(true)->GetFolderIdForBackendId($folder->BackendId, true, DeviceManager::FLD_ORIGIN_CONFIG, $af['name']);
$folder->parentid = 0; // only top folders are supported
$folder->displayname = $af['name'];
$folder->type = $af['type'];
// save store as custom property which is not streamed directly to the device
$folder->NoBackendFolder = true;
$folder->Store = $af['store'];
self::$addSyncFolders[$folder->BackendId] = $folder;
} }
} }
ZLog::Write(LOGLEVEL_DEBUG, sprintf("Used timezone '%s'", date_default_timezone_get())); ZLog::Write(LOGLEVEL_DEBUG, sprintf("Used timezone '%s'", date_default_timezone_get()));
...@@ -603,7 +588,7 @@ class ZPush { ...@@ -603,7 +588,7 @@ class ZPush {
static public function GetAdditionalSyncFolders($backendIdsAsKeys = true) { static public function GetAdditionalSyncFolders($backendIdsAsKeys = true) {
// get user based folders which should be synchronized // get user based folders which should be synchronized
$userFolder = self::GetDeviceManager()->GetAdditionalUserSyncFolders(); $userFolder = self::GetDeviceManager()->GetAdditionalUserSyncFolders();
$addfolders = self::$addSyncFolders + $userFolder; $addfolders = self::getAddSyncFolders() + $userFolder;
// if requested, we rewrite the backendids to folderids here // if requested, we rewrite the backendids to folderids here
if ($backendIdsAsKeys === false && !empty($addfolders)) { if ($backendIdsAsKeys === false && !empty($addfolders)) {
ZLog::Write(LOGLEVEL_DEBUG, "ZPush::GetAdditionalSyncFolders(): Requested AS folderids as keys for additional folders array, converting"); ZLog::Write(LOGLEVEL_DEBUG, "ZPush::GetAdditionalSyncFolders(): Requested AS folderids as keys for additional folders array, converting");
...@@ -628,8 +613,8 @@ class ZPush { ...@@ -628,8 +613,8 @@ class ZPush {
* @return string * @return string
*/ */
static public function GetAdditionalSyncFolderStore($backendid, $noDebug = false) { static public function GetAdditionalSyncFolderStore($backendid, $noDebug = false) {
if(isset(self::$addSyncFolders[$backendid]->Store)) { if(isset(self::getAddSyncFolders()[$backendid]->Store)) {
$val = self::$addSyncFolders[$backendid]->Store; $val = self::getAddSyncFolders()[$backendid]->Store;
} }
else { else {
$val = self::GetDeviceManager()->GetAdditionalUserSyncFolderStore($backendid); $val = self::GetDeviceManager()->GetAdditionalUserSyncFolderStore($backendid);
...@@ -660,6 +645,46 @@ class ZPush { ...@@ -660,6 +645,46 @@ class ZPush {
return new $class(); return new $class();
} }
/**
* Initializes the SyncObjects for additional folders on demand.
* Uses DeviceManager->BuildSyncFolderObject() to do patching required for ZP-907.
*
* @access private
* @return array
*/
static private function getAddSyncFolders() {
global $additionalFolders;
if (!isset(self::$addSyncFolders)) {
self::$addSyncFolders = array();
if (isset($additionalFolders) && !is_array($additionalFolders)) {
ZLog::Write(LOGLEVEL_ERROR, "ZPush::getAddSyncFolders() : The additional folders synchronization not available as array.");
}
else {
foreach ($additionalFolders as $af) {
if (!is_array($af) || !isset($af['store']) || !isset($af['folderid']) || !isset($af['name']) || !isset($af['type'])) {
ZLog::Write(LOGLEVEL_ERROR, "ZPush::getAddSyncFolders() : the additional folder synchronization is not configured correctly. Missing parameters. Entry will be ignored.");
continue;
}
if ($af['store'] == "" || $af['folderid'] == "" || $af['name'] == "" || $af['type'] == "") {
ZLog::Write(LOGLEVEL_WARN, "ZPush::getAddSyncFolders() : the additional folder synchronization is not configured correctly. Empty parameters. Entry will be ignored.");
continue;
}
if (!in_array($af['type'], array(SYNC_FOLDER_TYPE_USER_NOTE, SYNC_FOLDER_TYPE_USER_CONTACT, SYNC_FOLDER_TYPE_USER_APPOINTMENT, SYNC_FOLDER_TYPE_USER_TASK, SYNC_FOLDER_TYPE_USER_MAIL))) {
ZLog::Write(LOGLEVEL_ERROR, sprintf("ZPush::getAddSyncFolders() : the type of the additional synchronization folder '%s is not permitted.", $af['name']));
continue;
}
$folder = self::GetDeviceManager()->BuildSyncFolderObject($af['store'], $af['folderid'], '0', $af['name'], $af['type'], 0, DeviceManager::FLD_ORIGIN_CONFIG);
self::$addSyncFolders[$folder->BackendId] = $folder;
}
}
}
return self::$addSyncFolders;
}
/** /**
* Returns the default foldertype for a folder class * Returns the default foldertype for a folder class
* *
......
...@@ -77,7 +77,7 @@ class FolderSync extends RequestProcessor { ...@@ -77,7 +77,7 @@ class FolderSync extends RequestProcessor {
$changesMem = self::$deviceManager->GetHierarchyChangesWrapper(); $changesMem = self::$deviceManager->GetHierarchyChangesWrapper();
// the hierarchyCache should now fully be initialized - check for changes in the additional folders // the hierarchyCache should now fully be initialized - check for changes in the additional folders
$changesMem->Config(ZPush::GetAdditionalSyncFolders(false)); $changesMem->Config(ZPush::GetAdditionalSyncFolders(false), ChangesMemoryWrapper::SYNCHRONIZING);
// reset to default store in backend // reset to default store in backend
self::$backend->Setup(false); self::$backend->Setup(false);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment