My problem is that, I want to add a select dropdown in registration form to choose user type. But this code not shows the form element on front end. Can somebody please look at the code and tell me what's wrong with that code. I can see the array which is contains this element but not showing in the registration form.
Please check here is my code below:
<?php
function registration_role_dropdown_form_alter($form, &$form_state, $form_id){
if ($form_id == 'user_register_form') {
/*$query = db_select('role', 'r');
$query->addTag('translatable');
$query->fields('r', array('rid', 'name'));
$query->orderBy('weight');
$query->orderBy('name');
if (!empty($permission)) {
$query->innerJoin('role_permission', 'p', 'r.rid = p.rid');
$query->condition('p.permission', $permission);
}
$result = $query->execute();*/
$form['account']['roles']= array(
'#type' => 'select',
'#title' => t('Register As'),
'#options' => array(
registration_role_dropdown_user_roles()
),
'#description' => t('Select the <em>User type</em> from the dropdown.'),
);
}
}
function registration_role_dropdown_user_roles($membersonly = FALSE, $permission = NULL) {
$query = db_select('role', 'r');
$query->addTag('translatable');
$query->fields('r', array('rid', 'name'));
$query->orderBy('weight');
$query->orderBy('name');
if (!empty($permission)) {
$query->innerJoin('role_permission', 'p', 'r.rid = p.rid');
$query->condition('p.permission', $permission);
}
$result = $query->execute();
$roles = array();
foreach ($result as $role) {
switch ($role->rid) {
// We only translate the built in role names
case DRUPAL_ANONYMOUS_RID:
if (!$membersonly) {
$roles[$role->rid] = t($role->name);
}
break;
case DRUPAL_AUTHENTICATED_RID:
$roles[$role->rid] = t($role->name);
break;
default:
$roles[$role->rid] = $role->name;
}
}
return $roles;
}
?>
You aren't passing the $form variable by reference so your changes to it are never passed back to the callee of your hook_form_alter implementation.
Change:
function registration_role_dropdown_form_alter($form, &$form_state, $form_id)
to
function registration_role_dropdown_form_alter(&$form, &$form_state, $form_id)
Note the addition of the ampersand before the $form parameter.
Side note: Drupal's convention is to not close the opening <?php tag in your module files.
Related
I wish to create the edit form in Silverstripe 4.2, much like this Stack Overflow's edit function that i'm looking for.
EDITED: I want to be able to have a page that is only available to the registered member of my website that they can post their class listings on the Frontend (not in CMS) as an owner, and need to have a 'edit' click that takes you to an identical form (same ClassListingForm) that lets member owner to edit/update their own class listings that they have posted. I have everything working except the edit and submit functions which I'm stuck on at the moment.
I have a link for editing the specific class listing:
Edit class listing</div>
It does redirected to 404 page not found with this url shown:
"http://.../learners/class-listings/edit/61"
Here's the code below I have so far, the ClassListingForm is working fine, just need to get the EditListingForm and doClassListing functions to work properly, and i may be doing something wrong in these codes? or is there a better way of doing the edit form properly which i'm unable to find anywhere on the search for specific on what i need as there's not much tutorial that covers the EditForm function on the SilverStripe lessons.
<?php
class ClassListings extends DataObject {
private static $table_name = 'ClassListings';
private static $db = [
'CourseTitle' => 'Varchar(255)',
'CourseLocation' => 'Varchar(255)',
];
private static $has_one = [
'ClassListingPage' => ClassListingPage::class,
];
}
<?php
class ClassListingPageController extends PageController {
private static $allowed_actions = [
'ClassListingForm',
'ClassEditForm'
];
public function ClassListingForm() {
$id = (int)$this->urlParams['ID'];
$data = ($id)? $data = ClassListings::get()->byID($id) : false;
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField'),
HiddenField::create('ID', 'ID')->setValue($ClassListingPageID)
),
FieldList::create(
FormAction::create('handleClassListing')
->setTitle('Post your class listing')
->addExtraClass('btn btn-primary primary')
),
RequiredFields::create(
'CourseTitle',
'CourseLocation'
)
);
$form->loadDataFrom(Member::get()->byID(Member::currentUserID()));
$form->getSecurityToken()->getValue();
if ($form->hasExtension('FormSpamProtectionExtension')) {
$form->enableSpamProtection();
}
$data = $this->getRequest()->getSession()->get("FormData.{$form->getName()}.data");
return $data ? $form->loadDataFrom($data) : $form;
}
public function handleClassListing($data, $form) {
$session = $this->getRequest()->getSession();
$session->set("FormData.{$form->getName()}.data", $data);
$class = ClassListings::create($this->owner);
$class->CourseTitle = $data['CourseTitle'];
$class->CourseLocation = $data['CourseLocation'];
$class->ID = $data['ID'];
$class->ClassListingPageID = $this->ID;
$form->saveInto($class);
$class->write();
$session->clear("FormData.{$form->getName()}.data");
$form->sessionMessage('Your class listing has been posted!','good');
$session = $this->getRequest()->getSession();
return $this->redirect($this->Link());
}
public function ClassEditForm() {
$ClassListingPageID = (int)$this->urlParams['ID'];
$data = ($ClassListingPageID)? $data = ClassListings::get()->byID($ClassListingPageID) : false;
$var = $this->getRequest()->getVar('$data');
if($var){
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField'),
HiddenField::create('ID', 'ID')->setValue($ClassListingPageID)
),
FieldList::create(
FormAction::create('doClassListing')
->setTitle('Post your class listing')
->addExtraClass('btn btn-primary primary')
),
RequiredFields::create(
'CourseTitle',
'CourseLocation',
)
);
$form->loadDataFrom(ClassListings::get()->filter(['ClassListingPageID' => $var])[0]);
$form->getSecurityToken()->getValue();
if ($form->hasExtension('FormSpamProtectionExtension')) {
$form->enableSpamProtection();
}
$data = $this->getRequest()->getSession()->get("FormData.{$form->getName()}.data");
return $data ? $form->loadDataFrom($data) : $form;
}
return;
}
public function doUpdateClassListing($data, Form $form) {
$session = $this->getRequest()->getSession();
$session->set("FormData.{$form->getName()}.data", $data);
$class = ClassListings::create($this->owner);
$class->CourseTitle = $data['CourseTitle'];
$class->CourseLocation = $data['CourseLocation'];
$class->ID = $data['ID'];
$class->ClassListingPageID = $this->ID;
$form->saveInto($class);
$class->write();
$session->clear("FormData.{$form->getName()}.data");
$form->sessionMessage('Your class listing has been updated!','good');
$session = $this->getRequest()->getSession();
return $this->redirect($this->Link());
}
}
Thought i post this answer to share in case if others have the same issue i had.
Finally got it working and solved the issue now, have replaced whole the codes for both ClassEditForm and doUpdateClassListing methods, and also created another funcation called Edit:
public function Edit(HTTPRequest $request) {
$id = (int)$request->param('ID');
$class = ClassListings::get()->byID($id);
if (!$class || !$class->exists()) {
return ErrorPage::response_for(404);
}
$form = $this->ClassEditForm($class);
$return = $this->customise(array(
'Title' => 'Edit: ' . $class->CourseTitle,
'Form' => $form,
));
return $return = $return->renderWith(array('ClassListingPage_edit', 'Page'));
}
public function ClassEditForm() {
$id = (int)$this->urlParams['ID'];
$class = ClassListings::get()->byID($id);
$fields = new FieldList(
HiddenField::create('ID')->setValue($id),
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField')
);
$actions = new FieldList(
FormAction::create('doUpdateClassListing')
->setTitle('Update your class listing')
->addExtraClass('btn btn-primary primary')
);
$validator = new RequiredFields([
'CourseTitle',
'CourseLocation'
]);
$form = Form::create($this, 'ClassEditForm', $fields, $actions, $validator);
if ($class) $form->loadDataFrom($class);
return $form;
}
public function doUpdateClassListing($data, Form $form) {
if($data['ID']){
$id = $data['ID'];
$class = ClassListings::get()->byID($id);
} else {
$class = ClassListings::create();
}
$form->saveInto($class);
$id = $class->write();
$form->sessionMessage('Your class listing has been updated!','good');
$this->redirect($this->Link() . "edit/".$id);
}
I am building a bundle for private messages between my users.
Here is my inbox action from my controller. What it does is fetches the current user's messages, it passes the query to KNPpaginator to display a part of them. I also save how many results to be displayed on the page in the database. One form is a dropdown that sends how many results to display per page. The other form is made of checkboxes and a dropdown with actions. Based on which action was selected, I pass the id's of the messages(selected checkboxes id's) to another function called markAction(which is also a page that can mark one single message by going to the specific url)
public function inboxAction(Request $request)
{
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$mymsg = $messages->findMyMessages($this->getUser());
$message_settings = $this->getDoctrine()->getRepository('PrivateMessageBundle:MessageSettings');
$perpage = $message_settings->findOneBy(array('user' => $this->getUser()));
$pagerform = $this->createForm(new MessageSettingsType(), $perpage);
$pagerform->handleRequest($request);
if ($pagerform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($perpage);
$em->flush();
}
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$mymsg,
$request->query->get('page', 1)/*page number*/,
$perpage ? $perpage->getResPerPage() : 10/*limit per page*/,
array('defaultSortFieldName' => 'a.sentAt', 'defaultSortDirection' => 'desc')
);
$form = $this
->createForm(
new ActionsType(),
$mymsg->execute()
);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$ids = array();
foreach ($data['checkboxes'] as $checkbox) {
$ids[] = $checkbox->getId();
}
$action = $data['inboxactions'];
$this->markAction($action, $ids);
return $this->redirectToRoute('private_message_inbox');
}
return $this->render(
'#PrivateMessage/inbox.html.twig',
array(
'messageList' => $pagination,
'form' => $form->createView(),
'pagerform' => $pagerform->createView(),
)
);
}
And the mark action user in my inbox controller. Based on one parameter, I apply the respective action to the second parameter, which is one message if the page was called through routing, and can be an array of messages if called through my inboxAction. I do a few consistency checks, and then mark my message.
public function markAction($action, $msgs)
{
if (!$msgs) {
$this->addFlash(
'error',
'Select at least one message!'
);
return;
} else {
if (!$action) {
$this->addFlash(
'error',
'Select one action to apply to your items!'
);
return;
} else {
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$em = $this->getDoctrine()->getManager();
$msg = $messages->findBy(array('receiver' => $this->getUser(), 'id' => $msgs));
$good = 0;
foreach ($msg as $isforme) {
$good++;
switch ($action) {
case 'spam': {
if ($isforme->getIsSpam() == false) {
$isforme->setIsSpam(true);
if (!$isforme->getSeenAt()) {
$isforme->setSeenAt(new \DateTime('now'));
}
$em->persist($isforme);
}
break;
}
case 'unspam': {
if ($isforme->getIsSpam() == true) {
$isforme->setIsSpam(false);
$em->persist($isforme);
}
break;
}
case 'viewed': {
if ($isforme->getSeenAt() == false) {
$isforme->setSeenAt(new \DateTime('now'));
$em->persist($isforme);
}
break;
}
case 'unviewed': {
if ($isforme->getSeenAt() != false) {
$isforme->setSeenAt(null);
$em->persist($isforme);
}
break;
}
default: {
$this->addFlash(
'error',
'There was an error!'
);
return;
}
}
$em->flush();
}
$this->addFlash(
'notice',
$good.' message'.($good == 1 ? '' : 's').' changed!'
);
}
}
if ($action == 'unspam') {
return $this->redirectToRoute('private_message_spam');
} else {
return $this->redirectToRoute('private_message_inbox');
}
}
Being kind of new to symfony, I'm not sure how good my markAction function is. I feel like it can be simplier, but I'm not sure how to make it.
Now, my actual question. How can I render other pages of my bundle, like Sent or Spam messages? The only lines from the inboxAction that I have to change are
$mymsg = $messages->findMyMessages($this->getUser());
to have it return spam or sent messages by the user, for instance.
and
return $this->render(
'#PrivateMessage/inbox.html.twig',...
so I actually return the respective page's view. I have already made the other pages and copied the code in the other actions, but I think I can make it so I write this code a single time, but don't know how.
Everything else is EXACTLY the same. How can I not copy and paste this code in all of the other actions and make it a bit more reusable?
You could strart to change your routing more dynamic:
# app/config/routing.yml
mailclient:
path: /mailclient/{page}
defaults: { _controller: AppBundle:Mailclient:index, page: "inbox" }
Resulting that this routes:
/mailclient
/mailclient/inbox
/mailclient/sent
/mailclient/trash
will all call the same action.
Now your method (Action) will get an extra parameter:
public function indexAction($page, Request $request)
{
// ...
}
Through this parameter you know what the user likes to see. Now you can start to write your code more dynamic. You can consider to add some private functions to your controller class that you can call from the indexAction or
you could simply create your own classes too.
I have file (ProfileController.php) which contains the following code:
public function editAction() {
if (Zend_Auth::getInstance()->hasIdentity()) {
try {
$form = new Application_Form_NewStory();
$request = $this->getRequest();
$story = new Application_Model_DbTable_Story();
$result = $story->find($request->getParam('id'));
// $values = array(
// 'names' => $result->names,
// 'password' => $result->password,
// );
if ($this->getRequest()->isPost()) {
if ($form->isValid($request->getPost())) {
$data = array(
'names' => $form->getValue("names"),
'password' => $form->getValue("password"),
);
$form->populate($data->toArray());
$where = array(
'id' => $request->getParam('id'),
);
$story->update($data, $where);
}
}
$this->view->form = $form;
$this->view->titleS= $result->title;
$this->view->storyS= $result->story;
} catch (Exception $e) {
echo $e;
}
} else {
$this->_helper->redirector->goToRoute(array(
'controller' => 'auth',
'action' => 'index'
));
}
}
and another file (edit.phtml) with following code:
<?php
try
{
$tmp = $this->form->setAction($this->url());
//$tmp->titleS=$this->title;
//$tmp->storyS=$this->story;
//echo $tmp->title = "aaaaa";
}
catch(Exception $e)
{
echo $e;
}
?>
I would like the users to be able to edit their Username and password. How do I go about it?
First: move the Zend_Auth stuff up to init() or preDispatch(), that way Auth will run against any or all actions in the controller.
The trick in getting more then one submit button to work is to give the buttons different names so that getParam('') has something to work with.
Normally I only do this sort of thing when doing deletes, for edit's or update's I just submit the whole array back to the database. I typically use the Zend_Db_Table_Row save() method instead of Zend_Db_Table's insert() or update() so the mechanism is a little different.
I just use a simple form to perform an update, here is the controller code (the view just echo's the form):
//update album information
public function updatealbumAction()
{ //get page number from session
$session = new Zend_Session_Namespace('page');
//get album id
$id = $this->getRequest()->getParam('id');
$model = new Music_Model_Mapper_Album();
//fetch the album database record
$album = $model->findById($id);
$form = new Admin_Form_Album();
//this form is used elsewhere so set the form action to this action
$form->setAction('/admin/music/updatealbum/');
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = $form->getValues();//get valid and filtered form values
$newAlbum = new Music_Model_Album($data);//create new entity object
$update = $model->saveAlbum($newAlbum);//save/update album info
$this->message->addMessage("Update of Album '$update->name' complete!");//generate flash message
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));//redirect back to the page the request came from
}
} else {
$form->populate($album->toArray());
$this->view->form = $form;
}
}
This is a pretty common update action.
Now here is how you might use different request parameters to perform an action on a record. I use this to delete database records but anything is possible.
public function deleteAction()
{
$session = new Zend_Session_Namespace('page');
$request = $this->getRequest()->getParams();
try {
switch ($request) {
//if
case isset($request['trackId']):
$id = $request['trackId'];
$model = new Music_Model_Mapper_Track();
$model->deleteTrack($id);
$this->message->addMessage("Track Deleted!");
break;
case isset($request['albumId']):
$id = $request['albumId'];
$model = new Music_Model_Mapper_Album();
$model->deletealbum($id);
$this->message->addMessage("Album Deleted!");
break;
case isset($request['artistId']):
$id = $request['artistId'];
$model = new Music_Model_Mapper_Artist();
$model->deleteArtist($id);
$this->message->addMessage("Artist Deleted!");
break;
default:
break;
}
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));
} catch (Exception $e) {
$this->message->addMessage($e->getMessage());
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));
}
}
you can pass the request parameters as submit button labels or as urls or whatever works for you.
Good Luck!
I'm new to drupal and need to create a login form which i've succesfully done. But when i'm logged in i want the form to swtich to another form where you can edit your details.
I'm having trouble finding out how to swtich between the forms.
<?php
/**
* Implements hook_help.
*
* Displays help and module information.
*
* #param path
* Which path of the site we're using to display help
* #param arg
* Array that holds the current path as returned from arg() function
*/
function login_kms_help($path, $arg) {
switch ($path) {
case "admin/help#login":
return '<p>'. t("Creates login module") .'</p>';
break;
}
}
/**
* Implements hook_block_info().
*/
function login_kms_block_info() {
$blocks['login_kms'] = array(
'info' => t('Login KMS'), //The name that will appear in the block list.
'cache' => DRUPAL_CACHE_PER_ROLE, //Default
);
return $blocks;
}
function login_kms_block_view($delta = '') {
$block = array();
if($delta == 'login_kms') {
$block['subject'] = 'Login';
$block['content'] = drupal_render(drupal_get_form('login_kms_form_mode0'));
} else if($delta == 'login_kms'){
$block['subject'] = 'Edit';
$block['content'] = drupal_render(drupal_get_form('login_kms_form_mode1'));
}
return $block;
}
function login_kms_form_mode0() {
$form['username'] = array(
'#type' => 'textfield',
'#title' => t('Username:'),
);
$form['password'] = array(
'#type' => 'password',
'#title' => t('Password:'),
);
$form['Log in'] = array(
'#type' => 'submit',
'#value' => t('Log in'),
);
return $form;
}
function login_kms_form_mode1(){
$form['username'] = array(
'#type' => 'textfield',
'#title' => t('mode1'),
);
}
function login_kms_form_submit($form, &$form_state) {
$mysql_user = $form_state['values']['username'];
$mysql_pass = $form_state['values']['password'];
// drupal_set_message(t($mysql_pass));
// some logic
}
The first approach is using drupal_goto("my_path").
The second, and more "right" is using $form_state['redirect'] or $form['#redirect'], like this;
function login_kms_form_submit($form, &$form_state) {
$mysql_user = $form_state['values']['username'];
$mysql_pass = $form_state['values']['password'];
// drupal_set_message(t($mysql_pass));
// some logic
$form_state['redirect'] = 'user/to_the_new_form';
}
You can simply use drupal_goto() to redirect the logged in user to the other form.
global $user;
if(!empty($user->uid) || $user->uid > 0)
{
drupal_goto("my/new/page");
}
Hope this works... Muhammad.
For my company I'm working on a custom translation module for Magento.
On the form for translating an existing string, I would like to change the behaviour of the "Save And Continue"-button to a "Save And Next"-button.
With which I mean that instead of still editing thesame string, you get the next one in line.
I have tried to edit the link that is called for the Save And Continue:
Original:
[save-link] + "/back/edit/"
To:
[save-link] + "/back/edit/id/[id]/"
But to no avail. I'm hoping someone can set me in the right direction.
The unchanged code of the edit-form:
<?php
class Phpro_Advancedtranslate_Block_Adminhtml_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
{
public function __construct()
{
parent::__construct();
$this->_objectId = 'id';
$this->_blockGroup = 'advancedtranslate';
$this->_controller = 'adminhtml';
$this->_updateButton('save', 'label', Mage::helper('advancedtranslate')->__('Save Item'));
$this->_updateButton('delete', 'label', Mage::helper('advancedtranslate')->__('Delete Item'));
$this->_addButton('saveandcontinue', array(
'label' => Mage::helper('adminhtml')->__('Save And Next'),
'onclick' => 'saveAndContinueEdit()',
'class' => 'save',
), -100);
$currentId = Mage::getSIngleton('adminhtml/session')->getTranslateId();
$strings = Mage::getModel("advancedtranslate/advancedtranslate")->getCollection();
foreach ($strings as $string) {
$id = $string->getId();
if ($id != $currentId && $id < $nextId) {
$nextId = $id;
}
}
$this->_formScripts[] = "
function toggleEditor() {
if (tinyMCE.getInstanceById('advancedtranslate_content') == null) {
tinyMCE.execCommand('mceAddControl', false, 'advancedtranslate_content');
} else {
tinyMCE.execCommand('mceRemoveControl', false, 'advancedtranslate_content');
}
}
function saveAndContinueEdit(){
editForm.submit($('edit_form').action+'back/edit/');
}
";
}
public function getHeaderText()
{
return Mage::helper('advancedtranslate')->__("Edit Item '%s'", 'test');
}
}
This functionality has to happen in the controller that handles the Post. Set the _redirect to redirect to the next item.