Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
alexhayes committed Sep 7, 2011
2 parents 9e07cbd + 789e8ec commit 83134df
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 27 deletions.
4 changes: 4 additions & 0 deletions _config.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
throw new Exception('The Member Profiles module requires the Orderable module.');
}

Director::addRules(20, array(
'member-approval' => 'MemberApprovalController'
));

Object::add_extension('Member', 'MemberProfileExtension');
87 changes: 64 additions & 23 deletions code/MemberProfilePage.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ class MemberProfilePage extends Page implements PermissionProvider {
'AllowProfileViewing' => 'Boolean',
'AllowProfileEditing' => 'Boolean',
'AllowAdding' => 'Boolean',
'RegistrationRedirect' => 'Boolean',

'EmailType' => 'Enum("Validation, Confirmation, None", "None")',
'EmailFrom' => 'Varchar(255)',
'EmailSubject' => 'Varchar(255)',
'EmailTemplate' => 'Text',
'ConfirmationTitle' => 'Varchar(255)',
'ConfirmationContent' => 'HTMLText'
'RegistrationRedirect' => 'Boolean',
'RequireApproval' => 'Boolean',
'EmailType' => 'Enum("Validation, Confirmation, None", "None")',
'EmailFrom' => 'Varchar(255)',
'EmailSubject' => 'Varchar(255)',
'EmailTemplate' => 'Text',
'ConfirmationTitle' => 'Varchar(255)',
'ConfirmationContent' => 'HTMLText'
);

public static $has_one = array(
Expand All @@ -46,8 +46,9 @@ class MemberProfilePage extends Page implements PermissionProvider {
);

public static $many_many = array (
'Groups' => 'Group',
'SelectableGroups' => 'Group',
'Groups' => 'Group',
'SelectableGroups' => 'Group',
'ApprovalGroups' => 'Group',
'RegistrationGroups' => 'Group'
);

Expand Down Expand Up @@ -127,6 +128,10 @@ public function providePermissions() {
public function getCMSFields() {
$fields = parent::getCMSFields();

Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery-livequery/jquery.livequery.js');
Requirements::javascript('memberprofiles/javascript/MemberProfilePageCms.js');

// Setup tabs
$fields->addFieldToTab('Root', $profile = new TabSet('Profile'), 'Content');
$fields->addFieldToTab('Root', $email = new Tab('Email'), 'Behaviour');
Expand Down Expand Up @@ -275,10 +280,18 @@ public function getCMSFields() {
_t('MemberProfiles.ALLOWADD',
'Allow members with member creation permissions to add members via this page')),
'ClassName');
$fields->addFieldToTab('Root.Behaviour',
new HeaderField('PageSettingsHeader',
_t('MemberProfiles.PAGEBEHAVIOUR', 'Page Behaviour')),
'ClassName');

$requireApproval = new CheckboxField('RequireApproval', _t(
'MemberProfiles.REQUIREREGAPPROVAL', 'Require registration approval by an administrator?'
));
$fields->addFieldToTab('Root.Behaviour', $requireApproval, 'ClassName');

$approvalGroups = _t('MemberProfiles.NOTIFYTHESEGROUPS', 'Notify these groups to approve new registrations');
$approvalGroups = new TreeMultiselectField('ApprovalGroups', $approvalGroups, 'Group');
$fields->addFieldToTab('Root.Behaviour', $approvalGroups, 'ClassName');

$pageSettings = new HeaderField('PageSettingsHeader', _t('MemberProfiles.PAGEBEHAVIOUR', 'Page Behaviour'));
$fields->addFieldToTab('Root.Behaviour', $pageSettings, 'ClassName');

return $fields;
}
Expand Down Expand Up @@ -473,7 +486,7 @@ public function RegisterForm() {
*/
public function register($data, Form $form) {
if($member = $this->addMember($form)) {
if($this->EmailType != 'Validation' && !$this->AllowAdding) {
if(!$this->RequireApproval && $this->EmailType != 'Validation' && !$this->AllowAdding) {
$member->logIn();
}

Expand Down Expand Up @@ -718,7 +731,10 @@ protected function addMember($form) {
$groupIds = $this->getSettableGroupIdsFrom($form);

$form->saveInto($member);
$member->ProfilePageID = $this->ID;

$member->ProfilePageID = $this->ID;
$member->NeedsValidation = ($this->EmailType == 'Validation');
$member->NeedsApproval = $this->RequireApproval;

try {
$member->write();
Expand All @@ -730,17 +746,42 @@ protected function addMember($form) {
// set after member is created otherwise the member object does not exist
$member->Groups()->setByIDList($groupIds);

if($this->EmailType == 'Validation') {
$email = new MemberConfirmationEmail($this, $member);
$email->send();
// If we require admin approval, send an email to the admin and delay
// sending an email to the member.
if ($this->RequireApproval) {
$groups = $this->ApprovalGroups();
$emails = array();

$member->NeedsValidation = true;
$member->write();
} elseif($this->EmailType == 'Confirmation') {
if ($groups) foreach ($groups as $group) {
foreach ($group->Members() as $_member) {
if ($member->Email) $emails[] = $_member->Email;
}
}

if ($emails) {
$email = new Email();
$config = SiteConfig::current_site_config();
$approve = Controller::join_links(
Director::baseURL(), 'member-approval', $member->ID, '?token=' . $member->ValidationKey
);

$email->setSubject("Registration Approval Requested for $config->Title");
$email->setBcc(implode(',', array_unique($emails)));
$email->setTemplate('MemberRequiresApprovalEmail');
$email->populateTemplate(array(
'SiteConfig' => $config,
'Member' => $member,
'ApproveLink' => Director::absoluteURL($approve)
));

$email->send();
}
} elseif($this->EmailType != 'None') {
$email = new MemberConfirmationEmail($this, $member);
$email->send();
}

$this->extend('onAddMember', $member);
return $member;
}

Expand All @@ -753,7 +794,7 @@ protected function getProfileFields($context) {
$fields = new FieldSet();

// depending on the context, load fields from the current member
if(Member::currentUserID() && $context != 'Add') {
if(Member::currentUser() && $context != 'Add') {
$memberFields = Member::currentUser()->getMemberFormFields();
} else {
$memberFields = singleton('Member')->getMemberFormFields();
Expand Down
64 changes: 64 additions & 0 deletions code/controllers/MemberApprovalController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* @package silverstripe-memberprofiles
*/
class MemberApprovalController extends Page_Controller {

public static $url_handlers = array(
'$ID' => 'index'
);

public static $allowed_actions = array(
'index'
);

public function index($request) {
$id = $request->param('ID');
$token = $request->getVar('token');

if (!$id || !ctype_digit($id)) {
$this->httpError(404, 'A member ID was not specified.');
}

$member = DataObject::get_by_id('Member', $id);

if (!$member) {
$this->httpError(404, 'The specified member could not be found.');
}

if (!$member->canEdit()) {
return Security::permissionFailure();
}

if ($token != $member->ValidationKey) {
$this->httpError(400, 'An invalid token was specified.');
}

if (!$member->NeedsApproval) {
$title = _t('MemberProfiles.ALREADYAPPROVED', 'Already Approved');
$content = _t('MemberProfiles.ALREADYAPPROVEDNOTE', 'This member has already been approved');

return $this->render(array(
'Title' => $title,
'Content' => "<p>$content</p>"
));
}

$member->NeedsApproval = false;
$member->write();

$title = _t('MemberProfiles.MEMBERAPPROVED', 'Member Approved');
$content = _t('MemberProfiles.MEMBERAPPROVED', 'The member "%s" has been approved and can now log in.');
$content = sprintf($content, Convert::raw2xml("$member->Name <$member->Email>"));

return $this->render(array(
'Title' => $title,
'Content' => $content
));
}

public function Link($action = null) {
return Controller::join_links(Director::baseURL(), 'member-approval', $action);
}

}
50 changes: 46 additions & 4 deletions code/extensions/MemberProfileExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public function extraStatics() {
'db' => array (
'ValidationKey' => 'Varchar(40)',
'NeedsValidation' => 'Boolean',
'PublicFieldsRaw' => 'Text'
'NeedsApproval' => 'Boolean',
'PublicFieldsRaw' => 'Text'
),
'has_one' => array (
'ProfilePage' => 'MemberProfilePage'
Expand All @@ -29,6 +30,11 @@ public function setPublicFields($fields) {
}

public function canLogIn($result) {
if($this->owner->NeedsApproval) $result->error(_t (
'MemberProfiles.NEEDSAPPROVALTOLOGIN',
'An administrator must confirm your account before you can log in.'
));

if($this->owner->NeedsValidation) $result->error(_t (
'MemberProfiles.NEEDSVALIDATIONTOLOGIN',
'You must validate your account before you can log in.'
Expand All @@ -51,11 +57,28 @@ public function populateDefaults() {
$this->owner->ValidationKey = sha1(mt_rand() . mt_rand());
}

public function onAfterWrite() {
$changed = $this->owner->getChangedFields();

if (array_key_exists('NeedsApproval', $changed)) {
$before = $changed['NeedsApproval']['before'];
$after = $changed['NeedsApproval']['after'];
$page = $this->owner->ProfilePage();
$email = $page->EmailType;

if ($before == true && $after == false && $email != 'None') {
$email = new MemberConfirmationEmail($page, $this->owner);
$email->send();
}
}
}

public function updateMemberFormFields($fields) {
$fields->removeByName('ValidationKey');
$fields->removeByName('NeedsValidation');
$fields->removeByName('NeedsApproval');
$fields->removeByName('ProfilePageID');
$fields->removeByName('PublicFields');
$fields->removeByName('PublicFieldsRaw');

// For now we just pass an empty array as the list of selectable groups -
// it's up to anything that uses this to populate it appropriately
Expand All @@ -64,12 +87,31 @@ public function updateMemberFormFields($fields) {
}

public function updateCMSFields($fields) {
$mainFields = $fields->fieldByName("Root")->fieldByName("Main")->Children;

$fields->removeByName('ValidationKey');
$fields->removeByName('NeedsValidation');
$fields->removeByName('NeedsApproval');
$fields->removeByName('ProfilePageID');
$fields->removeByName('PublicFields');
$fields->removeByName('PublicFieldsRaw');

if ($this->owner->NeedsApproval) {
$note = _t(
'MemberProfiles.NOLOGINUNTILAPPROVED',
'This user has not yet been approved. They cannot log in until their account is approved.'
);

$mainFields->merge(array(
new HeaderField('ApprovalHheader', _t('MemberProfiles.REGAPPROVAL', 'Registration Approval')),
new LiteralField('ApprovalNote', "<p>$note</p>"),
new DropdownField('NeedsApproval', '', array(
true => _t('MemberProfiles.DONOTCHANGE', 'Do not change'),
false => _t('MemberProfiles.APPROVETHISMEMBER', 'Approve this member')
))
));
}

if($this->owner->NeedsValidation) $fields->addFieldsToTab('Root.Main', array (
if($this->owner->NeedsValidation) $mainFields->merge(array(
new HeaderField(_t('MemberProfiles.EMAILCONFIRMATION', 'Email Confirmation')),
new LiteralField('ConfirmationNote', '<p>' . _t (
'MemberProfiles.NOLOGINTILLCONFIRMED',
Expand Down
7 changes: 7 additions & 0 deletions javascript/MemberProfilePageCms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
;(function($) {
$("#Form_EditForm_RequireApproval").livequery(function() {
$(this)
.change(function() { $("#ApprovalGroups").toggle(this.checked); })
.trigger("change");
});
})(jQuery);
25 changes: 25 additions & 0 deletions templates/Email/MemberRequiresApprovalEmail.ss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<p>
A new member has registered for $SiteConfig.Title, and requires approval
before they can log in:
</p>

<% control Member %>
<dl>
<dt>Name:</dt>
<dd>$Name</dd>
<dt>Email:</dt>
<dd>$Email</dd>
<dt>Registered:</dt>
<dd>$Created.Date</dd>
</dl>
<% end_control %>

<p>
Please visit the link below to confirm this member. Once approved they will
be sent a confirmation email if configured. If you do not approve this member
then they will not be able to log in.
</p>

<p>
<a href="$ApproveLink">$ApproveLink</a>
</p>

0 comments on commit 83134df

Please sign in to comment.