Browse Source

feat(nextcloud): Implement WebDAV proppatch remove

pull/520/head
jld3103 1 year ago
parent
commit
1fb9224c9d
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 14
      packages/nextcloud/lib/src/webdav/client.dart
  2. 23
      packages/nextcloud/lib/src/webdav/webdav.dart
  3. 101
      packages/nextcloud/lib/src/webdav/webdav.g.dart
  4. 52
      packages/nextcloud/test/webdav_test.dart

14
packages/nextcloud/lib/src/webdav/client.dart

@ -266,12 +266,15 @@ class WebDavClient {
/// Updates the props of the resource at [path].
///
/// The props in [set] will be updated.
/// The props in [remove] will be removed.
/// Returns true if the update was successful.
/// See http://www.webdav.org/specs/rfc2518.html#METHOD_PROPPATCH for more information.
Future<bool> proppatch(
final String path,
final WebDavProp prop,
) async {
final String path, {
final WebDavProp? set,
final WebDavPropWithoutValues? remove,
}) async {
final response = await _send(
'PROPPATCH',
_constructPath(path),
@ -279,7 +282,10 @@ class WebDavClient {
data: Stream.value(
Uint8List.fromList(
utf8.encode(
WebDavPropertyupdate(set: WebDavSet(prop: prop)).toXmlElement(namespaces: namespaces).toXmlString(),
WebDavPropertyupdate(
set: set != null ? WebDavSet(prop: set) : null,
remove: remove != null ? WebDavRemove(prop: remove) : null,
).toXmlElement(namespaces: namespaces).toXmlString(),
),
),
),

23
packages/nextcloud/lib/src/webdav/webdav.dart

@ -76,11 +76,15 @@ class WebDavPropstat with _$WebDavPropstatXmlSerializableMixin {
@annotation.XmlRootElement(name: 'propertyupdate', namespace: namespaceDav)
class WebDavPropertyupdate with _$WebDavPropertyupdateXmlSerializableMixin {
WebDavPropertyupdate({
required this.set,
this.set,
this.remove,
});
@annotation.XmlElement(name: 'set', namespace: namespaceDav)
final WebDavSet set;
@annotation.XmlElement(name: 'set', namespace: namespaceDav, includeIfNull: false)
final WebDavSet? set;
@annotation.XmlElement(name: 'remove', namespace: namespaceDav, includeIfNull: false)
final WebDavRemove? remove;
}
@annotation.XmlSerializable(createMixin: true)
@ -96,6 +100,19 @@ class WebDavSet with _$WebDavSetXmlSerializableMixin {
final WebDavProp prop; // coverage:ignore-line
}
@annotation.XmlSerializable(createMixin: true)
@annotation.XmlRootElement(name: 'remove', namespace: namespaceDav)
class WebDavRemove with _$WebDavRemoveXmlSerializableMixin {
WebDavRemove({
required this.prop,
});
factory WebDavRemove.fromXmlElement(final XmlElement element) => _$WebDavRemoveFromXmlElement(element);
@annotation.XmlElement(name: 'prop', namespace: namespaceDav)
final WebDavPropWithoutValues prop; // coverage:ignore-line
}
@annotation.XmlSerializable(createMixin: true)
@annotation.XmlRootElement(name: 'propfind', namespace: namespaceDav)
class WebDavPropfind with _$WebDavPropfindXmlSerializableMixin {

101
packages/nextcloud/lib/src/webdav/webdav.g.dart

@ -221,9 +221,18 @@ void _$WebDavPropertyupdateBuildXmlChildren(WebDavPropertyupdate instance, XmlBu
{Map<String, String> namespaces = const {}}) {
final set = instance.set;
final setSerialized = set;
builder.element('set', namespace: 'DAV:', nest: () {
setSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
if (setSerialized != null) {
builder.element('set', namespace: 'DAV:', nest: () {
setSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
final remove = instance.remove;
final removeSerialized = remove;
if (removeSerialized != null) {
builder.element('remove', namespace: 'DAV:', nest: () {
removeSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
}
void _$WebDavPropertyupdateBuildXmlElement(WebDavPropertyupdate instance, XmlBuilder builder,
@ -234,8 +243,11 @@ void _$WebDavPropertyupdateBuildXmlElement(WebDavPropertyupdate instance, XmlBui
}
WebDavPropertyupdate _$WebDavPropertyupdateFromXmlElement(XmlElement element) {
final set = element.getElement('set', namespace: 'DAV:')!;
return WebDavPropertyupdate(set: WebDavSet.fromXmlElement(set));
final set = element.getElement('set', namespace: 'DAV:');
final remove = element.getElement('remove', namespace: 'DAV:');
return WebDavPropertyupdate(
set: set != null ? WebDavSet.fromXmlElement(set) : null,
remove: remove != null ? WebDavRemove.fromXmlElement(remove) : null);
}
List<XmlAttribute> _$WebDavPropertyupdateToXmlAttributes(WebDavPropertyupdate instance,
@ -249,9 +261,22 @@ List<XmlNode> _$WebDavPropertyupdateToXmlChildren(WebDavPropertyupdate instance,
final children = <XmlNode>[];
final set = instance.set;
final setSerialized = set;
final setConstructed = XmlElement(XmlName('set', namespaces['DAV:']),
setSerialized.toXmlAttributes(namespaces: namespaces), setSerialized.toXmlChildren(namespaces: namespaces));
children.add(setConstructed);
final setConstructed = setSerialized != null
? XmlElement(XmlName('set', namespaces['DAV:']), setSerialized.toXmlAttributes(namespaces: namespaces),
setSerialized.toXmlChildren(namespaces: namespaces))
: null;
if (setConstructed != null) {
children.add(setConstructed);
}
final remove = instance.remove;
final removeSerialized = remove;
final removeConstructed = removeSerialized != null
? XmlElement(XmlName('remove', namespaces['DAV:']), removeSerialized.toXmlAttributes(namespaces: namespaces),
removeSerialized.toXmlChildren(namespaces: namespaces))
: null;
if (removeConstructed != null) {
children.add(removeConstructed);
}
return children;
}
@ -338,6 +363,66 @@ mixin _$WebDavSetXmlSerializableMixin {
_$WebDavSetToXmlElement(this as WebDavSet, namespaces: namespaces);
}
void _$WebDavRemoveBuildXmlChildren(WebDavRemove instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) {
final prop = instance.prop;
final propSerialized = prop;
builder.element('prop', namespace: 'DAV:', nest: () {
propSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
void _$WebDavRemoveBuildXmlElement(WebDavRemove instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) {
builder.element('remove', namespace: 'DAV:', namespaces: namespaces, nest: () {
instance.buildXmlChildren(builder, namespaces: namespaces);
});
}
WebDavRemove _$WebDavRemoveFromXmlElement(XmlElement element) {
final prop = element.getElement('prop', namespace: 'DAV:')!;
return WebDavRemove(prop: WebDavPropWithoutValues.fromXmlElement(prop));
}
List<XmlAttribute> _$WebDavRemoveToXmlAttributes(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
final attributes = <XmlAttribute>[];
return attributes;
}
List<XmlNode> _$WebDavRemoveToXmlChildren(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
final children = <XmlNode>[];
final prop = instance.prop;
final propSerialized = prop;
final propConstructed = XmlElement(XmlName('prop', namespaces['DAV:']),
propSerialized.toXmlAttributes(namespaces: namespaces), propSerialized.toXmlChildren(namespaces: namespaces));
children.add(propConstructed);
return children;
}
XmlElement _$WebDavRemoveToXmlElement(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
return XmlElement(
XmlName('remove', namespaces['DAV:']),
[...namespaces.toXmlAttributes(), ...instance.toXmlAttributes(namespaces: namespaces)],
instance.toXmlChildren(namespaces: namespaces));
}
mixin _$WebDavRemoveXmlSerializableMixin {
void buildXmlChildren(XmlBuilder builder, {Map<String, String> namespaces = const {}}) =>
_$WebDavRemoveBuildXmlChildren(this as WebDavRemove, builder, namespaces: namespaces);
void buildXmlElement(XmlBuilder builder, {Map<String, String> namespaces = const {}}) =>
_$WebDavRemoveBuildXmlElement(this as WebDavRemove, builder, namespaces: namespaces);
List<XmlAttribute> toXmlAttributes({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlAttributes(this as WebDavRemove, namespaces: namespaces);
List<XmlNode> toXmlChildren({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlChildren(this as WebDavRemove, namespaces: namespaces);
XmlElement toXmlElement({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlElement(this as WebDavRemove, namespaces: namespaces);
}
void _$WebDavPropfindBuildXmlChildren(WebDavPropfind instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) {
final prop = instance.prop;

52
packages/nextcloud/test/webdav_test.dart

@ -324,7 +324,7 @@ void main() {
final id = response.headers['oc-fileid']!.first;
await client.webdav.proppatch(
'test.txt',
WebDavProp(
set: WebDavProp(
ocfavorite: 1,
),
);
@ -356,7 +356,7 @@ void main() {
final updated = await client.webdav.proppatch(
'test.txt',
WebDavProp(
set: WebDavProp(
ocfavorite: 1,
nccreationtime: createdEpoch,
),
@ -380,5 +380,53 @@ void main() {
expect(DateTime.fromMillisecondsSinceEpoch(props.nccreationtime! * 1000).isAtSameMomentAs(createdDate), isTrue);
expectDateInReasonableTimeRange(DateTime.fromMillisecondsSinceEpoch(props.ncuploadtime! * 1000), uploadTime);
});
test('Remove properties', () async {
await client.webdav.put(Uint8List.fromList(utf8.encode('test')), 'test.txt');
var updated = await client.webdav.proppatch(
'test.txt',
set: WebDavProp(
ocfavorite: 1,
),
);
expect(updated, isTrue);
var props = (await client.webdav.propfind(
'test.txt',
prop: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
nccreationtime: true,
ncuploadtime: true,
),
))
.responses
.single
.propstats
.first
.prop;
expect(props.ocfavorite, 1);
updated = await client.webdav.proppatch(
'test.txt',
remove: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
),
);
expect(updated, isFalse);
props = (await client.webdav.propfind(
'test.txt',
prop: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
),
))
.responses
.single
.propstats
.first
.prop;
expect(props.ocfavorite, 0);
});
});
}

Loading…
Cancel
Save