summaryrefslogtreecommitdiffstats
path: root/apps/files_sharing/lib/propagation/recipientpropagator.php
blob: 5b7651f2ce794a3515346e19696356bccca05354 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
/**
 * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OCA\Files_Sharing\Propagation;

use OC\Files\Cache\ChangePropagator;
use OC\Files\View;
use OC\Share\Share;

/**
 * Propagate etags for share recipients
 */
class RecipientPropagator {
	/**
	 * @var string
	 */
	protected $userId;

	/**
	 * @var \OC\Files\Cache\ChangePropagator
	 */
	protected $changePropagator;

	/**
	 * @var \OCP\IConfig
	 */
	protected $config;

	/**
	 * @param string $userId 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
	 */
	public function __construct($userId, $changePropagator, $config) {
		$this->userId = $userId;
		$this->changePropagator = $changePropagator;
		$this->config = $config;
	}

	/**
	 * Propagate the etag changes for all shares marked as dirty and mark the shares as clean
	 *
	 * @param array $shares the shares for the users
	 * @param int $time
	 */
	public function propagateDirtyMountPoints(array $shares, $time = null) {
		if ($time === null) {
			$time = microtime(true);
		}
		$dirtyShares = $this->getDirtyShares($shares);
		foreach ($dirtyShares as $share) {
			$this->changePropagator->addChange($share['file_target']);
		}
		if (count($dirtyShares)) {
			$this->config->setUserValue($this->userId, 'files_sharing', 'last_propagate', $time);
			$this->changePropagator->propagateChanges(floor($time));
		}
	}

	/**
	 * Get all shares we need to update the etag for
	 *
	 * @param array $shares the shares for the users
	 * @return string[]
	 */
	protected function getDirtyShares($shares) {
		$dirty = [];
		$userTime = $this->config->getUserValue($this->userId, 'files_sharing', 'last_propagate', 0);
		foreach ($shares as $share) {
			$updateTime = $this->config->getAppValue('files_sharing', $share['id'], 0);
			if ($updateTime >= $userTime) {
				$dirty[] = $share;
			}
		}
		return $dirty;
	}

	/**
	 * @param array $share
	 * @param int $time
	 */
	public function markDirty($share, $time = null) {
		if ($time === null) {
			$time = microtime(true);
		}
		$this->config->setAppValue('files_sharing', $share['id'], $time);
	}

	/**
	 * Listen on the propagator for updates made to shares owned by a user
	 *
	 * @param \OC\Files\Cache\ChangePropagator $propagator
	 * @param string $owner
	 */
	public function attachToPropagator(ChangePropagator $propagator, $owner) {
		$propagator->listen('\OC\Files', 'propagate', function ($path, $entry) use ($owner) {
			$shares = Share::getAllSharesForFileId($entry['fileid']);
			foreach ($shares as $share) {
				// propagate down the share tree
				$this->markDirty($share, microtime(true));

				// propagate up the share tree
				$user = $share['uid_owner'];
				$view = new View('/' . $user . '/files');
				$path = $view->getPath($share['file_source']);
				$watcher = new ChangeWatcher($view);
				$watcher->writeHook(['path' => $path]);
			}
		});
	}
}