public function tearDown() { $connection = \OC::$server->getDatabaseConnection(); $deleteStatement = $connection->prepare('DELETE FROM `*PREFIX*properties`' . ' WHERE `userid` = ?'); $deleteStatement->execute(array($this->user->getUID())); $deleteStatement->closeCursor(); }
/** * @param $enabled * @return bool */ public function setRecoveryForUser($enabled) { $value = $enabled ? '1' : '0'; try { $this->config->setUserValue($this->user->getUID(), 'encryption', 'recoveryEnabled', $value); return true; } catch (PreConditionNotMetException $e) { return false; } }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID()); $shares = array_filter($shares, function ($share) { return $share['permissions'] > 0; }); $shares = array_map(function ($share) use($user, $storageFactory) { return new SharedMount('\\OC\\Files\\Storage\\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array('share' => $share, 'user' => $user->getUID()), $storageFactory); }, $shares); // array_filter removes the null values from the array return array_filter($shares); }
/** * Get the cache mount for a user * * @param IUser $user * @param IStorageFactory $loader * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $loader) { $cacheBaseDir = $this->config->getSystemValue('cache_path', ''); if ($cacheBaseDir !== '') { $cacheDir = rtrim($cacheBaseDir, '/') . '/' . $user->getUID(); if (!file_exists($cacheDir)) { mkdir($cacheDir, 0770, true); } return [new MountPoint('\\OC\\Files\\Storage\\Local', '/' . $user->getUID() . '/cache', ['datadir' => $cacheDir, $loader])]; } else { return []; } }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1)); $shares = array_filter($shares, function (\OCP\Share\IShare $share) { return $share->getPermissions() > 0; }); $mounts = []; foreach ($shares as $share) { $mounts[] = new SharedMount('\\OC\\Files\\Storage\\Shared', $mounts, ['user' => $user->getUID(), 'newShare' => $share], $storageFactory); } // array_filter removes the null values from the array return array_filter($mounts); }
/** * Get all mountpoints we need to update the etag for * * @return string[] */ protected function getDirtyMountPoints() { $dirty = array(); $mountPoints = $this->config->getAppKeys('files_external'); foreach ($mountPoints as $mountPoint) { if (substr($mountPoint, 0, 1) === '/') { $updateTime = $this->config->getAppValue('files_external', $mountPoint); $userTime = $this->config->getUserValue($this->user->getUID(), 'files_external', $mountPoint); if ($updateTime > $userTime) { $dirty[] = $mountPoint; } } } return $dirty; }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID()); $propagator = $this->propagationManager->getSharePropagator($user->getUID()); $propagator->propagateDirtyMountPoints($shares); $shares = array_filter($shares, function ($share) { return $share['permissions'] > 0; }); $shares = array_map(function ($share) use($user, $storageFactory) { // for updating etags for the share owner when we make changes to this share. $ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']); return new SharedMount('\\OC\\Files\\Storage\\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array('propagationManager' => $this->propagationManager, 'propagator' => $ownerPropagator, 'share' => $share, 'user' => $user->getUID()), $storageFactory); }, $shares); // array_filter removes the null values from the array return array_filter($shares); }
public function onPostRemoveUser(IGroup $group, IUser $targetUser) { $targetUserId = $targetUser->getUID(); $sharesAfter = $this->getUserShares($targetUserId); $this->propagateSharesDiff($targetUserId, $this->userShares[$targetUserId], $sharesAfter); unset($this->userShares[$targetUserId]); }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID()); $propagator = $this->propagationManager->getSharePropagator($user->getUID()); $propagator->propagateDirtyMountPoints($shares); $shares = array_filter($shares, function ($share) { return $share['permissions'] > 0; }); return array_map(function ($share) use($user, $storageFactory) { Filesystem::initMountPoints($share['uid_owner']); // for updating etags for the share owner when we make changes to this share. $ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']); // for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share) $this->propagationManager->listenToOwnerChanges($share['uid_owner'], $user->getUID()); return new SharedMount('\\OC\\Files\\Storage\\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array('propagator' => $ownerPropagator, 'share' => $share, 'user' => $user->getUID()), $storageFactory); }, $shares); }
public function testShowHiddenFiles() { $show = false; $this->config->expects($this->once())->method('setUserValue')->with($this->user->getUID(), 'files', 'show_hidden', $show); $expected = new Http\Response(); $actual = $this->apiController->showHiddenFiles($show); $this->assertEquals($expected, $actual); }
/** * Get the cache mount for a user * * @param IUser $user * @param IStorageFactory $loader * @return \OCP\Files\Mount\IMountPoint[] */ public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { $arguments = ['user' => $user]; if (\OC\Files\Cache\Storage::exists('local::' . $user->getHome() . '/')) { $arguments['legacy'] = true; } return new MountPoint('\\OC\\Files\\Storage\\Home', '/' . $user->getUID(), $arguments, $loader); }
/** * @param IUser $user current user, must match the propagator's * user * @param \OC\Files\Cache\ChangePropagator $changePropagator change propagator * initialized with a view for $user * @param \OCP\IConfig $config * @param PropagationManager $manager * @param IGroupManager $groupManager */ public function __construct(IUser $user, $changePropagator, $config, PropagationManager $manager, IGroupManager $groupManager) { $this->userId = $user->getUID(); $this->user = $user; $this->changePropagator = $changePropagator; $this->config = $config; $this->manager = $manager; $this->groupManager = $groupManager; }
/** * @param IUser $user */ protected function runScanner(IUser $user) { try { $scanner = new Scanner($user->getUID(), $this->dbConnection, $this->logger); $scanner->backgroundScan(''); } catch (\Exception $e) { $this->logger->logException($e, ['app' => 'files']); } \OC_Util::tearDownFS(); }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_USER, null, -1); $shares = array_merge($shares, $this->shareManager->getSharedWith($user->getUID(), \OCP\Share::SHARE_TYPE_GROUP, null, -1)); // filter out excluded shares and group shares that includes self $shares = array_filter($shares, function (\OCP\Share\IShare $share) use($user) { return $share->getPermissions() > 0 && $share->getShareOwner() !== $user->getUID(); }); $mounts = []; foreach ($shares as $share) { try { $mounts[] = new SharedMount('\\OC\\Files\\Storage\\Shared', $mounts, ['user' => $user->getUID(), 'newShare' => $share], $storageFactory); } catch (\Exception $e) { $this->logger->logException($e); $this->logger->error('Error while trying to create shared mount'); } } // array_filter removes the null values from the array return array_filter($mounts); }
/** * create new private/public key-pair for user * * @return array|bool */ public function createKeyPair() { $log = $this->logger; $res = $this->getOpenSSLPKey(); if (!$res) { $log->error("Encryption Library couldn't generate users key-pair for {$this->user->getUID()}", ['app' => 'encryption']); if (openssl_error_string()) { $log->error('Encryption library openssl_pkey_new() fails: ' . openssl_error_string(), ['app' => 'encryption']); } } elseif (openssl_pkey_export($res, $privateKey, null, $this->getOpenSSLConfig())) { $keyDetails = openssl_pkey_get_details($res); $publicKey = $keyDetails['key']; return ['publicKey' => $publicKey, 'privateKey' => $privateKey]; } $log->error('Encryption library couldn\'t export users private key, please check your servers OpenSSL configuration.' . $this->user->getUID(), ['app' => 'encryption']); if (openssl_error_string()) { $log->error('Encryption Library:' . openssl_error_string(), ['app' => 'encryption']); } return false; }
/** * @return Node the root node of the mount */ public function getMountPointNode() { // TODO injection etc Filesystem::initMountPoints($this->user->getUID()); $userNode = \OC::$server->getUserFolder($this->user->getUID()); $nodes = $userNode->getById($this->rootId); if (count($nodes) > 0) { return $nodes[0]; } else { return null; } }
/** * @param IUser $user */ public function runForUser($user) { $principal = 'principals/users/' . $user->getUID(); $calendars = $this->calDavBackend->getCalendarsForUser($principal); foreach ($calendars as $calendar) { $objects = $this->calDavBackend->getCalendarObjects($calendar['id']); foreach ($objects as $object) { $calObject = $this->calDavBackend->getCalendarObject($calendar['id'], $object['uri']); $classification = $this->extractClassification($calObject['calendardata']); $this->calDavBackend->setClassification($object['id'], $classification); } } }
public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) { if ($storage->getType() === StorageConfig::MOUNT_TYPE_ADMIN) { $uid = ''; } else { $uid = $user->getUID(); } $credentials = $this->credentialsManager->retrieve($uid, self::CREDENTIALS_IDENTIFIER); if (is_array($credentials)) { $storage->setBackendOption('user', $credentials['user']); $storage->setBackendOption('password', $credentials['password']); } }
public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = null) { if (!isset($user)) { throw new InsufficientDataForMeaningfulAnswerException('No login credentials saved'); } $uid = $user->getUID(); $credentials = $this->credentialsManager->retrieve($uid, self::CREDENTIALS_IDENTIFIER); if (!isset($credentials)) { throw new InsufficientDataForMeaningfulAnswerException('No login credentials saved'); } $storage->setBackendOption('user', $credentials['user']); $storage->setBackendOption('password', $credentials['password']); }
/** * Process storage ready for mounting * * @param StorageConfig $storage * @param IUser $user */ private function prepareStorageConfig(StorageConfig &$storage, IUser $user) { foreach ($storage->getBackendOptions() as $option => $value) { $storage->setBackendOption($option, \OC_Mount_Config::setUserVars($user->getUID(), $value)); } $objectStore = $storage->getBackendOption('objectstore'); if ($objectStore) { $objectClass = $objectStore['class']; $storage->setBackendOption('objectstore', new $objectClass($objectStore)); } $storage->getAuthMechanism()->manipulateStorageConfig($storage); $storage->getBackend()->manipulateStorageConfig($storage); }
public function testIndexWithRegularBrowser() { $this->request->expects($this->once())->method('isUserAgent')->with(['/MSIE 8.0/'])->will($this->returnValue(false)); $this->viewController->expects($this->once())->method('getStorageInfo')->will($this->returnValue(['relative' => 123, 'owner' => 'MyName', 'ownerDisplayName' => 'MyDisplayName'])); $this->config->expects($this->exactly(3))->method('getUserValue')->will($this->returnValueMap([[$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'], [$this->user->getUID(), 'files', 'file_sorting_direction', 'asc', 'asc'], [$this->user->getUID(), 'files', 'show_hidden', false, false]])); $this->config->expects($this->any())->method('getAppValue')->will($this->returnArgument(2)); $nav = new Template('files', 'appnavigation'); $nav->assign('navigationItems', [['id' => 'files', 'appname' => 'files', 'script' => 'list.php', 'order' => 0, 'name' => new \OC_L10N_String(new \OC_L10N('files'), 'All files', []), 'active' => false, 'icon' => ''], ['id' => 'favorites', 'appname' => 'files', 'script' => 'simplelist.php', 'order' => 5, 'name' => null, 'active' => false, 'icon' => ''], ['id' => 'sharingin', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 10, 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared with you', []), 'active' => false, 'icon' => ''], ['id' => 'sharingout', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 15, 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared with others', []), 'active' => false, 'icon' => ''], ['id' => 'sharinglinks', 'appname' => 'files_sharing', 'script' => 'list.php', 'order' => 20, 'name' => new \OC_L10N_String(new \OC_L10N('files_sharing'), 'Shared by link', []), 'active' => false, 'icon' => ''], ['id' => 'systemtagsfilter', 'appname' => 'systemtags', 'script' => 'list.php', 'order' => 25, 'name' => new \OC_L10N_String(new \OC_L10N('systemtags'), 'Tags', []), 'active' => false, 'icon' => ''], ['id' => 'trashbin', 'appname' => 'files_trashbin', 'script' => 'list.php', 'order' => 50, 'name' => new \OC_L10N_String(new \OC_L10N('files_trashbin'), 'Deleted files', []), 'active' => false, 'icon' => '']]); $expected = new Http\TemplateResponse('files', 'index', ['usedSpacePercent' => 123, 'owner' => 'MyName', 'ownerDisplayName' => 'MyDisplayName', 'isPublic' => false, 'defaultFileSorting' => 'name', 'defaultFileSortingDirection' => 'asc', 'showHiddenFiles' => 0, 'fileNotFound' => 0, 'mailNotificationEnabled' => 'no', 'mailPublicNotificationEnabled' => 'no', 'allowShareWithLink' => 'yes', 'appNavigation' => $nav, 'appContents' => [['id' => 'files', 'content' => null], ['id' => 'favorites', 'content' => null], ['id' => 'sharingin', 'content' => null], ['id' => 'sharingout', 'content' => null], ['id' => 'sharinglinks', 'content' => null], ['id' => 'systemtagsfilter', 'content' => null], ['id' => 'trashbin', 'content' => null]]]); $policy = new Http\ContentSecurityPolicy(); $policy->addAllowedFrameDomain('\'self\''); $expected->setContentSecurityPolicy($policy); $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); }
public function testCreateShareInvalidExpireDate() { $ocs = $this->mockFormatShare(); $this->request->method('getParam')->will($this->returnValueMap([['path', null, 'valid-path'], ['shareType', '-1', \OCP\Share::SHARE_TYPE_LINK], ['publicUpload', null, 'false'], ['expireDate', '', 'a1b2d3'], ['password', '', '']])); $path = $this->getMock('\\OCP\\Files\\Folder'); $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); $this->rootFolder->method('get')->with('valid-path')->willReturn($path); $this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare()); $this->shareManager->method('shareApiAllowLinks')->willReturn(true); $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); $expected = new \OC_OCS_Result(null, 404, 'Invalid Date. Format must be YYYY-MM-DD.'); $result = $ocs->createShare(); $this->assertEquals($expected->getMeta(), $result->getMeta()); $this->assertEquals($expected->getData(), $result->getData()); }
/** * Get all mountpoints applicable for the user and check for shares where we need to update the etags * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $storageFactory * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $storageFactory) { $shares = \OCP\Share::getItemsSharedWithUser('file', $user->getUID()); $propagator = $this->propagationManager->getSharePropagator($user->getUID()); $propagator->propagateDirtyMountPoints($shares); $shares = array_filter($shares, function ($share) { return $share['permissions'] > 0; }); $shares = array_map(function ($share) use($user, $storageFactory) { try { Filesystem::initMountPoints($share['uid_owner']); } catch (NoUserException $e) { \OC::$server->getLogger()->warning('The user \'' . $share['uid_owner'] . '\' of share with ID \'' . $share['id'] . '\' can\'t be retrieved.', array('app' => 'files_sharing')); return null; } // for updating etags for the share owner when we make changes to this share. $ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']); // for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share) $this->propagationManager->listenToOwnerChanges($share['uid_owner'], $user->getUID()); return new SharedMount('\\OC\\Files\\Storage\\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array('propagator' => $ownerPropagator, 'share' => $share, 'user' => $user->getUID()), $storageFactory); }, $shares); // array_filter removes the null values from the array return array_filter($shares); }
public function getMountsForUser(IUser $user, IStorageFactory $loader) { $query = $this->connection->prepare(' SELECT `remote`, `share_token`, `password`, `mountpoint`, `owner` FROM `*PREFIX*share_external` WHERE `user` = ? AND `accepted` = ? '); $query->execute([$user->getUID(), 1]); $mounts = []; while ($row = $query->fetch()) { $row['manager'] = $this; $row['token'] = $row['share_token']; $mounts[] = $this->getMount($user, $row, $loader); } return $mounts; }
/** * Process storage ready for mounting * * @param StorageConfig $storage * @param IUser $user */ private function prepareStorageConfig(StorageConfig &$storage, IUser $user) { foreach ($storage->getBackendOptions() as $option => $value) { $storage->setBackendOption($option, \OC_Mount_Config::setUserVars($user->getUID(), $value)); } $objectStore = $storage->getBackendOption('objectstore'); if ($objectStore) { $objectClass = $objectStore['class']; if (!is_subclass_of($objectClass, '\\OCP\\Files\\ObjectStore\\IObjectStore')) { throw new \InvalidArgumentException('Invalid object store'); } $storage->setBackendOption('objectstore', new $objectClass($objectStore)); } $storage->getAuthMechanism()->manipulateStorageConfig($storage); $storage->getBackend()->manipulateStorageConfig($storage); }
/** * @dataProvider dataFormatShare * * @param array $expects * @param \OCP\Share\IShare $share * @param array $users * @param $exception */ public function testFormatShare(array $expects, \OCP\Share\IShare $share, array $users, $exception) { $this->userManager->method('get')->will($this->returnValueMap($users)); $this->urlGenerator->method('linkToRouteAbsolute')->with('files_sharing.sharecontroller.showShare', ['token' => 'myToken'])->willReturn('myLink'); $this->rootFolder->method('getUserFolder')->with($this->currentUser->getUID())->will($this->returnSelf()); if (!$exception) { $this->rootFolder->method('getById')->with($share->getNodeId())->willReturn([$share->getNode()]); $this->rootFolder->method('getRelativePath')->with($share->getNode()->getPath())->will($this->returnArgument(0)); } try { $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]); $this->assertFalse($exception); $this->assertEquals($expects, $result); } catch (NotFoundException $e) { $this->assertTrue($exception); } }
public function testUpdateOtherPermissions() { $ocs = $this->mockFormatShare(); $file = $this->getMock('\\OCP\\Files\\File'); $share = \OC::$server->getShareManager()->newShare(); $share->setPermissions(\OCP\Constants::PERMISSION_ALL)->setSharedBy($this->currentUser->getUID())->setShareType(\OCP\Share::SHARE_TYPE_USER)->setNode($file); $this->request->method('getParam')->will($this->returnValueMap([['permissions', null, '31']])); $this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share); $this->shareManager->method('shareApiLinkAllowPublicUpload')->willReturn(true); $this->shareManager->expects($this->once())->method('updateShare')->with($this->callback(function (\OCP\Share\IShare $share) { return $share->getPermissions() === \OCP\Constants::PERMISSION_ALL; }))->will($this->returnArgument(0)); $expected = new \OC_OCS_Result(null); $result = $ocs->updateShare(42); $this->assertEquals($expected->getMeta(), $result->getMeta()); $this->assertEquals($expected->getData(), $result->getData()); }
public function testPropagateWhenRemovedFromGroupWithSubdirTarget() { $this->recipientGroup->addUser($this->recipientUser); // relogin to refresh mount points $this->loginAsUser($this->recipientUser->getUID()); $recipientView = new View('/' . $this->recipientUser->getUID() . '/files'); $this->assertTrue($recipientView->mkdir('sub')); $this->assertTrue($recipientView->rename('folder', 'sub/folder')); $this->propagationManager->expects($this->once())->method('propagateSharesToUser')->with($this->callback(function ($shares) { if (count($shares) !== 1) { return false; } $share = array_values($shares)[0]; return $share['file_source'] === $this->fileInfo['fileid'] && $share['share_with'] === $this->recipientGroup->getGID() && $share['file_target'] === '/sub/folder'; }), $this->recipientUser->getUID()); $this->recipientGroup->removeUser($this->recipientUser); }
/** * Get all mountpoints applicable for the user * * @param \OCP\IUser $user * @param \OCP\Files\Storage\IStorageFactory $loader * @return \OCP\Files\Mount\IMountPoint[] */ public function getMountsForUser(IUser $user, IStorageFactory $loader) { $mountPoints = \OC_Mount_Config::getAbsoluteMountPoints($user->getUID()); $mounts = array(); foreach ($mountPoints as $mountPoint => $options) { if (isset($options['options']['objectstore'])) { $objectClass = $options['options']['objectstore']['class']; $options['options']['objectstore'] = new $objectClass($options['options']['objectstore']); } $mountOptions = isset($options['mountOptions']) ? $options['mountOptions'] : []; if (isset($options['personal']) && $options['personal']) { $mounts[] = new PersonalMount($options['class'], $mountPoint, $options['options'], $loader, $mountOptions); } else { $mounts[] = new MountPoint($options['class'], $mountPoint, $options['options'], $loader, $mountOptions); } } return $mounts; }
/** * @param VCard $vCard * @param IUser $user * @return bool */ public function updateCard(VCard $vCard, IUser $user) { $uid = $user->getUID(); $displayName = $user->getDisplayName(); $displayName = empty($displayName) ? $uid : $displayName; $emailAddress = $user->getEMailAddress(); $cloudId = $user->getCloudId(); $image = $user->getAvatarImage(-1); $updated = false; if ($this->propertyNeedsUpdate($vCard, 'FN', $displayName)) { $vCard->FN = new Text($vCard, 'FN', $displayName); unset($vCard->N); $vCard->add(new Text($vCard, 'N', $this->splitFullName($displayName))); $updated = true; } if ($this->propertyNeedsUpdate($vCard, 'EMAIL', $emailAddress)) { $vCard->EMAIL = new Text($vCard, 'EMAIL', $emailAddress); $updated = true; } if ($this->propertyNeedsUpdate($vCard, 'CLOUD', $cloudId)) { $vCard->CLOUD = new Text($vCard, 'CLOUD', $cloudId); $updated = true; } if ($this->propertyNeedsUpdate($vCard, 'PHOTO', $image)) { $vCard->add('PHOTO', $image->data(), ['ENCODING' => 'b', 'TYPE' => $image->mimeType()]); $updated = true; } if (empty($emailAddress) && !is_null($vCard->EMAIL)) { unset($vCard->EMAIL); $updated = true; } if (empty($cloudId) && !is_null($vCard->CLOUD)) { unset($vCard->CLOUD); $updated = true; } if (empty($image) && !is_null($vCard->PHOTO)) { unset($vCard->PHOTO); $updated = true; } return $updated; }