util.stanza: Add method for extracting a single attribute value
authorKim Alvefur <zash@zash.se>
Wed, 17 Aug 2022 19:04:30 +0200
changeset 12640 e8934ce6ea0f
parent 12639 f928cb5c5d04
child 12642 a47af78a9347
util.stanza: Add method for extracting a single attribute value Sometimes you only care about a single attribute, but the child tag itself may be optional, leading to needing `tag and tag.attr.foo` or `stanza:find("tag@foo")`. The `:find()` method is fairly complex, so avoiding it for this kind of simpler use case is a win.
plugins/mod_pubsub/pubsub.lib.lua
spec/util_dataforms_spec.lua
util/stanza.lua
--- a/plugins/mod_pubsub/pubsub.lib.lua	Mon Aug 15 16:35:14 2022 +0200
+++ b/plugins/mod_pubsub/pubsub.lib.lua	Wed Aug 17 19:04:30 2022 +0200
@@ -678,8 +678,7 @@
 function handlers.set_retract(origin, stanza, retract, service)
 	local node, notify = retract.attr.node, retract.attr.notify;
 	notify = (notify == "1") or (notify == "true");
-	local item = retract:get_child("item");
-	local id = item and item.attr.id
+	local id = retract:get_child_attr("item", nil, "id");
 	if not (node and id) then
 		origin.send(pubsub_error_reply(stanza, node and "item-not-found" or "nodeid-required"));
 		return true;
--- a/spec/util_dataforms_spec.lua	Mon Aug 15 16:35:14 2022 +0200
+++ b/spec/util_dataforms_spec.lua	Wed Aug 17 19:04:30 2022 +0200
@@ -130,7 +130,7 @@
 		assert.truthy(st.is_stanza(xform));
 		assert.equal("x", xform.name);
 		assert.equal("jabber:x:data", xform.attr.xmlns);
-		assert.equal("FORM_TYPE", xform:find("field@var"));
+		assert.equal("FORM_TYPE", xform:get_child_attr("field", nil, "var"));
 		assert.equal("xmpp:prosody.im/spec/util.dataforms#1", xform:find("field/value#"));
 		local allowed_direct_children = {
 			title = true,
--- a/util/stanza.lua	Mon Aug 15 16:35:14 2022 +0200
+++ b/util/stanza.lua	Wed Aug 17 19:04:30 2022 +0200
@@ -176,6 +176,14 @@
 	return nil;
 end
 
+function stanza_mt:get_child_attr(name, xmlns, attr)
+	local tag = self:get_child(name, xmlns);
+	if tag then
+		return tag.attr[attr];
+	end
+	return nil;
+end
+
 function stanza_mt:child_with_name(name)
 	for _, child in ipairs(self.tags) do
 		if child.name == name then return child; end