@@ -25,294 +25,294 @@ |
||
25 | 25 | namespace OC; |
26 | 26 | |
27 | 27 | class DateTimeFormatter implements \OCP\IDateTimeFormatter { |
28 | - /** @var \DateTimeZone */ |
|
29 | - protected $defaultTimeZone; |
|
28 | + /** @var \DateTimeZone */ |
|
29 | + protected $defaultTimeZone; |
|
30 | 30 | |
31 | - /** @var \OCP\IL10N */ |
|
32 | - protected $defaultL10N; |
|
31 | + /** @var \OCP\IL10N */ |
|
32 | + protected $defaultL10N; |
|
33 | 33 | |
34 | - /** |
|
35 | - * Constructor |
|
36 | - * |
|
37 | - * @param \DateTimeZone $defaultTimeZone Set the timezone for the format |
|
38 | - * @param \OCP\IL10N $defaultL10N Set the language for the format |
|
39 | - */ |
|
40 | - public function __construct(\DateTimeZone $defaultTimeZone, \OCP\IL10N $defaultL10N) { |
|
41 | - $this->defaultTimeZone = $defaultTimeZone; |
|
42 | - $this->defaultL10N = $defaultL10N; |
|
43 | - } |
|
34 | + /** |
|
35 | + * Constructor |
|
36 | + * |
|
37 | + * @param \DateTimeZone $defaultTimeZone Set the timezone for the format |
|
38 | + * @param \OCP\IL10N $defaultL10N Set the language for the format |
|
39 | + */ |
|
40 | + public function __construct(\DateTimeZone $defaultTimeZone, \OCP\IL10N $defaultL10N) { |
|
41 | + $this->defaultTimeZone = $defaultTimeZone; |
|
42 | + $this->defaultL10N = $defaultL10N; |
|
43 | + } |
|
44 | 44 | |
45 | - /** |
|
46 | - * Get TimeZone to use |
|
47 | - * |
|
48 | - * @param \DateTimeZone $timeZone The timezone to use |
|
49 | - * @return \DateTimeZone The timezone to use, falling back to the current user's timezone |
|
50 | - */ |
|
51 | - protected function getTimeZone($timeZone = null) { |
|
52 | - if ($timeZone === null) { |
|
53 | - $timeZone = $this->defaultTimeZone; |
|
54 | - } |
|
45 | + /** |
|
46 | + * Get TimeZone to use |
|
47 | + * |
|
48 | + * @param \DateTimeZone $timeZone The timezone to use |
|
49 | + * @return \DateTimeZone The timezone to use, falling back to the current user's timezone |
|
50 | + */ |
|
51 | + protected function getTimeZone($timeZone = null) { |
|
52 | + if ($timeZone === null) { |
|
53 | + $timeZone = $this->defaultTimeZone; |
|
54 | + } |
|
55 | 55 | |
56 | - return $timeZone; |
|
57 | - } |
|
56 | + return $timeZone; |
|
57 | + } |
|
58 | 58 | |
59 | - /** |
|
60 | - * Get \OCP\IL10N to use |
|
61 | - * |
|
62 | - * @param \OCP\IL10N $l The locale to use |
|
63 | - * @return \OCP\IL10N The locale to use, falling back to the current user's locale |
|
64 | - */ |
|
65 | - protected function getLocale($l = null) { |
|
66 | - if ($l === null) { |
|
67 | - $l = $this->defaultL10N; |
|
68 | - } |
|
59 | + /** |
|
60 | + * Get \OCP\IL10N to use |
|
61 | + * |
|
62 | + * @param \OCP\IL10N $l The locale to use |
|
63 | + * @return \OCP\IL10N The locale to use, falling back to the current user's locale |
|
64 | + */ |
|
65 | + protected function getLocale($l = null) { |
|
66 | + if ($l === null) { |
|
67 | + $l = $this->defaultL10N; |
|
68 | + } |
|
69 | 69 | |
70 | - return $l; |
|
71 | - } |
|
70 | + return $l; |
|
71 | + } |
|
72 | 72 | |
73 | - /** |
|
74 | - * Generates a DateTime object with the given timestamp and TimeZone |
|
75 | - * |
|
76 | - * @param mixed $timestamp |
|
77 | - * @param \DateTimeZone $timeZone The timezone to use |
|
78 | - * @return \DateTime |
|
79 | - */ |
|
80 | - protected function getDateTime($timestamp, \DateTimeZone $timeZone = null) { |
|
81 | - if ($timestamp === null) { |
|
82 | - return new \DateTime('now', $timeZone); |
|
83 | - } else if (!$timestamp instanceof \DateTime) { |
|
84 | - $dateTime = new \DateTime('now', $timeZone); |
|
85 | - $dateTime->setTimestamp($timestamp); |
|
86 | - return $dateTime; |
|
87 | - } |
|
88 | - if ($timeZone) { |
|
89 | - $timestamp->setTimezone($timeZone); |
|
90 | - } |
|
91 | - return $timestamp; |
|
92 | - } |
|
73 | + /** |
|
74 | + * Generates a DateTime object with the given timestamp and TimeZone |
|
75 | + * |
|
76 | + * @param mixed $timestamp |
|
77 | + * @param \DateTimeZone $timeZone The timezone to use |
|
78 | + * @return \DateTime |
|
79 | + */ |
|
80 | + protected function getDateTime($timestamp, \DateTimeZone $timeZone = null) { |
|
81 | + if ($timestamp === null) { |
|
82 | + return new \DateTime('now', $timeZone); |
|
83 | + } else if (!$timestamp instanceof \DateTime) { |
|
84 | + $dateTime = new \DateTime('now', $timeZone); |
|
85 | + $dateTime->setTimestamp($timestamp); |
|
86 | + return $dateTime; |
|
87 | + } |
|
88 | + if ($timeZone) { |
|
89 | + $timestamp->setTimezone($timeZone); |
|
90 | + } |
|
91 | + return $timestamp; |
|
92 | + } |
|
93 | 93 | |
94 | - /** |
|
95 | - * Formats the date of the given timestamp |
|
96 | - * |
|
97 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
98 | - * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
99 | - * full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014' |
|
100 | - * long: e.g. 'MMMM d, y' => 'August 20, 2014' |
|
101 | - * medium: e.g. 'MMM d, y' => 'Aug 20, 2014' |
|
102 | - * short: e.g. 'M/d/yy' => '8/20/14' |
|
103 | - * The exact format is dependent on the language |
|
104 | - * @param \DateTimeZone $timeZone The timezone to use |
|
105 | - * @param \OCP\IL10N $l The locale to use |
|
106 | - * @return string Formatted date string |
|
107 | - */ |
|
108 | - public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
109 | - return $this->format($timestamp, 'date', $format, $timeZone, $l); |
|
110 | - } |
|
94 | + /** |
|
95 | + * Formats the date of the given timestamp |
|
96 | + * |
|
97 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
98 | + * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
99 | + * full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014' |
|
100 | + * long: e.g. 'MMMM d, y' => 'August 20, 2014' |
|
101 | + * medium: e.g. 'MMM d, y' => 'Aug 20, 2014' |
|
102 | + * short: e.g. 'M/d/yy' => '8/20/14' |
|
103 | + * The exact format is dependent on the language |
|
104 | + * @param \DateTimeZone $timeZone The timezone to use |
|
105 | + * @param \OCP\IL10N $l The locale to use |
|
106 | + * @return string Formatted date string |
|
107 | + */ |
|
108 | + public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
109 | + return $this->format($timestamp, 'date', $format, $timeZone, $l); |
|
110 | + } |
|
111 | 111 | |
112 | - /** |
|
113 | - * Formats the date of the given timestamp |
|
114 | - * |
|
115 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
116 | - * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
117 | - * full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014' |
|
118 | - * long: e.g. 'MMMM d, y' => 'August 20, 2014' |
|
119 | - * medium: e.g. 'MMM d, y' => 'Aug 20, 2014' |
|
120 | - * short: e.g. 'M/d/yy' => '8/20/14' |
|
121 | - * The exact format is dependent on the language |
|
122 | - * Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable |
|
123 | - * @param \DateTimeZone $timeZone The timezone to use |
|
124 | - * @param \OCP\IL10N $l The locale to use |
|
125 | - * @return string Formatted relative date string |
|
126 | - */ |
|
127 | - public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
128 | - if (substr($format, -1) !== '*' && substr($format, -1) !== '*') { |
|
129 | - $format .= '^'; |
|
130 | - } |
|
112 | + /** |
|
113 | + * Formats the date of the given timestamp |
|
114 | + * |
|
115 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
116 | + * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
117 | + * full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014' |
|
118 | + * long: e.g. 'MMMM d, y' => 'August 20, 2014' |
|
119 | + * medium: e.g. 'MMM d, y' => 'Aug 20, 2014' |
|
120 | + * short: e.g. 'M/d/yy' => '8/20/14' |
|
121 | + * The exact format is dependent on the language |
|
122 | + * Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable |
|
123 | + * @param \DateTimeZone $timeZone The timezone to use |
|
124 | + * @param \OCP\IL10N $l The locale to use |
|
125 | + * @return string Formatted relative date string |
|
126 | + */ |
|
127 | + public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
128 | + if (substr($format, -1) !== '*' && substr($format, -1) !== '*') { |
|
129 | + $format .= '^'; |
|
130 | + } |
|
131 | 131 | |
132 | - return $this->format($timestamp, 'date', $format, $timeZone, $l); |
|
133 | - } |
|
132 | + return $this->format($timestamp, 'date', $format, $timeZone, $l); |
|
133 | + } |
|
134 | 134 | |
135 | - /** |
|
136 | - * Gives the relative date of the timestamp |
|
137 | - * Only works for past dates |
|
138 | - * |
|
139 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
140 | - * @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time |
|
141 | - * @return string Dates returned are: |
|
142 | - * < 1 month => Today, Yesterday, n days ago |
|
143 | - * < 13 month => last month, n months ago |
|
144 | - * >= 13 month => last year, n years ago |
|
145 | - * @param \OCP\IL10N $l The locale to use |
|
146 | - * @return string Formatted date span |
|
147 | - */ |
|
148 | - public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) { |
|
149 | - $l = $this->getLocale($l); |
|
150 | - $timestamp = $this->getDateTime($timestamp); |
|
151 | - $timestamp->setTime(0, 0, 0); |
|
135 | + /** |
|
136 | + * Gives the relative date of the timestamp |
|
137 | + * Only works for past dates |
|
138 | + * |
|
139 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
140 | + * @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time |
|
141 | + * @return string Dates returned are: |
|
142 | + * < 1 month => Today, Yesterday, n days ago |
|
143 | + * < 13 month => last month, n months ago |
|
144 | + * >= 13 month => last year, n years ago |
|
145 | + * @param \OCP\IL10N $l The locale to use |
|
146 | + * @return string Formatted date span |
|
147 | + */ |
|
148 | + public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) { |
|
149 | + $l = $this->getLocale($l); |
|
150 | + $timestamp = $this->getDateTime($timestamp); |
|
151 | + $timestamp->setTime(0, 0, 0); |
|
152 | 152 | |
153 | - if ($baseTimestamp === null) { |
|
154 | - $baseTimestamp = time(); |
|
155 | - } |
|
156 | - $baseTimestamp = $this->getDateTime($baseTimestamp); |
|
157 | - $baseTimestamp->setTime(0, 0, 0); |
|
158 | - $dateInterval = $timestamp->diff($baseTimestamp); |
|
153 | + if ($baseTimestamp === null) { |
|
154 | + $baseTimestamp = time(); |
|
155 | + } |
|
156 | + $baseTimestamp = $this->getDateTime($baseTimestamp); |
|
157 | + $baseTimestamp->setTime(0, 0, 0); |
|
158 | + $dateInterval = $timestamp->diff($baseTimestamp); |
|
159 | 159 | |
160 | - if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 0) { |
|
161 | - return $l->t('today'); |
|
162 | - } else if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 1) { |
|
163 | - if ($timestamp > $baseTimestamp) { |
|
164 | - return $l->t('tomorrow'); |
|
165 | - } else { |
|
166 | - return $l->t('yesterday'); |
|
167 | - } |
|
168 | - } else if ($dateInterval->y == 0 && $dateInterval->m == 0) { |
|
169 | - if ($timestamp > $baseTimestamp) { |
|
170 | - return $l->n('in %n day', 'in %n days', $dateInterval->d); |
|
171 | - } else { |
|
172 | - return $l->n('%n day ago', '%n days ago', $dateInterval->d); |
|
173 | - } |
|
174 | - } else if ($dateInterval->y == 0 && $dateInterval->m == 1) { |
|
175 | - if ($timestamp > $baseTimestamp) { |
|
176 | - return $l->t('next month'); |
|
177 | - } else { |
|
178 | - return $l->t('last month'); |
|
179 | - } |
|
180 | - } else if ($dateInterval->y == 0) { |
|
181 | - if ($timestamp > $baseTimestamp) { |
|
182 | - return $l->n('in %n month', 'in %n months', $dateInterval->m); |
|
183 | - } else { |
|
184 | - return $l->n('%n month ago', '%n months ago', $dateInterval->m); |
|
185 | - } |
|
186 | - } else if ($dateInterval->y == 1) { |
|
187 | - if ($timestamp > $baseTimestamp) { |
|
188 | - return $l->t('next year'); |
|
189 | - } else { |
|
190 | - return $l->t('last year'); |
|
191 | - } |
|
192 | - } |
|
193 | - if ($timestamp > $baseTimestamp) { |
|
194 | - return $l->n('in %n year', 'in %n years', $dateInterval->y); |
|
195 | - } else { |
|
196 | - return $l->n('%n year ago', '%n years ago', $dateInterval->y); |
|
197 | - } |
|
198 | - } |
|
160 | + if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 0) { |
|
161 | + return $l->t('today'); |
|
162 | + } else if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 1) { |
|
163 | + if ($timestamp > $baseTimestamp) { |
|
164 | + return $l->t('tomorrow'); |
|
165 | + } else { |
|
166 | + return $l->t('yesterday'); |
|
167 | + } |
|
168 | + } else if ($dateInterval->y == 0 && $dateInterval->m == 0) { |
|
169 | + if ($timestamp > $baseTimestamp) { |
|
170 | + return $l->n('in %n day', 'in %n days', $dateInterval->d); |
|
171 | + } else { |
|
172 | + return $l->n('%n day ago', '%n days ago', $dateInterval->d); |
|
173 | + } |
|
174 | + } else if ($dateInterval->y == 0 && $dateInterval->m == 1) { |
|
175 | + if ($timestamp > $baseTimestamp) { |
|
176 | + return $l->t('next month'); |
|
177 | + } else { |
|
178 | + return $l->t('last month'); |
|
179 | + } |
|
180 | + } else if ($dateInterval->y == 0) { |
|
181 | + if ($timestamp > $baseTimestamp) { |
|
182 | + return $l->n('in %n month', 'in %n months', $dateInterval->m); |
|
183 | + } else { |
|
184 | + return $l->n('%n month ago', '%n months ago', $dateInterval->m); |
|
185 | + } |
|
186 | + } else if ($dateInterval->y == 1) { |
|
187 | + if ($timestamp > $baseTimestamp) { |
|
188 | + return $l->t('next year'); |
|
189 | + } else { |
|
190 | + return $l->t('last year'); |
|
191 | + } |
|
192 | + } |
|
193 | + if ($timestamp > $baseTimestamp) { |
|
194 | + return $l->n('in %n year', 'in %n years', $dateInterval->y); |
|
195 | + } else { |
|
196 | + return $l->n('%n year ago', '%n years ago', $dateInterval->y); |
|
197 | + } |
|
198 | + } |
|
199 | 199 | |
200 | - /** |
|
201 | - * Formats the time of the given timestamp |
|
202 | - * |
|
203 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
204 | - * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
205 | - * full: e.g. 'h:mm:ss a zzzz' => '11:42:13 AM GMT+0:00' |
|
206 | - * long: e.g. 'h:mm:ss a z' => '11:42:13 AM GMT' |
|
207 | - * medium: e.g. 'h:mm:ss a' => '11:42:13 AM' |
|
208 | - * short: e.g. 'h:mm a' => '11:42 AM' |
|
209 | - * The exact format is dependent on the language |
|
210 | - * @param \DateTimeZone $timeZone The timezone to use |
|
211 | - * @param \OCP\IL10N $l The locale to use |
|
212 | - * @return string Formatted time string |
|
213 | - */ |
|
214 | - public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
215 | - return $this->format($timestamp, 'time', $format, $timeZone, $l); |
|
216 | - } |
|
200 | + /** |
|
201 | + * Formats the time of the given timestamp |
|
202 | + * |
|
203 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
204 | + * @param string $format Either 'full', 'long', 'medium' or 'short' |
|
205 | + * full: e.g. 'h:mm:ss a zzzz' => '11:42:13 AM GMT+0:00' |
|
206 | + * long: e.g. 'h:mm:ss a z' => '11:42:13 AM GMT' |
|
207 | + * medium: e.g. 'h:mm:ss a' => '11:42:13 AM' |
|
208 | + * short: e.g. 'h:mm a' => '11:42 AM' |
|
209 | + * The exact format is dependent on the language |
|
210 | + * @param \DateTimeZone $timeZone The timezone to use |
|
211 | + * @param \OCP\IL10N $l The locale to use |
|
212 | + * @return string Formatted time string |
|
213 | + */ |
|
214 | + public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
215 | + return $this->format($timestamp, 'time', $format, $timeZone, $l); |
|
216 | + } |
|
217 | 217 | |
218 | - /** |
|
219 | - * Gives the relative past time of the timestamp |
|
220 | - * |
|
221 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
222 | - * @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time |
|
223 | - * @return string Dates returned are: |
|
224 | - * < 60 sec => seconds ago |
|
225 | - * < 1 hour => n minutes ago |
|
226 | - * < 1 day => n hours ago |
|
227 | - * < 1 month => Yesterday, n days ago |
|
228 | - * < 13 month => last month, n months ago |
|
229 | - * >= 13 month => last year, n years ago |
|
230 | - * @param \OCP\IL10N $l The locale to use |
|
231 | - * @return string Formatted time span |
|
232 | - */ |
|
233 | - public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) { |
|
234 | - $l = $this->getLocale($l); |
|
235 | - $timestamp = $this->getDateTime($timestamp); |
|
236 | - if ($baseTimestamp === null) { |
|
237 | - $baseTimestamp = time(); |
|
238 | - } |
|
239 | - $baseTimestamp = $this->getDateTime($baseTimestamp); |
|
218 | + /** |
|
219 | + * Gives the relative past time of the timestamp |
|
220 | + * |
|
221 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
222 | + * @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time |
|
223 | + * @return string Dates returned are: |
|
224 | + * < 60 sec => seconds ago |
|
225 | + * < 1 hour => n minutes ago |
|
226 | + * < 1 day => n hours ago |
|
227 | + * < 1 month => Yesterday, n days ago |
|
228 | + * < 13 month => last month, n months ago |
|
229 | + * >= 13 month => last year, n years ago |
|
230 | + * @param \OCP\IL10N $l The locale to use |
|
231 | + * @return string Formatted time span |
|
232 | + */ |
|
233 | + public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) { |
|
234 | + $l = $this->getLocale($l); |
|
235 | + $timestamp = $this->getDateTime($timestamp); |
|
236 | + if ($baseTimestamp === null) { |
|
237 | + $baseTimestamp = time(); |
|
238 | + } |
|
239 | + $baseTimestamp = $this->getDateTime($baseTimestamp); |
|
240 | 240 | |
241 | - $diff = $timestamp->diff($baseTimestamp); |
|
242 | - if ($diff->y > 0 || $diff->m > 0 || $diff->d > 0) { |
|
243 | - return $this->formatDateSpan($timestamp, $baseTimestamp, $l); |
|
244 | - } |
|
241 | + $diff = $timestamp->diff($baseTimestamp); |
|
242 | + if ($diff->y > 0 || $diff->m > 0 || $diff->d > 0) { |
|
243 | + return $this->formatDateSpan($timestamp, $baseTimestamp, $l); |
|
244 | + } |
|
245 | 245 | |
246 | - if ($diff->h > 0) { |
|
247 | - if ($timestamp > $baseTimestamp) { |
|
248 | - return $l->n('in %n hour', 'in %n hours', $diff->h); |
|
249 | - } else { |
|
250 | - return $l->n('%n hour ago', '%n hours ago', $diff->h); |
|
251 | - } |
|
252 | - } else if ($diff->i > 0) { |
|
253 | - if ($timestamp > $baseTimestamp) { |
|
254 | - return $l->n('in %n minute', 'in %n minutes', $diff->i); |
|
255 | - } else { |
|
256 | - return $l->n('%n minute ago', '%n minutes ago', $diff->i); |
|
257 | - } |
|
258 | - } |
|
259 | - if ($timestamp > $baseTimestamp) { |
|
260 | - return $l->t('in a few seconds'); |
|
261 | - } else { |
|
262 | - return $l->t('seconds ago'); |
|
263 | - } |
|
264 | - } |
|
246 | + if ($diff->h > 0) { |
|
247 | + if ($timestamp > $baseTimestamp) { |
|
248 | + return $l->n('in %n hour', 'in %n hours', $diff->h); |
|
249 | + } else { |
|
250 | + return $l->n('%n hour ago', '%n hours ago', $diff->h); |
|
251 | + } |
|
252 | + } else if ($diff->i > 0) { |
|
253 | + if ($timestamp > $baseTimestamp) { |
|
254 | + return $l->n('in %n minute', 'in %n minutes', $diff->i); |
|
255 | + } else { |
|
256 | + return $l->n('%n minute ago', '%n minutes ago', $diff->i); |
|
257 | + } |
|
258 | + } |
|
259 | + if ($timestamp > $baseTimestamp) { |
|
260 | + return $l->t('in a few seconds'); |
|
261 | + } else { |
|
262 | + return $l->t('seconds ago'); |
|
263 | + } |
|
264 | + } |
|
265 | 265 | |
266 | - /** |
|
267 | - * Formats the date and time of the given timestamp |
|
268 | - * |
|
269 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
270 | - * @param string $formatDate See formatDate() for description |
|
271 | - * @param string $formatTime See formatTime() for description |
|
272 | - * @param \DateTimeZone $timeZone The timezone to use |
|
273 | - * @param \OCP\IL10N $l The locale to use |
|
274 | - * @return string Formatted date and time string |
|
275 | - */ |
|
276 | - public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
277 | - return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l); |
|
278 | - } |
|
266 | + /** |
|
267 | + * Formats the date and time of the given timestamp |
|
268 | + * |
|
269 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
270 | + * @param string $formatDate See formatDate() for description |
|
271 | + * @param string $formatTime See formatTime() for description |
|
272 | + * @param \DateTimeZone $timeZone The timezone to use |
|
273 | + * @param \OCP\IL10N $l The locale to use |
|
274 | + * @return string Formatted date and time string |
|
275 | + */ |
|
276 | + public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
277 | + return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l); |
|
278 | + } |
|
279 | 279 | |
280 | - /** |
|
281 | - * Formats the date and time of the given timestamp |
|
282 | - * |
|
283 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
284 | - * @param string $formatDate See formatDate() for description |
|
285 | - * Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable |
|
286 | - * @param string $formatTime See formatTime() for description |
|
287 | - * @param \DateTimeZone $timeZone The timezone to use |
|
288 | - * @param \OCP\IL10N $l The locale to use |
|
289 | - * @return string Formatted relative date and time string |
|
290 | - */ |
|
291 | - public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
292 | - if (substr($formatDate, -1) !== '^' && substr($formatDate, -1) !== '*') { |
|
293 | - $formatDate .= '^'; |
|
294 | - } |
|
280 | + /** |
|
281 | + * Formats the date and time of the given timestamp |
|
282 | + * |
|
283 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
284 | + * @param string $formatDate See formatDate() for description |
|
285 | + * Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable |
|
286 | + * @param string $formatTime See formatTime() for description |
|
287 | + * @param \DateTimeZone $timeZone The timezone to use |
|
288 | + * @param \OCP\IL10N $l The locale to use |
|
289 | + * @return string Formatted relative date and time string |
|
290 | + */ |
|
291 | + public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
292 | + if (substr($formatDate, -1) !== '^' && substr($formatDate, -1) !== '*') { |
|
293 | + $formatDate .= '^'; |
|
294 | + } |
|
295 | 295 | |
296 | - return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l); |
|
297 | - } |
|
296 | + return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l); |
|
297 | + } |
|
298 | 298 | |
299 | - /** |
|
300 | - * Formats the date and time of the given timestamp |
|
301 | - * |
|
302 | - * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
303 | - * @param string $type One of 'date', 'datetime' or 'time' |
|
304 | - * @param string $format Format string |
|
305 | - * @param \DateTimeZone $timeZone The timezone to use |
|
306 | - * @param \OCP\IL10N $l The locale to use |
|
307 | - * @return string Formatted date and time string |
|
308 | - */ |
|
309 | - protected function format($timestamp, $type, $format, \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
310 | - $l = $this->getLocale($l); |
|
311 | - $timeZone = $this->getTimeZone($timeZone); |
|
312 | - $timestamp = $this->getDateTime($timestamp, $timeZone); |
|
299 | + /** |
|
300 | + * Formats the date and time of the given timestamp |
|
301 | + * |
|
302 | + * @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object |
|
303 | + * @param string $type One of 'date', 'datetime' or 'time' |
|
304 | + * @param string $format Format string |
|
305 | + * @param \DateTimeZone $timeZone The timezone to use |
|
306 | + * @param \OCP\IL10N $l The locale to use |
|
307 | + * @return string Formatted date and time string |
|
308 | + */ |
|
309 | + protected function format($timestamp, $type, $format, \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) { |
|
310 | + $l = $this->getLocale($l); |
|
311 | + $timeZone = $this->getTimeZone($timeZone); |
|
312 | + $timestamp = $this->getDateTime($timestamp, $timeZone); |
|
313 | 313 | |
314 | - return $l->l($type, $timestamp, [ |
|
315 | - 'width' => $format, |
|
316 | - ]); |
|
317 | - } |
|
314 | + return $l->l($type, $timestamp, [ |
|
315 | + 'width' => $format, |
|
316 | + ]); |
|
317 | + } |
|
318 | 318 | } |
@@ -25,80 +25,80 @@ |
||
25 | 25 | |
26 | 26 | trait EmitterTrait { |
27 | 27 | |
28 | - /** |
|
29 | - * @var callable[][] $listeners |
|
30 | - */ |
|
31 | - protected $listeners = []; |
|
28 | + /** |
|
29 | + * @var callable[][] $listeners |
|
30 | + */ |
|
31 | + protected $listeners = []; |
|
32 | 32 | |
33 | - /** |
|
34 | - * @param string $scope |
|
35 | - * @param string $method |
|
36 | - * @param callable $callback |
|
37 | - */ |
|
38 | - public function listen($scope, $method, callable $callback) { |
|
39 | - $eventName = $scope . '::' . $method; |
|
40 | - if (!isset($this->listeners[$eventName])) { |
|
41 | - $this->listeners[$eventName] = []; |
|
42 | - } |
|
43 | - if (array_search($callback, $this->listeners[$eventName], true) === false) { |
|
44 | - $this->listeners[$eventName][] = $callback; |
|
45 | - } |
|
46 | - } |
|
33 | + /** |
|
34 | + * @param string $scope |
|
35 | + * @param string $method |
|
36 | + * @param callable $callback |
|
37 | + */ |
|
38 | + public function listen($scope, $method, callable $callback) { |
|
39 | + $eventName = $scope . '::' . $method; |
|
40 | + if (!isset($this->listeners[$eventName])) { |
|
41 | + $this->listeners[$eventName] = []; |
|
42 | + } |
|
43 | + if (array_search($callback, $this->listeners[$eventName], true) === false) { |
|
44 | + $this->listeners[$eventName][] = $callback; |
|
45 | + } |
|
46 | + } |
|
47 | 47 | |
48 | - /** |
|
49 | - * @param string $scope optional |
|
50 | - * @param string $method optional |
|
51 | - * @param callable $callback optional |
|
52 | - */ |
|
53 | - public function removeListener($scope = null, $method = null, callable $callback = null) { |
|
54 | - $names = []; |
|
55 | - $allNames = array_keys($this->listeners); |
|
56 | - if ($scope and $method) { |
|
57 | - $name = $scope . '::' . $method; |
|
58 | - if (isset($this->listeners[$name])) { |
|
59 | - $names[] = $name; |
|
60 | - } |
|
61 | - } elseif ($scope) { |
|
62 | - foreach ($allNames as $name) { |
|
63 | - $parts = explode('::', $name, 2); |
|
64 | - if ($parts[0] == $scope) { |
|
65 | - $names[] = $name; |
|
66 | - } |
|
67 | - } |
|
68 | - } elseif ($method) { |
|
69 | - foreach ($allNames as $name) { |
|
70 | - $parts = explode('::', $name, 2); |
|
71 | - if ($parts[1] == $method) { |
|
72 | - $names[] = $name; |
|
73 | - } |
|
74 | - } |
|
75 | - } else { |
|
76 | - $names = $allNames; |
|
77 | - } |
|
48 | + /** |
|
49 | + * @param string $scope optional |
|
50 | + * @param string $method optional |
|
51 | + * @param callable $callback optional |
|
52 | + */ |
|
53 | + public function removeListener($scope = null, $method = null, callable $callback = null) { |
|
54 | + $names = []; |
|
55 | + $allNames = array_keys($this->listeners); |
|
56 | + if ($scope and $method) { |
|
57 | + $name = $scope . '::' . $method; |
|
58 | + if (isset($this->listeners[$name])) { |
|
59 | + $names[] = $name; |
|
60 | + } |
|
61 | + } elseif ($scope) { |
|
62 | + foreach ($allNames as $name) { |
|
63 | + $parts = explode('::', $name, 2); |
|
64 | + if ($parts[0] == $scope) { |
|
65 | + $names[] = $name; |
|
66 | + } |
|
67 | + } |
|
68 | + } elseif ($method) { |
|
69 | + foreach ($allNames as $name) { |
|
70 | + $parts = explode('::', $name, 2); |
|
71 | + if ($parts[1] == $method) { |
|
72 | + $names[] = $name; |
|
73 | + } |
|
74 | + } |
|
75 | + } else { |
|
76 | + $names = $allNames; |
|
77 | + } |
|
78 | 78 | |
79 | - foreach ($names as $name) { |
|
80 | - if ($callback) { |
|
81 | - $index = array_search($callback, $this->listeners[$name], true); |
|
82 | - if ($index !== false) { |
|
83 | - unset($this->listeners[$name][$index]); |
|
84 | - } |
|
85 | - } else { |
|
86 | - $this->listeners[$name] = []; |
|
87 | - } |
|
88 | - } |
|
89 | - } |
|
79 | + foreach ($names as $name) { |
|
80 | + if ($callback) { |
|
81 | + $index = array_search($callback, $this->listeners[$name], true); |
|
82 | + if ($index !== false) { |
|
83 | + unset($this->listeners[$name][$index]); |
|
84 | + } |
|
85 | + } else { |
|
86 | + $this->listeners[$name] = []; |
|
87 | + } |
|
88 | + } |
|
89 | + } |
|
90 | 90 | |
91 | - /** |
|
92 | - * @param string $scope |
|
93 | - * @param string $method |
|
94 | - * @param array $arguments optional |
|
95 | - */ |
|
96 | - protected function emit($scope, $method, array $arguments = []) { |
|
97 | - $eventName = $scope . '::' . $method; |
|
98 | - if (isset($this->listeners[$eventName])) { |
|
99 | - foreach ($this->listeners[$eventName] as $callback) { |
|
100 | - call_user_func_array($callback, $arguments); |
|
101 | - } |
|
102 | - } |
|
103 | - } |
|
91 | + /** |
|
92 | + * @param string $scope |
|
93 | + * @param string $method |
|
94 | + * @param array $arguments optional |
|
95 | + */ |
|
96 | + protected function emit($scope, $method, array $arguments = []) { |
|
97 | + $eventName = $scope . '::' . $method; |
|
98 | + if (isset($this->listeners[$eventName])) { |
|
99 | + foreach ($this->listeners[$eventName] as $callback) { |
|
100 | + call_user_func_array($callback, $arguments); |
|
101 | + } |
|
102 | + } |
|
103 | + } |
|
104 | 104 | } |
@@ -29,14 +29,14 @@ |
||
29 | 29 | * @deprecated 18.0.0 use events and the \OCP\EventDispatcher\IEventDispatcher service |
30 | 30 | */ |
31 | 31 | class PublicEmitter extends BasicEmitter { |
32 | - /** |
|
33 | - * @param string $scope |
|
34 | - * @param string $method |
|
35 | - * @param array $arguments optional |
|
36 | - * |
|
37 | - * @suppress PhanAccessMethodProtected |
|
38 | - */ |
|
39 | - public function emit($scope, $method, array $arguments = []) { |
|
40 | - parent::emit($scope, $method, $arguments); |
|
41 | - } |
|
32 | + /** |
|
33 | + * @param string $scope |
|
34 | + * @param string $method |
|
35 | + * @param array $arguments optional |
|
36 | + * |
|
37 | + * @suppress PhanAccessMethodProtected |
|
38 | + */ |
|
39 | + public function emit($scope, $method, array $arguments = []) { |
|
40 | + parent::emit($scope, $method, $arguments); |
|
41 | + } |
|
42 | 42 | } |
@@ -27,133 +27,133 @@ |
||
27 | 27 | use OCP\IMemcache; |
28 | 28 | |
29 | 29 | class ArrayCache extends Cache implements IMemcache { |
30 | - /** @var array Array with the cached data */ |
|
31 | - protected $cachedData = []; |
|
30 | + /** @var array Array with the cached data */ |
|
31 | + protected $cachedData = []; |
|
32 | 32 | |
33 | - use CADTrait; |
|
33 | + use CADTrait; |
|
34 | 34 | |
35 | - /** |
|
36 | - * {@inheritDoc} |
|
37 | - */ |
|
38 | - public function get($key) { |
|
39 | - if ($this->hasKey($key)) { |
|
40 | - return $this->cachedData[$key]; |
|
41 | - } |
|
42 | - return null; |
|
43 | - } |
|
35 | + /** |
|
36 | + * {@inheritDoc} |
|
37 | + */ |
|
38 | + public function get($key) { |
|
39 | + if ($this->hasKey($key)) { |
|
40 | + return $this->cachedData[$key]; |
|
41 | + } |
|
42 | + return null; |
|
43 | + } |
|
44 | 44 | |
45 | - /** |
|
46 | - * {@inheritDoc} |
|
47 | - */ |
|
48 | - public function set($key, $value, $ttl = 0) { |
|
49 | - $this->cachedData[$key] = $value; |
|
50 | - return true; |
|
51 | - } |
|
45 | + /** |
|
46 | + * {@inheritDoc} |
|
47 | + */ |
|
48 | + public function set($key, $value, $ttl = 0) { |
|
49 | + $this->cachedData[$key] = $value; |
|
50 | + return true; |
|
51 | + } |
|
52 | 52 | |
53 | - /** |
|
54 | - * {@inheritDoc} |
|
55 | - */ |
|
56 | - public function hasKey($key) { |
|
57 | - return isset($this->cachedData[$key]); |
|
58 | - } |
|
53 | + /** |
|
54 | + * {@inheritDoc} |
|
55 | + */ |
|
56 | + public function hasKey($key) { |
|
57 | + return isset($this->cachedData[$key]); |
|
58 | + } |
|
59 | 59 | |
60 | - /** |
|
61 | - * {@inheritDoc} |
|
62 | - */ |
|
63 | - public function remove($key) { |
|
64 | - unset($this->cachedData[$key]); |
|
65 | - return true; |
|
66 | - } |
|
60 | + /** |
|
61 | + * {@inheritDoc} |
|
62 | + */ |
|
63 | + public function remove($key) { |
|
64 | + unset($this->cachedData[$key]); |
|
65 | + return true; |
|
66 | + } |
|
67 | 67 | |
68 | - /** |
|
69 | - * {@inheritDoc} |
|
70 | - */ |
|
71 | - public function clear($prefix = '') { |
|
72 | - if ($prefix === '') { |
|
73 | - $this->cachedData = []; |
|
74 | - return true; |
|
75 | - } |
|
68 | + /** |
|
69 | + * {@inheritDoc} |
|
70 | + */ |
|
71 | + public function clear($prefix = '') { |
|
72 | + if ($prefix === '') { |
|
73 | + $this->cachedData = []; |
|
74 | + return true; |
|
75 | + } |
|
76 | 76 | |
77 | - foreach ($this->cachedData as $key => $value) { |
|
78 | - if (strpos($key, $prefix) === 0) { |
|
79 | - $this->remove($key); |
|
80 | - } |
|
81 | - } |
|
82 | - return true; |
|
83 | - } |
|
77 | + foreach ($this->cachedData as $key => $value) { |
|
78 | + if (strpos($key, $prefix) === 0) { |
|
79 | + $this->remove($key); |
|
80 | + } |
|
81 | + } |
|
82 | + return true; |
|
83 | + } |
|
84 | 84 | |
85 | - /** |
|
86 | - * Set a value in the cache if it's not already stored |
|
87 | - * |
|
88 | - * @param string $key |
|
89 | - * @param mixed $value |
|
90 | - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 |
|
91 | - * @return bool |
|
92 | - */ |
|
93 | - public function add($key, $value, $ttl = 0) { |
|
94 | - // since this cache is not shared race conditions aren't an issue |
|
95 | - if ($this->hasKey($key)) { |
|
96 | - return false; |
|
97 | - } else { |
|
98 | - return $this->set($key, $value, $ttl); |
|
99 | - } |
|
100 | - } |
|
85 | + /** |
|
86 | + * Set a value in the cache if it's not already stored |
|
87 | + * |
|
88 | + * @param string $key |
|
89 | + * @param mixed $value |
|
90 | + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 |
|
91 | + * @return bool |
|
92 | + */ |
|
93 | + public function add($key, $value, $ttl = 0) { |
|
94 | + // since this cache is not shared race conditions aren't an issue |
|
95 | + if ($this->hasKey($key)) { |
|
96 | + return false; |
|
97 | + } else { |
|
98 | + return $this->set($key, $value, $ttl); |
|
99 | + } |
|
100 | + } |
|
101 | 101 | |
102 | - /** |
|
103 | - * Increase a stored number |
|
104 | - * |
|
105 | - * @param string $key |
|
106 | - * @param int $step |
|
107 | - * @return int | bool |
|
108 | - */ |
|
109 | - public function inc($key, $step = 1) { |
|
110 | - $oldValue = $this->get($key); |
|
111 | - if (is_int($oldValue)) { |
|
112 | - $this->set($key, $oldValue + $step); |
|
113 | - return $oldValue + $step; |
|
114 | - } else { |
|
115 | - $success = $this->add($key, $step); |
|
116 | - return $success ? $step : false; |
|
117 | - } |
|
118 | - } |
|
102 | + /** |
|
103 | + * Increase a stored number |
|
104 | + * |
|
105 | + * @param string $key |
|
106 | + * @param int $step |
|
107 | + * @return int | bool |
|
108 | + */ |
|
109 | + public function inc($key, $step = 1) { |
|
110 | + $oldValue = $this->get($key); |
|
111 | + if (is_int($oldValue)) { |
|
112 | + $this->set($key, $oldValue + $step); |
|
113 | + return $oldValue + $step; |
|
114 | + } else { |
|
115 | + $success = $this->add($key, $step); |
|
116 | + return $success ? $step : false; |
|
117 | + } |
|
118 | + } |
|
119 | 119 | |
120 | - /** |
|
121 | - * Decrease a stored number |
|
122 | - * |
|
123 | - * @param string $key |
|
124 | - * @param int $step |
|
125 | - * @return int | bool |
|
126 | - */ |
|
127 | - public function dec($key, $step = 1) { |
|
128 | - $oldValue = $this->get($key); |
|
129 | - if (is_int($oldValue)) { |
|
130 | - $this->set($key, $oldValue - $step); |
|
131 | - return $oldValue - $step; |
|
132 | - } else { |
|
133 | - return false; |
|
134 | - } |
|
135 | - } |
|
120 | + /** |
|
121 | + * Decrease a stored number |
|
122 | + * |
|
123 | + * @param string $key |
|
124 | + * @param int $step |
|
125 | + * @return int | bool |
|
126 | + */ |
|
127 | + public function dec($key, $step = 1) { |
|
128 | + $oldValue = $this->get($key); |
|
129 | + if (is_int($oldValue)) { |
|
130 | + $this->set($key, $oldValue - $step); |
|
131 | + return $oldValue - $step; |
|
132 | + } else { |
|
133 | + return false; |
|
134 | + } |
|
135 | + } |
|
136 | 136 | |
137 | - /** |
|
138 | - * Compare and set |
|
139 | - * |
|
140 | - * @param string $key |
|
141 | - * @param mixed $old |
|
142 | - * @param mixed $new |
|
143 | - * @return bool |
|
144 | - */ |
|
145 | - public function cas($key, $old, $new) { |
|
146 | - if ($this->get($key) === $old) { |
|
147 | - return $this->set($key, $new); |
|
148 | - } else { |
|
149 | - return false; |
|
150 | - } |
|
151 | - } |
|
137 | + /** |
|
138 | + * Compare and set |
|
139 | + * |
|
140 | + * @param string $key |
|
141 | + * @param mixed $old |
|
142 | + * @param mixed $new |
|
143 | + * @return bool |
|
144 | + */ |
|
145 | + public function cas($key, $old, $new) { |
|
146 | + if ($this->get($key) === $old) { |
|
147 | + return $this->set($key, $new); |
|
148 | + } else { |
|
149 | + return false; |
|
150 | + } |
|
151 | + } |
|
152 | 152 | |
153 | - /** |
|
154 | - * {@inheritDoc} |
|
155 | - */ |
|
156 | - static public function isAvailable() { |
|
157 | - return true; |
|
158 | - } |
|
153 | + /** |
|
154 | + * {@inheritDoc} |
|
155 | + */ |
|
156 | + static public function isAvailable() { |
|
157 | + return true; |
|
158 | + } |
|
159 | 159 | } |
@@ -35,193 +35,193 @@ |
||
35 | 35 | use OCP\IMemcache; |
36 | 36 | |
37 | 37 | class Memcached extends Cache implements IMemcache { |
38 | - use CASTrait; |
|
39 | - |
|
40 | - /** |
|
41 | - * @var \Memcached $cache |
|
42 | - */ |
|
43 | - private static $cache = null; |
|
44 | - |
|
45 | - use CADTrait; |
|
46 | - |
|
47 | - public function __construct($prefix = '') { |
|
48 | - parent::__construct($prefix); |
|
49 | - if (is_null(self::$cache)) { |
|
50 | - self::$cache = new \Memcached(); |
|
51 | - |
|
52 | - $defaultOptions = [ |
|
53 | - \Memcached::OPT_CONNECT_TIMEOUT => 50, |
|
54 | - \Memcached::OPT_RETRY_TIMEOUT => 50, |
|
55 | - \Memcached::OPT_SEND_TIMEOUT => 50, |
|
56 | - \Memcached::OPT_RECV_TIMEOUT => 50, |
|
57 | - \Memcached::OPT_POLL_TIMEOUT => 50, |
|
58 | - |
|
59 | - // Enable compression |
|
60 | - \Memcached::OPT_COMPRESSION => true, |
|
61 | - |
|
62 | - // Turn on consistent hashing |
|
63 | - \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, |
|
64 | - |
|
65 | - // Enable Binary Protocol |
|
66 | - //\Memcached::OPT_BINARY_PROTOCOL => true, |
|
67 | - ]; |
|
68 | - // by default enable igbinary serializer if available |
|
69 | - if (\Memcached::HAVE_IGBINARY) { |
|
70 | - $defaultOptions[\Memcached::OPT_SERIALIZER] = |
|
71 | - \Memcached::SERIALIZER_IGBINARY; |
|
72 | - } |
|
73 | - $options = \OC::$server->getConfig()->getSystemValue('memcached_options', []); |
|
74 | - if (is_array($options)) { |
|
75 | - $options = $options + $defaultOptions; |
|
76 | - self::$cache->setOptions($options); |
|
77 | - } else { |
|
78 | - throw new HintException("Expected 'memcached_options' config to be an array, got $options"); |
|
79 | - } |
|
80 | - |
|
81 | - $servers = \OC::$server->getSystemConfig()->getValue('memcached_servers'); |
|
82 | - if (!$servers) { |
|
83 | - $server = \OC::$server->getSystemConfig()->getValue('memcached_server'); |
|
84 | - if ($server) { |
|
85 | - $servers = [$server]; |
|
86 | - } else { |
|
87 | - $servers = [['localhost', 11211]]; |
|
88 | - } |
|
89 | - } |
|
90 | - self::$cache->addServers($servers); |
|
91 | - } |
|
92 | - } |
|
93 | - |
|
94 | - /** |
|
95 | - * entries in XCache gets namespaced to prevent collisions between owncloud instances and users |
|
96 | - */ |
|
97 | - protected function getNameSpace() { |
|
98 | - return $this->prefix; |
|
99 | - } |
|
100 | - |
|
101 | - public function get($key) { |
|
102 | - $result = self::$cache->get($this->getNameSpace() . $key); |
|
103 | - if ($result === false and self::$cache->getResultCode() == \Memcached::RES_NOTFOUND) { |
|
104 | - return null; |
|
105 | - } else { |
|
106 | - return $result; |
|
107 | - } |
|
108 | - } |
|
109 | - |
|
110 | - public function set($key, $value, $ttl = 0) { |
|
111 | - if ($ttl > 0) { |
|
112 | - $result = self::$cache->set($this->getNameSpace() . $key, $value, $ttl); |
|
113 | - } else { |
|
114 | - $result = self::$cache->set($this->getNameSpace() . $key, $value); |
|
115 | - } |
|
116 | - if ($result !== true) { |
|
117 | - $this->verifyReturnCode(); |
|
118 | - } |
|
119 | - return $result; |
|
120 | - } |
|
121 | - |
|
122 | - public function hasKey($key) { |
|
123 | - self::$cache->get($this->getNameSpace() . $key); |
|
124 | - return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; |
|
125 | - } |
|
126 | - |
|
127 | - public function remove($key) { |
|
128 | - $result= self::$cache->delete($this->getNameSpace() . $key); |
|
129 | - if (self::$cache->getResultCode() !== \Memcached::RES_NOTFOUND) { |
|
130 | - $this->verifyReturnCode(); |
|
131 | - } |
|
132 | - return $result; |
|
133 | - } |
|
134 | - |
|
135 | - public function clear($prefix = '') { |
|
136 | - $prefix = $this->getNameSpace() . $prefix; |
|
137 | - $allKeys = self::$cache->getAllKeys(); |
|
138 | - if ($allKeys === false) { |
|
139 | - // newer Memcached doesn't like getAllKeys(), flush everything |
|
140 | - self::$cache->flush(); |
|
141 | - return true; |
|
142 | - } |
|
143 | - $keys = []; |
|
144 | - $prefixLength = strlen($prefix); |
|
145 | - foreach ($allKeys as $key) { |
|
146 | - if (substr($key, 0, $prefixLength) === $prefix) { |
|
147 | - $keys[] = $key; |
|
148 | - } |
|
149 | - } |
|
150 | - if (method_exists(self::$cache, 'deleteMulti')) { |
|
151 | - self::$cache->deleteMulti($keys); |
|
152 | - } else { |
|
153 | - foreach ($keys as $key) { |
|
154 | - self::$cache->delete($key); |
|
155 | - } |
|
156 | - } |
|
157 | - return true; |
|
158 | - } |
|
159 | - |
|
160 | - /** |
|
161 | - * Set a value in the cache if it's not already stored |
|
162 | - * |
|
163 | - * @param string $key |
|
164 | - * @param mixed $value |
|
165 | - * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 |
|
166 | - * @return bool |
|
167 | - * @throws \Exception |
|
168 | - */ |
|
169 | - public function add($key, $value, $ttl = 0) { |
|
170 | - $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); |
|
171 | - if (self::$cache->getResultCode() !== \Memcached::RES_NOTSTORED) { |
|
172 | - $this->verifyReturnCode(); |
|
173 | - } |
|
174 | - return $result; |
|
175 | - } |
|
176 | - |
|
177 | - /** |
|
178 | - * Increase a stored number |
|
179 | - * |
|
180 | - * @param string $key |
|
181 | - * @param int $step |
|
182 | - * @return int | bool |
|
183 | - */ |
|
184 | - public function inc($key, $step = 1) { |
|
185 | - $this->add($key, 0); |
|
186 | - $result = self::$cache->increment($this->getPrefix() . $key, $step); |
|
187 | - |
|
188 | - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { |
|
189 | - return false; |
|
190 | - } |
|
191 | - |
|
192 | - return $result; |
|
193 | - } |
|
194 | - |
|
195 | - /** |
|
196 | - * Decrease a stored number |
|
197 | - * |
|
198 | - * @param string $key |
|
199 | - * @param int $step |
|
200 | - * @return int | bool |
|
201 | - */ |
|
202 | - public function dec($key, $step = 1) { |
|
203 | - $result = self::$cache->decrement($this->getPrefix() . $key, $step); |
|
204 | - |
|
205 | - if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { |
|
206 | - return false; |
|
207 | - } |
|
208 | - |
|
209 | - return $result; |
|
210 | - } |
|
211 | - |
|
212 | - static public function isAvailable() { |
|
213 | - return extension_loaded('memcached'); |
|
214 | - } |
|
215 | - |
|
216 | - /** |
|
217 | - * @throws \Exception |
|
218 | - */ |
|
219 | - private function verifyReturnCode() { |
|
220 | - $code = self::$cache->getResultCode(); |
|
221 | - if ($code === \Memcached::RES_SUCCESS) { |
|
222 | - return; |
|
223 | - } |
|
224 | - $message = self::$cache->getResultMessage(); |
|
225 | - throw new \Exception("Error $code interacting with memcached : $message"); |
|
226 | - } |
|
38 | + use CASTrait; |
|
39 | + |
|
40 | + /** |
|
41 | + * @var \Memcached $cache |
|
42 | + */ |
|
43 | + private static $cache = null; |
|
44 | + |
|
45 | + use CADTrait; |
|
46 | + |
|
47 | + public function __construct($prefix = '') { |
|
48 | + parent::__construct($prefix); |
|
49 | + if (is_null(self::$cache)) { |
|
50 | + self::$cache = new \Memcached(); |
|
51 | + |
|
52 | + $defaultOptions = [ |
|
53 | + \Memcached::OPT_CONNECT_TIMEOUT => 50, |
|
54 | + \Memcached::OPT_RETRY_TIMEOUT => 50, |
|
55 | + \Memcached::OPT_SEND_TIMEOUT => 50, |
|
56 | + \Memcached::OPT_RECV_TIMEOUT => 50, |
|
57 | + \Memcached::OPT_POLL_TIMEOUT => 50, |
|
58 | + |
|
59 | + // Enable compression |
|
60 | + \Memcached::OPT_COMPRESSION => true, |
|
61 | + |
|
62 | + // Turn on consistent hashing |
|
63 | + \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, |
|
64 | + |
|
65 | + // Enable Binary Protocol |
|
66 | + //\Memcached::OPT_BINARY_PROTOCOL => true, |
|
67 | + ]; |
|
68 | + // by default enable igbinary serializer if available |
|
69 | + if (\Memcached::HAVE_IGBINARY) { |
|
70 | + $defaultOptions[\Memcached::OPT_SERIALIZER] = |
|
71 | + \Memcached::SERIALIZER_IGBINARY; |
|
72 | + } |
|
73 | + $options = \OC::$server->getConfig()->getSystemValue('memcached_options', []); |
|
74 | + if (is_array($options)) { |
|
75 | + $options = $options + $defaultOptions; |
|
76 | + self::$cache->setOptions($options); |
|
77 | + } else { |
|
78 | + throw new HintException("Expected 'memcached_options' config to be an array, got $options"); |
|
79 | + } |
|
80 | + |
|
81 | + $servers = \OC::$server->getSystemConfig()->getValue('memcached_servers'); |
|
82 | + if (!$servers) { |
|
83 | + $server = \OC::$server->getSystemConfig()->getValue('memcached_server'); |
|
84 | + if ($server) { |
|
85 | + $servers = [$server]; |
|
86 | + } else { |
|
87 | + $servers = [['localhost', 11211]]; |
|
88 | + } |
|
89 | + } |
|
90 | + self::$cache->addServers($servers); |
|
91 | + } |
|
92 | + } |
|
93 | + |
|
94 | + /** |
|
95 | + * entries in XCache gets namespaced to prevent collisions between owncloud instances and users |
|
96 | + */ |
|
97 | + protected function getNameSpace() { |
|
98 | + return $this->prefix; |
|
99 | + } |
|
100 | + |
|
101 | + public function get($key) { |
|
102 | + $result = self::$cache->get($this->getNameSpace() . $key); |
|
103 | + if ($result === false and self::$cache->getResultCode() == \Memcached::RES_NOTFOUND) { |
|
104 | + return null; |
|
105 | + } else { |
|
106 | + return $result; |
|
107 | + } |
|
108 | + } |
|
109 | + |
|
110 | + public function set($key, $value, $ttl = 0) { |
|
111 | + if ($ttl > 0) { |
|
112 | + $result = self::$cache->set($this->getNameSpace() . $key, $value, $ttl); |
|
113 | + } else { |
|
114 | + $result = self::$cache->set($this->getNameSpace() . $key, $value); |
|
115 | + } |
|
116 | + if ($result !== true) { |
|
117 | + $this->verifyReturnCode(); |
|
118 | + } |
|
119 | + return $result; |
|
120 | + } |
|
121 | + |
|
122 | + public function hasKey($key) { |
|
123 | + self::$cache->get($this->getNameSpace() . $key); |
|
124 | + return self::$cache->getResultCode() === \Memcached::RES_SUCCESS; |
|
125 | + } |
|
126 | + |
|
127 | + public function remove($key) { |
|
128 | + $result= self::$cache->delete($this->getNameSpace() . $key); |
|
129 | + if (self::$cache->getResultCode() !== \Memcached::RES_NOTFOUND) { |
|
130 | + $this->verifyReturnCode(); |
|
131 | + } |
|
132 | + return $result; |
|
133 | + } |
|
134 | + |
|
135 | + public function clear($prefix = '') { |
|
136 | + $prefix = $this->getNameSpace() . $prefix; |
|
137 | + $allKeys = self::$cache->getAllKeys(); |
|
138 | + if ($allKeys === false) { |
|
139 | + // newer Memcached doesn't like getAllKeys(), flush everything |
|
140 | + self::$cache->flush(); |
|
141 | + return true; |
|
142 | + } |
|
143 | + $keys = []; |
|
144 | + $prefixLength = strlen($prefix); |
|
145 | + foreach ($allKeys as $key) { |
|
146 | + if (substr($key, 0, $prefixLength) === $prefix) { |
|
147 | + $keys[] = $key; |
|
148 | + } |
|
149 | + } |
|
150 | + if (method_exists(self::$cache, 'deleteMulti')) { |
|
151 | + self::$cache->deleteMulti($keys); |
|
152 | + } else { |
|
153 | + foreach ($keys as $key) { |
|
154 | + self::$cache->delete($key); |
|
155 | + } |
|
156 | + } |
|
157 | + return true; |
|
158 | + } |
|
159 | + |
|
160 | + /** |
|
161 | + * Set a value in the cache if it's not already stored |
|
162 | + * |
|
163 | + * @param string $key |
|
164 | + * @param mixed $value |
|
165 | + * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 |
|
166 | + * @return bool |
|
167 | + * @throws \Exception |
|
168 | + */ |
|
169 | + public function add($key, $value, $ttl = 0) { |
|
170 | + $result = self::$cache->add($this->getPrefix() . $key, $value, $ttl); |
|
171 | + if (self::$cache->getResultCode() !== \Memcached::RES_NOTSTORED) { |
|
172 | + $this->verifyReturnCode(); |
|
173 | + } |
|
174 | + return $result; |
|
175 | + } |
|
176 | + |
|
177 | + /** |
|
178 | + * Increase a stored number |
|
179 | + * |
|
180 | + * @param string $key |
|
181 | + * @param int $step |
|
182 | + * @return int | bool |
|
183 | + */ |
|
184 | + public function inc($key, $step = 1) { |
|
185 | + $this->add($key, 0); |
|
186 | + $result = self::$cache->increment($this->getPrefix() . $key, $step); |
|
187 | + |
|
188 | + if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { |
|
189 | + return false; |
|
190 | + } |
|
191 | + |
|
192 | + return $result; |
|
193 | + } |
|
194 | + |
|
195 | + /** |
|
196 | + * Decrease a stored number |
|
197 | + * |
|
198 | + * @param string $key |
|
199 | + * @param int $step |
|
200 | + * @return int | bool |
|
201 | + */ |
|
202 | + public function dec($key, $step = 1) { |
|
203 | + $result = self::$cache->decrement($this->getPrefix() . $key, $step); |
|
204 | + |
|
205 | + if (self::$cache->getResultCode() !== \Memcached::RES_SUCCESS) { |
|
206 | + return false; |
|
207 | + } |
|
208 | + |
|
209 | + return $result; |
|
210 | + } |
|
211 | + |
|
212 | + static public function isAvailable() { |
|
213 | + return extension_loaded('memcached'); |
|
214 | + } |
|
215 | + |
|
216 | + /** |
|
217 | + * @throws \Exception |
|
218 | + */ |
|
219 | + private function verifyReturnCode() { |
|
220 | + $code = self::$cache->getResultCode(); |
|
221 | + if ($code === \Memcached::RES_SUCCESS) { |
|
222 | + return; |
|
223 | + } |
|
224 | + $message = self::$cache->getResultMessage(); |
|
225 | + throw new \Exception("Error $code interacting with memcached : $message"); |
|
226 | + } |
|
227 | 227 | } |
@@ -41,349 +41,349 @@ |
||
41 | 41 | use OCP\RichObjectStrings\IValidator; |
42 | 42 | |
43 | 43 | class Manager implements IManager { |
44 | - /** @var IRequest */ |
|
45 | - protected $request; |
|
46 | - |
|
47 | - /** @var IUserSession */ |
|
48 | - protected $session; |
|
49 | - |
|
50 | - /** @var IConfig */ |
|
51 | - protected $config; |
|
52 | - |
|
53 | - /** @var IValidator */ |
|
54 | - protected $validator; |
|
55 | - |
|
56 | - /** @var string */ |
|
57 | - protected $formattingObjectType; |
|
58 | - |
|
59 | - /** @var int */ |
|
60 | - protected $formattingObjectId; |
|
61 | - |
|
62 | - /** @var bool */ |
|
63 | - protected $requirePNG = false; |
|
64 | - |
|
65 | - /** @var string */ |
|
66 | - protected $currentUserId; |
|
67 | - |
|
68 | - public function __construct(IRequest $request, |
|
69 | - IUserSession $session, |
|
70 | - IConfig $config, |
|
71 | - IValidator $validator) { |
|
72 | - $this->request = $request; |
|
73 | - $this->session = $session; |
|
74 | - $this->config = $config; |
|
75 | - $this->validator = $validator; |
|
76 | - } |
|
77 | - |
|
78 | - /** @var \Closure[] */ |
|
79 | - private $consumersClosures = []; |
|
80 | - |
|
81 | - /** @var IConsumer[] */ |
|
82 | - private $consumers = []; |
|
83 | - |
|
84 | - /** |
|
85 | - * @return \OCP\Activity\IConsumer[] |
|
86 | - */ |
|
87 | - protected function getConsumers(): array { |
|
88 | - if (!empty($this->consumers)) { |
|
89 | - return $this->consumers; |
|
90 | - } |
|
91 | - |
|
92 | - $this->consumers = []; |
|
93 | - foreach($this->consumersClosures as $consumer) { |
|
94 | - $c = $consumer(); |
|
95 | - if ($c instanceof IConsumer) { |
|
96 | - $this->consumers[] = $c; |
|
97 | - } else { |
|
98 | - throw new \InvalidArgumentException('The given consumer does not implement the \OCP\Activity\IConsumer interface'); |
|
99 | - } |
|
100 | - } |
|
101 | - |
|
102 | - return $this->consumers; |
|
103 | - } |
|
104 | - |
|
105 | - /** |
|
106 | - * Generates a new IEvent object |
|
107 | - * |
|
108 | - * Make sure to call at least the following methods before sending it to the |
|
109 | - * app with via the publish() method: |
|
110 | - * - setApp() |
|
111 | - * - setType() |
|
112 | - * - setAffectedUser() |
|
113 | - * - setSubject() |
|
114 | - * |
|
115 | - * @return IEvent |
|
116 | - */ |
|
117 | - public function generateEvent(): IEvent { |
|
118 | - return new Event($this->validator); |
|
119 | - } |
|
120 | - |
|
121 | - /** |
|
122 | - * Publish an event to the activity consumers |
|
123 | - * |
|
124 | - * Make sure to call at least the following methods before sending an Event: |
|
125 | - * - setApp() |
|
126 | - * - setType() |
|
127 | - * - setAffectedUser() |
|
128 | - * - setSubject() |
|
129 | - * |
|
130 | - * @param IEvent $event |
|
131 | - * @throws \BadMethodCallException if required values have not been set |
|
132 | - */ |
|
133 | - public function publish(IEvent $event): void { |
|
134 | - if ($event->getAuthor() === '') { |
|
135 | - if ($this->session->getUser() instanceof IUser) { |
|
136 | - $event->setAuthor($this->session->getUser()->getUID()); |
|
137 | - } |
|
138 | - } |
|
139 | - |
|
140 | - if (!$event->getTimestamp()) { |
|
141 | - $event->setTimestamp(time()); |
|
142 | - } |
|
143 | - |
|
144 | - if (!$event->isValid()) { |
|
145 | - throw new \BadMethodCallException('The given event is invalid'); |
|
146 | - } |
|
147 | - |
|
148 | - foreach ($this->getConsumers() as $c) { |
|
149 | - $c->receive($event); |
|
150 | - } |
|
151 | - } |
|
152 | - |
|
153 | - /** |
|
154 | - * In order to improve lazy loading a closure can be registered which will be called in case |
|
155 | - * activity consumers are actually requested |
|
156 | - * |
|
157 | - * $callable has to return an instance of OCA\Activity\IConsumer |
|
158 | - * |
|
159 | - * @param \Closure $callable |
|
160 | - */ |
|
161 | - public function registerConsumer(\Closure $callable): void { |
|
162 | - $this->consumersClosures[] = $callable; |
|
163 | - $this->consumers = []; |
|
164 | - } |
|
165 | - |
|
166 | - /** @var string[] */ |
|
167 | - protected $filterClasses = []; |
|
168 | - |
|
169 | - /** @var IFilter[] */ |
|
170 | - protected $filters = []; |
|
171 | - |
|
172 | - /** |
|
173 | - * @param string $filter Class must implement OCA\Activity\IFilter |
|
174 | - * @return void |
|
175 | - */ |
|
176 | - public function registerFilter(string $filter): void { |
|
177 | - $this->filterClasses[$filter] = false; |
|
178 | - } |
|
179 | - |
|
180 | - /** |
|
181 | - * @return IFilter[] |
|
182 | - * @throws \InvalidArgumentException |
|
183 | - */ |
|
184 | - public function getFilters(): array { |
|
185 | - foreach ($this->filterClasses as $class => $false) { |
|
186 | - /** @var IFilter $filter */ |
|
187 | - $filter = \OC::$server->query($class); |
|
188 | - |
|
189 | - if (!$filter instanceof IFilter) { |
|
190 | - throw new \InvalidArgumentException('Invalid activity filter registered'); |
|
191 | - } |
|
192 | - |
|
193 | - $this->filters[$filter->getIdentifier()] = $filter; |
|
194 | - |
|
195 | - unset($this->filterClasses[$class]); |
|
196 | - } |
|
197 | - return $this->filters; |
|
198 | - } |
|
199 | - |
|
200 | - /** |
|
201 | - * @param string $id |
|
202 | - * @return IFilter |
|
203 | - * @throws \InvalidArgumentException when the filter was not found |
|
204 | - * @since 11.0.0 |
|
205 | - */ |
|
206 | - public function getFilterById(string $id): IFilter { |
|
207 | - $filters = $this->getFilters(); |
|
208 | - |
|
209 | - if (isset($filters[$id])) { |
|
210 | - return $filters[$id]; |
|
211 | - } |
|
212 | - |
|
213 | - throw new \InvalidArgumentException('Requested filter does not exist'); |
|
214 | - } |
|
215 | - |
|
216 | - /** @var string[] */ |
|
217 | - protected $providerClasses = []; |
|
218 | - |
|
219 | - /** @var IProvider[] */ |
|
220 | - protected $providers = []; |
|
221 | - |
|
222 | - /** |
|
223 | - * @param string $provider Class must implement OCA\Activity\IProvider |
|
224 | - * @return void |
|
225 | - */ |
|
226 | - public function registerProvider(string $provider): void { |
|
227 | - $this->providerClasses[$provider] = false; |
|
228 | - } |
|
229 | - |
|
230 | - /** |
|
231 | - * @return IProvider[] |
|
232 | - * @throws \InvalidArgumentException |
|
233 | - */ |
|
234 | - public function getProviders(): array { |
|
235 | - foreach ($this->providerClasses as $class => $false) { |
|
236 | - /** @var IProvider $provider */ |
|
237 | - $provider = \OC::$server->query($class); |
|
238 | - |
|
239 | - if (!$provider instanceof IProvider) { |
|
240 | - throw new \InvalidArgumentException('Invalid activity provider registered'); |
|
241 | - } |
|
242 | - |
|
243 | - $this->providers[] = $provider; |
|
244 | - |
|
245 | - unset($this->providerClasses[$class]); |
|
246 | - } |
|
247 | - return $this->providers; |
|
248 | - } |
|
249 | - |
|
250 | - /** @var string[] */ |
|
251 | - protected $settingsClasses = []; |
|
252 | - |
|
253 | - /** @var ISetting[] */ |
|
254 | - protected $settings = []; |
|
255 | - |
|
256 | - /** |
|
257 | - * @param string $setting Class must implement OCA\Activity\ISetting |
|
258 | - * @return void |
|
259 | - */ |
|
260 | - public function registerSetting(string $setting): void { |
|
261 | - $this->settingsClasses[$setting] = false; |
|
262 | - } |
|
263 | - |
|
264 | - /** |
|
265 | - * @return ISetting[] |
|
266 | - * @throws \InvalidArgumentException |
|
267 | - */ |
|
268 | - public function getSettings(): array { |
|
269 | - foreach ($this->settingsClasses as $class => $false) { |
|
270 | - /** @var ISetting $setting */ |
|
271 | - $setting = \OC::$server->query($class); |
|
272 | - |
|
273 | - if (!$setting instanceof ISetting) { |
|
274 | - throw new \InvalidArgumentException('Invalid activity filter registered'); |
|
275 | - } |
|
276 | - |
|
277 | - $this->settings[$setting->getIdentifier()] = $setting; |
|
278 | - |
|
279 | - unset($this->settingsClasses[$class]); |
|
280 | - } |
|
281 | - return $this->settings; |
|
282 | - } |
|
283 | - |
|
284 | - /** |
|
285 | - * @param string $id |
|
286 | - * @return ISetting |
|
287 | - * @throws \InvalidArgumentException when the setting was not found |
|
288 | - * @since 11.0.0 |
|
289 | - */ |
|
290 | - public function getSettingById(string $id): ISetting { |
|
291 | - $settings = $this->getSettings(); |
|
292 | - |
|
293 | - if (isset($settings[$id])) { |
|
294 | - return $settings[$id]; |
|
295 | - } |
|
296 | - |
|
297 | - throw new \InvalidArgumentException('Requested setting does not exist'); |
|
298 | - } |
|
299 | - |
|
300 | - |
|
301 | - /** |
|
302 | - * @param string $type |
|
303 | - * @param int $id |
|
304 | - */ |
|
305 | - public function setFormattingObject(string $type, int $id): void { |
|
306 | - $this->formattingObjectType = $type; |
|
307 | - $this->formattingObjectId = $id; |
|
308 | - } |
|
309 | - |
|
310 | - /** |
|
311 | - * @return bool |
|
312 | - */ |
|
313 | - public function isFormattingFilteredObject(): bool { |
|
314 | - return $this->formattingObjectType !== null && $this->formattingObjectId !== null |
|
315 | - && $this->formattingObjectType === $this->request->getParam('object_type') |
|
316 | - && $this->formattingObjectId === (int) $this->request->getParam('object_id'); |
|
317 | - } |
|
318 | - |
|
319 | - /** |
|
320 | - * @param bool $status Set to true, when parsing events should not use SVG icons |
|
321 | - */ |
|
322 | - public function setRequirePNG(bool $status): void { |
|
323 | - $this->requirePNG = $status; |
|
324 | - } |
|
325 | - |
|
326 | - /** |
|
327 | - * @return bool |
|
328 | - */ |
|
329 | - public function getRequirePNG(): bool { |
|
330 | - return $this->requirePNG; |
|
331 | - } |
|
332 | - |
|
333 | - /** |
|
334 | - * Set the user we need to use |
|
335 | - * |
|
336 | - * @param string|null $currentUserId |
|
337 | - * @throws \UnexpectedValueException If the user is invalid |
|
338 | - */ |
|
339 | - public function setCurrentUserId(string $currentUserId = null): void { |
|
340 | - if (!is_string($currentUserId) && $currentUserId !== null) { |
|
341 | - throw new \UnexpectedValueException('The given current user is invalid'); |
|
342 | - } |
|
343 | - $this->currentUserId = $currentUserId; |
|
344 | - } |
|
345 | - |
|
346 | - /** |
|
347 | - * Get the user we need to use |
|
348 | - * |
|
349 | - * Either the user is logged in, or we try to get it from the token |
|
350 | - * |
|
351 | - * @return string |
|
352 | - * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique |
|
353 | - */ |
|
354 | - public function getCurrentUserId(): string { |
|
355 | - if ($this->currentUserId !== null) { |
|
356 | - return $this->currentUserId; |
|
357 | - } |
|
358 | - |
|
359 | - if (!$this->session->isLoggedIn()) { |
|
360 | - return $this->getUserFromToken(); |
|
361 | - } |
|
362 | - |
|
363 | - return $this->session->getUser()->getUID(); |
|
364 | - } |
|
365 | - |
|
366 | - /** |
|
367 | - * Get the user for the token |
|
368 | - * |
|
369 | - * @return string |
|
370 | - * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique |
|
371 | - */ |
|
372 | - protected function getUserFromToken(): string { |
|
373 | - $token = (string) $this->request->getParam('token', ''); |
|
374 | - if (strlen($token) !== 30) { |
|
375 | - throw new \UnexpectedValueException('The token is invalid'); |
|
376 | - } |
|
377 | - |
|
378 | - $users = $this->config->getUsersForUserValue('activity', 'rsstoken', $token); |
|
379 | - |
|
380 | - if (count($users) !== 1) { |
|
381 | - // No unique user found |
|
382 | - throw new \UnexpectedValueException('The token is invalid'); |
|
383 | - } |
|
384 | - |
|
385 | - // Token found login as that user |
|
386 | - return array_shift($users); |
|
387 | - } |
|
44 | + /** @var IRequest */ |
|
45 | + protected $request; |
|
46 | + |
|
47 | + /** @var IUserSession */ |
|
48 | + protected $session; |
|
49 | + |
|
50 | + /** @var IConfig */ |
|
51 | + protected $config; |
|
52 | + |
|
53 | + /** @var IValidator */ |
|
54 | + protected $validator; |
|
55 | + |
|
56 | + /** @var string */ |
|
57 | + protected $formattingObjectType; |
|
58 | + |
|
59 | + /** @var int */ |
|
60 | + protected $formattingObjectId; |
|
61 | + |
|
62 | + /** @var bool */ |
|
63 | + protected $requirePNG = false; |
|
64 | + |
|
65 | + /** @var string */ |
|
66 | + protected $currentUserId; |
|
67 | + |
|
68 | + public function __construct(IRequest $request, |
|
69 | + IUserSession $session, |
|
70 | + IConfig $config, |
|
71 | + IValidator $validator) { |
|
72 | + $this->request = $request; |
|
73 | + $this->session = $session; |
|
74 | + $this->config = $config; |
|
75 | + $this->validator = $validator; |
|
76 | + } |
|
77 | + |
|
78 | + /** @var \Closure[] */ |
|
79 | + private $consumersClosures = []; |
|
80 | + |
|
81 | + /** @var IConsumer[] */ |
|
82 | + private $consumers = []; |
|
83 | + |
|
84 | + /** |
|
85 | + * @return \OCP\Activity\IConsumer[] |
|
86 | + */ |
|
87 | + protected function getConsumers(): array { |
|
88 | + if (!empty($this->consumers)) { |
|
89 | + return $this->consumers; |
|
90 | + } |
|
91 | + |
|
92 | + $this->consumers = []; |
|
93 | + foreach($this->consumersClosures as $consumer) { |
|
94 | + $c = $consumer(); |
|
95 | + if ($c instanceof IConsumer) { |
|
96 | + $this->consumers[] = $c; |
|
97 | + } else { |
|
98 | + throw new \InvalidArgumentException('The given consumer does not implement the \OCP\Activity\IConsumer interface'); |
|
99 | + } |
|
100 | + } |
|
101 | + |
|
102 | + return $this->consumers; |
|
103 | + } |
|
104 | + |
|
105 | + /** |
|
106 | + * Generates a new IEvent object |
|
107 | + * |
|
108 | + * Make sure to call at least the following methods before sending it to the |
|
109 | + * app with via the publish() method: |
|
110 | + * - setApp() |
|
111 | + * - setType() |
|
112 | + * - setAffectedUser() |
|
113 | + * - setSubject() |
|
114 | + * |
|
115 | + * @return IEvent |
|
116 | + */ |
|
117 | + public function generateEvent(): IEvent { |
|
118 | + return new Event($this->validator); |
|
119 | + } |
|
120 | + |
|
121 | + /** |
|
122 | + * Publish an event to the activity consumers |
|
123 | + * |
|
124 | + * Make sure to call at least the following methods before sending an Event: |
|
125 | + * - setApp() |
|
126 | + * - setType() |
|
127 | + * - setAffectedUser() |
|
128 | + * - setSubject() |
|
129 | + * |
|
130 | + * @param IEvent $event |
|
131 | + * @throws \BadMethodCallException if required values have not been set |
|
132 | + */ |
|
133 | + public function publish(IEvent $event): void { |
|
134 | + if ($event->getAuthor() === '') { |
|
135 | + if ($this->session->getUser() instanceof IUser) { |
|
136 | + $event->setAuthor($this->session->getUser()->getUID()); |
|
137 | + } |
|
138 | + } |
|
139 | + |
|
140 | + if (!$event->getTimestamp()) { |
|
141 | + $event->setTimestamp(time()); |
|
142 | + } |
|
143 | + |
|
144 | + if (!$event->isValid()) { |
|
145 | + throw new \BadMethodCallException('The given event is invalid'); |
|
146 | + } |
|
147 | + |
|
148 | + foreach ($this->getConsumers() as $c) { |
|
149 | + $c->receive($event); |
|
150 | + } |
|
151 | + } |
|
152 | + |
|
153 | + /** |
|
154 | + * In order to improve lazy loading a closure can be registered which will be called in case |
|
155 | + * activity consumers are actually requested |
|
156 | + * |
|
157 | + * $callable has to return an instance of OCA\Activity\IConsumer |
|
158 | + * |
|
159 | + * @param \Closure $callable |
|
160 | + */ |
|
161 | + public function registerConsumer(\Closure $callable): void { |
|
162 | + $this->consumersClosures[] = $callable; |
|
163 | + $this->consumers = []; |
|
164 | + } |
|
165 | + |
|
166 | + /** @var string[] */ |
|
167 | + protected $filterClasses = []; |
|
168 | + |
|
169 | + /** @var IFilter[] */ |
|
170 | + protected $filters = []; |
|
171 | + |
|
172 | + /** |
|
173 | + * @param string $filter Class must implement OCA\Activity\IFilter |
|
174 | + * @return void |
|
175 | + */ |
|
176 | + public function registerFilter(string $filter): void { |
|
177 | + $this->filterClasses[$filter] = false; |
|
178 | + } |
|
179 | + |
|
180 | + /** |
|
181 | + * @return IFilter[] |
|
182 | + * @throws \InvalidArgumentException |
|
183 | + */ |
|
184 | + public function getFilters(): array { |
|
185 | + foreach ($this->filterClasses as $class => $false) { |
|
186 | + /** @var IFilter $filter */ |
|
187 | + $filter = \OC::$server->query($class); |
|
188 | + |
|
189 | + if (!$filter instanceof IFilter) { |
|
190 | + throw new \InvalidArgumentException('Invalid activity filter registered'); |
|
191 | + } |
|
192 | + |
|
193 | + $this->filters[$filter->getIdentifier()] = $filter; |
|
194 | + |
|
195 | + unset($this->filterClasses[$class]); |
|
196 | + } |
|
197 | + return $this->filters; |
|
198 | + } |
|
199 | + |
|
200 | + /** |
|
201 | + * @param string $id |
|
202 | + * @return IFilter |
|
203 | + * @throws \InvalidArgumentException when the filter was not found |
|
204 | + * @since 11.0.0 |
|
205 | + */ |
|
206 | + public function getFilterById(string $id): IFilter { |
|
207 | + $filters = $this->getFilters(); |
|
208 | + |
|
209 | + if (isset($filters[$id])) { |
|
210 | + return $filters[$id]; |
|
211 | + } |
|
212 | + |
|
213 | + throw new \InvalidArgumentException('Requested filter does not exist'); |
|
214 | + } |
|
215 | + |
|
216 | + /** @var string[] */ |
|
217 | + protected $providerClasses = []; |
|
218 | + |
|
219 | + /** @var IProvider[] */ |
|
220 | + protected $providers = []; |
|
221 | + |
|
222 | + /** |
|
223 | + * @param string $provider Class must implement OCA\Activity\IProvider |
|
224 | + * @return void |
|
225 | + */ |
|
226 | + public function registerProvider(string $provider): void { |
|
227 | + $this->providerClasses[$provider] = false; |
|
228 | + } |
|
229 | + |
|
230 | + /** |
|
231 | + * @return IProvider[] |
|
232 | + * @throws \InvalidArgumentException |
|
233 | + */ |
|
234 | + public function getProviders(): array { |
|
235 | + foreach ($this->providerClasses as $class => $false) { |
|
236 | + /** @var IProvider $provider */ |
|
237 | + $provider = \OC::$server->query($class); |
|
238 | + |
|
239 | + if (!$provider instanceof IProvider) { |
|
240 | + throw new \InvalidArgumentException('Invalid activity provider registered'); |
|
241 | + } |
|
242 | + |
|
243 | + $this->providers[] = $provider; |
|
244 | + |
|
245 | + unset($this->providerClasses[$class]); |
|
246 | + } |
|
247 | + return $this->providers; |
|
248 | + } |
|
249 | + |
|
250 | + /** @var string[] */ |
|
251 | + protected $settingsClasses = []; |
|
252 | + |
|
253 | + /** @var ISetting[] */ |
|
254 | + protected $settings = []; |
|
255 | + |
|
256 | + /** |
|
257 | + * @param string $setting Class must implement OCA\Activity\ISetting |
|
258 | + * @return void |
|
259 | + */ |
|
260 | + public function registerSetting(string $setting): void { |
|
261 | + $this->settingsClasses[$setting] = false; |
|
262 | + } |
|
263 | + |
|
264 | + /** |
|
265 | + * @return ISetting[] |
|
266 | + * @throws \InvalidArgumentException |
|
267 | + */ |
|
268 | + public function getSettings(): array { |
|
269 | + foreach ($this->settingsClasses as $class => $false) { |
|
270 | + /** @var ISetting $setting */ |
|
271 | + $setting = \OC::$server->query($class); |
|
272 | + |
|
273 | + if (!$setting instanceof ISetting) { |
|
274 | + throw new \InvalidArgumentException('Invalid activity filter registered'); |
|
275 | + } |
|
276 | + |
|
277 | + $this->settings[$setting->getIdentifier()] = $setting; |
|
278 | + |
|
279 | + unset($this->settingsClasses[$class]); |
|
280 | + } |
|
281 | + return $this->settings; |
|
282 | + } |
|
283 | + |
|
284 | + /** |
|
285 | + * @param string $id |
|
286 | + * @return ISetting |
|
287 | + * @throws \InvalidArgumentException when the setting was not found |
|
288 | + * @since 11.0.0 |
|
289 | + */ |
|
290 | + public function getSettingById(string $id): ISetting { |
|
291 | + $settings = $this->getSettings(); |
|
292 | + |
|
293 | + if (isset($settings[$id])) { |
|
294 | + return $settings[$id]; |
|
295 | + } |
|
296 | + |
|
297 | + throw new \InvalidArgumentException('Requested setting does not exist'); |
|
298 | + } |
|
299 | + |
|
300 | + |
|
301 | + /** |
|
302 | + * @param string $type |
|
303 | + * @param int $id |
|
304 | + */ |
|
305 | + public function setFormattingObject(string $type, int $id): void { |
|
306 | + $this->formattingObjectType = $type; |
|
307 | + $this->formattingObjectId = $id; |
|
308 | + } |
|
309 | + |
|
310 | + /** |
|
311 | + * @return bool |
|
312 | + */ |
|
313 | + public function isFormattingFilteredObject(): bool { |
|
314 | + return $this->formattingObjectType !== null && $this->formattingObjectId !== null |
|
315 | + && $this->formattingObjectType === $this->request->getParam('object_type') |
|
316 | + && $this->formattingObjectId === (int) $this->request->getParam('object_id'); |
|
317 | + } |
|
318 | + |
|
319 | + /** |
|
320 | + * @param bool $status Set to true, when parsing events should not use SVG icons |
|
321 | + */ |
|
322 | + public function setRequirePNG(bool $status): void { |
|
323 | + $this->requirePNG = $status; |
|
324 | + } |
|
325 | + |
|
326 | + /** |
|
327 | + * @return bool |
|
328 | + */ |
|
329 | + public function getRequirePNG(): bool { |
|
330 | + return $this->requirePNG; |
|
331 | + } |
|
332 | + |
|
333 | + /** |
|
334 | + * Set the user we need to use |
|
335 | + * |
|
336 | + * @param string|null $currentUserId |
|
337 | + * @throws \UnexpectedValueException If the user is invalid |
|
338 | + */ |
|
339 | + public function setCurrentUserId(string $currentUserId = null): void { |
|
340 | + if (!is_string($currentUserId) && $currentUserId !== null) { |
|
341 | + throw new \UnexpectedValueException('The given current user is invalid'); |
|
342 | + } |
|
343 | + $this->currentUserId = $currentUserId; |
|
344 | + } |
|
345 | + |
|
346 | + /** |
|
347 | + * Get the user we need to use |
|
348 | + * |
|
349 | + * Either the user is logged in, or we try to get it from the token |
|
350 | + * |
|
351 | + * @return string |
|
352 | + * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique |
|
353 | + */ |
|
354 | + public function getCurrentUserId(): string { |
|
355 | + if ($this->currentUserId !== null) { |
|
356 | + return $this->currentUserId; |
|
357 | + } |
|
358 | + |
|
359 | + if (!$this->session->isLoggedIn()) { |
|
360 | + return $this->getUserFromToken(); |
|
361 | + } |
|
362 | + |
|
363 | + return $this->session->getUser()->getUID(); |
|
364 | + } |
|
365 | + |
|
366 | + /** |
|
367 | + * Get the user for the token |
|
368 | + * |
|
369 | + * @return string |
|
370 | + * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique |
|
371 | + */ |
|
372 | + protected function getUserFromToken(): string { |
|
373 | + $token = (string) $this->request->getParam('token', ''); |
|
374 | + if (strlen($token) !== 30) { |
|
375 | + throw new \UnexpectedValueException('The token is invalid'); |
|
376 | + } |
|
377 | + |
|
378 | + $users = $this->config->getUsersForUserValue('activity', 'rsstoken', $token); |
|
379 | + |
|
380 | + if (count($users) !== 1) { |
|
381 | + // No unique user found |
|
382 | + throw new \UnexpectedValueException('The token is invalid'); |
|
383 | + } |
|
384 | + |
|
385 | + // Token found login as that user |
|
386 | + return array_shift($users); |
|
387 | + } |
|
388 | 388 | |
389 | 389 | } |
@@ -33,45 +33,45 @@ |
||
33 | 33 | */ |
34 | 34 | class File extends \OCP\Search\Provider { |
35 | 35 | |
36 | - /** |
|
37 | - * Search for files and folders matching the given query |
|
38 | - * @param string $query |
|
39 | - * @return \OCP\Search\Result |
|
40 | - */ |
|
41 | - public function search($query) { |
|
42 | - $files = Filesystem::search($query); |
|
43 | - $results = []; |
|
44 | - // edit results |
|
45 | - foreach ($files as $fileData) { |
|
46 | - // skip versions |
|
47 | - if (strpos($fileData['path'], '_versions') === 0) { |
|
48 | - continue; |
|
49 | - } |
|
50 | - // skip top-level folder |
|
51 | - if ($fileData['name'] === 'files' && $fileData['parent'] === -1) { |
|
52 | - continue; |
|
53 | - } |
|
54 | - // create audio result |
|
55 | - if($fileData['mimepart'] === 'audio'){ |
|
56 | - $result = new \OC\Search\Result\Audio($fileData); |
|
57 | - } |
|
58 | - // create image result |
|
59 | - elseif($fileData['mimepart'] === 'image'){ |
|
60 | - $result = new \OC\Search\Result\Image($fileData); |
|
61 | - } |
|
62 | - // create folder result |
|
63 | - elseif($fileData['mimetype'] === 'httpd/unix-directory'){ |
|
64 | - $result = new \OC\Search\Result\Folder($fileData); |
|
65 | - } |
|
66 | - // or create file result |
|
67 | - else{ |
|
68 | - $result = new \OC\Search\Result\File($fileData); |
|
69 | - } |
|
70 | - // add to results |
|
71 | - $results[] = $result; |
|
72 | - } |
|
73 | - // return |
|
74 | - return $results; |
|
75 | - } |
|
36 | + /** |
|
37 | + * Search for files and folders matching the given query |
|
38 | + * @param string $query |
|
39 | + * @return \OCP\Search\Result |
|
40 | + */ |
|
41 | + public function search($query) { |
|
42 | + $files = Filesystem::search($query); |
|
43 | + $results = []; |
|
44 | + // edit results |
|
45 | + foreach ($files as $fileData) { |
|
46 | + // skip versions |
|
47 | + if (strpos($fileData['path'], '_versions') === 0) { |
|
48 | + continue; |
|
49 | + } |
|
50 | + // skip top-level folder |
|
51 | + if ($fileData['name'] === 'files' && $fileData['parent'] === -1) { |
|
52 | + continue; |
|
53 | + } |
|
54 | + // create audio result |
|
55 | + if($fileData['mimepart'] === 'audio'){ |
|
56 | + $result = new \OC\Search\Result\Audio($fileData); |
|
57 | + } |
|
58 | + // create image result |
|
59 | + elseif($fileData['mimepart'] === 'image'){ |
|
60 | + $result = new \OC\Search\Result\Image($fileData); |
|
61 | + } |
|
62 | + // create folder result |
|
63 | + elseif($fileData['mimetype'] === 'httpd/unix-directory'){ |
|
64 | + $result = new \OC\Search\Result\Folder($fileData); |
|
65 | + } |
|
66 | + // or create file result |
|
67 | + else{ |
|
68 | + $result = new \OC\Search\Result\File($fileData); |
|
69 | + } |
|
70 | + // add to results |
|
71 | + $results[] = $result; |
|
72 | + } |
|
73 | + // return |
|
74 | + return $results; |
|
75 | + } |
|
76 | 76 | |
77 | 77 | } |
@@ -37,265 +37,265 @@ |
||
37 | 37 | |
38 | 38 | class DecryptAll { |
39 | 39 | |
40 | - /** @var OutputInterface */ |
|
41 | - protected $output; |
|
42 | - |
|
43 | - /** @var InputInterface */ |
|
44 | - protected $input; |
|
45 | - |
|
46 | - /** @var Manager */ |
|
47 | - protected $encryptionManager; |
|
48 | - |
|
49 | - /** @var IUserManager */ |
|
50 | - protected $userManager; |
|
51 | - |
|
52 | - /** @var View */ |
|
53 | - protected $rootView; |
|
54 | - |
|
55 | - /** @var array files which couldn't be decrypted */ |
|
56 | - protected $failed; |
|
57 | - |
|
58 | - /** |
|
59 | - * @param Manager $encryptionManager |
|
60 | - * @param IUserManager $userManager |
|
61 | - * @param View $rootView |
|
62 | - */ |
|
63 | - public function __construct( |
|
64 | - Manager $encryptionManager, |
|
65 | - IUserManager $userManager, |
|
66 | - View $rootView |
|
67 | - ) { |
|
68 | - $this->encryptionManager = $encryptionManager; |
|
69 | - $this->userManager = $userManager; |
|
70 | - $this->rootView = $rootView; |
|
71 | - $this->failed = []; |
|
72 | - } |
|
73 | - |
|
74 | - /** |
|
75 | - * start to decrypt all files |
|
76 | - * |
|
77 | - * @param InputInterface $input |
|
78 | - * @param OutputInterface $output |
|
79 | - * @param string $user which users data folder should be decrypted, default = all users |
|
80 | - * @return bool |
|
81 | - * @throws \Exception |
|
82 | - */ |
|
83 | - public function decryptAll(InputInterface $input, OutputInterface $output, $user = '') { |
|
84 | - |
|
85 | - $this->input = $input; |
|
86 | - $this->output = $output; |
|
87 | - |
|
88 | - if ($user !== '' && $this->userManager->userExists($user) === false) { |
|
89 | - $this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again'); |
|
90 | - return false; |
|
91 | - } |
|
92 | - |
|
93 | - $this->output->writeln('prepare encryption modules...'); |
|
94 | - if ($this->prepareEncryptionModules($user) === false) { |
|
95 | - return false; |
|
96 | - } |
|
97 | - $this->output->writeln(' done.'); |
|
98 | - |
|
99 | - $this->decryptAllUsersFiles($user); |
|
100 | - |
|
101 | - if (empty($this->failed)) { |
|
102 | - $this->output->writeln('all files could be decrypted successfully!'); |
|
103 | - } else { |
|
104 | - $this->output->writeln('Files for following users couldn\'t be decrypted, '); |
|
105 | - $this->output->writeln('maybe the user is not set up in a way that supports this operation: '); |
|
106 | - foreach ($this->failed as $uid => $paths) { |
|
107 | - $this->output->writeln(' ' . $uid); |
|
108 | - foreach ($paths as $path) { |
|
109 | - $this->output->writeln(' ' . $path); |
|
110 | - } |
|
111 | - } |
|
112 | - $this->output->writeln(''); |
|
113 | - } |
|
114 | - |
|
115 | - return true; |
|
116 | - } |
|
117 | - |
|
118 | - /** |
|
119 | - * prepare encryption modules to perform the decrypt all function |
|
120 | - * |
|
121 | - * @param $user |
|
122 | - * @return bool |
|
123 | - */ |
|
124 | - protected function prepareEncryptionModules($user) { |
|
125 | - // prepare all encryption modules for decrypt all |
|
126 | - $encryptionModules = $this->encryptionManager->getEncryptionModules(); |
|
127 | - foreach ($encryptionModules as $moduleDesc) { |
|
128 | - /** @var IEncryptionModule $module */ |
|
129 | - $module = call_user_func($moduleDesc['callback']); |
|
130 | - $this->output->writeln(''); |
|
131 | - $this->output->writeln('Prepare "' . $module->getDisplayName() . '"'); |
|
132 | - $this->output->writeln(''); |
|
133 | - if ($module->prepareDecryptAll($this->input, $this->output, $user) === false) { |
|
134 | - $this->output->writeln('Module "' . $moduleDesc['displayName'] . '" does not support the functionality to decrypt all files again or the initialization of the module failed!'); |
|
135 | - return false; |
|
136 | - } |
|
137 | - } |
|
138 | - |
|
139 | - return true; |
|
140 | - } |
|
141 | - |
|
142 | - /** |
|
143 | - * iterate over all user and encrypt their files |
|
144 | - * |
|
145 | - * @param string $user which users files should be decrypted, default = all users |
|
146 | - */ |
|
147 | - protected function decryptAllUsersFiles($user = '') { |
|
148 | - |
|
149 | - $this->output->writeln("\n"); |
|
150 | - |
|
151 | - $userList = []; |
|
152 | - if ($user === '') { |
|
153 | - |
|
154 | - $fetchUsersProgress = new ProgressBar($this->output); |
|
155 | - $fetchUsersProgress->setFormat(" %message% \n [%bar%]"); |
|
156 | - $fetchUsersProgress->start(); |
|
157 | - $fetchUsersProgress->setMessage("Fetch list of users..."); |
|
158 | - $fetchUsersProgress->advance(); |
|
159 | - |
|
160 | - foreach ($this->userManager->getBackends() as $backend) { |
|
161 | - $limit = 500; |
|
162 | - $offset = 0; |
|
163 | - do { |
|
164 | - $users = $backend->getUsers('', $limit, $offset); |
|
165 | - foreach ($users as $user) { |
|
166 | - $userList[] = $user; |
|
167 | - } |
|
168 | - $offset += $limit; |
|
169 | - $fetchUsersProgress->advance(); |
|
170 | - } while (count($users) >= $limit); |
|
171 | - $fetchUsersProgress->setMessage("Fetch list of users... finished"); |
|
172 | - $fetchUsersProgress->finish(); |
|
173 | - } |
|
174 | - } else { |
|
175 | - $userList[] = $user; |
|
176 | - } |
|
177 | - |
|
178 | - $this->output->writeln("\n\n"); |
|
179 | - |
|
180 | - $progress = new ProgressBar($this->output); |
|
181 | - $progress->setFormat(" %message% \n [%bar%]"); |
|
182 | - $progress->start(); |
|
183 | - $progress->setMessage("starting to decrypt files..."); |
|
184 | - $progress->advance(); |
|
185 | - |
|
186 | - $numberOfUsers = count($userList); |
|
187 | - $userNo = 1; |
|
188 | - foreach ($userList as $uid) { |
|
189 | - $userCount = "$uid ($userNo of $numberOfUsers)"; |
|
190 | - $this->decryptUsersFiles($uid, $progress, $userCount); |
|
191 | - $userNo++; |
|
192 | - } |
|
193 | - |
|
194 | - $progress->setMessage("starting to decrypt files... finished"); |
|
195 | - $progress->finish(); |
|
196 | - |
|
197 | - $this->output->writeln("\n\n"); |
|
198 | - |
|
199 | - } |
|
200 | - |
|
201 | - /** |
|
202 | - * encrypt files from the given user |
|
203 | - * |
|
204 | - * @param string $uid |
|
205 | - * @param ProgressBar $progress |
|
206 | - * @param string $userCount |
|
207 | - */ |
|
208 | - protected function decryptUsersFiles($uid, ProgressBar $progress, $userCount) { |
|
209 | - |
|
210 | - $this->setupUserFS($uid); |
|
211 | - $directories = []; |
|
212 | - $directories[] = '/' . $uid . '/files'; |
|
213 | - |
|
214 | - while ($root = array_pop($directories)) { |
|
215 | - $content = $this->rootView->getDirectoryContent($root); |
|
216 | - foreach ($content as $file) { |
|
217 | - // only decrypt files owned by the user |
|
218 | - if($file->getStorage()->instanceOfStorage('OCA\Files_Sharing\SharedStorage')) { |
|
219 | - continue; |
|
220 | - } |
|
221 | - $path = $root . '/' . $file['name']; |
|
222 | - if ($this->rootView->is_dir($path)) { |
|
223 | - $directories[] = $path; |
|
224 | - continue; |
|
225 | - } else { |
|
226 | - try { |
|
227 | - $progress->setMessage("decrypt files for user $userCount: $path"); |
|
228 | - $progress->advance(); |
|
229 | - if ($file->isEncrypted() === false) { |
|
230 | - $progress->setMessage("decrypt files for user $userCount: $path (already decrypted)"); |
|
231 | - $progress->advance(); |
|
232 | - } else { |
|
233 | - if ($this->decryptFile($path) === false) { |
|
234 | - $progress->setMessage("decrypt files for user $userCount: $path (already decrypted)"); |
|
235 | - $progress->advance(); |
|
236 | - } |
|
237 | - } |
|
238 | - } catch (\Exception $e) { |
|
239 | - if (isset($this->failed[$uid])) { |
|
240 | - $this->failed[$uid][] = $path; |
|
241 | - } else { |
|
242 | - $this->failed[$uid] = [$path]; |
|
243 | - } |
|
244 | - } |
|
245 | - } |
|
246 | - } |
|
247 | - } |
|
248 | - } |
|
249 | - |
|
250 | - /** |
|
251 | - * encrypt file |
|
252 | - * |
|
253 | - * @param string $path |
|
254 | - * @return bool |
|
255 | - */ |
|
256 | - protected function decryptFile($path) { |
|
257 | - |
|
258 | - // skip already decrypted files |
|
259 | - $fileInfo = $this->rootView->getFileInfo($path); |
|
260 | - if ($fileInfo !== false && !$fileInfo->isEncrypted()) { |
|
261 | - return true; |
|
262 | - } |
|
263 | - |
|
264 | - $source = $path; |
|
265 | - $target = $path . '.decrypted.' . $this->getTimestamp(); |
|
266 | - |
|
267 | - try { |
|
268 | - $this->rootView->copy($source, $target); |
|
269 | - $this->rootView->touch($target, $fileInfo->getMTime()); |
|
270 | - $this->rootView->rename($target, $source); |
|
271 | - } catch (DecryptionFailedException $e) { |
|
272 | - if ($this->rootView->file_exists($target)) { |
|
273 | - $this->rootView->unlink($target); |
|
274 | - } |
|
275 | - return false; |
|
276 | - } |
|
277 | - |
|
278 | - return true; |
|
279 | - } |
|
280 | - |
|
281 | - /** |
|
282 | - * get current timestamp |
|
283 | - * |
|
284 | - * @return int |
|
285 | - */ |
|
286 | - protected function getTimestamp() { |
|
287 | - return time(); |
|
288 | - } |
|
289 | - |
|
290 | - |
|
291 | - /** |
|
292 | - * setup user file system |
|
293 | - * |
|
294 | - * @param string $uid |
|
295 | - */ |
|
296 | - protected function setupUserFS($uid) { |
|
297 | - \OC_Util::tearDownFS(); |
|
298 | - \OC_Util::setupFS($uid); |
|
299 | - } |
|
40 | + /** @var OutputInterface */ |
|
41 | + protected $output; |
|
42 | + |
|
43 | + /** @var InputInterface */ |
|
44 | + protected $input; |
|
45 | + |
|
46 | + /** @var Manager */ |
|
47 | + protected $encryptionManager; |
|
48 | + |
|
49 | + /** @var IUserManager */ |
|
50 | + protected $userManager; |
|
51 | + |
|
52 | + /** @var View */ |
|
53 | + protected $rootView; |
|
54 | + |
|
55 | + /** @var array files which couldn't be decrypted */ |
|
56 | + protected $failed; |
|
57 | + |
|
58 | + /** |
|
59 | + * @param Manager $encryptionManager |
|
60 | + * @param IUserManager $userManager |
|
61 | + * @param View $rootView |
|
62 | + */ |
|
63 | + public function __construct( |
|
64 | + Manager $encryptionManager, |
|
65 | + IUserManager $userManager, |
|
66 | + View $rootView |
|
67 | + ) { |
|
68 | + $this->encryptionManager = $encryptionManager; |
|
69 | + $this->userManager = $userManager; |
|
70 | + $this->rootView = $rootView; |
|
71 | + $this->failed = []; |
|
72 | + } |
|
73 | + |
|
74 | + /** |
|
75 | + * start to decrypt all files |
|
76 | + * |
|
77 | + * @param InputInterface $input |
|
78 | + * @param OutputInterface $output |
|
79 | + * @param string $user which users data folder should be decrypted, default = all users |
|
80 | + * @return bool |
|
81 | + * @throws \Exception |
|
82 | + */ |
|
83 | + public function decryptAll(InputInterface $input, OutputInterface $output, $user = '') { |
|
84 | + |
|
85 | + $this->input = $input; |
|
86 | + $this->output = $output; |
|
87 | + |
|
88 | + if ($user !== '' && $this->userManager->userExists($user) === false) { |
|
89 | + $this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again'); |
|
90 | + return false; |
|
91 | + } |
|
92 | + |
|
93 | + $this->output->writeln('prepare encryption modules...'); |
|
94 | + if ($this->prepareEncryptionModules($user) === false) { |
|
95 | + return false; |
|
96 | + } |
|
97 | + $this->output->writeln(' done.'); |
|
98 | + |
|
99 | + $this->decryptAllUsersFiles($user); |
|
100 | + |
|
101 | + if (empty($this->failed)) { |
|
102 | + $this->output->writeln('all files could be decrypted successfully!'); |
|
103 | + } else { |
|
104 | + $this->output->writeln('Files for following users couldn\'t be decrypted, '); |
|
105 | + $this->output->writeln('maybe the user is not set up in a way that supports this operation: '); |
|
106 | + foreach ($this->failed as $uid => $paths) { |
|
107 | + $this->output->writeln(' ' . $uid); |
|
108 | + foreach ($paths as $path) { |
|
109 | + $this->output->writeln(' ' . $path); |
|
110 | + } |
|
111 | + } |
|
112 | + $this->output->writeln(''); |
|
113 | + } |
|
114 | + |
|
115 | + return true; |
|
116 | + } |
|
117 | + |
|
118 | + /** |
|
119 | + * prepare encryption modules to perform the decrypt all function |
|
120 | + * |
|
121 | + * @param $user |
|
122 | + * @return bool |
|
123 | + */ |
|
124 | + protected function prepareEncryptionModules($user) { |
|
125 | + // prepare all encryption modules for decrypt all |
|
126 | + $encryptionModules = $this->encryptionManager->getEncryptionModules(); |
|
127 | + foreach ($encryptionModules as $moduleDesc) { |
|
128 | + /** @var IEncryptionModule $module */ |
|
129 | + $module = call_user_func($moduleDesc['callback']); |
|
130 | + $this->output->writeln(''); |
|
131 | + $this->output->writeln('Prepare "' . $module->getDisplayName() . '"'); |
|
132 | + $this->output->writeln(''); |
|
133 | + if ($module->prepareDecryptAll($this->input, $this->output, $user) === false) { |
|
134 | + $this->output->writeln('Module "' . $moduleDesc['displayName'] . '" does not support the functionality to decrypt all files again or the initialization of the module failed!'); |
|
135 | + return false; |
|
136 | + } |
|
137 | + } |
|
138 | + |
|
139 | + return true; |
|
140 | + } |
|
141 | + |
|
142 | + /** |
|
143 | + * iterate over all user and encrypt their files |
|
144 | + * |
|
145 | + * @param string $user which users files should be decrypted, default = all users |
|
146 | + */ |
|
147 | + protected function decryptAllUsersFiles($user = '') { |
|
148 | + |
|
149 | + $this->output->writeln("\n"); |
|
150 | + |
|
151 | + $userList = []; |
|
152 | + if ($user === '') { |
|
153 | + |
|
154 | + $fetchUsersProgress = new ProgressBar($this->output); |
|
155 | + $fetchUsersProgress->setFormat(" %message% \n [%bar%]"); |
|
156 | + $fetchUsersProgress->start(); |
|
157 | + $fetchUsersProgress->setMessage("Fetch list of users..."); |
|
158 | + $fetchUsersProgress->advance(); |
|
159 | + |
|
160 | + foreach ($this->userManager->getBackends() as $backend) { |
|
161 | + $limit = 500; |
|
162 | + $offset = 0; |
|
163 | + do { |
|
164 | + $users = $backend->getUsers('', $limit, $offset); |
|
165 | + foreach ($users as $user) { |
|
166 | + $userList[] = $user; |
|
167 | + } |
|
168 | + $offset += $limit; |
|
169 | + $fetchUsersProgress->advance(); |
|
170 | + } while (count($users) >= $limit); |
|
171 | + $fetchUsersProgress->setMessage("Fetch list of users... finished"); |
|
172 | + $fetchUsersProgress->finish(); |
|
173 | + } |
|
174 | + } else { |
|
175 | + $userList[] = $user; |
|
176 | + } |
|
177 | + |
|
178 | + $this->output->writeln("\n\n"); |
|
179 | + |
|
180 | + $progress = new ProgressBar($this->output); |
|
181 | + $progress->setFormat(" %message% \n [%bar%]"); |
|
182 | + $progress->start(); |
|
183 | + $progress->setMessage("starting to decrypt files..."); |
|
184 | + $progress->advance(); |
|
185 | + |
|
186 | + $numberOfUsers = count($userList); |
|
187 | + $userNo = 1; |
|
188 | + foreach ($userList as $uid) { |
|
189 | + $userCount = "$uid ($userNo of $numberOfUsers)"; |
|
190 | + $this->decryptUsersFiles($uid, $progress, $userCount); |
|
191 | + $userNo++; |
|
192 | + } |
|
193 | + |
|
194 | + $progress->setMessage("starting to decrypt files... finished"); |
|
195 | + $progress->finish(); |
|
196 | + |
|
197 | + $this->output->writeln("\n\n"); |
|
198 | + |
|
199 | + } |
|
200 | + |
|
201 | + /** |
|
202 | + * encrypt files from the given user |
|
203 | + * |
|
204 | + * @param string $uid |
|
205 | + * @param ProgressBar $progress |
|
206 | + * @param string $userCount |
|
207 | + */ |
|
208 | + protected function decryptUsersFiles($uid, ProgressBar $progress, $userCount) { |
|
209 | + |
|
210 | + $this->setupUserFS($uid); |
|
211 | + $directories = []; |
|
212 | + $directories[] = '/' . $uid . '/files'; |
|
213 | + |
|
214 | + while ($root = array_pop($directories)) { |
|
215 | + $content = $this->rootView->getDirectoryContent($root); |
|
216 | + foreach ($content as $file) { |
|
217 | + // only decrypt files owned by the user |
|
218 | + if($file->getStorage()->instanceOfStorage('OCA\Files_Sharing\SharedStorage')) { |
|
219 | + continue; |
|
220 | + } |
|
221 | + $path = $root . '/' . $file['name']; |
|
222 | + if ($this->rootView->is_dir($path)) { |
|
223 | + $directories[] = $path; |
|
224 | + continue; |
|
225 | + } else { |
|
226 | + try { |
|
227 | + $progress->setMessage("decrypt files for user $userCount: $path"); |
|
228 | + $progress->advance(); |
|
229 | + if ($file->isEncrypted() === false) { |
|
230 | + $progress->setMessage("decrypt files for user $userCount: $path (already decrypted)"); |
|
231 | + $progress->advance(); |
|
232 | + } else { |
|
233 | + if ($this->decryptFile($path) === false) { |
|
234 | + $progress->setMessage("decrypt files for user $userCount: $path (already decrypted)"); |
|
235 | + $progress->advance(); |
|
236 | + } |
|
237 | + } |
|
238 | + } catch (\Exception $e) { |
|
239 | + if (isset($this->failed[$uid])) { |
|
240 | + $this->failed[$uid][] = $path; |
|
241 | + } else { |
|
242 | + $this->failed[$uid] = [$path]; |
|
243 | + } |
|
244 | + } |
|
245 | + } |
|
246 | + } |
|
247 | + } |
|
248 | + } |
|
249 | + |
|
250 | + /** |
|
251 | + * encrypt file |
|
252 | + * |
|
253 | + * @param string $path |
|
254 | + * @return bool |
|
255 | + */ |
|
256 | + protected function decryptFile($path) { |
|
257 | + |
|
258 | + // skip already decrypted files |
|
259 | + $fileInfo = $this->rootView->getFileInfo($path); |
|
260 | + if ($fileInfo !== false && !$fileInfo->isEncrypted()) { |
|
261 | + return true; |
|
262 | + } |
|
263 | + |
|
264 | + $source = $path; |
|
265 | + $target = $path . '.decrypted.' . $this->getTimestamp(); |
|
266 | + |
|
267 | + try { |
|
268 | + $this->rootView->copy($source, $target); |
|
269 | + $this->rootView->touch($target, $fileInfo->getMTime()); |
|
270 | + $this->rootView->rename($target, $source); |
|
271 | + } catch (DecryptionFailedException $e) { |
|
272 | + if ($this->rootView->file_exists($target)) { |
|
273 | + $this->rootView->unlink($target); |
|
274 | + } |
|
275 | + return false; |
|
276 | + } |
|
277 | + |
|
278 | + return true; |
|
279 | + } |
|
280 | + |
|
281 | + /** |
|
282 | + * get current timestamp |
|
283 | + * |
|
284 | + * @return int |
|
285 | + */ |
|
286 | + protected function getTimestamp() { |
|
287 | + return time(); |
|
288 | + } |
|
289 | + |
|
290 | + |
|
291 | + /** |
|
292 | + * setup user file system |
|
293 | + * |
|
294 | + * @param string $uid |
|
295 | + */ |
|
296 | + protected function setupUserFS($uid) { |
|
297 | + \OC_Util::tearDownFS(); |
|
298 | + \OC_Util::setupFS($uid); |
|
299 | + } |
|
300 | 300 | |
301 | 301 | } |
@@ -38,242 +38,242 @@ |
||
38 | 38 | |
39 | 39 | class Manager implements IManager { |
40 | 40 | |
41 | - /** @var array */ |
|
42 | - protected $encryptionModules; |
|
43 | - |
|
44 | - /** @var IConfig */ |
|
45 | - protected $config; |
|
46 | - |
|
47 | - /** @var ILogger */ |
|
48 | - protected $logger; |
|
49 | - |
|
50 | - /** @var Il10n */ |
|
51 | - protected $l; |
|
52 | - |
|
53 | - /** @var View */ |
|
54 | - protected $rootView; |
|
55 | - |
|
56 | - /** @var Util */ |
|
57 | - protected $util; |
|
58 | - |
|
59 | - /** @var ArrayCache */ |
|
60 | - protected $arrayCache; |
|
61 | - |
|
62 | - /** |
|
63 | - * @param IConfig $config |
|
64 | - * @param ILogger $logger |
|
65 | - * @param IL10N $l10n |
|
66 | - * @param View $rootView |
|
67 | - * @param Util $util |
|
68 | - * @param ArrayCache $arrayCache |
|
69 | - */ |
|
70 | - public function __construct(IConfig $config, ILogger $logger, IL10N $l10n, View $rootView, Util $util, ArrayCache $arrayCache) { |
|
71 | - $this->encryptionModules = []; |
|
72 | - $this->config = $config; |
|
73 | - $this->logger = $logger; |
|
74 | - $this->l = $l10n; |
|
75 | - $this->rootView = $rootView; |
|
76 | - $this->util = $util; |
|
77 | - $this->arrayCache = $arrayCache; |
|
78 | - } |
|
79 | - |
|
80 | - /** |
|
81 | - * Check if encryption is enabled |
|
82 | - * |
|
83 | - * @return bool true if enabled, false if not |
|
84 | - */ |
|
85 | - public function isEnabled() { |
|
86 | - |
|
87 | - $installed = $this->config->getSystemValue('installed', false); |
|
88 | - if (!$installed) { |
|
89 | - return false; |
|
90 | - } |
|
91 | - |
|
92 | - $enabled = $this->config->getAppValue('core', 'encryption_enabled', 'no'); |
|
93 | - return $enabled === 'yes'; |
|
94 | - } |
|
95 | - |
|
96 | - /** |
|
97 | - * check if new encryption is ready |
|
98 | - * |
|
99 | - * @return bool |
|
100 | - * @throws ServiceUnavailableException |
|
101 | - */ |
|
102 | - public function isReady() { |
|
103 | - |
|
104 | - if ($this->isKeyStorageReady() === false) { |
|
105 | - throw new ServiceUnavailableException('Key Storage is not ready'); |
|
106 | - } |
|
107 | - |
|
108 | - return true; |
|
109 | - } |
|
110 | - |
|
111 | - /** |
|
112 | - * @param string $user |
|
113 | - */ |
|
114 | - public function isReadyForUser($user) { |
|
115 | - if (!$this->isReady()) { |
|
116 | - return false; |
|
117 | - } |
|
118 | - |
|
119 | - foreach ($this->getEncryptionModules() as $module) { |
|
120 | - /** @var IEncryptionModule $m */ |
|
121 | - $m = call_user_func($module['callback']); |
|
122 | - if (!$m->isReadyForUser($user)) { |
|
123 | - return false; |
|
124 | - } |
|
125 | - } |
|
126 | - |
|
127 | - return true; |
|
128 | - } |
|
129 | - |
|
130 | - /** |
|
131 | - * Registers an callback function which must return an encryption module instance |
|
132 | - * |
|
133 | - * @param string $id |
|
134 | - * @param string $displayName |
|
135 | - * @param callable $callback |
|
136 | - * @throws Exceptions\ModuleAlreadyExistsException |
|
137 | - */ |
|
138 | - public function registerEncryptionModule($id, $displayName, callable $callback) { |
|
139 | - |
|
140 | - if (isset($this->encryptionModules[$id])) { |
|
141 | - throw new Exceptions\ModuleAlreadyExistsException($id, $displayName); |
|
142 | - } |
|
143 | - |
|
144 | - $this->encryptionModules[$id] = [ |
|
145 | - 'id' => $id, |
|
146 | - 'displayName' => $displayName, |
|
147 | - 'callback' => $callback, |
|
148 | - ]; |
|
149 | - |
|
150 | - $defaultEncryptionModuleId = $this->getDefaultEncryptionModuleId(); |
|
151 | - |
|
152 | - if (empty($defaultEncryptionModuleId)) { |
|
153 | - $this->setDefaultEncryptionModule($id); |
|
154 | - } |
|
155 | - } |
|
156 | - |
|
157 | - /** |
|
158 | - * Unregisters an encryption module |
|
159 | - * |
|
160 | - * @param string $moduleId |
|
161 | - */ |
|
162 | - public function unregisterEncryptionModule($moduleId) { |
|
163 | - unset($this->encryptionModules[$moduleId]); |
|
164 | - } |
|
165 | - |
|
166 | - /** |
|
167 | - * get a list of all encryption modules |
|
168 | - * |
|
169 | - * @return array [id => ['id' => $id, 'displayName' => $displayName, 'callback' => callback]] |
|
170 | - */ |
|
171 | - public function getEncryptionModules() { |
|
172 | - return $this->encryptionModules; |
|
173 | - } |
|
174 | - |
|
175 | - /** |
|
176 | - * get a specific encryption module |
|
177 | - * |
|
178 | - * @param string $moduleId |
|
179 | - * @return IEncryptionModule |
|
180 | - * @throws Exceptions\ModuleDoesNotExistsException |
|
181 | - */ |
|
182 | - public function getEncryptionModule($moduleId = '') { |
|
183 | - if (!empty($moduleId)) { |
|
184 | - if (isset($this->encryptionModules[$moduleId])) { |
|
185 | - return call_user_func($this->encryptionModules[$moduleId]['callback']); |
|
186 | - } else { |
|
187 | - $message = "Module with ID: $moduleId does not exist."; |
|
188 | - $hint = $this->l->t('Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator.', [$moduleId]); |
|
189 | - throw new Exceptions\ModuleDoesNotExistsException($message, $hint); |
|
190 | - } |
|
191 | - } else { |
|
192 | - return $this->getDefaultEncryptionModule(); |
|
193 | - } |
|
194 | - } |
|
195 | - |
|
196 | - /** |
|
197 | - * get default encryption module |
|
198 | - * |
|
199 | - * @return \OCP\Encryption\IEncryptionModule |
|
200 | - * @throws Exceptions\ModuleDoesNotExistsException |
|
201 | - */ |
|
202 | - protected function getDefaultEncryptionModule() { |
|
203 | - $defaultModuleId = $this->getDefaultEncryptionModuleId(); |
|
204 | - if (!empty($defaultModuleId)) { |
|
205 | - if (isset($this->encryptionModules[$defaultModuleId])) { |
|
206 | - return call_user_func($this->encryptionModules[$defaultModuleId]['callback']); |
|
207 | - } else { |
|
208 | - $message = 'Default encryption module not loaded'; |
|
209 | - throw new Exceptions\ModuleDoesNotExistsException($message); |
|
210 | - } |
|
211 | - } else { |
|
212 | - $message = 'No default encryption module defined'; |
|
213 | - throw new Exceptions\ModuleDoesNotExistsException($message); |
|
214 | - } |
|
215 | - |
|
216 | - } |
|
217 | - |
|
218 | - /** |
|
219 | - * set default encryption module Id |
|
220 | - * |
|
221 | - * @param string $moduleId |
|
222 | - * @return bool |
|
223 | - */ |
|
224 | - public function setDefaultEncryptionModule($moduleId) { |
|
225 | - try { |
|
226 | - $this->getEncryptionModule($moduleId); |
|
227 | - } catch (\Exception $e) { |
|
228 | - return false; |
|
229 | - } |
|
230 | - |
|
231 | - $this->config->setAppValue('core', 'default_encryption_module', $moduleId); |
|
232 | - return true; |
|
233 | - } |
|
234 | - |
|
235 | - /** |
|
236 | - * get default encryption module Id |
|
237 | - * |
|
238 | - * @return string |
|
239 | - */ |
|
240 | - public function getDefaultEncryptionModuleId() { |
|
241 | - return $this->config->getAppValue('core', 'default_encryption_module'); |
|
242 | - } |
|
243 | - |
|
244 | - /** |
|
245 | - * Add storage wrapper |
|
246 | - */ |
|
247 | - public function setupStorage() { |
|
248 | - // If encryption is disabled and there are no loaded modules it makes no sense to load the wrapper |
|
249 | - if (!empty($this->encryptionModules) || $this->isEnabled()) { |
|
250 | - $encryptionWrapper = new EncryptionWrapper($this->arrayCache, $this, $this->logger); |
|
251 | - Filesystem::addStorageWrapper('oc_encryption', [$encryptionWrapper, 'wrapStorage'], 2); |
|
252 | - } |
|
253 | - } |
|
254 | - |
|
255 | - |
|
256 | - /** |
|
257 | - * check if key storage is ready |
|
258 | - * |
|
259 | - * @return bool |
|
260 | - */ |
|
261 | - protected function isKeyStorageReady() { |
|
262 | - |
|
263 | - $rootDir = $this->util->getKeyStorageRoot(); |
|
264 | - |
|
265 | - // the default root is always valid |
|
266 | - if ($rootDir === '') { |
|
267 | - return true; |
|
268 | - } |
|
269 | - |
|
270 | - // check if key storage is mounted correctly |
|
271 | - if ($this->rootView->file_exists($rootDir . '/' . Storage::KEY_STORAGE_MARKER)) { |
|
272 | - return true; |
|
273 | - } |
|
274 | - |
|
275 | - return false; |
|
276 | - } |
|
41 | + /** @var array */ |
|
42 | + protected $encryptionModules; |
|
43 | + |
|
44 | + /** @var IConfig */ |
|
45 | + protected $config; |
|
46 | + |
|
47 | + /** @var ILogger */ |
|
48 | + protected $logger; |
|
49 | + |
|
50 | + /** @var Il10n */ |
|
51 | + protected $l; |
|
52 | + |
|
53 | + /** @var View */ |
|
54 | + protected $rootView; |
|
55 | + |
|
56 | + /** @var Util */ |
|
57 | + protected $util; |
|
58 | + |
|
59 | + /** @var ArrayCache */ |
|
60 | + protected $arrayCache; |
|
61 | + |
|
62 | + /** |
|
63 | + * @param IConfig $config |
|
64 | + * @param ILogger $logger |
|
65 | + * @param IL10N $l10n |
|
66 | + * @param View $rootView |
|
67 | + * @param Util $util |
|
68 | + * @param ArrayCache $arrayCache |
|
69 | + */ |
|
70 | + public function __construct(IConfig $config, ILogger $logger, IL10N $l10n, View $rootView, Util $util, ArrayCache $arrayCache) { |
|
71 | + $this->encryptionModules = []; |
|
72 | + $this->config = $config; |
|
73 | + $this->logger = $logger; |
|
74 | + $this->l = $l10n; |
|
75 | + $this->rootView = $rootView; |
|
76 | + $this->util = $util; |
|
77 | + $this->arrayCache = $arrayCache; |
|
78 | + } |
|
79 | + |
|
80 | + /** |
|
81 | + * Check if encryption is enabled |
|
82 | + * |
|
83 | + * @return bool true if enabled, false if not |
|
84 | + */ |
|
85 | + public function isEnabled() { |
|
86 | + |
|
87 | + $installed = $this->config->getSystemValue('installed', false); |
|
88 | + if (!$installed) { |
|
89 | + return false; |
|
90 | + } |
|
91 | + |
|
92 | + $enabled = $this->config->getAppValue('core', 'encryption_enabled', 'no'); |
|
93 | + return $enabled === 'yes'; |
|
94 | + } |
|
95 | + |
|
96 | + /** |
|
97 | + * check if new encryption is ready |
|
98 | + * |
|
99 | + * @return bool |
|
100 | + * @throws ServiceUnavailableException |
|
101 | + */ |
|
102 | + public function isReady() { |
|
103 | + |
|
104 | + if ($this->isKeyStorageReady() === false) { |
|
105 | + throw new ServiceUnavailableException('Key Storage is not ready'); |
|
106 | + } |
|
107 | + |
|
108 | + return true; |
|
109 | + } |
|
110 | + |
|
111 | + /** |
|
112 | + * @param string $user |
|
113 | + */ |
|
114 | + public function isReadyForUser($user) { |
|
115 | + if (!$this->isReady()) { |
|
116 | + return false; |
|
117 | + } |
|
118 | + |
|
119 | + foreach ($this->getEncryptionModules() as $module) { |
|
120 | + /** @var IEncryptionModule $m */ |
|
121 | + $m = call_user_func($module['callback']); |
|
122 | + if (!$m->isReadyForUser($user)) { |
|
123 | + return false; |
|
124 | + } |
|
125 | + } |
|
126 | + |
|
127 | + return true; |
|
128 | + } |
|
129 | + |
|
130 | + /** |
|
131 | + * Registers an callback function which must return an encryption module instance |
|
132 | + * |
|
133 | + * @param string $id |
|
134 | + * @param string $displayName |
|
135 | + * @param callable $callback |
|
136 | + * @throws Exceptions\ModuleAlreadyExistsException |
|
137 | + */ |
|
138 | + public function registerEncryptionModule($id, $displayName, callable $callback) { |
|
139 | + |
|
140 | + if (isset($this->encryptionModules[$id])) { |
|
141 | + throw new Exceptions\ModuleAlreadyExistsException($id, $displayName); |
|
142 | + } |
|
143 | + |
|
144 | + $this->encryptionModules[$id] = [ |
|
145 | + 'id' => $id, |
|
146 | + 'displayName' => $displayName, |
|
147 | + 'callback' => $callback, |
|
148 | + ]; |
|
149 | + |
|
150 | + $defaultEncryptionModuleId = $this->getDefaultEncryptionModuleId(); |
|
151 | + |
|
152 | + if (empty($defaultEncryptionModuleId)) { |
|
153 | + $this->setDefaultEncryptionModule($id); |
|
154 | + } |
|
155 | + } |
|
156 | + |
|
157 | + /** |
|
158 | + * Unregisters an encryption module |
|
159 | + * |
|
160 | + * @param string $moduleId |
|
161 | + */ |
|
162 | + public function unregisterEncryptionModule($moduleId) { |
|
163 | + unset($this->encryptionModules[$moduleId]); |
|
164 | + } |
|
165 | + |
|
166 | + /** |
|
167 | + * get a list of all encryption modules |
|
168 | + * |
|
169 | + * @return array [id => ['id' => $id, 'displayName' => $displayName, 'callback' => callback]] |
|
170 | + */ |
|
171 | + public function getEncryptionModules() { |
|
172 | + return $this->encryptionModules; |
|
173 | + } |
|
174 | + |
|
175 | + /** |
|
176 | + * get a specific encryption module |
|
177 | + * |
|
178 | + * @param string $moduleId |
|
179 | + * @return IEncryptionModule |
|
180 | + * @throws Exceptions\ModuleDoesNotExistsException |
|
181 | + */ |
|
182 | + public function getEncryptionModule($moduleId = '') { |
|
183 | + if (!empty($moduleId)) { |
|
184 | + if (isset($this->encryptionModules[$moduleId])) { |
|
185 | + return call_user_func($this->encryptionModules[$moduleId]['callback']); |
|
186 | + } else { |
|
187 | + $message = "Module with ID: $moduleId does not exist."; |
|
188 | + $hint = $this->l->t('Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator.', [$moduleId]); |
|
189 | + throw new Exceptions\ModuleDoesNotExistsException($message, $hint); |
|
190 | + } |
|
191 | + } else { |
|
192 | + return $this->getDefaultEncryptionModule(); |
|
193 | + } |
|
194 | + } |
|
195 | + |
|
196 | + /** |
|
197 | + * get default encryption module |
|
198 | + * |
|
199 | + * @return \OCP\Encryption\IEncryptionModule |
|
200 | + * @throws Exceptions\ModuleDoesNotExistsException |
|
201 | + */ |
|
202 | + protected function getDefaultEncryptionModule() { |
|
203 | + $defaultModuleId = $this->getDefaultEncryptionModuleId(); |
|
204 | + if (!empty($defaultModuleId)) { |
|
205 | + if (isset($this->encryptionModules[$defaultModuleId])) { |
|
206 | + return call_user_func($this->encryptionModules[$defaultModuleId]['callback']); |
|
207 | + } else { |
|
208 | + $message = 'Default encryption module not loaded'; |
|
209 | + throw new Exceptions\ModuleDoesNotExistsException($message); |
|
210 | + } |
|
211 | + } else { |
|
212 | + $message = 'No default encryption module defined'; |
|
213 | + throw new Exceptions\ModuleDoesNotExistsException($message); |
|
214 | + } |
|
215 | + |
|
216 | + } |
|
217 | + |
|
218 | + /** |
|
219 | + * set default encryption module Id |
|
220 | + * |
|
221 | + * @param string $moduleId |
|
222 | + * @return bool |
|
223 | + */ |
|
224 | + public function setDefaultEncryptionModule($moduleId) { |
|
225 | + try { |
|
226 | + $this->getEncryptionModule($moduleId); |
|
227 | + } catch (\Exception $e) { |
|
228 | + return false; |
|
229 | + } |
|
230 | + |
|
231 | + $this->config->setAppValue('core', 'default_encryption_module', $moduleId); |
|
232 | + return true; |
|
233 | + } |
|
234 | + |
|
235 | + /** |
|
236 | + * get default encryption module Id |
|
237 | + * |
|
238 | + * @return string |
|
239 | + */ |
|
240 | + public function getDefaultEncryptionModuleId() { |
|
241 | + return $this->config->getAppValue('core', 'default_encryption_module'); |
|
242 | + } |
|
243 | + |
|
244 | + /** |
|
245 | + * Add storage wrapper |
|
246 | + */ |
|
247 | + public function setupStorage() { |
|
248 | + // If encryption is disabled and there are no loaded modules it makes no sense to load the wrapper |
|
249 | + if (!empty($this->encryptionModules) || $this->isEnabled()) { |
|
250 | + $encryptionWrapper = new EncryptionWrapper($this->arrayCache, $this, $this->logger); |
|
251 | + Filesystem::addStorageWrapper('oc_encryption', [$encryptionWrapper, 'wrapStorage'], 2); |
|
252 | + } |
|
253 | + } |
|
254 | + |
|
255 | + |
|
256 | + /** |
|
257 | + * check if key storage is ready |
|
258 | + * |
|
259 | + * @return bool |
|
260 | + */ |
|
261 | + protected function isKeyStorageReady() { |
|
262 | + |
|
263 | + $rootDir = $this->util->getKeyStorageRoot(); |
|
264 | + |
|
265 | + // the default root is always valid |
|
266 | + if ($rootDir === '') { |
|
267 | + return true; |
|
268 | + } |
|
269 | + |
|
270 | + // check if key storage is mounted correctly |
|
271 | + if ($this->rootView->file_exists($rootDir . '/' . Storage::KEY_STORAGE_MARKER)) { |
|
272 | + return true; |
|
273 | + } |
|
274 | + |
|
275 | + return false; |
|
276 | + } |
|
277 | 277 | |
278 | 278 | |
279 | 279 | } |