From 4491e82762e498a02ec4f8a9f6c98cc194071e1f Mon Sep 17 00:00:00 2001
From: Evan Prodromou <evan@controlyourself.ca>
Date: Wed, 21 Jan 2009 11:47:23 -0500
Subject: [PATCH] Add actions for joining or leaving a group, and fixup JS to
 match

---
 actions/joingroup.php  | 149 +++++++++++++++++++++++++++++++++++++++
 actions/leavegroup.php | 153 +++++++++++++++++++++++++++++++++++++++++
 js/util.js             |  33 +++++++--
 3 files changed, 329 insertions(+), 6 deletions(-)
 create mode 100644 actions/joingroup.php
 create mode 100644 actions/leavegroup.php

diff --git a/actions/joingroup.php b/actions/joingroup.php
new file mode 100644
index 0000000000..45470f0888
--- /dev/null
+++ b/actions/joingroup.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Join a group
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Group
+ * @package   Laconica
+ * @author    Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Join a group
+ *
+ * This is the action for joining a group. It works more or less like the subscribe action
+ * for users.
+ *
+ * @category Group
+ * @package  Laconica
+ * @author   Evan Prodromou <evan@controlyourself.ca>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://laconi.ca/
+ */
+
+class JoingroupAction extends Action
+{
+    var $group = null;
+
+    /**
+     * Prepare to run
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if (!common_config('inboxes','enabled')) {
+            $this->serverError(_('Inboxes must be enabled for groups to work'));
+            return false;
+        }
+
+        if (!common_logged_in()) {
+            $this->clientError(_('You must be logged in to join a group.'));
+            return false;
+        }
+
+        $nickname_arg = $this->trimmed('nickname');
+        $nickname = common_canonical_nickname($nickname_arg);
+
+        // Permanent redirect on non-canonical nickname
+
+        if ($nickname_arg != $nickname) {
+            $args = array('nickname' => $nickname);
+            common_redirect(common_local_url('editgroup', $args), 301);
+            return false;
+        }
+
+        if (!$nickname) {
+            $this->clientError(_('No nickname'), 404);
+            return false;
+        }
+
+        $this->group = User_group::staticGet('nickname', $nickname);
+
+        if (!$this->group) {
+            $this->clientError(_('No such group'), 404);
+            return false;
+        }
+
+        $cur = common_current_user();
+
+        if ($cur->isMember($group)) {
+            $this->clientError(_('You are already a member of that group'), 403);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * On POST, add the current user to the group
+     *
+     * @param array $args unused
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        $cur = common_current_user();
+
+        $member = new Group_member();
+
+        $member->group_id   = $this->group->id;
+        $member->profile_id = $cur->id;
+        $member->created    = common_sql_now();
+
+        $result = $member->insert();
+
+        if (!$result) {
+            common_log_db_error($member, 'INSERT', __FILE__);
+            $this->serverError(sprintf(_('Could not join user %s to group %s'),
+                                       $cur->nickname, $this->group->nickname));
+        }
+
+        if ($this->boolean('ajax')) {
+            $this->startHTML('text/xml;charset=utf-8');
+            $this->elementStart('head');
+            $this->element('title', null, sprintf(_('%s joined group %s'),
+                                                  $cur->nickname,
+                                                  $this->group->nickname));
+            $this->elementEnd('head');
+            $this->elementStart('body');
+            $lf = new LeaveForm($this, $this->group);
+            $lf->show();
+            $this->elementEnd('body');
+            $this->elementEnd('html');
+        } else {
+            common_redirect(common_local_url('groupmembers', array('nickname' =>
+                                                                   $this->group->nickname)));
+        }
+    }
+}
\ No newline at end of file
diff --git a/actions/leavegroup.php b/actions/leavegroup.php
new file mode 100644
index 0000000000..587208b36a
--- /dev/null
+++ b/actions/leavegroup.php
@@ -0,0 +1,153 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Leave a group
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Group
+ * @package   Laconica
+ * @author    Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2008-2009 Control Yourself, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+    exit(1);
+}
+
+/**
+ * Leave a group
+ *
+ * This is the action for leaving a group. It works more or less like the subscribe action
+ * for users.
+ *
+ * @category Group
+ * @package  Laconica
+ * @author   Evan Prodromou <evan@controlyourself.ca>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://laconi.ca/
+ */
+
+class LeavegroupAction extends Action
+{
+    var $group = null;
+
+    /**
+     * Prepare to run
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if (!common_config('inboxes','enabled')) {
+            $this->serverError(_('Inboxes must be enabled for groups to work'));
+            return false;
+        }
+
+        if (!common_logged_in()) {
+            $this->clientError(_('You must be logged in to join a group.'));
+            return false;
+        }
+
+        $nickname_arg = $this->trimmed('nickname');
+        $nickname = common_canonical_nickname($nickname_arg);
+
+        // Permanent redirect on non-canonical nickname
+
+        if ($nickname_arg != $nickname) {
+            $args = array('nickname' => $nickname);
+            common_redirect(common_local_url('editgroup', $args), 301);
+            return false;
+        }
+
+        if (!$nickname) {
+            $this->clientError(_('No nickname'), 404);
+            return false;
+        }
+
+        $this->group = User_group::staticGet('nickname', $nickname);
+
+        if (!$this->group) {
+            $this->clientError(_('No such group'), 404);
+            return false;
+        }
+
+        $cur = common_current_user();
+
+        if (!$cur->isMember($group)) {
+            $this->clientError(_('You are not a member of that group'), 403);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * On POST, add the current user to the group
+     *
+     * @param array $args unused
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        $cur = common_current_user();
+
+        $member = new Group_member();
+
+        $member->group_id   = $this->group->id;
+        $member->profile_id = $cur->id;
+
+        if (!$member->find(true)) {
+            $this->serverError(_('Could not find membership record.'));
+            return;
+        }
+
+        $result = $member->delete();
+
+        if (!$result) {
+            common_log_db_error($member, 'INSERT', __FILE__);
+            $this->serverError(sprintf(_('Could not remove user %s to group %s'),
+                                       $cur->nickname, $this->group->nickname));
+        }
+
+        if ($this->boolean('ajax')) {
+            $this->startHTML('text/xml;charset=utf-8');
+            $this->elementStart('head');
+            $this->element('title', null, sprintf(_('%s left group %s'),
+                                                  $cur->nickname,
+                                                  $this->group->nickname));
+            $this->elementEnd('head');
+            $this->elementStart('body');
+            $jf = new JoinForm($this, $this->group);
+            $jf->show();
+            $this->elementEnd('body');
+            $this->elementEnd('html');
+        } else {
+            common_redirect(common_local_url('groupmembers', array('nickname' =>
+                                                                   $this->group->nickname)));
+        }
+    }
+}
\ No newline at end of file
diff --git a/js/util.js b/js/util.js
index 0a03b86c23..4aad841340 100644
--- a/js/util.js
+++ b/js/util.js
@@ -24,7 +24,7 @@ $(document).ready(function(){
 		var remaining = maxLength - currentLength;
 		var counter = $("#notice_text-count");
 		counter.text(remaining);
-		
+
 		if (remaining <= 0) {
 			$("#form_notice").addClass("warning");
 		} else {
@@ -45,10 +45,10 @@ $(document).ready(function(){
 	if ($("#notice_data-text").length) {
 		$("#notice_data-text").bind("keyup", counter);
 		$("#notice_data-text").bind("keydown", submitonreturn);
-		
+
 		// run once in case there's something in there
 		counter();
-		
+
 		// set the focus
 		$("#notice_data-text").focus();
 	}
@@ -73,6 +73,24 @@ $(document).ready(function(){
 											  }
 					 };
 
+	var joinoptions = { dataType: 'xml',
+					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
+												var leave = new_form.id;
+												var join = leave.replace('leave', 'join');
+												$('form#'+join).replaceWith(new_form);
+												$('form#'+leave).ajaxForm(leaveoptions).each(addAjaxHidden);
+											  }
+					 };
+
+	var leaveoptions = { dataType: 'xml',
+					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
+												var join = new_form.id;
+												var leave = join.replace('join', 'leave');
+												$('form#'+leave).replaceWith(new_form);
+												$('form#'+join).ajaxForm(joinoptions).each(addAjaxHidden);
+											  }
+					 };
+
 	function addAjaxHidden() {
 		var ajax = document.createElement('input');
 		ajax.setAttribute('type', 'hidden');
@@ -83,14 +101,18 @@ $(document).ready(function(){
 
 	$("form.form_favor").ajaxForm(favoptions);
 	$("form.form_disfavor").ajaxForm(disoptions);
+	$("form.form_group_join").ajaxForm(joinoptions);
+	$("form.form_group_leave").ajaxForm(leaveoptions);
 	$("form.form_favor").each(addAjaxHidden);
 	$("form.form_disfavor").each(addAjaxHidden);
+	$("form.form_group_join").each(addAjaxHidden);
+	$("form.form_group_leave").each(addAjaxHidden);
 
 	$("#nudge").ajaxForm ({ dataType: 'xml',
 							beforeSubmit: function(xml) { $("form#nudge input[type=submit]").attr("disabled", "disabled");
 														  $("form#nudge input[type=submit]").addClass("disabled");
 														},
-							success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); 
+							success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true));
 												     $("#nudge input[type=submit]").removeAttr("disabled");
 												     $("#nudge input[type=submit]").removeClass("disabled");
 												   }
@@ -134,7 +156,6 @@ $(document).ready(function(){
 	$("form.subscribe").each(addAjaxHidden);
 	$("form.unsubscribe").each(addAjaxHidden);
 
-
 	var PostNotice = { dataType: 'xml',
 					   beforeSubmit: function(formData, jqForm, options) { if ($("#notice_data-text").get(0).value.length == 0) {
 																				$("#form_notice").addClass("warning");
@@ -166,7 +187,7 @@ $(document).ready(function(){
     $(".notice").hover(
         function () {
             $(this).addClass('hover');
-        }, 
+        },
         function () {
             $(this).removeClass('hover');
         }