Матвей Земсков

Заметки веб-мастера

Четверг, 14 мая 2015 16:13

Joomla 3 форма обратной связи - добавляем возможность прикрепления файла

Оцените материал
(2 голосов)

Недавно один из посетителей моего сайта предложил мне расширить функционал формы обратной связи: добавить возможность прикладывать файлы к сообщению, которое отправляется после заполнения формы. Файлы, отправляемые через форму должны быть графического формата. Таким образом посетитель сможет приложить к своему сообщению какой-нибудь скриншот.

Меня заинтересовало это предложение и немного поразмыслив, я приступил к работе. На самом деле, расширить таким образом компонент Joomla com_contact несложно. Правда есть один «нехороший» момент: если внести изменения в файлы компонента, то обновлять его больше будет невозможно, потому что при обновлении все ваши изменения будут потеряны.

Можно попытаться клонировать компонент. Но так как он встроен в систему, сделать это тоже не так просто — в нем много различных зависимостей, поэтому работающая копия компонента com_contact у меня не получилась. В итоге решение получилось совсем не идеальным, но работающим :).

Уже по завершении работы я «наткнулся» на одну статью на сайте с документацией для Joomla. В ней говориться о том, что для расширения формы обратной связи (и других системных компонентов) нужно создавать плагин. Таким образом вы не изменяете файлы в системном компоненте и не теряете возможность обновлять CMS.

Правда, в статье не указано, как добавить логику (в данном случае проверку и отправку файла вместе с остальными данными) не изменяя файлы компонента.

Сейчас я опишу весь процесс изменения компонента обратной связи, который я проводил для добавления в форму поля типа “file”.

Итак, сначала вносим небольшие изменения в административной части сайта:

► Изменяем языковые файлы.

/administrator/language/ru-RU/ru-RU.com_contact.ini 
Добавляем следующие строки:

COM_CONTACT_FIELD_IMAGES_ATTACH_ALLOW_LABEL="Включить поле для отправки изображений"
COM_CONTACT_FIELD_IMAGES_ATTACH_ALLOW_DESC="Добавить или отключить возможность отправки изображений в форме обратной связи" 

В файл /administrator/language/en-EN/en-EN.com_contact.ini добавляем те же строки, только с их значением будут фразы на английском языке. Таким образом обеспечиваем многоязычность.

► Редактируем файлы: /administrator/components/com_contact/config.xml (секция fieldset name="Contact_Form") и /administrator/components/com_contact/models/form/contact.xml (секция fieldset name="email") добавляем в оба файла следующий код:

XML

<field name="allow_images_attach" 
  type="radio" 
  class="btn-group btn-group-yesno"
  default="1"
  label="COM_CONTACT_FIELD_IMAGES_ATTACH_ALLOW_LABEL"
  description="COM_CONTACT_FIELD_IMAGES_ATTACH_ALLOW_DESC"
  >
    <option value="1">JSHOW</option>
    <option value="0">JHIDE</option>
  </field> 

В результате этих двух действий в административной части сайта на странице компонента Joomla com_contact, появится возможность включать и выключать показ поля для добавления файлов в форме обратной связи.

Напомню читателю, что при изменении параметров контакта в админке, они сохраняются в БД: таблица __contact_details, поле params.

Теперь переходим к изменению файлов компонента в публичной части сайта.

► Теперь в шаблоне компонента com_contact станет доступно значение добавленного параметра allow_images_attach. Перед внесением изменений в код шаблона, его следует скопировать в папку шаблона сайта: /templates/имя_шаблона/html/com_contact/contact/default_form.php

Для проверки можно разместить в указанном файле следующий код.

PHP

	<?php echo $this->params->get('allow_images_attach');?> 

Если ошибок нет, то странице компонента в публичной части сайта выведется цифра «1».

► Далее добавляем описание поля для прикрепления файла (изображения) в xml-файл с описанием полей формы в модели (/components/com_contact/models/forms/contact.xml).

XML

	<field name="contact_attachment" 
	type="file"
	id="contact-attach"
	size="30"
	description="COM_CONTACT_CONTACT_ATTACHMENT_DESC"
	label="COM_CONTACT_CONTACT_ATTACHMENT_LABEL"
	/> 

► В языковые файлы нужно добавить подпись (label) и описание (description) для нового поля (/language/ru-RU/ru-RU.com_contact.ini):

COM_CONTACT_CONTACT_ATTACHMENT_DESC="Прикрепите файл с изображением (скриншот)"
COM_CONTACT_CONTACT_ATTACHMENT_LABEL="Прикрепить изображение"

В файл /language/en-EN/en-EN.com_contact.ini добавляем те же строки, только с английским текстом в качестве значения.

► Добавляем в шаблон формы (/templates/имя_шаблона/html/com_contact/contact/default_form.php) следующий код:

PHP

	<?php if($this->params->get('allow_images_attach')){?>
	<dt><?php echo $this->form->getLabel('contact_attachment');?></dt>
	<dd><?php echo $this->form->getInput('contact_attachment');?></dd>
	<?php }?> 

После добавления этого кода на странице с компонентом обратной связи появляется поле для добавления файла.

Чтобы форма отрабатывала правильно, необходимо добавить в тег <form> следующее выражение:

PHP

enctype="<?php if ($this->params->get('allow_images_attach') == 1) {echo 'multipart/form-data'; }else{ echo 'application/x-www-form-urlencoded';}?>"

Кроме того, добавим скрытое поле, в котором будет хранится максимальный размер прикрепляемого файла:

PHP

	<?php if ($this->params->get('allow_images_attach') == 1):?>
	<input type="hidden" name="MAX_FILE_SIZE" value="10000000" />
	<?php endif;?>

► Теперь можно подумать о валидации добавленного поля. Для начала в блок с описанием поля в файле /components/com_contact/models/forms/contact.xml добавим элемент validate.

XML

validate="contactemailattachment"

Затем нужно создать файлы с кодом (правилами) для проведения валидации. Файл будет называться contactemailattachment.php и располагаться в папке /components/com_contact/models/rules/.

Изначально в системе нет валидации поля формы для прикрепления файлов, поэтому необходимо добавить еще один файл в /libraries/joomla/form/rule/. Назовем его attachment.php

В этом файле создадим класс JFormRuleAttachment, от которого будет наследоваться класс JFormRuleContactEmailAttachment, расположенный в файле /components/com_contact/models/rules/contactemailattachment.php

PHP

	class  JFormRuleAttachment extends JFormRule
	{
		public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
		{
			  // If the field is empty and not required, the field is valid.
			  $required = ((string) $element['required'] == 'true' || (string) $element['required'] == 'required');

			  if (!$required && empty($value))
			  {
				return true;
			  }
		} 
	}

В нем, как мы видим размещен код для проверки полей на пустоту. Кроме того проверяется обязательно ли поле для заполнения или нет.

PHP

	class JFormRuleContactEmailAttachment extends JFormRuleAttachment
	{
		
		protected $arrAllowFileTypes = array('.jpg','.png','.gif','.jpeg');
		
		public function test(SimpleXMLElement $element, $value, $group = null, JRegistry $input = null, JForm $form = null)
		{
		   if (!parent::test($element, $value, $group, $input, $form))
			{
			  return false;
			}
			
			$elName = (string) $element->attributes()->name;
		  
			if($_FILES["jform"]["error"][$elName] == 0){
				$fname = $_FILES["jform"]["name"][$elName];
				$p = (strlen($fname) - strpos($fname,"."))*(-1);
				$fext = substr($fname, $p);
						   
			   if(!in_array($fext, $this->arrAllowFileTypes)){
				   return false; 
				}           
			}
			else{
				return false;
			}
			
			return true;    
		}
	}

В этом, созданном нами классе, мы проверяем значение «нашего» нового добавленного поля. Файл, который пользователь прикладывает к сообщению, должен быть исключительно изображением, плюс проводится проверка на пустоту, в случае, если поле обязательное для заполнения (код из родительского класса).

► После валидации можно переходить непосредственно к отправке сообщения. Для этого добавим необходимый код в метод ContactControllerContact::_sendEmail в контроллере компонента (файл - /components/com_contact/controllers/contact.php).

PHP

	private function _sendEmail($data, $contact, $copy_email_activated)
	 {
	   $app = JFactory::getApplication();

	   if ($contact->email_to == '' && $contact->user_id != 0)
		{
		   $contact_user = JUser::getInstance($contact->user_id);
		   $contact->email_to = $contact_user->get('email');
		}

		$mailfrom = $app->get('mailfrom');
		$fromname = $app->get('fromname');
		$sitename = $app->get('sitename');

		$name = $data['contact_name'];
		$email = JStringPunycode::emailToPunycode($data['contact_email']);
		$subject = $data['contact_subject'];
		$body = $data['contact_message'];
		  
		  
		  /*attach files*/
		$attachment = $_FILES['jform']['tmp_name']['contact_attachment'];
		  $att_name = $_FILES['jform']['name']['contact_attachment'];
		  /*attach files*/     

		// Prepare email body
		$prefix = JText::sprintf('COM_CONTACT_ENQUIRY_TEXT', JUri::base());
		$body	= $prefix . "\n" . $name . ' <' . $email . '>' . "\r\n\r\n" . stripslashes($body);

		$mail = JFactory::getMailer();
		$mail->addRecipient($contact->email_to);
		$mail->addReplyTo(array($email, $name));
		$mail->setSender(array($mailfrom, $fromname));
		$mail->setSubject($sitename . ': ' . $subject);
		/*attach files*/
		$mail->addAttachment($attachment, $att_name);
		/*attach files*/
		  $mail->setBody($body);    
		$sent = $mail->Send();

		// If we are supposed to copy the sender, do so.
		// Check whether email copy function activated
		  if ($copy_email_activated == true && !empty($data['contact_email_copy']))
		   {
			$copytext    = JText::sprintf('COM_CONTACT_COPYTEXT_OF', $contact->name, $sitename);
			$copytext    .= "\r\n\r\n" . $body;
			$copysubject = JText::sprintf('COM_CONTACT_COPYSUBJECT_OF', $subject);

			$mail = JFactory::getMailer();
			$mail->addRecipient($email);
			$mail->addReplyTo(array($email, $name));
			$mail->setSender(array($mailfrom, $fromname));
			$mail->setSubject($copysubject);
			/*attach files*/		
			$mail->addAttachment($attachment, $att_name);
			/*attach files*/            
			   $mail->setBody($copytext);
			 $sent = $mail->Send();
		   }

	   return $sent;
	 }

Код, который был добавлен мной, я разместил между комментариев (/*attach files*/).

Ну вот, собственно, и все изменения.

Теперь, если все сделано правильно, у посетителей вашего сайта, желающих отправить вам сообщение появилась возможность приложить к нему графический файл, а вы можете управлять этой возможностью через админку сайта: в любой момент отключить поле для добавления файла из формы обратной связи Joomla3 или включить его снова.

Прочитано 5719 раз
Добавить комментарий

Комментарии   

 
0 # Кирилл 10.08.2015 17:04
Очень полезная штука. Спасибо!
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 13.08.2015 16:43
Пожалуйста! :)
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Владимир 20.08.2015 16:46
Место нахождения файлов компонента абсолютно отличается joomla 3.4.
К сожалению разобраться не удалось :(
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 25.08.2015 11:00
Владимир, уточните, пожалуйста, о местонахождении каких файлов идет речь? Специально скачал и установил Joomla 3.4, особых отличий не обнаружил. Все файлы на своих местах, как написано в статье
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Роман 08.11.2015 16:29
Чтобы форма отрабатывала правильно, необходимо добавить в тег следующее выражение: - Куда именно в какой файл добавлять это виражение? в файле: /templates/имя_шаблона/html/com_contact/contact/default_form.php
Я его не наблюдаю.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 11.11.2015 14:20
Роман, этот код нужно вставить в тег form в файле - /templates/имя_шаблона/html/com_contact/contact/de fault_form.php
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Роман 08.11.2015 16:39
а если нужно добавить 10-100 файлов а не 1?
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 11.11.2015 14:21
Роман, такая возможность в этом случае не предусмотрена.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Вячеслав 15.03.2016 18:41
Чтобы я без тебя делал. Молодец!
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 16.03.2016 12:26
Спасибо! Очень приятно! :)
Ответить | Ответить с цитатой | Цитировать
 
Мои услуги

Предлагаю следующие услуги:

  • Верстка шаблона сайта из дизайн-макета для CMS «1С-Битрикс Управление сайтом» и CMS “Joomla”
  • Создание форм различной сложности (обратная связь, анкеты и тп) для указанных CMS
  • Настройка и кастомизация компонентов и модулей для указанных CMS
  • Доработка модулей и компонентов для указанных CMS, добавление нестандартного функционала
  • Разработка лендингов (landing-pages)

По все вопросам обращайтесь через форму обратной связи

Скачать

Предлагаю вашему вниманию: