We are no longer offering accounts on this server. Consider https://gitlab.freedesktop.org/ as a place to host projects.

invite.php 11.5 KB
Newer Older
Evan Prodromou's avatar
Evan Prodromou committed
1 2
<?php
/*
3
 * StatusNet - the distributed open-source microblogging tool
4
 * Copyright (C) 2008-2011, StatusNet, Inc.
Evan Prodromou's avatar
Evan Prodromou committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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/>.
 */

20
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
Evan Prodromou's avatar
Evan Prodromou committed
21

22
// @todo XXX: Add documentation.
23
class InviteAction extends CurrentUserDesignAction
24
{
Evan Prodromou's avatar
Evan Prodromou committed
25
    var $mode = null;
Evan Prodromou's avatar
Evan Prodromou committed
26 27 28 29
    var $error = null;
    var $already = null;
    var $subbed = null;
    var $sent = null;
Evan Prodromou's avatar
Evan Prodromou committed
30

Evan Prodromou's avatar
Evan Prodromou committed
31 32 33 34 35
    function showNoticeForm()
    {
        return;
    }

36
    function isReadOnly($args)
37
    {
38 39
        return false;
    }
Evan Prodromou's avatar
Evan Prodromou committed
40

41 42
    function handle($args)
    {
Evan Prodromou's avatar
Evan Prodromou committed
43
        parent::handle($args);
44
        if (!common_config('invite', 'enabled')) {
45
            // TRANS: Client error displayed when trying to sent invites while they have been disabled.
46 47
            $this->clientError(_('Invites have been disabled.'));
        } else if (!common_logged_in()) {
48 49
            // TRANS: Client error displayed when trying to sent invites while not logged in.
            // TRANS: %s is the StatusNet site name.
50
            $this->clientError(sprintf(_('You must be logged in to invite other users to use %s.'),
51 52 53
                                        common_config('site', 'name')));
            return;
        } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
Evan Prodromou's avatar
Evan Prodromou committed
54
            $this->sendInvitations();
55
        } else {
Evan Prodromou's avatar
Evan Prodromou committed
56
            $this->showForm();
57 58 59
        }
    }

Evan Prodromou's avatar
Evan Prodromou committed
60
    function sendInvitations()
61
    {
62
        if (Event::handle('StartSendInvitations', array(&$this))) {
63

64 65 66 67 68 69 70
            // CSRF protection
            $token = $this->trimmed('token');
            if (!$token || $token != common_session_token()) {
                // TRANS: Client error displayed when the session token does not match or is not given.
                $this->showForm(_('There was a problem with your session token. Try again, please.'));
                return;
            }
71

72 73
            $user = common_current_user();
            $profile = $user->getProfile();
74

75 76 77
            $bestname = $profile->getBestName();
            $sitename = common_config('site', 'name');
            $personal = $this->trimmed('personal');
78

79 80 81 82
            $addresses = explode("\n", $this->trimmed('addresses'));
            foreach ($addresses as $email) {
                $email = trim($email);
                $valid = null;
83

84
                try {
85

86 87 88 89
                    if (Event::handle('StartValidateUserEmail', array(null, $email, &$valid))) {
                        $valid = Validate::email($email, common_config('email', 'check_domain'));
                        Event::handle('EndValidateUserEmail', array(null, $email, &$valid));
                    }
90

91 92 93 94 95
                    if ($valid) {
                        if (Event::handle('StartValidateEmailInvite', array($user, $email, &$valid))) {
                            $valid = true;
                            Event::handle('EndValidateEmailInvite', array($user, $email, &$valid));
                        }
96
                    }
97

98 99 100 101 102 103 104 105
                    if (!$valid) {
                        // TRANS: Form validation message when providing an e-mail address that does not validate.
                        // TRANS: %s is an invalid e-mail address.
                        $this->showForm(sprintf(_('Invalid email address: %s.'), $email));
                        return;
                    }
                } catch (ClientException $e) {
                    $this->showForm($e->getMessage());
106 107
                    return;
                }
108 109
            }

110 111 112 113 114 115 116 117 118 119 120 121 122
            $this->already = array();
            $this->subbed = array();

            foreach ($addresses as $email) {
                $email = common_canonical_email($email);
                $other = User::staticGet('email', $email);
                if ($other) {
                    if ($user->isSubscribed($other)) {
                        $this->already[] = $other;
                    } else {
                        subs_subscribe_to($user, $other);
                        $this->subbed[] = $other;
                    }
123
                } else {
124 125
                    $this->sent[] = $email;
                    $this->sendInvitation($email, $user, $personal);
126 127 128
                }
            }

129
            $this->mode = 'sent';
Evan Prodromou's avatar
Evan Prodromou committed
130

131 132 133
            $this->showPage();
            Event::handle('EndSendInvitations', array($this));
        }
Evan Prodromou's avatar
Evan Prodromou committed
134 135
    }

136 137 138 139 140 141
    function showScripts()
    {
        parent::showScripts();
        $this->autofocus('addresses');
    }

Evan Prodromou's avatar
Evan Prodromou committed
142 143 144
    function title()
    {
        if ($this->mode == 'sent') {
145 146
            // TRANS: Page title when invitations have been sent.
            return _('Invitations sent');
Evan Prodromou's avatar
Evan Prodromou committed
147
        } else {
148
            // TRANS: Page title when inviting potential users.
Evan Prodromou's avatar
Evan Prodromou committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
            return _('Invite new users');
        }
    }

    function showContent()
    {
        if ($this->mode == 'sent') {
            $this->showInvitationSuccess();
        } else {
            $this->showInviteForm();
        }
    }

    function showInvitationSuccess()
    {
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
        if (Event::handle('StartShowInvitationSuccess', array($this))) {

            if ($this->already) {
                // TRANS: Message displayed inviting users to use a StatusNet site while the inviting user
                // TRANS: is already subscribed to one or more users with the given e-mail address(es).
                // TRANS: Plural form is based on the number of reported already subscribed e-mail addresses.
                // TRANS: Followed by a bullet list.
                $this->element('p', null, _m('You are already subscribed to this user:',
                                             'You are already subscribed to these users:',
                                             count($this->already)));
                $this->elementStart('ul');
                foreach ($this->already as $other) {
                    // TRANS: Used as list item for already subscribed users (%1$s is nickname, %2$s is e-mail address).
                    $this->element('li', null, sprintf(_m('INVITE','%1$s (%2$s)'), $other->nickname, $other->email));
                }
                $this->elementEnd('ul');
180
            }
181 182 183 184 185 186 187 188 189 190 191 192 193
            if ($this->subbed) {
                // TRANS: Message displayed inviting users to use a StatusNet site while the invited user
                // TRANS: already uses a this StatusNet site. Plural form is based on the number of
                // TRANS: reported already present people. Followed by a bullet list.
                $this->element('p', null, _m('This person is already a user and you were automatically subscribed:',
                                             'These people are already users and you were automatically subscribed to them:',
                                             count($this->subbed)));
                $this->elementStart('ul');
                foreach ($this->subbed as $other) {
                    // TRANS: Used as list item for already registered people (%1$s is nickname, %2$s is e-mail address).
                    $this->element('li', null, sprintf(_m('INVITE','%1$s (%2$s)'), $other->nickname, $other->email));
                }
                $this->elementEnd('ul');
194
            }
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
            if ($this->sent) {
                // TRANS: Message displayed inviting users to use a StatusNet site. Plural form is
                // TRANS: based on the number of invitations sent. Followed by a bullet list of
                // TRANS: e-mail addresses to which invitations were sent.
                $this->element('p', null, _m('Invitation sent to the following person:',
                                             'Invitations sent to the following people:',
                                             count($this->sent)));
                $this->elementStart('ul');
                foreach ($this->sent as $other) {
                    $this->element('li', null, $other);
                }
                $this->elementEnd('ul');
                // TRANS: Generic message displayed after sending out one or more invitations to
                // TRANS: people to join a StatusNet site.
                $this->element('p', null, _('You will be notified when your invitees accept the invitation and register on the site. Thanks for growing the community!'));
210
            }
211
            Event::handle('EndShowInvitationSuccess', array($this));
212 213 214
        }
    }

Evan Prodromou's avatar
Evan Prodromou committed
215
    function showPageNotice()
216
    {
Evan Prodromou's avatar
Evan Prodromou committed
217 218 219 220 221 222
        if ($this->mode != 'sent') {
            if ($this->error) {
                $this->element('p', 'error', $this->error);
            } else {
                $this->elementStart('div', 'instructions');
                $this->element('p', null,
223
                               // TRANS: Form instructions.
Evan Prodromou's avatar
Evan Prodromou committed
224 225 226
                               _('Use this form to invite your friends and colleagues to use this service.'));
                $this->elementEnd('div');
            }
227 228 229
        }
    }

Evan Prodromou's avatar
Evan Prodromou committed
230
    function showForm($error=null)
231
    {
Evan Prodromou's avatar
Evan Prodromou committed
232 233 234 235
        $this->mode = 'form';
        $this->error = $error;
        $this->showPage();
    }
236

Evan Prodromou's avatar
Evan Prodromou committed
237 238
    function showInviteForm()
    {
239 240 241 242 243
        if (Event::handle('StartShowInviteForm', array($this))) {
            $form = new InviteForm($this);
            $form->show();
            Event::handle('EndShowInviteForm', array($this));
        }
244 245
    }

Evan Prodromou's avatar
Evan Prodromou committed
246
    function sendInvitation($email, $user, $personal)
247
    {
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
        $profile = $user->getProfile();
        $bestname = $profile->getBestName();

        $sitename = common_config('site', 'name');

        $invite = new Invitation();

        $invite->address = $email;
        $invite->address_type = 'email';
        $invite->code = common_confirmation_code(128);
        $invite->user_id = $user->id;
        $invite->created = common_sql_now();

        if (!$invite->insert()) {
            common_log_db_error($invite, 'INSERT', __FILE__);
            return false;
        }

266 267
        $confirmUrl = common_local_url('register', array('code' => $invite->code));

268 269 270
        $recipients = array($email);

        $headers['From'] = mail_notify_from();
271
        $headers['To'] = trim($email);
272 273
        $headers['Content-Type'] = 'text/html; charset=UTF-8';

274 275 276
        // TRANS: Subject for invitation email. Note that 'them' is correct as a gender-neutral
        // TRANS: singular 3rd-person pronoun in English. %1$s is the inviting user, $2$s is
        // TRANS: the StatusNet sitename.
277 278
        $headers['Subject'] = sprintf(_('%1$s has invited you to join them on %2$s'), $bestname, $sitename);

279 280
        $title = (empty($personal)) ? 'invite' : 'invitepersonal';

281
        // @todo FIXME: i18n issue.
282
        $inviteTemplate = DocFile::forTitle($title, DocFile::mailPaths());
283 284

        $body = $inviteTemplate->toHTML(array('inviter' => $bestname,
Evan Prodromou's avatar
Evan Prodromou committed
285
                                              'inviterurl' => $profile->profileurl,
286 287 288 289
                                              'confirmurl' => $confirmUrl,
                                              'personal' => $personal));

        common_debug('Confirm URL is ' . common_local_url('register', array('code' => $invite->code)));
290 291 292

        mail_send($recipients, $headers, $body);
    }
Evan Prodromou's avatar
Evan Prodromou committed
293
}