Double registration form in moodle - forms

I'm editing a site based on moodle, and i need to create a double registration form. The first is already set (for schools), i need to create another one for private user. What would be the best way to do it?
Would be worth to copy the main signup files (signup.php and signup_form.php) and then make changes there?
Really thanks

I think the best solution would be to create a new authentication plugin.
https://docs.moodle.org/dev/Authentication_plugins
Maybe copy the code from here /auth/email into /auth/newname - replacing email with newname in the code.
Possibly extend the class? so something like this in /auth/newname/auth.php
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/auth/email/auth.php');
class auth_plugin_newname extends auth_plugin_email {
...
function can_signup() {
return true;
}
...
Then copy /login/signup_form.php into /auth/newname/signup_form.php
The next bit I'm not too sure about but you will probably need to modify /login/signup.php
Around the lines
if (empty($CFG->registerauth)) {
print_error('notlocalisederrormessage', 'error', '', 'Sorry, you may not use this page.');
}
$authplugin = get_auth_plugin($CFG->registerauth);
Change to
if (optional_param('newname', false, PARAM_BOOL)) {
$authplugin = get_auth_plugin('newname');
} else {
if (empty($CFG->registerauth)) {
print_error('notlocalisederrormessage', 'error', '', 'Sorry, you may not use this page.');
}
$authplugin = get_auth_plugin($CFG->registerauth);
}
Then for private registrations use
http://www.yoursite.com/login/signup.php?newname=1
Replace 'newname' with the name of your new authentication plugin.

Related

typo3 fe-manager how to get different admin emails

i have a question about fe-manager. In this extension it is possible to send a confirmation email to a admin. But it is always the same email. i like to send emails to various admins. for example: if the new user is from germany the receiving adress should be some#thing.de. if the new user is from switzerland the adress should be some#thing.ch.
any idea how to approach this?
any hints/solutions are more than welcome.
current state:
extension is created. i copied the finalCreate-Method from the AbstractController to my NewController. i changed the makeEmailArray() from:
Div::makeEmailArray(
$this->settings['new']['notifyAdmin'],
$this->settings['new']['email']['createAdminNotify']['receiver']['name']['value']
),
to:
Div::makeEmailArray('xxx#xxx.ch',
$this->settings['new']['email']['createAdminNotify']['receiver']['name']['value']
),
the ts setup.txt file is located in femanager_extended/Configuration/TypoScript/setup.txt
and contains the following code:
config.tx_extbase.objects {
In2\Femanager\Controller\NewController.className = Lbaumann\FemanagerExtended\Controller\NewController
}
is this the right approach?
There is no TypoScriptConfig for this behaiviour, but you can easily override the ControllerMethod and extend it with your needs.
Create your own extension like Vender "Vendor" (company/customername) and key "femanager_extended" with the extension_builder.
femanager_extended/Classes/Controller/NewController.php
<?php
namespace Vendor\FemanagerExtended\Controller;
class NewController extends \In2\Femanager\Controller\NewController
{
public function finalCreate($user, $action, $redirectByActionName, $login = true)
{
// own business logic
// replace the first Div::makeEmailArray...
// with your selected Admin-email-address
// see parent::finalCreate($user, $action, $redirectByActionName, $login);
}
}
femanager_extened/ext_typoscript_setup.txt
config.tx_extbase.objects {
In2\Femanager\Controller\NewController.className = Vendor\FemanagerExtended\Controller\NewController
}
I hope this will help you and i don´t forgot any settings.

How to add custom javascript code to validate field in contacts module in sugarcrm

I want custom code to be made on onblur of first_name field in sugarcrm.
The code should also be upgrade safe.
Please help!
Copy modules/Contacts/metadata/editviewdefs.php
into
custom/modules/Contacts/metadata/editviewdefs.php
(if it does not already exist. If so, use the existing one)
All your changes in this file are upgrade safe. Now open your new file, and you'll see one big array containing everything that's in the EditView of the Contacts-module.
Add the following inside the "templateMeta" array, for instance, right after "form".
'includes'=> array(
array('file'=>'custom/modules/Contacts/EditView.js'),
),
This includes the file custom/modules/Contacts/EditView.js, in which you are free to write all the javascript you feel like!
Remember to do a Quick Repair & Rebuild when you are done.
I don't know which version of SugarCRM you uses, but in SugarCRM 7, the following works:
Create a file 'record.js' in /custom/modules/Contacts/clients/base/views/record/. In that file, you can add custom validation.
Some code you could use is:
({
extendsFrom: 'YourModuleRecordView',
initialize: function (options) {
app.error.errorName2Keys['field_error'] = 'This is an error message';
this._super('initialize', [options]);
this.model.addValidationTask('check_field', _.bind(this._doValidateField, this));
},
_doValidateField: function(fields, errors, callback) {
if (this.model.get('myField') .... ) {
errors['myField'] = errors['myField'] || {};
errors['myField'].field_error = true;
}
callback(null, fields, errors);
}
});
Don't forget to change the fields names like you named them!
This result is only for edit mode. To add this validation to the creation mode, add the file 'create_actions.js' to /custom/modules/Contacts/clients/base/views/create_actions/
Enter the folling code in your 'create_actions.js':
({
extendsFrom: 'CreateActionsView',
initialize: function (options) {
app.error.errorName2Keys['field_error'] = 'Thsis is an error message';
this._super('initialize', [options]);
this.model.addValidationTask('check_field', _.bind(this._doValidateField, this));
},
_doValidateField: function(fields, errors, callback) {
if (.....) {
errors['myField'] = errors['myField'] || {};
errors['myField'].field_error = true;
}
callback(null, fields, errors);
}
});
Perform a repair/rebuild when you added this files with the right code.
You can customize this code to your own needs.

PHPUnit: Testing form submissions with session variables stored in Symfony2

I had a small test done in PHP for a Controller I had written in Symfony2:
class DepositControllerTest extends WebTestCase {
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'POST',
'/deposit',
array( "amount" => 23),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
}
Up to here, everything was great. Problem started when I realized I wanted to disable possible re-submissions while refreshing the page. So I added a small mechanism to send nonce on every submission.
It works something like this:
class ReplayManager {
public function getNonce() {
$uid = $this->getRandomUID();
$this->session->set("nonce", $uid);
return $uid;
}
public function checkNonce($cnonce) {
$nonce = $this->session->get("nonce");
if ($cnonce !== $nonce)
return false;
$this->session->set("nonce", null);
return true;
}
}
So I had to mofidy the controller to get the nonce when displaying the form, and consume it when submitting.
But now this introduces a problem. I cant make a request to POST /deposit because I dont know what nonce to send. I thought to requesting first GET /deposit to render the form, and setting one, to use it in the POST, but I suspect Symfony2 sessions are not working in PHPUnit.
How could I solve this issue? I would not want to go to Selenium tests, since they are significant slower, not to mention that I would have to rewrite A LOT of tests.
UPDATE: I add a very simplified version of the controller code by request.
class DepositController extends Controller{
public function formAction(Request $request){
$this->replayManager = $this->getReplayManager();
$context["nonce"] = $this->replayManager->getNonce();
return $this->renderTemplate("form.twig", $context);
}
protected function depositAction(){
$this->replayManager = $this->getReplayManager();
$nonce = $_POST["nonce"];
if (!$this->replayManager->checkNonce($nonce))
return $this->renderErrorTemplate("Nonce expired!");
deposit($_POST["amount"]);
return $this->renderTemplate('confirmation.twig');
}
protected function getSession() {
$session = $this->get('session');
$session->start();
return $session;
}
protected function getReplayManager() {
return new ReplayManager($this->getSession());
}
}
I'm not sure what ReplayManager does, but it looks to me as if it is not the right class to handle the 'nonce'. As the 'nonce' is ultimately stored in and retrieved from the session it should either be handled by the controller or abstracted out into its own class which is then passed in as a dependency. This will allow you to mock the nonce (sounds like a sitcom!) for testing.
In my experience problems in testing are actually problems with code design and should be considered a smell. In this case your problem stems from handling the nonce in the wrong place. A quick refactoring session should solve your testing problems.
It is possible to access the Symfony2 session from PHPUnit via the WebTestCase client. I think something like this should work:
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'GET',
'/deposit',
);
$session = $this->client->getContainer()->get('session');
$nonce = $session->get('nonce');
$this->crawler = self::$client->request(
'POST',
'/deposit',
array("amount" => 23, "nonce" => $nonce),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
EDIT:
Alternatively, if there is a problem getting the nonce value from the session, you could try replacing the two lines between the GET and POST requests above with:
$form = $crawler->selectButton('submit');
$nonce = $form->get('nonce')->getValue(); // replace 'nonce' with the actual name of the element

Field validations in sugarcrm

I just started using SugarCRM CE for the first time (Version 6.5.15 (Build 1083)). I'm quite impressed with the ease of use when adding new fields or modules, but there's one quite indispensable thing that seems to be missing: Validation of user input.
I would for example like to check a lot of things:
Check if a emailadres has a valid format, using some regular expression
Check if a postalcode exists (maybe do a webswervice call to validate it)
Do a calculation to see if a citizen service number is valid
etc.
The only thing I seem to be able to do in studio is make a field required or not, there doesn't seem to be any standard way to execute a validation on a field.
All I can find when I google on it is lots of ways to hack into the source code, like this one: http://phpbugs.wordpress.com/2010/01/22/sugarcrm-adding-javascript-validation-on-form-submit/ And even then I don't find any examples that actually do a validation.
Am I just missing something? Or is editing source code the only way to add this?
I don't think the "standard" validations are available in the CE edition.
What surprises me is that you can't define a validation somewhere and attach it to a field. I kind of expected this, since the rest of the system is very well structured (modules, packages, etc..)
I now for instance created a 11-check, this is a very specific check for a dutch bank account number. to get this to work, I did the following (based upon examples I found googling around):
I added the bank account to contacts in studio and after that edited \custom\modules\Contacts\metadata\editviewdefs.php
I added the following snippets:
'includes'=> array(
array('file'=>'custom/modules/Contacts/customJavascript.js')),
array (
0 =>
array(
'customCode' =>
'<input title="Save [Alt+S]" accessKey="S" onclick="this.form.action.value=\'Save\'; return check_custom_data();" type="submit" name="button" value="'.$GLOBALS['app_strings']['LBL_SAVE_BUTTON_LABEL']>',
),
1 =>
array(
'customCode' =>
'<input title="Cancel [Alt+X]" accessKey="X" onclick="this.form.action.value=\'index\'; this.form.module.value=\''.$module_name.'\'; this.form.record.value=\'\';" type="submit" name="button" value="'.$GLOBALS['app_strings']['LBL_CANCEL_BUTTON_LABEL'].'">'
)
),
And in customJavascript.js i placed this code:
function check_custom_data()
{
if (!eleven_check(document.getElementById("bankaccount_c").value)){
alert ('Bank account not valid');
return false;
} else {
return check_form('EditView');
}
function eleven_check(bankaccount) {
bankaccount=bankaccount.replace(/\D/, "");
charcount=bankaccount.length;
var som=0;
for (i=1; i<10; i++) {
getal=bankaccount.charAt(i-1);
som+=getal*(10-i);
}
if (som % 11==0 && charcount==9) {
return true
} else {
return false
}
}
}
This check now works the way I want it to work, but I'm wondering if this is the best way to add a validation. this way of adding a validation doesn't however accommodate PHP validations, for instance, if I want to validate against some data in the database for one or another reason, I would have to use ajax calls to get that done.
Email validation is in the pro edition, I had assumed it was in CE as well but I'm not 100% sure.
The other 2 are a lot more specific - postcode validation would depend upon your country so would be difficult to roll out. For these you will need to write your own custom validation.
I know its late, but maybe still someone needs this.
You can just add your custom javascript validation as a callback in your vardefs like this:
'validation' =>
array (
'type' => 'callback',
'callback' => 'function(formname,nameIndex){if($("#" + nameIndex).val()!=999){add_error_style(formname,nameIndex,"Only 999 is allowed!"); return false;}; return true;}',
),
I documented it here as its not well documented elsewhere:
https://gunnicom.wordpress.com/2015/09/21/suitecrm-sugarcrm-6-5-add-custom-javascript-field-validation/
You can add custom validation code to the following file: ./custom/modules/.../clients/base/views/record/record.js
There you can add validation code. In this example, I will validate if the phone_number is not empty when an accounts has a customer-type:
EXAMPLE CODE IN RECORD.JS:
({
extendsFrom: 'RecordView',
initialize: function (options) {
app.view.invokeParent(this, {type: 'view', name: 'record', method: 'initialize', args:[options]});
//add validation
this.model.addValidationTask('check_account_type', _.bind(this._doValidateCheckType, this));
},
_doValidateCheckType: function(fields, errors, callback) {
//validate requirements
if (this.model.get('account_type') == 'Customer' && _.isEmpty(this.model.get('phone_office')))
{
errors['phone_office'] = errors['phone_office'] || {};
errors['phone_office'].required = true;
}
callback(null, fields, errors);
}
})
Don't forget to repair en rebuild!
The full documentation can be found here

How to get the complete request that calls my MVC2 controller?

Newbie question … sorry ;-)
I have to write and to integrate a new website in a complex web application.
My new (MVC2) website will be hosted on a separate server and only called when the user clicks on a link in the already existing, complex website.
Means I(!) define the URL which calls my(!) new website.
But “they” (the calling, already existing, complex web application/website) will add an attribute to the url. This attribute is the sessionID.
Ok, I think I understand already that this calls my (MVC2) controller.
But how can I get in my (MVC2) controller the “calling URL” (which include the added sessionID)?
Hopefully that someone understand what I ask ;-)
Thanks in advance!
I want just share my little parser - hopefully it helps someone. ;-)
Also requests like
(Request.Url.Query =) "?sessionID=12345678901234567890123456789012&argumentWithoutValue&x=1&y&z=3"
will be well parsed.
Here my code:
Hashtable attributes = new Hashtable();
string query = Request.Url.Query;
string[] arrPairs = query.Split('&'); // ...?x=1&y=2
if (arrPairs != null)
{
foreach(string s in arrPairs)
{
if (!String.IsNullOrEmpty(s))
{
string onePair = s.Replace("?", "").Replace("&", "");
if (onePair.Contains("="))
{
string[] arr = onePair.Split('=');
if (arr != null)
{
if (arr.Count() == 2)
{
attributes.Add(arr[0], arr[1]);
}
}
}
else
{
// onePair does not contain a pair!
attributes.Add(onePair, "");
}
}
}
You really should set your URL and Route to be more MVC-Like. The URL you are calling should be:
newapp/controller/action/sessionId
Then set your route up:
routes.MapRoute(
"sessionId",
"{controller}/{action}/{sessionId}",
new { controller = "controller", action = "action", sessionId = 0 });
Then in your controller:
public ActionResult Action(int sessionId)
{
}
In your controller you still have direct access to the Request object, so you can use Request.Url, etc.
Does that answer your question, or is it something else that you need?