I am working on an online newspaper/blogging application with CodeIgniter 3.1.8 and Twig. I use the Twig template engine for the front-end views.
I have put together this simple contact form which uses a controller, a view, and no model.
The controller:
class Contact extends CI_Controller {
public function __construct()
{
parent::__construct();
}
private $headers = "";
private $to = '[email protected]';
private $email_address = '';
private $name = '';
private $subject = '';
private $message = '';
private $body = '';
private $message_success = false;
private $message_fail = false;
public function index(){
$this->form_validation->set_rules('name', 'Name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|trim|valid_email');
$this->form_validation->set_rules('subject', 'Subject', 'required');
$this->form_validation->set_rules('message', 'Message', 'required');
$this->form_validation->set_error_delimiters('<p class="form-error">', '</p>');
if($this->form_validation->run() === FALSE) {
$data['errors'] = validation_errors();
$this->displayForm();
} else {
//Prepare mail
$this->subject = "Website Contact Form: " . $this->input->post('subject');
$this->name = $this->input->post('name');
$this->email_address = $this->input->post('email');
$this->message = $this->input->post('message');
$this->body = "You have received a new message from your website contact form. Here are the details:\n\nName: $this->name\n\nEmail: $this->email_address\n\nMessage:\n$this->message";
$this->headers = "From: [email protected]\n";
$this->headers .= "Reply-To: $this->email_address";
//Send mail
$this->send_mail();
$this->displayForm();
}
}
public function displayForm() {
$data = $this->Static_model->get_static_data();
$data['base_url'] = base_url("/");
$data['pages'] = $this->Pages_model->get_pages();
$data['categories'] = $this->Categories_model->get_categories();
$data['tagline'] = "Contact us";
$data['errors'] = validation_errors();
$data['message_success'] = $this->message_success;
$data['message_fail'] = $this->message_fail;
$this->twig->addGlobal('contactForm',"themes/{$data['theme_directory']}/templates/contact.twig");
$this->twig->display("themes/{$data['theme_directory']}/layout", $data);
}
//mail sender method
public function send_mail() {
if (mail($this->to, $this->subject, $this->body, $this->headers)) {
$this->message_success = true;
} else {
$this->message_fail = true;
}
}
}
The contact.twig
view:
<div class="wrapper style1">
<div class="content">
<div class="contact image fit flush">
<img src="{{base_url}}themes/caminar/assets/images/woman-with-laptop.jpg" alt="Contact">
</div>
<h2>Contact us</h2>
{% if message_success == true %}
<div class="alert alert-success alert-dismissible text-center">
<button type="button" class="close" data-dismiss="alert">×</button>
Your message was sent. We will reply as soon as possible.
</div>
{% endif %}
{% if message_fail == true %}
<div class="alert alert-danger alert-dismissible text-center">
<button type="button" class="close" data-dismiss="alert">×</button>
Something went wrong while sending your message.
</div>
{% endif %}
<div id="msgContainer" class="alert alert-hidden alert-success mb-4"></div>
<form name="contactForm"
id="ajaxForm"
action="{{base_url}}contact"
method="post"
data-successmsg="Your message was sent. We will reply as soon as possible."
data-failmsg="Sorry, we could not deliver your message"
novalidate>
<div class="row uniform">
<div class="form-controll 12u$">
<input type="text" class="form-control px-1 {{ form_error('name') ? 'error' }}" placeholder="Name" name="name" id="name" value="{{set_value('name' )}}" data-rule-required="true">
{{ form_error('name') ? form_error('name') }}
</div>
<div class="form-controll 12u$">
<input type="email" class="form-control px-1 {{ form_error('email') ? 'error' }}" placeholder="Email" name="email" id="email" value="{{set_value('email' )}}" data-rule-required="true">
{{ form_error('email') ? form_error('email') }}
</div>
</div>
<div class="row uniform">
<div class="form-controll 12u$">
<input type="text" class="form-control px-1 {{ form_error('subject') ? 'error' }}" placeholder="Subject" name="subject" id="subject" value="{{set_value('subject' )}}" data-rule-required="true">
{{ form_error('subject') ? form_error('subject') }}
</div>
<div class="form-controll 12u$">
<textarea rows="5" class="form-control px-1 {{ form_error('message') ? 'error' }}" placeholder="Message" name="message" id="message" data-rule-required="true">{{set_value('message')}}</textarea>
{{ form_error('message') ? form_error('message') }}
</div>
<div class="12u$">
<button type="submit" class="button special fit" id="sendMessageButton">Send</button>
</div>
</div>
</form>
</div>
</div>
The error and success messages at the top of the above view play a role only if JavaScript is disabled in the browser, otherwise the messages are delivered via jQuery Ajax:
(function($) {
// Add comments via AJAX
$("#ajaxForm").validate({
rules: {
email: {
email: true
}
},
submitHandler: function(form) {
var form = $("#ajaxForm"),
$fields = form.find('input[type="text"],input[type="email"],textarea'),
$succesMsg = form.data('successmsg'),
$failMsg = form.data('failmsg'),
url = form.attr('action'),
data = form.serialize();
$.ajax({
type: "POST",
url: url,
data: data,
success: function() {
$('#msgContainer').text($succesMsg).slideDown(250).delay(2500).slideUp(250);
$fields.val('');
},
error: function() {
$('#msgContainer').removeClass('alert-success').addClass('alert-danger')
.text($failMsg).slideDown(250).delay(2500).slideUp(250);
}
});
}
});
})(jQuery);
The form is validated with the jQuery Validation Plugin.
The script above is designed to "fit" multiple forms as long as they have an attribute id="ajaxForm"
.
Concerns:
- Does the contact form have security weaknesses?
- Is the lack of a model an issue?