/** * handle options request */ protected function _handleOptions() { $command = new Syncroton_Command_Options(); $this->_sendHeaders($command->getHeaders()); }
/** * generate FolderSync response * * @todo changes are missing in response (folder got renamed for example) */ public function getResponse() { $folderSync = $this->_outputDom->documentElement; // invalid synckey provided if (!$this->_syncState instanceof Syncroton_Model_SyncState) { if ($this->_logger instanceof Syncroton_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " invalid synckey provided. FolderSync 0 needed."); } $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_INVALID_SYNC_KEY)); return $this->_outputDom; } // send headers from options command also when FolderSync SyncKey is 0 if ($this->_syncState->counter == 0) { $optionsCommand = new Syncroton_Command_Options(); $this->_headers = array_merge($this->_headers, $optionsCommand->getHeaders()); } $adds = array(); $updates = array(); $deletes = array(); foreach ($this->_classes as $class) { try { $dataController = Syncroton_Data_Factory::factory($class, $this->_device, $this->_syncTimeStamp); } catch (Exception $e) { // backend not defined if ($this->_logger instanceof Syncroton_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " no data backend defined for class: " . $class); } continue; } try { // retrieve all folders available in data backend $serverFolders = $dataController->getAllFolders(); // retrieve all folders sent to client $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class); if ($this->_syncState->counter > 0) { // retrieve all folders changed since last sync $changedFolders = $dataController->getChangedFolders($this->_syncState->lastsync, $this->_syncTimeStamp); } else { $changedFolders = array(); } if ($class == 'Contacts' && sizeof($serverFolders) > 2) { //debug($this->_syncState->lastsync); //die; } // only folders which were sent to the client already are allowed to be in $changedFolders $clientFolders = $this->_folderBackend->getFolderState($this->_device, $class); $changedFolders = array_intersect_key($changedFolders, $clientFolders); } catch (Exception $e) { if ($this->_logger instanceof Syncroton_Log) { $this->_logger->critical(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getMessage()); } if ($this->_logger instanceof Syncroton_Log) { $this->_logger->debug(__METHOD__ . '::' . __LINE__ . " Syncing folder hierarchy failed: " . $e->getTraceAsString()); } // The Status element is global for all collections. If one collection fails, // a failure status MUST be returned for all collections. if ($e instanceof Syncroton_Exception_Status) { $status = $e->getCode(); } else { $status = Syncroton_Exception_Status_FolderSync::UNKNOWN_ERROR; } $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', $status)); return $this->_outputDom; } $serverFoldersIds = array_keys($serverFolders); // is this the first sync? if ($this->_syncState->counter == 0) { $clientFoldersIds = array(); } else { $clientFoldersIds = array_keys($clientFolders); } // calculate added entries $serverDiff = array_diff($serverFoldersIds, $clientFoldersIds); foreach ($serverDiff as $serverFolderId) { // have we created a folderObject in syncroton_folder before? if (isset($clientFolders[$serverFolderId])) { $add = $clientFolders[$serverFolderId]; } else { $add = $serverFolders[$serverFolderId]; $add->creationTime = $this->_syncTimeStamp; $add->deviceId = $this->_device; unset($add->id); } $add->class = $class; $adds[] = $add; } // calculate changed entries foreach ($changedFolders as $changedFolder) { $change = $clientFolders[$changedFolder->serverId]; $change->displayName = $changedFolder->displayName; $change->parentId = $changedFolder->parentId; $change->type = $changedFolder->type; $updates[] = $change; } // calculate deleted entries $serverDiff = array_diff($clientFoldersIds, $serverFoldersIds); foreach ($serverDiff as $serverFolderId) { $deletes[] = $clientFolders[$serverFolderId]; } } $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Status', self::STATUS_SUCCESS)); $count = count($adds) + count($updates) + count($deletes); if ($count > 0) { $this->_syncState->counter++; $this->_syncState->lastsync = $this->_syncTimeStamp; } // create xml output $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'SyncKey', $this->_syncState->counter)); $changes = $folderSync->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Changes')); $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Count', $count)); foreach ($adds as $folder) { $add = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Add')); $folder->appendXML($add, $this->_device); // store folder in backend if (empty($folder->id)) { $this->_folderBackend->create($folder); } } foreach ($updates as $folder) { $update = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Update')); $folder->appendXML($update, $this->_device); $this->_folderBackend->update($folder); } foreach ($deletes as $folder) { $delete = $changes->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'Delete')); $delete->appendChild($this->_outputDom->createElementNS('uri:FolderHierarchy', 'ServerId', $folder->serverId)); $this->_folderBackend->delete($folder); } if (empty($this->_syncState->id)) { $this->_syncStateBackend->create($this->_syncState); } else { $this->_syncStateBackend->update($this->_syncState); } return $this->_outputDom; }