Readme to the Module Contact me for Joomla 5
Tags: webdev, joomla, php, module
Published: 2024-01-17 13:59:05

Even though there are already a lot of modules written for Joomla, I have not been able to find a Contact module that is suitable for me.
Most probably - this is only the first version of the module. I plan to improve it to perfection.
You can see the current version of the working module on [my CV site](https://tatsiana-dev.eu/en/#contact), the module code in the [repository](https://github.com/DollarDevTa/sta_contact_module).
File structure + Language files:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qv7x8sej1bwqaesg9ptn.png)
A short description of the file assignments:
- mod_sta_contact.xml - 
File for installation and configuration of the module in joomla
```
<?xml version="1.0" encoding="UTF-8"?>
<extension type="module" client="site" method="upgrade">
	<name>mod_sta_contact</name>
	<author>Joomla! Project</author>
	<creationDate>2024-01</creationDate>
	<copyright>(C) 2024 Open Source Tatsiana, Inc.</copyright>
	<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
	<authorEmail>dollar2901@gmail.com</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>1.0.0</version>
	<description>MOD_STA_CONTACT_XML_DESCRIPTION</description>
	<namespace path="src">Joomla\Module\StaContact</namespace>
	<files>
		<filename module="mod_sta_contact">mod_sta_contact.php</filename>
		<folder>forms</folder>
		<folder>src</folder>
		<folder>tmpl</folder>
	</files>
	<languages>
		<language tag="en-GB">language/en-GB/mod_sta_contact.ini</language>
		<language tag="en-GB">language/en-GB/mod_sta_contact.sys.ini</language>
		<language tag="pl-PL">language/pl-PL/mod_sta_contact.ini</language>
		<language tag="pl-PL">language/pl-PL/mod_sta_contact.sys.ini</language>
	</languages>
	
</extension>
```

- mod_sta_contact.php - Module controller
```
<?php

\defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Helper\AuthenticationHelper;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Module\StaContact\Site\Helper\StaContactHelper;

$data = Factory::getApplication()->input->post->get('jform', [], 'array');

Form::addFormPath(JPATH_SITE . '/modules/mod_sta_contact/forms');

$form = Form::getInstance('mod_sta_contact.sendmessage', 'sendmessage',['control' => 'jform']);

if(isset($data['contact_sta_send_mail'])){
	$staContact = new StaContactHelper();
	$staContact->submit();
}

require ModuleHelper::getLayoutPath('mod_sta_contact');
```

- forms\sendmessage.xml - 
Xml file for configuring form fields
```
<?xml version="1.0" encoding="UTF-8"?>
<form>
	<fieldset name="stacontact" label="MOD_STA_CONTACT_DEFAULT_LABEL">
		<field
			name="contact_name"
			type="text"
			label="MOD_STA_CONTACT_EMAIL_NAME_LABEL"
			id="contact-name"
			size="30"
			filter="string"
			required="true"
			hint="MOD_STA_CONTACT_EMAIL_NAME_LABEL"
		/>

		<field
			name="contact_email"
			type="email"
			label="MOD_STA_CONTACT_EMAIL_LABEL"
			id="contact-email"
			size="30"
			filter="string"
			autocomplete="email"
			required="true"
			hint="MOD_STA_CONTACT_EMAIL_LABEL"
		/>

		<field
			name="contact_subject"
			type="text"
			label="MOD_STA_CONTACT_MESSAGE_SUBJECT_LABEL"
			id="contact-emailmsg"
			size="60"
			filter="string"
			required="true"
			hint="MOD_STA_CONTACT_MESSAGE_SUBJECT_LABEL"
		/>

		<field
			name="contact_message"
			type="textarea"
			label="MOD_STA_CONTACT_ENTER_MESSAGE_LABEL"
			cols="20"
			rows="5"
			id="contact-message"
			filter="safehtml"
			hint="MOD_STA_CONTACT_ENTER_MESSAGE_LABEL"
		/>

		<field
			name="contact_sta_send_mail"
			type="hidden"
			default="1"
		/>
	</fieldset>

	<fieldset name="captcha">
		<field
			name="captcha"
			type="captcha"
			label="MOD_STA_CONTACT_CAPTCHA_LABEL"
			validate="captcha"
			required="true"
			namespace="contact"
		/>
	</fieldset>
	
</form>
```

- tmpl\default.php - 
Main module template. Here for now you need to manually change the **action ** to the one you need. It will be improved in the next versions - **action ** can be customized in the module administration.
```
<?php
defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Factory;

$document  = Factory::getDocument();
$app->getDocument()->getWebAssetManager()
    ->useScript('core')
    ->useScript('keepalive')
    ->useScript('form.validate');
	
// Get the message queue
$messages = Factory::getApplication()->getMessageQueue();
$list_messages = [];
// Build the sorted message list
if (\is_array($messages) && !empty($messages)) {
	foreach ($messages as $msg) {
		if (isset($msg['type']) && isset($msg['message'])) {
			$list_messages[$msg['type']][] = $msg['message'];
		}
	}
}
?>
<form id="sta-contact-form" class="mod-sta-contact needs-validation" novalidate action="<?php echo Route::_('index.php#contact'); ?>" method="post">
	<h1 style="color:#013F4E" class="h3 mb-3 fw-normal">Contact me</h1>
	<?php if (is_array($list_messages) && !empty($list_messages)) {
		echo $list_messages["info"][0];
	}else{ ?>
	<p><?=Text::_('MOD_STA_CONTACT_ADD_MESSAGE_TEXT')?></p>
	
	<?php foreach ($form->getFieldsets() as $fieldset) : ?>
            <?php if ($fieldset->name === 'captcha') : ?>
                <?php continue; ?>
            <?php endif; ?>
            <?php $fields = $form->getFieldset($fieldset->name); ?>
            <?php if (count($fields)) : ?>
                <fieldset class="m-0 text-start">
                    <?php foreach ($fields as $field) : ?>
						<div class="control-group form-floating">
						<?php echo $field->input; ?>
						<?php echo $field->label; ?>
						</div>
                    <?php endforeach; ?>
                </fieldset>
            <?php endif; ?>
        <?php endforeach; ?>
		
    <?php echo $form->renderFieldset('captcha'); ?>
	<?php echo HTMLHelper::_('form.token'); ?>
	<button class="btn btn-primary w-100 py-2" id="contact-send" type="button"><?= Text::_('MOD_STA_CONTACT_SEND'); ?></button>
</form>
<?php 
Factory::getDocument()->addScriptDeclaration('
	window.onload = function(){

  document.getElementById("contact-send").addEventListener("click",function (){
	var form = document.getElementById("sta-contact-form");
	if (!form.checkValidity()) {
          event.preventDefault();
          event.stopPropagation();
		  form.classList.add("was-validated");
        }else{
			document.getElementById("sta-contact-form").submit();
		}
   });
};');
}?>
```
- src\Helper\StaContactHelper.php - 
Helper file with module functions
```
<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_sta_contact
 *
 */
namespace Joomla\Module\StaContact\Site\Helper;

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\String\PunycodeHelper;
use Joomla\CMS\Mail\MailTemplate;
use Joomla\CMS\Uri\Uri;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
 * Helper for mod_sta_contact
 *
 * @since  1.5
 */
class StaContactHelper
{
	public function submit()
    {
        // Check for request forgeries.
        Factory::getApplication()->checkToken();
        $app    = Factory::getApplication();
       
        // Get the data from POST
        $data = $app->input->post->get('jform', [], 'array');
        $msg = '';
        $sent = false;

        $sent = $this->_sendEmail($data);

        // Set the success message if it was a success
        if ($sent) {
            $msg = Text::_('MOD_STA_CONTACT_EMAIL_THANKS');
        }
		$app->enqueueMessage($msg);
		
        return true;
    }
	
	private function _sendEmail($data)
    {
        $app = Factory::getApplication();

        $templateData = [
            'sitename'     => $app->get('sitename'),
            'name'         => $data['contact_name'],
            'contactname'  => 'Contact me form',
            'email'        => PunycodeHelper::emailToPunycode($data['contact_email']),
            'subject'      => $data['contact_subject'],
            'body'         => stripslashes($data['contact_message']),
            'url'          => Uri::base(),
            'customfields' => '',
        ];

        try {
            $mailer = new MailTemplate('com_contact.mail', $app->getLanguage()->getTag());
            $mailer->addRecipient($app->get('mailfrom'));
            $mailer->setReplyTo($templateData['email'], $templateData['name']);
            $mailer->addTemplateData($templateData);
            $sent = $mailer->send();

		} catch (MailDisabledException | phpMailerException $exception) {
            try {
                Log::add(Text::_($exception->getMessage()), Log::WARNING, 'jerror');

                $sent = false;
            } catch (\RuntimeException $exception) {
                $app->enqueueMessage(Text::_($exception->errorMessage()), 'warning');

                $sent = false;
            }
        }
        return $sent;
    }
}
```

You can **install** the module in the standard method:
System -> Install Extensions -> Upload Package File.
In the module settings add a **position** for module output and **published** it:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frq9gaejtlrqx2jn12h3.png)

As a result, a form should appear on the selected position:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7uqr08e3d6o3w7hk1xnq.png)

I planned to add the ability to customize in the Joomla admin: the choice of fields, which to display in the module, adding styles for fields, email to which to send emails, perhaps a few more settings.