My form:
<form id="main-contact-form" name="contact-form" ata-request="onSend" data-request-success="alert('Message Sent')">
I cant seem to get a form to post; where do I place this file? Which file do I edit to make it send the form data fields to my email? I have already setup the backend mail settings:
function onSend()
{
// Collect input
$name = post('name');
$email = post('email');
$message = post('message');
// Submit form
$to = System\Models\MailSettings::get('sender_email');
$params = compact('name','email');
Mail::sendTo($to, 'temp.website::mail.newrequest', $params);
return true;
}
Please refer to the documentation: Plugin Components.
You can create a component (SomeForm.php)
<?php namespace My\Plugin\Components;
use Cms\Classes\ComponentBase;
class SomeForm extends ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Form',
'description' => 'Some form'
];
}
public function onSend()
{
// Collect input
$name = post('name');
$email = post('email');
$message = post('message');
// Submit form
$to = System\Models\MailSettings::get('sender_email');
$params = compact('name','email');
Mail::sendTo($to, 'temp.website::mail.newrequest', $params);
return true;
}
}
And then create a view for it (e.g. default.htm)
<form id="main-contact-form" name="contact-form" data-request="{{ __SELF__ }}::onSend" data-request-success="alert('Message Sent')">
...
</form>
Usage in pages/layouts:
[someForm]
==
{% component "someForm" %}
You goto the CMS section in your backend and paste that into the Code section of the default.htm layout. I already answered this question in the OctoberCMS.com forum. You can read about it here. Make sure that whatever form you use this on has a data-request="onSend" else it will not work. This is how it would ultimately look like...
You can add the Form's HTML either in your component partials directory, Theme's partial directory or just add it directly to any page / layout. It does not really matter.
Read more about including Partials
{% partial "contact-form.htm" %}
Or
{% partial __SELF__ ~ "::contact-form.htm" %} // reference to component's partial
October's AJAX framework requires the use of the JavaScript API or data attributes. It is fine how you are doing it in the example but forgot to add the Component's Name before the onSend Handler
data-request="SendEmails::onSend"
Where SendEmails = Component Name or Alias given in the page, if the form is in the component's partial just use {{ __SELF__ }}::onSend
or with the JavaScript API, just do :
$.request('onSend', {
data:{email:email, message:message, name:name},
success: function (data) {
//
},
error:function(e){
//
}
});
then in the component handling the request create a function onSend:
<?php namespace AuthorName\PluginName\Components;
use Cms\Classes\ComponentBase;
use Mail;
use Url;
use Input;
use Request;
use Response;
use ApplicationException;
use Validator;
use ValidationException;
class SendEmails extends ComponentBase
{
public function onSend()
{
if (Request::ajax()) {
try {
$data = post();
// Quick Validation rules for E-mail, Name & Message
if (!array_key_exists('email', $data)) {
$data['email'] = post('email');
}
if (!array_key_exists('norad', $data)) {
$data['message'] = post('message');
}
if (!array_key_exists('name', $data)) {
$data['name'] = post('name');
}
$rules = [
'email' => 'required|email|between:6,255',
'name' => 'required|between:4,255'
//..
];
$validation = Validator::make($data, $rules);
if ($validation->fails()) {
throw new ValidationException($validation);
}
// Check if E-mail Template Exists # "author.plugin::mail.templatename"
if (View::exists("author.plugin::mail.templatename")) {
Mail::send("author.plugin::mail.templatename", $data, function ($message) {
$message->from('noreply#yourdomain.com', 'Site Name');
$message->to($data['email'], $data['name']);
$message->subject('Subject here..');
});
// Handle Erros
if (count(Mail::failures()) > 0) {
echo "Failed to send Mail "; // Handle Failure
} else {
// Mail sent
echo "Mail Sent!"; // Handle Success
}
}
} catch (Exception $ex) {
throw $ex;
}
}
}
}
Related
I'm still trying to add a recaptcha to my website, I want try the recaptcha from Google but I can't use it properly. Checked or not, my email is still sent.
I tried to understand the code of How to validate Google reCaptcha v2 using phalcon/volt forms?.
But i don't understand where are my problems and more over how can you create an element like
$recaptcha = new Check('recaptcha');
My controller implementation :
<?php
/**
* ContactController
*
* Allows to contact the staff using a contact form
*/
class ContactController extends ControllerBase
{
public function initialize()
{
$this->tag->setTitle('Contact');
parent::initialize();
}
public function indexAction()
{
$this->view->form = new ContactForm;
}
/**
* Saves the contact information in the database
*/
public function sendAction()
{
if ($this->request->isPost() != true) {
return $this->forward('contact/index');
}
$form = new ContactForm;
$contact = new Contact();
// Validate the form
$data = $this->request->getPost();
if (!$form->isValid($data, $contact)) {
foreach ($form->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
if ($contact->save() == false) {
foreach ($contact->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
$this->flash->success('Merci, nous vous contacterons très rapidement');
return $this->forward('index/index');
}
}
In my view i added :
<div class="g-recaptcha" data-sitekey="mypublickey0123456789"></div>
{{ form.messages('recaptcha') }}
But my problem is after : i create a new validator for the recaptcha like in How to validate Google reCaptcha v2 using phalcon/volt forms? :
use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
if (!$this->isValid($validation)) {
$message = $this->getOption('message');
if ($message) {
$validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
}
return false;
}
return true;
}
public function isValid($validation)
{
try {
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
$url = $config->'https://www.google.com/recaptcha/api/siteverify'
$data = ['secret' => $config->mysecretkey123456789
'response' => $value,
'remoteip' => $ip,
];
// Prepare POST request
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
],
];
// Make POST request and evaluate the response
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
}
So i don't know if tjis code is correct anyway, i have a problem too after that : how to create an object "recaptcha" in my form add
$recaptcha = new ?????('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'Please confirm that you are human'
]));
$this->add($recaptcha);
PS: I apologize because i'm a noob here and my mother tongue is not english, so if you don't understand me or want give me some advices to create a proper question, don't hesitate ^^
I've made a custom form element for recaptcha. Used it for many projects so far.
The form element class:
class Recaptcha extends \Phalcon\Forms\Element
{
public function render($attributes = null)
{
$html = '<script src="https://www.google.com/recaptcha/api.js?hl=en"></script>';
$html.= '<div class="g-recaptcha" data-sitekey="YOUR_PUBLIC_KEY"></div>';
return $html;
}
}
The recaptcha validator class:
use Phalcon\Validation\Validator;
use Phalcon\Validation\ValidatorInterface;
use Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
if (!$this->verify($value, $ip)) {
$validation->appendMessage(new Message($this->getOption('message'), $attribute, 'Recaptcha'));
return false;
}
return true;
}
protected function verify($value, $ip)
{
$params = [
'secret' => 'YOUR_PRIVATE_KEY',
'response' => $value,
'remoteip' => $ip
];
$response = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?' . http_build_query($params)));
return (bool)$response->success;
}
}
Using in your form class:
$recaptcha = new Recaptcha($name);
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'YOUR_RECAPTCHA_ERROR_MESSAGE'
]));
Note 1: You were almost there, you just missed to create custom form element (the first and last code piece from my example);
Note 2: Also there is a library in Github: https://github.com/fizzka/phalcon-recaptcha I have not used it, but few peeps at phalcon forum recommended it.
I am using Zend 1.12
I have a form which has two fields: email, and file
My index view shows the form. And after validation is successful, I want to parse the csv file and show the content on result view:
My Code:
IndexController:
class IndexController extends Zend_Controller_Action {
public function init() {
/* Initialize action controller here */
}
public function indexAction() {
// action body
$form = new Application_Form_FileUpload();
$form->submit->setLabel('Upload');
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$file = $form->getValue('file');
$email = $form->getValue('email');
//$this->_helper->viewRenderer('result', null, true);
//$this->_helper->redirector('result', 'index','', array('email' => $email, 'file' => $file));
$this->_helper->redirector->gotoRouteAndExit (array(
'controller' => 'index',
'action' =>'result',
'name' => $file));
} else {
$form->populate($formData);
}
}
}
public function resultAction() {
$email = $this->_getParam('name');
$this->view->email = $email;
}
}
My index view:
<?php
$this->form->setAction($this->url(array('action' => 'index')));
echo $this->form;
?>
My result view:
<?php
echo $this->email;
//echo the content of the csv file;
?>
My result view is empty always.
What is the correct/right way to get the form data, and if validation is successful, show the content in result view.
Edit: I have succeeded to get parameters passed to resultaction.
I just was looking into different file. That is why it was not showing up.
But still, is it the right way to do it for my case? For it seems not correct.
I have made a contact form and I want to send the user to a thank you page or back to the contact form with an error message saying what fields were missing that need to be filled.
Initially I tried:
public function submit() {
if (Input::has('name')) {
$name = Input::get('name');
} else {
return Redirect::to('apply')->with('message', 'Login Failed');
}
$this->thanks($name);
}
public function thanks() {
return View::make('apply.thanks', array('metaTitle' => 'Application Sent | Thank you'));
}
But this gives me an error.
So I replaced the line $this->thanks($name); with return Redirect::to('apply/thanks')->with('message', 'Login Failed');
And it works.
My two questions are:
Is this the right way to send the user to the thank you page?
If there is an error, I would like to send back which errors occurred (what required fields weren't filled out). How is this achieved?
I have tried to implement route names:
routes file
Route::post('apply/submit', array('as' => 'applicationSubmit', 'uses' => 'ApplyController#submit'));
Route::post('apply/thanks', array('as' => 'applicationThanks', 'uses' => 'ApplyController#thanks'));
apply file
public function submit() {
$validationErrors = array();
if (Input::has('name')) {
$name = Input::get('name');
} else {
$validationErrors[] = 'You must enter your name';
}
if($validationErrors) {
if(Request::ajax()){
} else {
return Redirect::to('apply')->with('validationErrors', $validationErrors);
}
} else {
if(Request::ajax()){
} else {
return Redirect::route('applicationThanks')->with('name', $name);
}
}
}
But I'm getting the error Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException (I found out how to turn the detailed error messages on :) )
I think you want something like this:
public function submit() {
if (Input::has('name')) {
$name = Input::get('name');
} else {
return Redirect::to('apply')->with('message', 'Login Failed');
}
return Redirect::to('thanks')->with('name', $name);
}
public function thanks() {
return View::make('apply.thanks', array('metaTitle' => 'Application Sent | Thank you'));
}
Of course you need to have defined route to thanks.
But you could also make it simpler without using thanks method at all:
public function submit() {
if (Input::has('name')) {
$name = Input::get('name');
return View::make('apply.thanks', array('metaTitle' => 'Application Sent | Thank you'));
}
return Redirect::to('apply')->with('message', 'Login Failed');
}
I would rather go for second method (there's no need to make extra redirection just to display view).
You could also consider using named routes in case you will change your urls in future
EDIT
Route for thanks need to use get method and not post because you make redirection to it (no form data are sent by user to this route), so instead of:
Route::post('apply/thanks', array('as' => 'applicationThanks', 'uses' => 'ApplyController#thanks'));
it should be rather:
Route::get('apply/thanks', array('as' => 'applicationThanks', 'uses' => 'ApplyController#thanks'));
I advise you to look at Basic routing - you should really understand verbs and routing and in case you don't care you can always use Route::any to match all verbs: POST, GET, PUT, PATCH and DELETE - but in my opinion it's better to use correct verb and not all of them.
I am trying to send a parameter from the indexAction to the editAction using the viewRender function. The problem is when the editAction is called it causes my $form to think it has been posted.
public funciton indexAction(){
...
if(isset($_POST['edit'])){
$this->_helper->viewRenderer('edit');
$this->editAction($thingINeed);
}
...
}
public function editAction($thingINeed){
...
if($form->posted){
var_dump('FORM POSTED');
}
...
}
"FORM POSTED" is printed immediately even though I have not posted the form yet. I'm not sure why the form $form->posted is set to true on the initial render. Does anyone have an idea of why this is or a work around?
You should check your form like this:
$form = new MyForm();
if ($this->_request->isPost()) {
$formData = $this->_request->getPost();
if ($form->isValid($formData)) {
echo 'success';
exit;
} else {
$form->populate($formData);
}
}
$this->view->form = $form;
I'm not sure about what you want to obtain, but in order to communicate value between two action, it should be better to use _getParam and _setParam method :
public funciton indexAction(){
...
if(isset($_POST['edit'])){
$this->_setParam( 'posted', true );
$this->_helper->viewRenderer('edit');
//$this->editAction($thingINeed);
// It should be better to use Action stack helper to route correctly your action :
Zend_Controller_Action_HelperBroker::getStaticHelper( 'actionStack' )->actionToStack( 'edit' );
} else {
$this->_setParam( 'posted', false );
}
...
}
// param $thingINeed is not "needed" anymore
public function editAction(){
...
if( true == $this->_getParam( 'posted' ) {
var_dump('FORM POSTED');
}
...
}
I want to limit my registration to emails with #mywork.com I made the following in My_Form_validation.
public function email_check($email)
{
$findme='mywork.com';
$pos = strpos($email,$findme);
if ($pos===FALSE)
{
$this->CI->form_validation->set_message('email_check', "The %s field does not have our email.");
return FALSE;
}
else
{
return TRUE;
}
}
I use it as follows. I use CI rules for username and password and it works, for email it accepts any email address. Any I appreciate any help.
function register_form($container)
{
....
....
/ Set Rules
$config = array(
...//for username
// for email
array(
'field'=>'email',
'label'=>$this->CI->lang->line('userlib_email'),
'rules'=>"trim|required|max_length[254]|valid_email|callback_email_check|callback_spare_email"
),
...// for password
);
$this->CI->form_validation->set_rules($config);
The problem with creating a callback directly in the controller is that it is now accessible in the url by calling http://localhost/yourapp/yourcontroller/yourcallback which isn't desirable. There is a more modular approach that tucks your validation rules away into configuration files. I recommend:
Your controller:
<?php
class Your_Controller extends CI_Controller{
function submit_signup(){
$this->load->library('form_validation');
if(!$this->form_validation->run('submit_signup')){
//error
}
else{
$p = $this->input->post();
//insert $p into database....
}
}
}
application/config/form_validation.php:
<?php
$config = array
(
//this array key matches what you passed into run()
'submit_signup' => array
(
array(
'field' => 'email',
'label' => 'Email',
'rules' => 'required|max_length[255]|valid_email|belongstowork'
)
/*
,
array(
...
)
*/
)
//you would add more run() routines here, for separate form submissions.
);
application/libraries/MY_Form_validation.php:
<?php
class MY_Form_validation extends CI_Form_validation{
function __construct($config = array()){
parent::__construct($config);
}
function belongstowork($email){
$endsWith = "#mywork.com";
//see: http://stackoverflow.com/a/619725/568884
return substr_compare($endsWith, $email, -strlen($email), strlen($email)) === 0;
}
}
application/language/english/form_validation_lang.php:
Add: $lang['belongstowork'] = "Sorry, the email must belong to work.";
Are you need validation something like this in a Codeigniter callback function?
$this->form_validation->set_rules('email', 'email', 'trim|required|max_length[254]|valid_email|xss_clean|callback_spare_email[' . $this->input->post('email') . ']');
if ($this->form_validation->run() == FALSE)
{
// failed
echo 'FAIL';
}
else
{
// success
echo 'GOOD';
}
function spare_email($str)
{
// if first_item and second_item are equal
if(stristr($str, '#mywork.com') !== FALSE)
{
// success
return $str;
}
else
{
// set error message
$this->form_validation->set_message('spare_email', 'No match');
// return fail
return FALSE;
}
}
A correction to Jordan's answer, the language file that you need to edit should be located in
system/language/english/form_validation_lang.php
not application/.../form_validation_lang.php. If you create the new file under the application path with the same name, it will overwrite the original in the system path. Thus you will lose all the usage of the original filters.