Index: branches/5.1.x/core/units/forms/form_fields/form_field_eh.php
===================================================================
diff -u
--- branches/5.1.x/core/units/forms/form_fields/form_field_eh.php (revision 0)
+++ branches/5.1.x/core/units/forms/form_fields/form_field_eh.php (revision 13390)
@@ -0,0 +1,35 @@
+Application->LoggedIn() && !$this->Application->isAdminUser) {
+ return '%1$s.Visibility = ' . FORM_FIELD_EVERYONE;
+ }
+
+ return '';
+ }
+
+ /**
+ * Shows fields based on user logged-in status
+ *
+ * @param kEvent $event
+ */
+ function SetCustomQuery(&$event)
+ {
+ parent::SetCustomQuery($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBList */
+
+ $visibility_filter = $this->getVisiblilityFilter();
+
+ $object->addFilter('visibility_filter', $visibility_filter);
+ }
+ }
Index: branches/5.1.x/core/admin_templates/img/toolbar/tool_resend.gif
===================================================================
diff -u
Binary files differ
Fisheye: Tag 13390 refers to a dead (removed) revision in file `branches/5.1.x/core/units/forms/forms_tp.php'.
Fisheye: No comparison available. Pass `N' to diff?
Index: branches/5.1.x/core/install/install_schema.sql
===================================================================
diff -u -r13188 -r13390
--- branches/5.1.x/core/install/install_schema.sql (.../install_schema.sql) (revision 13188)
+++ branches/5.1.x/core/install/install_schema.sql (.../install_schema.sql) (revision 13390)
@@ -1064,28 +1064,102 @@
DisplayInGrid tinyint(1) NOT NULL DEFAULT '1',
DefaultValue text,
Validation tinyint(4) NOT NULL DEFAULT '0',
+ Visibility tinyint(4) NOT NULL DEFAULT '1',
+ EmailCommunicationRole tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (FormFieldId),
KEY `Type` (`Type`),
KEY FormId (FormId),
KEY Priority (Priority),
KEY IsSystem (IsSystem),
- KEY DisplayInGrid (DisplayInGrid)
+ KEY DisplayInGrid (DisplayInGrid),
+ KEY Visibility (Visibility),
+ KEY EmailCommunicationRole (EmailCommunicationRole)
);
CREATE TABLE FormSubmissions (
FormSubmissionId int(11) NOT NULL AUTO_INCREMENT,
FormId int(11) NOT NULL DEFAULT '0',
SubmissionTime int(11) DEFAULT NULL,
+ IPAddress varchar(15) NOT NULL DEFAULT '',
+ ReferrerURL varchar(255) NOT NULL DEFAULT '',
+ LogStatus tinyint(3) unsigned NOT NULL DEFAULT '2',
+ LastUpdatedOn int(10) unsigned DEFAULT NULL,
+ Notes text,
PRIMARY KEY (FormSubmissionId),
KEY FormId (FormId),
- KEY SubmissionTime (SubmissionTime)
+ KEY SubmissionTime (SubmissionTime),
+ KEY LogStatus (LogStatus),
+ KEY LastUpdatedOn (LastUpdatedOn)
);
+CREATE TABLE SubmissionLog (
+ SubmissionLogId int(11) NOT NULL AUTO_INCREMENT,
+ FormSubmissionId int(10) unsigned NOT NULL,
+ FromEmail varchar(255) NOT NULL DEFAULT '',
+ ToEmail varchar(255) NOT NULL DEFAULT '',
+ Cc text,
+ Bcc text,
+ `Subject` varchar(255) NOT NULL DEFAULT '',
+ Message text,
+ Attachment text,
+ ReplyStatus tinyint(3) unsigned NOT NULL DEFAULT '0',
+ SentStatus tinyint(3) unsigned NOT NULL DEFAULT '0',
+ SentOn int(10) unsigned DEFAULT NULL,
+ RepliedOn int(10) unsigned DEFAULT NULL,
+ VerifyCode varchar(32) NOT NULL DEFAULT '',
+ DraftId int(10) unsigned NOT NULL DEFAULT '0',
+ MessageId varchar(255) NOT NULL DEFAULT '',
+ BounceInfo text,
+ BounceDate int(11) DEFAULT NULL,
+ PRIMARY KEY (SubmissionLogId),
+ KEY FormSubmissionId (FormSubmissionId),
+ KEY ReplyStatus (ReplyStatus),
+ KEY SentStatus (SentStatus),
+ KEY SentOn (SentOn),
+ KEY RepliedOn (RepliedOn),
+ KEY VerifyCode (VerifyCode),
+ KEY DraftId (DraftId),
+ KEY BounceDate (BounceDate),
+ KEY MessageId (MessageId)
+);
+
+CREATE TABLE Drafts (
+ DraftId int(11) NOT NULL AUTO_INCREMENT,
+ FormSubmissionId int(10) unsigned NOT NULL DEFAULT '0',
+ CreatedOn int(10) unsigned DEFAULT NULL,
+ CreatedById int(11) NOT NULL,
+ Message text,
+ PRIMARY KEY (DraftId),
+ KEY FormSubmissionId (FormSubmissionId),
+ KEY CreatedOn (CreatedOn),
+ KEY CreatedById (CreatedById)
+);
+
CREATE TABLE Forms (
- FormId int(11) NOT NULL auto_increment,
- Title VARCHAR(255) NOT NULL DEFAULT '',
+ FormId int(11) NOT NULL AUTO_INCREMENT,
+ Title varchar(255) NOT NULL DEFAULT '',
Description text,
- PRIMARY KEY (FormId)
+ RequireLogin tinyint(4) NOT NULL DEFAULT '0',
+ UseSecurityImage tinyint(4) NOT NULL DEFAULT '0',
+ EnableEmailCommunication tinyint(4) NOT NULL DEFAULT '0',
+ ReplyFromName varchar(255) NOT NULL DEFAULT '',
+ ReplyFromEmail varchar(255) NOT NULL DEFAULT '',
+ ReplyCc varchar(255) NOT NULL DEFAULT '',
+ ReplyBcc varchar(255) NOT NULL DEFAULT '',
+ ReplyMessageSignature text,
+ ReplyServer varchar(255) NOT NULL DEFAULT '',
+ ReplyPort int(11) NOT NULL DEFAULT '110',
+ ReplyUsername varchar(255) NOT NULL DEFAULT '',
+ ReplyPassword varchar(255) NOT NULL DEFAULT '',
+ BounceEmail varchar(255) NOT NULL DEFAULT '',
+ BounceServer varchar(255) NOT NULL DEFAULT '',
+ BouncePort int(11) NOT NULL DEFAULT '110',
+ BounceUsername varchar(255) NOT NULL DEFAULT '',
+ BouncePassword varchar(255) NOT NULL DEFAULT '',
+ PRIMARY KEY (FormId),
+ KEY UseSecurityImage (UseSecurityImage),
+ KEY RequireLogin (RequireLogin),
+ KEY EnableEmailCommunication (EnableEmailCommunication)
);
CREATE TABLE Semaphores (
Index: branches/5.1.x/core/admin_templates/forms/form_edit_emails.tpl
===================================================================
diff -u
--- branches/5.1.x/core/admin_templates/forms/form_edit_emails.tpl (revision 0)
+++ branches/5.1.x/core/admin_templates/forms/form_edit_emails.tpl (revision 13390)
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/img/toolbar/tool_reply_f2.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/units/forms/drafts/drafts_config.php
===================================================================
diff -u
--- branches/5.1.x/core/units/forms/drafts/drafts_config.php (revision 0)
+++ branches/5.1.x/core/units/forms/drafts/drafts_config.php (revision 13390)
@@ -0,0 +1,48 @@
+ 'draft',
+ 'ItemClass' => Array ('class' => 'kDBItem', 'file' => '', 'build_event' => 'OnItemBuild'),
+ 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'),
+ 'EventHandlerClass' => Array ('class' => 'DraftEventHandler', 'file' => 'draft_eh.php', 'build_event' => 'OnBuild'),
+ 'TagProcessorClass' => Array ('class' => 'kDBTagProcessor', 'file' => '', 'build_event' => 'OnBuild'),
+
+ 'AutoLoad' => true,
+
+ 'QueryString' => Array (
+ 1 => 'id',
+ 2 => 'Page',
+ 3 => 'event',
+ 4 => 'mode',
+ ),
+
+ 'IDField' => 'DraftId',
+
+ 'ParentPrefix' => 'formsubs',
+ 'ForeignKey' => 'FormSubmissionId',
+ 'ParentTableKey' => 'FormSubmissionId',
+ 'AutoDelete' => true,
+ 'AutoClone' => true,
+
+ 'TableName' => TABLE_PREFIX . 'Drafts',
+
+ 'TitleField' => 'DraftId',
+
+ 'ListSQLs' => Array (
+ '' => ' SELECT %1$s.* %2$s FROM %1$s',
+ ),
+
+ 'ListSortings' => Array (
+ '' => Array (
+ 'Sorting' => Array ('DraftId' => 'desc'),
+ )
+ ),
+
+ 'Fields' => Array (
+ 'DraftId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
+ 'FormSubmissionId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
+ 'CreatedOn' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
+ 'CreatedById' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0),
+ 'Message' => Array ('type' => 'string', 'default' => NULL),
+ ),
+ );
\ No newline at end of file
Fisheye: Tag 13390 refers to a dead (removed) revision in file `branches/5.1.x/core/units/forms/forms_config.php'.
Fisheye: No comparison available. Pass `N' to diff?
Index: branches/5.1.x/core/admin_templates/img/toolbar/tool_reply_f3.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/units/forms/forms/forms_eh.php
===================================================================
diff -u -r13168 -r13390
--- branches/5.1.x/core/units/forms/forms/forms_eh.php (.../forms_eh.php) (revision 13168)
+++ branches/5.1.x/core/units/forms/forms/forms_eh.php (.../forms/forms_eh.php) (revision 13390)
@@ -1,6 +1,6 @@
Conn->Query('DESCRIBE '.TABLE_PREFIX.'FormSubmissions', 'Field');
- $cur_fields = array_keys($cur_fields);
+ * Dynamically fills customdata config
+ *
+ * @param kEvent $event
+ */
+ function OnCreateFormFields(&$event)
+ {
+ $cur_fields = $this->Conn->Query('DESCRIBE '.TABLE_PREFIX.'FormSubmissions', 'Field');
+ $cur_fields = array_keys($cur_fields);
- // keep all fields, that are not created on the fly (includes ones, that are added during customizations)
- foreach ($cur_fields as $field_index => $field_name) {
- if (!preg_match('/^fld_[\d]+/', $field_name)) {
- unset($cur_fields[$field_index]);
- }
+ // keep all fields, that are not created on the fly (includes ones, that are added during customizations)
+ foreach ($cur_fields as $field_index => $field_name) {
+ if (!preg_match('/^fld_[\d]+/', $field_name)) {
+ unset($cur_fields[$field_index]);
}
+ }
- $desired_fields = $this->Conn->GetCol('SELECT CONCAT(\'fld_\', FormFieldId) FROM '.TABLE_PREFIX.'FormFields ORDER BY FormFieldId');
+ $desired_fields = $this->Conn->GetCol('SELECT CONCAT(\'fld_\', FormFieldId) FROM '.TABLE_PREFIX.'FormFields ORDER BY FormFieldId');
- $sql = array();
+ $sql = array();
- $fields_to_add = array_diff($desired_fields, $cur_fields);
- foreach ($fields_to_add as $field) {
- $field_expression = $field.' Text NULL';
- $sql[] = 'ADD COLUMN '.$field_expression;
- }
+ $fields_to_add = array_diff($desired_fields, $cur_fields);
+ foreach ($fields_to_add as $field) {
+ $field_expression = $field.' Text NULL';
+ $sql[] = 'ADD COLUMN '.$field_expression;
+ }
- $fields_to_drop = array_diff($cur_fields, $desired_fields);
- foreach ($fields_to_drop as $field) {
- $sql[] = 'DROP COLUMN '.$field;
- }
-
- if ($sql) {
- $query = 'ALTER TABLE '.TABLE_PREFIX.'FormSubmissions '.implode(', ', $sql);
- $this->Conn->Query($query);
- }
+ $fields_to_drop = array_diff($cur_fields, $desired_fields);
+ foreach ($fields_to_drop as $field) {
+ $sql[] = 'DROP COLUMN '.$field;
}
- /*function GetPassedId($event)
- {
- return 0;
+ if ($sql) {
+ $query = 'ALTER TABLE '.TABLE_PREFIX.'FormSubmissions '.implode(', ', $sql);
+ $this->Conn->Query($query);
+ }
}
- function LoadItem(&$event)
- {
- $object =& $event->getObject();
- $object->SetField('Id',0);
- $object->SetId(0);
- }
-*/
/**
* Enter description here...
*
@@ -210,4 +198,310 @@
$event->status = erFAIL;
}
}
+
+ /**
+ * Don't use security image, when form requires login
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemCreate(&$event)
+ {
+ parent::OnBeforeItemCreate($event);
+
+ $this->_validatePopSettings($event);
+ $this->_disableSecurityImage($event);
+ $this->_setRequired($event);
+ }
+
+ /**
+ * Don't use security image, when form requires login
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemUpdate(&$event)
+ {
+ parent::OnBeforeItemUpdate($event);
+
+ $this->_validatePopSettings($event);
+ $this->_disableSecurityImage($event);
+ $this->_setRequired($event);
+ }
+
+ /**
+ * Validates POP3 settings (performs test connect)
+ *
+ * @param kEvent $event
+ */
+ function _validatePopSettings(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $modes = Array ('Reply', 'Bounce');
+ $fields = Array ('Server', 'Port', 'Username', 'Password');
+ $changed_fields = array_keys( $object->GetChangedFields() );
+
+ foreach ($modes as $mode) {
+ $set = true;
+ $changed = false;
+
+ foreach ($fields as $field) {
+ $value = $object->GetDBField($mode . $field);
+
+ if (strlen( trim($value) ) == 0) {
+ $set = false;
+ break;
+ }
+
+ if (!$changed && in_array($mode . $field, $changed_fields)) {
+ $changed = true;
+ }
+ }
+
+ if ($set && $changed) {
+ // fields are set and at least on of them is changed
+ $connection_info = Array ();
+
+ foreach ($fields as $field) {
+ $connection_info[ strtolower($field) ] = $object->GetDBField($mode . $field);
+ }
+
+ $pop3_helper =& $this->Application->makeClass('POP3Helper', $connection_info, 10);
+ /* @var $pop3_helper POP3Helper */
+
+ switch ( $pop3_helper->initMailbox(true) ) {
+ case 'socket':
+ $object->SetError($mode . 'Server', 'connection_failed');
+ break;
+
+ case 'login':
+ $object->SetError($mode . 'Username', 'login_failed');
+ break;
+
+ case 'list':
+ $object->SetError($mode . 'Server', 'message_listing_failed');
+ break;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Makes email communication fields required, when form uses email communication
+ *
+ * @param kEvent $event
+ */
+ function _setRequired(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $required = $object->GetDBField('EnableEmailCommunication');
+ $fields = Array (
+ 'ReplyFromName', 'ReplyFromEmail', 'ReplyServer', 'ReplyPort', 'ReplyUsername', 'ReplyPassword',
+ );
+
+ if ($required && $object->GetDBField('BounceEmail')) {
+ $bounce_fields = Array ('BounceEmail', 'BounceServer', 'BouncePort', 'BounceUsername', 'BouncePassword');
+ $fields = array_merge($fields, $bounce_fields);
+ }
+
+ foreach ($fields as $field) {
+ $object->setRequired($field, $required);
+ }
+ }
+
+ /**
+ * Don't use security image, when form requires login
+ *
+ * @param kEvent $event
+ */
+ function _disableSecurityImage(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ if ($object->GetDBField('RequireLogin')) {
+ $object->SetDBField('UseSecurityImage', 0);
+ }
+ }
+
+ /**
+ * Queries pop3 server about new incoming mail
+ *
+ * @param kEvent $event
+ */
+ function OnProcessReplies(&$event)
+ {
+ $this->_processMailbox($event, false);
+ }
+
+ /**
+ * Queries pop3 server about new incoming mail
+ *
+ * @param kEvent $event
+ */
+ function OnProcessBouncedReplies(&$event)
+ {
+ $this->_processMailbox($event, true);
+ }
+
+ /**
+ * Queries pop3 server about new incoming mail
+ *
+ * @param kEvent $event
+ */
+ function _processMailbox(&$event, $bounce_mode = false)
+ {
+ $this->Application->SetVar('client_mode', 1);
+
+ $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
+
+ $sql = 'SELECT *
+ FROM ' . $table_name . '
+ WHERE EnableEmailCommunication = 1';
+ $forms = $this->Conn->Query($sql, $id_field);
+
+ $mailbox_helper =& $this->Application->recallObject('MailboxHelper');
+ /* @var $mailbox_helper MailboxHelper */
+
+ $field_prefix = $bounce_mode ? 'Bounce' : 'Reply';
+
+ foreach ($forms as $form_id => $form_info) {
+ $recipient_email = $bounce_mode ? $form_info['BounceEmail'] : $form_info['ReplyFromEmail'];
+
+ if (!$recipient_email) {
+ continue;
+ }
+
+ $mailbox_helper->process(
+ Array (
+ 'server' => $form_info[$field_prefix . 'Server'],
+ 'port' => $form_info[$field_prefix . 'Port'],
+ 'username' => $form_info[$field_prefix . 'Username'],
+ 'password' => $form_info[$field_prefix . 'Password']
+ ),
+ Array (&$this, 'isValidRecipient'),
+ Array (&$this, 'processEmail'),
+ Array (
+ 'recipient_email' => $recipient_email,
+ 'bounce_mode' => $bounce_mode,
+ )
+ );
+ }
+ }
+
+ function isValidRecipient($params)
+ {
+ $mailbox_helper =& $this->Application->recallObject('MailboxHelper');
+ /* @var $mailbox_helper MailboxHelper */
+
+ $recipients = $mailbox_helper->getRecipients();
+ $recipient_email = $params['recipient_email'];
+
+ $emails_found = preg_match_all('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $recipients, $all_emails);
+
+ if (is_array($all_emails)) {
+ for ($i = 0; $i < $emails_found; $i++) {
+ if ($all_emails[1][$i] == $recipient_email) {
+ // only read messages, that are addresses to submission reply email
+ return true;
+ }
+ }
+ }
+
+ // If this is a forwarded message - we drop all the other aliases and deliver only to the x-forward to address;
+ if (preg_match('/((' . REGEX_EMAIL_USER . ')(@' . REGEX_EMAIL_DOMAIN . '))/i', $mailbox_helper->headers['x-forward-to'], $get_to_email)) {
+ if ($get_to_email[1] == $recipient_email) {
+ // only read messages, that are addresses to submission reply email
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ function processEmail($params, &$fields_hash)
+ {
+ if ($params['bounce_mode']) {
+ // mark original message as bounced
+
+ $mailbox_helper =& $this->Application->recallObject('MailboxHelper');
+ /* @var $mailbox_helper MailboxHelper */
+
+ if (!array_key_exists('attachments', $mailbox_helper->parsedMessage)) {
+ // for now only parse bounces based on attachments, skip other bounce types
+ return false;
+ }
+
+ for ($i = 0; $i < count($mailbox_helper->parsedMessage['attachments']); $i++) {
+ $attachment =& $mailbox_helper->parsedMessage['attachments'][$i];
+
+ switch ($attachment['headers']['content-type']) {
+ case 'message/delivery-status':
+ // save as BounceInfo
+ $mime_decode_helper =& $this->Application->recallObject('MimeDecodeHelper');
+ /* @var $mime_decode_helper MimeDecodeHelper */
+
+ $charset = $mailbox_helper->parsedMessage[ $fields_hash['MessageType'] ][0]['charset'];
+ $fields_hash['Message'] = $mime_decode_helper->convertEncoding($charset, $attachment['data']);
+ break;
+
+ case 'message/rfc822':
+ // undelivered message
+ $fields_hash['Subject'] = $attachment['filename2'] ? $attachment['filename2'] : $attachment['filename'];
+ break;
+ }
+ }
+ }
+
+ if (!preg_match('/^(.*) #verify(.*)$/', $fields_hash['Subject'], $regs)) {
+ // incorrect subject, no verification code
+ return false;
+ }
+
+ $sql = 'SELECT ' . $this->Application->getUnitOption('submission-log', 'IDField') . '
+ FROM ' . $this->Application->getUnitOption('submission-log', 'TableName') . '
+ WHERE MessageId = ' . $this->Conn->qstr($fields_hash['MessageId']);
+ $found = $this->Conn->GetOne($sql);
+
+ if ($found) {
+ // don't process same message twice
+ return false;
+ }
+
+ $reply_to =& $this->Application->recallObject('submission-log.-reply-to', null, Array ('skip_autoload' => true));
+ /* @var $reply_to kDBItem */
+
+ $reply_to->Load($regs[2], 'VerifyCode');
+ if (!$reply_to->isLoaded()) {
+ // fake verification code OR feedback, containing submission log was deleted
+ return false;
+ }
+
+ if ($params['bounce_mode']) {
+ // mark original message as bounced
+ $reply_to->SetDBField('BounceInfo', $fields_hash['Message']);
+ $reply_to->SetDBField('BounceDate_date', TIMENOW);
+ $reply_to->SetDBField('BounceDate_time', TIMENOW);
+ $reply_to->SetDBField('SentStatus', SUBMISSION_LOG_BOUNCE);
+ $reply_to->Update();
+
+ return true;
+ }
+
+ $reply =& $this->Application->recallObject('submission-log.-reply', null, Array ('skip_autoload' => true));
+ /* @var $reply kDBItem */
+
+ $reply->SetDBFieldsFromHash($fields_hash);
+ $reply->SetDBField('ReplyTo', $reply_to->GetID());
+ $reply->SetDBField('FormSubmissionId', $reply_to->GetDBField('FormSubmissionId'));
+ $reply->SetDBField('ToEmail', $params['recipient_email']);
+ $reply->SetDBField('Subject', $regs[1]); // save subject without verification code
+ $reply->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
+
+ return $reply->Create();
+ }
}
\ No newline at end of file
Index: branches/5.1.x/core/units/forms/submission_log/submission_log_eh.php
===================================================================
diff -u
--- branches/5.1.x/core/units/forms/submission_log/submission_log_eh.php (revision 0)
+++ branches/5.1.x/core/units/forms/submission_log/submission_log_eh.php (revision 13390)
@@ -0,0 +1,677 @@
+ Array ('subitem' => 'add|edit'),
+ 'OnSaveDraft' => Array ('subitem' => 'add|edit'),
+ 'OnUseDraft' => Array ('subitem' => 'add|edit'),
+ 'OnDeleteDraft' => Array ('subitem' => 'add|edit'),
+
+ 'OnProcessBounceMail' => Array ('subitem' => true),
+ );
+
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ /**
+ * Checks event permissions
+ *
+ * @param kEvent $event
+ * @return bool
+ */
+ function CheckPermission(&$event)
+ {
+ $section = $event->getSection();
+ $form_id = $this->Application->GetVar('form_id');
+
+ if ($form_id) {
+ // copy form_id to env to be passed info upload links
+ $this->Application->SetVar($event->getPrefixSpecial() . '_form_id', $form_id);
+ }
+ else {
+ $form_id = $this->Application->GetVar($event->getPrefixSpecial() . '_form_id');
+ }
+
+ $event->setEventParam('PermSection', $section . ':' . $form_id);
+
+ return parent::CheckPermission($event);
+ }
+
+ /**
+ * Prepares new kDBItem object
+ *
+ * @param kEvent $event
+ * @access protected
+ */
+ function OnNew(&$event)
+ {
+ parent::OnNew($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $form_submission =& $this->Application->recallObject('formsubs');
+ /* @var $form_submission kDBItem */
+
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $form =& $form_submission_helper->getForm($form_submission);
+
+ $from_email = $form->GetDBField('ReplyFromEmail');
+ $to_email = $form_submission_helper->getFieldByRole($form_submission, EMAIL_COMMUNICATION_ROLE_EMAIL);
+
+ if ($this->Application->GetVar('client_mode')) {
+ // debug code for sending email from client
+ $object->SetDBField('FromEmail', $to_email);
+ $object->SetDBField('ToEmail', $from_email);
+
+ }
+ else {
+ $object->SetDBField('FromEmail', $from_email);
+ $object->SetDBField('ToEmail', $to_email);
+ }
+
+ $object->SetDBField('Cc', $form->GetDBField('ReplyCc'));
+ $object->SetDBField('Bcc', $form->GetDBField('ReplyBcc'));
+
+ $ids = $this->StoreSelectedIDs($event);
+ if ($ids) {
+ $org_message =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
+ /* @var $org_message kDBItem */
+
+ $org_message->Load( array_shift($ids) );
+ // client could reply from different email, so compare to admin email!
+ if ($org_message->GetDBField('ToEmail') == $from_email) {
+ // can reply only to client email, not own :)
+
+ // transform subject
+ $message_subject = $org_message->GetDBField('Subject');
+
+ if ($message_subject) {
+ $object->SetDBField('Subject', $this->_transformSubject($message_subject, 'Re'));
+ }
+
+ // add signature
+ $message_body = $form->GetDBField('ReplyMessageSignature');
+
+ if ($org_message->GetDBField('Message')) {
+ // add replied marks
+ $message_body .= '> ' . preg_replace('/([\r]*\n)/', '\\1> ', $org_message->GetDBField('Message'));
+ }
+
+ $object->SetDBField('ToEmail', $org_message->GetDBField('FromEmail')); // user client's email from reply
+ $object->SetDBField('Message', $message_body);
+ $object->SetDBField('ReplyTo', $org_message->GetID());
+ }
+ }
+ else {
+ $sql = 'SELECT COUNT(*)
+ FROM ' . $object->TableName . '
+ WHERE FormSubmissionId = ' . $form_submission->GetID();
+ $replies_found = $this->Conn->GetOne($sql);
+
+ if (!$replies_found) {
+ // 1st message from admin -> quote subject & text from feedback
+ $message_subject = $form_submission_helper->getFieldByRole($form_submission, EMAIL_COMMUNICATION_ROLE_SUBJECT);
+
+ if ($message_subject) {
+ $object->SetDBField('Subject', $this->_transformSubject($message_subject, 'Re'));
+ }
+
+ // add signature
+ $message_body = $form->GetDBField('ReplyMessageSignature');
+
+ // add replied marks
+ $original_message_body = $form_submission_helper->getFieldByRole($form_submission, EMAIL_COMMUNICATION_ROLE_BODY);
+
+ if ($original_message_body) {
+ $message_body .= '> ' . preg_replace('/([\r]*\n)/', '\\1> ', $original_message_body);
+ }
+
+ $object->SetDBField('Message', $message_body);
+ }
+ }
+
+ $this->clearSelectedIDs($event);
+ }
+
+ /**
+ * Parses $search string in subject and reformats it
+ * Used for replying and forwarding
+ *
+ * @param string $subject
+ * @param string $search
+ * @return string
+ */
+ function _transformSubject($subject, $search = 'Re')
+ {
+ $regex = '/'.$search.'(\[([\d]+)\]){0,1}:/i';
+ preg_match_all($regex, $subject, $regs);
+
+ if ($regs[2]) {
+ $reply_count = 0; // reply count without numbers (equals to "re[1]")
+ $max_reply_number = 0; // maximal reply number
+ sort($regs[2], SORT_NUMERIC); // sort ascending (non-numeric replies first)
+ foreach ($regs[2] as $match) {
+ if (!$match) {
+ // found "re:"
+ $reply_count++;
+ }
+ elseif ($match > $max_reply) {
+ // found "re:[number]"
+ $max_reply_number = $match;
+ }
+ }
+
+ return $search.'['.($reply_count + $max_reply_number + 1).']: '.trim(preg_replace($regex, '', $subject));
+ }
+
+ return $search.': '.$subject;
+ }
+
+ /**
+ * Resends reply, that was not sent last time
+ *
+ * @param kEvent $event
+ */
+ function OnResendReply(&$event)
+ {
+ $ids = $this->StoreSelectedIDs($event);
+
+ if (!$ids) {
+ return ;
+ }
+
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $sql = 'SELECT f.ReplyFromEmail, sl.' . $object->IDField . '
+ FROM ' . $object->TableName . ' sl
+ JOIN ' . $this->Application->getUnitOption('formsubs', 'TableName') . ' fs ON fs.FormSubmissionId = sl.FormSubmissionId
+ JOIN ' . $this->Application->getUnitOption('form', 'TableName') . ' f ON f.FormId = fs.FormId
+ WHERE sl.' . $object->IDField . ' IN (' . implode(',', $ids) . ')';
+ $reply_emails = $this->Conn->GetCol($sql, $object->IDField);
+
+ foreach ($ids as $id) {
+ $object->Load($id);
+
+ // allow to send messages, that were successfully sended before :(
+ if (($object->GetDBField('ToEmail') != $reply_emails[$id]) && ($object->GetDBField('SentStatus') != SUBMISSION_LOG_SENT)) {
+ $object->SetOriginalField('SentStatus', 0); // reset sent status to update sent date automatically
+
+ $this->_sendEmail($object); // resend email here
+ }
+ }
+
+ $this->clearSelectedIDs($event);
+
+ if (!$this->Application->GetVar('from_list')) {
+ $event->SetRedirectParam('opener', 'u');
+ }
+ }
+
+ /**
+ * Updates last operation dates for log record
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemCreate(&$event)
+ {
+ parent::OnBeforeItemCreate($event);
+
+ $this->_validateRecipients($event);
+ $this->_updateStatusDates($event);
+ }
+
+ /**
+ * Updates last operation dates for log record
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemUpdate(&$event)
+ {
+ parent::OnBeforeItemUpdate($event);
+
+ $this->_validateRecipients($event);
+ $this->_updateStatusDates($event);
+ }
+
+ /**
+ * Validates email recipients
+ *
+ * @param kEvent $event
+ */
+ function _validateRecipients(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $esender =& $this->Application->recallObject('EmailSender');
+ /* @var $esender kEmailSendingHelper */
+
+ $cc = $object->GetDBField('Cc');
+
+ if ($cc && ($esender->GetRecipients($cc) === false)) {
+ $object->SetError('Cc', 'invalid_format');
+ }
+
+ $bcc = $object->GetDBField('Bcc');
+
+ if ($bcc && ($esender->GetRecipients($bcc) === false)) {
+ $object->SetError('Bcc', 'invalid_format');
+ }
+ }
+
+ /**
+ * Generates verification code and sets it inside sent message
+ *
+ * @param kDBItem $object
+ * @return string
+ */
+ function _generateVerificationCode(&$object)
+ {
+ $code = Array (
+ $object->GetDBField('FromEmail'),
+ $object->GetDBField('ToEmail'),
+ $object->GetID(),
+ getmicrotime()
+ );
+
+ $object->SetDBField('VerifyCode', md5( implode('-', $code) ));
+ }
+
+ /**
+ * Sends email based on fields from given submission-log record
+ *
+ * @param kDBItem $object
+ */
+ function _sendEmail(&$object)
+ {
+ if ($this->Application->GetVar('client_mode')) {
+ return ;
+ }
+
+ if (!$object->GetDBField('VerifyCode')) {
+ $this->_generateVerificationCode($object);
+ }
+
+ $form_submission =& $this->_getFormSubmission($object);
+
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $form =& $form_submission_helper->getForm($form_submission);
+
+ $send_params = Array (
+ 'from_name' => $form->GetDBField('ReplyFromName'),
+ 'from_email' => $object->GetDBField('FromEmail'),
+
+ 'to_email' => $object->GetDBField('ToEmail'),
+
+ 'subject' => $object->GetDBField('Subject'),
+ 'message' => $object->GetDBField('Message'),
+ );
+
+ $to_name = $form_submission_helper->getFieldByRole($form_submission, EMAIL_COMMUNICATION_ROLE_NAME);
+
+ if ($to_name) {
+ $send_params['to_name'] = $to_name;
+ }
+
+ $esender =& $this->Application->recallObject('EmailSender');
+ /* @var $esender kEmailSendingHelper */
+
+ $esender->SetReturnPath( $form->GetDBField('BounceEmail') );
+
+ if ($object->GetDBField('Cc')) {
+ $recipients = $esender->GetRecipients( $object->GetDBField('Cc') );
+
+ foreach ($recipients as $recipient_info) {
+ $esender->AddCc($recipient_info['Email'], $recipient_info['Name']);
+ }
+ }
+
+ if ($object->GetDBField('Bcc')) {
+ $recipients = $esender->GetRecipients( $object->GetDBField('Bcc') );
+
+ foreach ($recipients as $recipient_info) {
+ $esender->AddBcc($recipient_info['Email'], $recipient_info['Name']);
+ }
+ }
+
+ if ($object->GetDBField('Attachment')) {
+ $attachments = explode('|', $object->GetField('Attachment', 'file_paths'));
+
+ foreach ($attachments as $attachment) {
+ $esender->AddAttachment($attachment);
+ }
+ }
+
+ $this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.TO.USER', null, $send_params);
+
+ // mark as sent after sending is finished
+ $object->SetDBField('SentStatus', SUBMISSION_LOG_SENT);
+
+ // reset bounce status before (re-)sending
+ $object->SetDBField('BounceInfo', NULL);
+ $object->SetDBField('BounceDate_date', NULL);
+ $object->SetDBField('BounceDate_time', NULL);
+
+ if ($object->GetDBField('DraftId')) {
+ $temp_handler =& $this->Application->recallObject('draft_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems('draft', '', Array ($object->GetDBField('DraftId')));
+ $object->SetDBField('DraftId', 0);
+ }
+
+ $object->Update();
+ }
+
+ /**
+ * Sends new email after log record was created
+ * Updates last update time for submission
+ *
+ * @param kEvent $event
+ */
+ function OnAfterItemCreate(&$event)
+ {
+ parent::OnAfterItemCreate($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $this->_sendEmail($object); // send email
+
+ $this->_updateSubmission($event);
+
+ $reply_to = $object->GetDBField('ReplyTo');
+ if (!$reply_to) {
+ $reply_to = $this->_getLastMessageId($event, !$this->Application->GetVar('client_mode'));
+ }
+
+ if ($reply_to) {
+ // this is reply to other message -> mark it as replied
+ $org_message =& $this->Application->recallObject($event->Prefix . '.-item', null, Array ('skip_autoload' => true));
+ /* @var $org_message kDBItem */
+
+ $org_message->Load($reply_to);
+ $org_message->SetDBField('ReplyStatus', SUBMISSION_LOG_REPLIED);
+ $org_message->Update();
+ }
+
+ if ($this->Application->GetVar('client_mode')) {
+ // new reply from client received -> send notification about it
+ $this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.FROM.USER');
+ }
+ }
+
+ /**
+ * Returns last message id (client OR admin)
+ *
+ * @param kEvent $event
+ * @param bool $from_client
+ * @return int
+ */
+ function _getLastMessageId(&$event, $from_client = false)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $form_submission =& $this->_getFormSubmission($object);
+
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $form =& $form_submission_helper->getForm($form_submission);
+ $reply_email = $form->GetDBField('ReplyFromEmail');
+
+ $sql = 'SELECT MAX(' . $object->IDField . ')
+ FROM ' . $object->TableName . '
+ WHERE (FormSubmissionId = ' . $form_submission->GetID() . ') AND (ToEmail' . ($from_client ? ' = ' : ' <> ') . $this->Conn->qstr($reply_email) . ')';
+ return $this->Conn->GetOne($sql);
+ }
+
+ /**
+ * Updates last update time for submission
+ *
+ * @param kEvent $event
+ */
+ function OnAfterItemUpdate(&$event)
+ {
+ parent::OnAfterItemUpdate($event);
+
+ $this->_updateSubmission($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ // send out email event to admin for bouncing
+ if ( $object->GetOriginalField('SentStatus') != $object->GetDBField('SentStatus')
+ && $object->GetDBField('SentStatus') == SUBMISSION_LOG_BOUNCE ) {
+
+ $this->Application->EmailEventAdmin('FORM.SUBMISSION.REPLY.FROM.USER.BOUNCED');
+ }
+ }
+
+ /**
+ * Sets last sent/reply dates based on field changes in log record
+ *
+ * @param kEvent $event
+ */
+ function _updateStatusDates(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $now = adodb_mktime();
+
+ $sent_status = $object->GetDBField('SentStatus');
+ if (($sent_status == SUBMISSION_LOG_SENT) && ($sent_status != $object->GetOriginalField('SentStatus'))) {
+ // sent status was set
+ $object->SetDBField('SentOn_date', $now);
+ $object->SetDBField('SentOn_time', $now);
+ }
+
+ $reply_status = $object->GetDBField('ReplyStatus');
+ if (($reply_status == SUBMISSION_LOG_REPLIED) && ($reply_status != $object->GetOriginalField('ReplyStatus'))) {
+ // sent status was set
+ $object->SetDBField('RepliedOn_date', $now);
+ $object->SetDBField('RepliedOn_time', $now);
+ }
+ }
+
+ /**
+ * Returns form submission by given event of submission log
+ *
+ * @param kDBItem $object
+ * @return kDBItem
+ */
+ function &_getFormSubmission(&$object)
+ {
+ $submission_id = $object->GetDBField('FormSubmissionId');
+
+ $form_submission =& $this->Application->recallObject('formsubs.-item', null, Array ('skip_autoload' => true));
+ /* @var $form_submission kDBItem */
+
+ if ($form_submission->isLoaded() && ($form_submission->GetID() == $submission_id)) {
+ // already loaded AND has needed id
+ return $form_submission;
+ }
+
+ $form_submission->Load($submission_id);
+
+ return $form_submission;
+ }
+
+ /**
+ * Sets last updated field for form submission
+ *
+ * @param kEvent $event
+ */
+ function _updateSubmission(&$event)
+ {
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $form_submission =& $this->_getFormSubmission($object);
+
+ // 1. set last updated
+ $last_updated = max ($object->GetDBField('SentOn'), $object->GetDBField('RepliedOn'));
+
+ if ($form_submission->GetDBField('LastUpdatedOn') < $last_updated) {
+ // don't set smaller last update, that currenly set
+ $form_submission->SetDBField('LastUpdatedOn_date', $last_updated);
+ $form_submission->SetDBField('LastUpdatedOn_time', $last_updated);
+ }
+
+ // 2. update submission status
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $form =& $form_submission_helper->getForm($form_submission);
+ $client_responce = $form->GetDBField('ReplyFromEmail') == $object->GetDBField('ToEmail');
+ $replied = $object->GetDBField('ReplyStatus') == SUBMISSION_LOG_REPLIED;
+
+ if (!$client_responce && !$replied) {
+ // admin sends new email to client
+ $form_submission->SetDBField('LogStatus', SUBMISSION_REPLIED);
+ }
+ elseif ($client_responce) {
+ // client email becomes replied OR receiving new unreplied email from client
+ $form_submission->SetDBField('LogStatus', $replied ? SUBMISSION_REPLIED : SUBMISSION_NEW_EMAIL);
+ }
+
+ if ($object->GetDBField('SentStatus') == SUBMISSION_LOG_BOUNCE) {
+ // propagate bounce status from reply
+ $form_submission->SetDBField('LogStatus', SUBMISSION_BOUNCE);
+ }
+
+ $form_submission->Update();
+ }
+
+ /**
+ * Saves current unsent message as draft
+ *
+ * @param kEvent $event
+ */
+ function OnSaveDraft(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
+ /* @var $draft kDBItem */
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info) {
+ foreach ($items_info as $id => $field_values) {
+ $object->setID($id);
+ $object->SetFieldsFromHash($field_values);
+
+ $load_keys = Array (
+ 'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
+ 'CreatedById' => $this->Application->RecallVar('user_id'),
+ );
+
+ // get existing draft for given submission and user
+ $draft->Load($load_keys);
+
+ $draft->SetDBField('Message', $object->GetDBField('Message'));
+
+ if ($draft->isLoaded()) {
+ $draft->Update();
+ }
+ else {
+ $draft->SetDBFieldsFromHash($load_keys);
+ $draft->Create();
+ }
+ }
+ }
+
+ $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
+ $event->SetRedirectParam('opener', 'u');
+ }
+
+ /**
+ * Uses found draft instead of submission reply body
+ *
+ * @param kEvent $event
+ */
+ function OnUseDraft(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
+ /* @var $draft kDBItem */
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info) {
+ foreach ($items_info as $id => $field_values) {
+ $object->setID($id);
+ $object->SetFieldsFromHash($field_values);
+
+ $load_keys = Array (
+ 'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
+ 'CreatedById' => $this->Application->RecallVar('user_id'),
+ );
+
+ // get existing draft for given submission and user
+ $draft->Load($load_keys);
+ if ($draft->isLoaded()) {
+ $object->SetDBField('Message', $draft->GetDBField('Message'));
+ $object->SetDBField('DraftId', $draft->GetID());
+ }
+ }
+ }
+
+ $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
+ $event->redirect = false;
+ }
+
+ /**
+ * Deletes draft, that matches given user and form submission
+ *
+ * @param kEvent $event
+ */
+ function OnDeleteDraft(&$event)
+ {
+ $object =& $event->getObject( Array('skip_autoload' => true) );
+ /* @var $object kDBItem */
+
+ $draft =& $this->Application->recallObject('draft', null, Array('skip_autoload' => true));
+ /* @var $draft kDBItem */
+
+ $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
+ if ($items_info) {
+ foreach ($items_info as $id => $field_values) {
+ $object->setID($id);
+ $object->SetFieldsFromHash($field_values);
+ $object->SetDBField('DraftId', 0);
+
+ $load_keys = Array (
+ 'FormSubmissionId' => $object->GetDBField('FormSubmissionId'),
+ 'CreatedById' => $this->Application->RecallVar('user_id'),
+ );
+
+ // get existing draft for given submission and user
+ $draft->Load($load_keys);
+ if ($draft->isLoaded()) {
+ $temp_handler =& $this->Application->recallObject('draft_TempHandler', 'kTempTablesHandler');
+ /* @var $temp_handler kTempTablesHandler */
+
+ $temp_handler->DeleteItems('draft', '', Array ($draft->GetID()));
+ }
+ }
+ }
+
+ $this->Application->SetVar($event->getPrefixSpecial() . '_SaveEvent', 'OnCreate');
+ $event->redirect = false;
+ }
+ }
\ No newline at end of file
Index: branches/5.1.x/core/install/english.lang
===================================================================
diff -u -r13140 -r13390
--- branches/5.1.x/core/install/english.lang (.../english.lang) (revision 13140)
+++ branches/5.1.x/core/install/english.lang (.../english.lang) (revision 13390)
@@ -20,6 +20,7 @@
Q2hhbmdl
Q29udGVudCBNb2Rl
RGVsZXRl
+ RGVsZXRl
RGVzaWduIE1vZGU=
RG93bg==
RWRpdA==
@@ -33,6 +34,7 @@
U2VjdGlvbiBQcm9wZXJ0aWVz
U2VjdGlvbiBUZW1wbGF0ZQ==
VXA=
+ VXNl
Q2FuY2Vs
U2VjdGlvbg==
TnVtYmVyIG9mIGRheXMgZm9yIGEgY2F0LiB0byBiZSBORVc=
@@ -61,10 +63,12 @@
RHVyYXRpb24=
RWZmZWN0aXZl
RW1haWw=
+ RS1tYWlsIENvbW11bmljYXRpb24gUm9sZQ==
UXVldWU=
U2VudA==
VG90YWw=
RW5hYmxlZA==
+ RW5hYmxlIEUtbWFpbCBDb21tdW5pY2F0aW9u
RW5kIERhdGU=
Jm5ic3A7
RXZlbnQ=
@@ -75,6 +79,7 @@
RmlsZW5hbWU=
UGF0aA==
Rmlyc3QgTmFtZQ==
+ RnJvbSBFLW1haWw=
RnJvbSAvIFRvIFVzZXI=
RnJvbnQtRW5kIE9ubHk=
QWxsb3cgUmVnaXN0cmF0aW9u
@@ -106,6 +111,7 @@
TGFzdCBSdW4gT24=
TGFzdCBSdW4gU3RhdHVz
TGFzdCBBdHRlbXB0
+ TGFzdCBVcGRhdGVkIE9u
TGluayBVUkw=
TmFtZQ==
TG9jYXRpb24=
@@ -114,6 +120,7 @@
TWFzdGVyIElE
TWFzdGVyIFByZWZpeA==
TWVtYmVyc2hpcCBFeHBpcmVz
+ TWVzc2FnZQ==
TWVzc2FnZSBIZWFkZXJz
SFRNTA==
UGxhaW4gVGV4dA==
@@ -145,7 +152,11 @@
UmF0aW5n
UmVjaXBpZW50IFR5cGU=
UmVmZXJlcg==
+ UmVmZXJyZXIgVVJM
UmVsYXRpb24gVHlwZQ==
+ UmVwbGllZCBPbg==
+ UmVwbGllZA==
+ UmVxdWlyZSBMb2dpbg==
UmVzZXQgdG8gZGVmYXVsdA==
Q29tbWVudHM=
Q3JlYXRlZCBieQ==
@@ -156,6 +167,8 @@
U2VhcmNoIFRlcm0=
U2VsZWN0b3I=
QXR0ZW1wdHMg
+ U2VudCBPbg==
+ U2VudA==
U2Vzc2lvbiBFbmQ=
U2Vzc2lvbiBMb2cgSUQ=
U2Vzc2lvbiBTdGFydA==
@@ -173,13 +186,16 @@
VGhlc2F1cnVzIFRlcm0=
VGhlc2F1cnVzIFR5cGU=
VGl0bGU=
+ VG8gRS1tYWls
VmFsdWU=
VHlwZQ==
VXNlcnM=
TGFzdG5hbWUgRmlyc3RuYW1l
VXNlcm5hbWU=
+ VXNlIFNlY3VyaXR5IEltYWdl
RmllbGQgVmFsdWU=
VmVyc2lvbg==
+ VmlzaWJpbGl0eQ==
VmlzaWJsZQ==
VmlzaXQgRGF0ZQ==
QXNjZW5kaW5n
@@ -504,6 +520,7 @@
RG93bmxvYWQgQ1NW
RG93bmxvYWQgRXhwb3J0IEZpbGU=
RG93bmxvYWQgTGFuZ3VhZ2UgRXhwb3J0
+ RHJhZnQgQXZhaWxhYmxl
Q29udGVudCBFZGl0b3I=
WW91IGhhdmUgbm90IHNhdmVkIGNoYW5nZXMgdG8gdGhlIGl0ZW0geW91IGFyZSBlZGl0aW5nITxiciAvPkNsaWNrIE9LIHRvIGxvb3NlIGNoYW5nZXMgYW5kIGdvIHRvIHRoZSBzZWxlY3RlZCBzZWN0aW9uPGJyIC8+b3IgQ2FuY2VsIHRvIHN0YXkgaW4gdGhlIGN1cnJlbnQgc2VjdGlvbi4=
RGVmYXVsdCB0ZXh0
@@ -512,11 +529,13 @@
RmlsZSBpcyBlbXB0eQ==
RW5hYmxlZA==
Q2FuJ3Qgc2F2ZSBhIGZpbGU=
+ Q29ubmVjdGlvbiBGYWlsZWQ=
RXJyb3IgY29weWluZyBzdWJzZWN0aW9ucw==
Q3VzdG9tIGZpZWxkIHdpdGggaWRlbnRpY2FsIG5hbWUgYWxyZWFkeSBleGlzdHM=
RmlsZSBpcyB0b28gbGFyZ2U=
SW52YWxpZCBGaWxlIEZvcm1hdA==
aW52YWxpZCBvcHRpb24=
+ TG9naW4gRmFpbGVk
RXJyb3IgbW92aW5nIHN1YnNlY3Rpb24=
Q2FuJ3QgaW5oZXJpdCB0ZW1wbGF0ZSBmcm9tIHRvcCBjYXRlZ29yeQ==
UGFzc3dvcmRzIGRvIG5vdCBtYXRjaCE=
@@ -570,17 +589,22 @@
QmFja2dyb3VuZCBJbWFnZQ==
QmFja2dyb3VuZCBQb3NpdGlvbg==
QmFja2dyb3VuZCBSZXBlYXQ=
+ QmNj
RWxlbWVudCBQb3NpdGlvbg==
Qm9yZGVyIEJvdHRvbQ==
Qm9yZGVyIExlZnQ=
Qm9yZGVyIFJpZ2h0
Qm9yZGVycw==
Qm9yZGVyIFRvcA==
+ Qm91bmNlIERhdGU=
+ Qm91bmNlIEVtYWls
+ Qm91bmNlIEluZm8=
U2VjdGlvbg==
U2VjdGlvbiBGb3JtYXQ=
U2VjdGlvbiBJRA==
U2VjdGlvbiBzZXBhcmF0b3I=
U2VjdGlvbiBUZW1wbGF0ZQ==
+ Q2M=
Q2hhbmdlcw==
Q2hhcnNldA==
Q2hlY2sgRHVwbGljYXRlcyBieQ==
@@ -607,9 +631,11 @@
RWRpdG9ycyBQaWNr
RWxhcHNlZCBUaW1l
RS1tYWls
+ RS1tYWlsIENvbW11bmljYXRpb24gUm9sZQ==
RW1haWxzIGluIFF1ZXVl
RW1haWxzIFNlbnQ=
RW1haWxzIFRvdGFs
+ RW5hYmxl
RW5hYmxlZA==
RXJyb3IgVGFn
RXN0aW1hdGVkIFRpbWU=
@@ -647,6 +673,7 @@
T25saW5lIEZvcm0=
T25saW5lIEZvcm0gU3VibWl0dGVkIFRlbXBsYXRl
U2hvcnQgVVJM
+ RnJvbSBFbWFpbA==
RnJvbSAvIFRvIFVzZXI=
RnJvbnQtRW5kIE9ubHk=
QWxsb3cgUmVnaXN0cmF0aW9uIG9uIEZyb250LWVuZA==
@@ -668,6 +695,7 @@
SW5wdXQgVGltZSBGb3JtYXQ=
SW5zdGFsbCBNb2R1bGVz
SW5zdGFsbCBQaHJhc2UgVHlwZXM=
+ SVAgQWRkcmVzcw==
VXNlIGN1cnJlbnQgc2VjdGlvbiBhcyByb290IGZvciB0aGUgZXhwb3J0
UHJpbWFyeQ==
UmVxdWlyZWQ=
@@ -682,6 +710,7 @@
TGFzdCBOYW1l
TGFzdCBSdW4gT24=
TGFzdCBSdW4gU3RhdHVz
+ TGFzdCBVcGRhdGVkIE9u
TGVmdA==
TGluZSBlbmRpbmdz
TGluZSBFbmRpbmdzIEluc2lkZSBGaWVsZHM=
@@ -702,6 +731,7 @@
TWF4aW11bSBudW1iZXIgb2YgU2VjdGlvbnMgb24gSXRlbSBjYW4gYmUgYWRkZWQgdG8=
Q3VzdG9tIE1lbnUgSWNvbiAoaWUuIGltZy9tZW51X3Byb2R1Y3RzLmdpZik=
TWVudSBTdGF0dXM=
+ TWVzc2FnZQ==
TWVzc2FnZSBCb2R5
UGxhaW4gVGV4dCBWZXJzaW9u
TWVzc2FnZSBUeXBl
@@ -715,6 +745,7 @@
TmFtZQ==
TmV3
TmV4dCBSdW4gT24=
+ Tm90ZXM=
T2NjdXJlZCBPbg==
T3B0aW9ucw==
T3B0aW9uIFRpdGxl
@@ -735,6 +766,7 @@
UGhyYXNlIFR5cGU=
UG9w
UG9wdWxhcg==
+ UG9ydA==
UG9zaXRpb24=
UHJlZml4
UHJpbWFyeQ==
@@ -743,11 +775,19 @@
UHJpbWFyeSBMYW5ndWFnZSBQaHJhc2U=
T3JkZXI=
UmF0aW5n
+ UmVmZXJyZXIgVVJM
S2V5d29yZA==
VHlwZQ==
UmVtb3RlIFVSTA==
UmVwbGFjZSBEdXBsaWNhdGVz
UmVwbGFjZW1lbnQgVGFncw==
+ UmVwbGllZCBPbg==
+ UmVwbHkgQmNj
+ UmVwbHkgQ2M=
+ UmVwbHkgRnJvbSBFLW1haWw=
+ UmVwbHkgRnJvbSBOYW1l
+ UmVwbHkgTWVzc2FnZSBTaWduYXR1cmU=
+ UmVwbGllZA==
UmVxdWlyZWQ=
Q29tbWVudA==
UnVsZSBUeXBl
@@ -760,6 +800,9 @@
U3R5bGU=
U2VsZWN0b3IgSUQ=
U2VsZWN0b3IgTmFtZQ==
+ U2VudCBPbg==
+ U2VudA==
+ U2VydmVy
U2Vzc2lvbiBMb2cgSUQ=
U2ltcGxlIFNlYXJjaA==
TmFtZQ==
@@ -786,6 +829,7 @@
VGltZSBGb3JtYXQ=
VGl0bGU=
VG8=
+ VG8gRS1tYWls
VG9w
VHJhY2tpbmcgQ29kZQ==
UGhyYXNl
@@ -798,6 +842,7 @@
VXNlciBEb2N1bWVudGF0aW9uIFVSTA==
VXNlciBHcm91cHM=
VXNlcm5hbWU=
+ VXNlIFNlY3VyaXR5IEltYWdl
UmUtZW50ZXIgUGFzc3dvcmQ=
VmVyc2lvbg==
VmlzaWJpbGl0eQ==
@@ -815,6 +860,8 @@
QWxsIEZpbGVz
Q1NWIEZpbGVz
SW1hZ2UgRmlsZXM=
+ UE9QMyBTZXJ2ZXIgUG9ydC4gRm9yIGV4LiAiMTEwIiBmb3IgcmVndWxhciBjb25uZWN0aW9uLCAiOTk1IiBmb3Igc2VjdXJlIGNvbm5lY3Rpb24u
+ UE9QMyBTZXJ2ZXIgQWRkcmVzcy4gRm9yIGV4LiB1c2UgInNzbDovL3BvcC5nbWFpbC5jb20iIGZvciBHbWFpbCwgInBvcC5tYWlsLnlhaG9vLmNvbSIgZm9yIFlhaG9vLg==
SG90
SFRNTA==
SUQgRmllbGQ=
@@ -880,6 +927,7 @@
QWZ0ZXI=
QWxsb3c=
QmVmb3Jl
+ Qm91bmNlZA==
Q2FuY2VsZWQ=
Q2l0eQ==
Q29sb24=
@@ -891,11 +939,15 @@
RGVzY3JpcHRpb24=
RGlzYWJsZWQ=
RWRpdG9yJ3MgUGljaw==
- RW1haWw=
+ RS1tYWls
+ RS1tYWlsIEJvZHk=
+ RS1tYWlsIFN1YmplY3Q=
+ RXZlcnlvbmU=
RXhhY3Q=
RXhwaXJlZA==
RmFpbGVk
Rmlyc3QgTmFtZQ==
+ R3Vlc3RzIE9ubHk=
aG91cihzKQ==
SW5oZXJpdCBmcm9tIFBhcmVudA==
SVAgQWRkcmVzcw==
@@ -904,12 +956,17 @@
bWludXRlKHMp
TW9kYWwgV2luZG93
bW9udGgocyk=
+ TmV3IEUtbWFpbA==
Tm90IFByb2Nlc3NlZA==
+ Tm90IFJlcGxpZWQ=
UGFydGlhbGx5IFByb2Nlc3NlZA==
UGhvbmU=
UG9wdXAgV2luZG93
UHJvY2Vzc2Vk
UmF0aW5n
+ UmVjaXBpZW50IEUtbWFpbA==
+ UmVjaXBpZW50IE5hbWU=
+ UmVwbGllZA==
UnVubmluZw==
U2FtZSBXaW5kb3c=
c2Vjb25kKHMp
@@ -1114,6 +1171,7 @@
U1NMIFNldHRpbmdz
U3lzdGVtIFNldHRpbmdz
V2Vic2l0ZSBTZXR0aW5ncw==
+ U3VibWlzc2lvbiBOb3Rlcw==
VGVtcGxhdGVz
VGh1bWJuYWlsIEltYWdl
VHJhbnNsYXRpb24=
@@ -1231,6 +1289,7 @@
R2VuZXJhbA==
Q3VzdG9t
RS1tYWlsIFRlbXBsYXRlcw==
+ RS1tYWlsIENvbW11bmljYXRpb24=
RW1haWwgRXZlbnRz
RS1tYWlsIExvZw==
RW1haWwgUXVldWU=
@@ -1245,6 +1304,7 @@
SW1wb3J0IERhdGE=
SXRlbXM=
TGFiZWxz
+ TWVzc2FnZXM=
UGFja2FnZSBDb250ZW50
UGVybWlzc2lvbnM=
UHJvcGVydGllcw==
@@ -1374,6 +1434,7 @@
QWdlbnRz
QmFzZSBTdHlsZXM=
QmxvY2sgU3R5bGVz
+ Qm91bmNlIFBPUDMgU2VydmVyIFNldHRpbmdz
U2VjdGlvbnM=
U2VsZWN0IHNlY3Rpb24=
Q29sdW1uIFBpY2tlcg==
@@ -1413,6 +1474,7 @@
RWRpdGluZyBTdHlsZXNoZWV0
RWRpdGluZyBUaGVtZQ==
RWRpdGluZyBVc2Vy
+ RS1tYWlsIENvbW11bmljYXRpb24=
RS1tYWlsIEV2ZW50cw==
RS1tYWlscw==
RS1tYWlsIFNldHRpbmdz
@@ -1434,9 +1496,11 @@
TGFuZ3VhZ2VzIE1hbmFnZW1lbnQ=
TG9hZGluZyAuLi4=
TWFpbGluZ3M=
+ TWVzc2FnZXM=
TW9kdWxlcw==
TmV3IEFnZW50
TmV3IEZpbGU=
+ TmV3IFJlcGx5
TmV3IFRoZW1l
TmV3IFRoZW1lIFRlbXBsYXRl
TmV3IEJhc2UgU3R5bGU=
@@ -1454,6 +1518,7 @@
UHJvcGVydGllcw==
UmVsYXRlZCBTZWFyY2hlcw==
UmVsYXRpb25z
+ UmVwbHkgUE9QMyBTZXJ2ZXIgU2V0dGluZ3M=
Q29tbWVudHM=
U2VsZWN0IEdyb3VwKHMp
U2VsZWN0IFVzZXI=
@@ -1471,6 +1536,7 @@
VXNlcnM=
Vmlld2luZyBmb3JtIHN1Ym1pc3Npb24=
Vmlld2luZyBNYWlsaW5nIExpc3Q=
+ Vmlld2luZyBSZXBseQ==
VmlzaXRz
V2Vic2l0ZQ==
Q3Vyci4gU2VjdGlvbg==
@@ -1537,12 +1603,15 @@
UmVidWlsZCBTZWN0aW9uIENhY2hl
UmVjYWxjdWxhdGUgUHJpb3JpdGllcw==
UmVmcmVzaA==
+ UmVwbHk=
UmVzY2FuIFRoZW1lcw==
+ UmVzZW5k
UmVzZXQ=
UmVzZXQgUGVyc2lzdGVudCBTZXR0aW5ncw==
UmVzZXQgVG8gQmFzZQ==
UnVuIFNRTA==
U2F2ZQ==
+ U2F2ZSBhcyBEcmFmdA==
U2VhcmNo
UmVzZXQ=
U2VsZWN0IFVzZXI=
@@ -1662,6 +1731,9 @@
U3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBhcHByb3ZlZAoKWW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnAyOmNfRmllbGQgbmFtZT0iTmFtZSIvPiIgaGFzIGJlZW4gYXBwcm92ZWQu
U3ViamVjdDogWW91ciBDYXRlZ29yeSAiPGlucDI6Y19GaWVsZCBuYW1lPSJOYW1lIi8+IiBoYXMgYmVlbiBEZW5pZWQKCllvdXIgY2F0ZWdvcnkgc3VnZ2VzdGlvbiAiPGlucDI6Y19GaWVsZCBuYW1lPSJOYW1lIi8+IiBoYXMgYmVlbiBkZW5pZWQu
U3ViamVjdDogQ29tbW9uIEZvb3RlciBUZW1wbGF0ZQoKPGJyLz48YnIvPg0KDQpTaW5jZXJlbHksPGJyLz48YnIvPg0KDQpXZWJzaXRlIGFkbWluaXN0cmF0aW9uLg==
+ U3ViamVjdDogTmV3IEVtYWlsIFJFUExZIFJlY2VpdmVkIGluICJGZWVkYmFjayBNYW5hZ2VyIiAoPGlucDI6Zm9ybXN1YnMuLWl0ZW1fRmllbGQgbmFtZT0iRm9ybVN1Ym1pc3Npb25JZCIvPikKCk5ldyBFbWFpbCBSRVBMWSBSZWNlaXZlZCBpbiAmcXVvdDtGZWVkYmFjayBNYW5hZ2VyJnF1b3Q7LjxiciAvPg0KPGJyIC8+DQpPcmlnaW5hbCBGZWVkYmFja0lkOiA8aW5wMjpmb3Jtc3Vicy4taXRlbV9GaWVsZCBuYW1lPSJGb3JtU3VibWlzc2lvbklkIi8+IDxiciAvPg0KT3JpZ2luYWwgU3ViamVjdDogPGlucDI6Zm9ybXN1YnMuLWl0ZW1fRm9ybUZpZWxkIHJvbGU9InN1YmplY3QiLz4gPGJyIC8+DQo8YnIgLz4NClBsZWFzZSBwcm9jZWVkIHRvIHRoZSBBZG1pbiBDb25zb2xlIGluIG9yZGVyIHRvIHJldmlldyBhbmQgcmVwbHkgdG8gdGhlIHVzZXIu
+ U3ViamVjdDogTmV3IEVtYWlsIC0gRGVsaXZlcnkgRmFpbHVyZSBSZWNlaXZlZCBpbiAiRmVlZGJhY2sgTWFuYWdlciIgKDxpbnAyOmZvcm1zdWJzLi1pdGVtX0ZpZWxkIG5hbWU9IkZvcm1TdWJtaXNzaW9uSWQiLz4pCgpOZXcgRW1haWwgRGVsaXZlcnkgRmFpbHVyZSBSZWNlaXZlZCBpbiAmcXVvdDtGZWVkYmFjayBNYW5hZ2VyJnF1b3Q7LjxiciAvPg0KPGJyIC8+DQpPcmlnaW5hbCBGZWVkYmFja0lkOiA8aW5wMjpmb3Jtc3Vicy4taXRlbV9GaWVsZCBuYW1lPSJGb3JtU3VibWlzc2lvbklkIi8+IDxiciAvPg0KT3JpZ2luYWwgU3ViamVjdDogPGlucDI6Zm9ybXN1YnMuLWl0ZW1fRm9ybUZpZWxkIHJvbGU9InN1YmplY3QiLz4gPGJyIC8+DQo8YnIgLz4NClBsZWFzZSBwcm9jZWVkIHRvIHRoZSBBZG1pbiBDb25zb2xlIGluIG9yZGVyIHRvIHJldmlldyBhbmQgcmVwbHkgdG8gdGhlIHVzZXIu
+ U3ViamVjdDogPGlucDI6bV9QYXJhbSBuYW1lPSJzdWJqZWN0Ii8+ICN2ZXJpZnk8aW5wMjpzdWJtaXNzaW9uLWxvZ19GaWVsZCBuYW1lPSJWZXJpZnlDb2RlIi8+Cgo8aW5wMjptX1BhcmFtIG5hbWU9Im1lc3NhZ2UiLz4=
U3ViamVjdDogVGhhbmsgWW91IGZvciBDb250YWN0aW5nIFVzIQoKPHA+VGhhbmsgeW91IGZvciBjb250YWN0aW5nIHVzLiBXZSdsbCBiZSBpbiB0b3VjaCB3aXRoIHlvdSBzaG9ydGx5ITwvcD4=
U3ViamVjdDogTmV3IGZvcm0gc3VibWlzc2lvbgoKPHA+Rm9ybSBoYXMgYmVlbiBzdWJtaXR0ZWQuIFBsZWFzZSBwcm9jZWVkIHRvIHRoZSBBZG1pbiBDb25zb2xlIHRvIHJldmlldyB0aGUgc3VibWlzc2lvbiE8L3A+
U3ViamVjdDogSW4tcG9ydGFsIHJlZ2lzdHJhdGlvbgoKRGVhciA8aW5wMjp1X0ZpZWxkIG5hbWU9IkZpcnN0TmFtZSIgLz4gPGlucDI6dV9GaWVsZCBuYW1lPSJMYXN0TmFtZSIgLz4sDQoNClRoYW5rIHlvdSBmb3IgcmVnaXN0ZXJpbmcgb24gPGlucDI6bV9CYXNlVXJsLz4uIFlvdXIgcmVnaXN0cmF0aW9uIGlzIG5vdyBhY3RpdmUu
Index: branches/5.1.x/core/install/install_data.sql
===================================================================
diff -u -r13188 -r13390
--- branches/5.1.x/core/install/install_data.sql (.../install_data.sql) (revision 13188)
+++ branches/5.1.x/core/install/install_data.sql (.../install_data.sql) (revision 13390)
@@ -160,6 +160,9 @@
INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'COMMON.FOOTER', NULL, 1, 0, NULL, 'Core', 'Common Footer Template', 1);
INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMITTED', NULL, 1, 0, NULL, 'Core:Category', 'This e-mail is sent to a user after filling in the Contact Us form', 1);
INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMITTED', NULL, 1, 0, NULL, 'Core:Category', 'This e-mail is sent to a user after filling in the Contact Us form', 0);
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.TO.USER', NULL, 1, 0, NULL, 'Core:Category', 'Admin Reply to User Form Submission', 1);
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.FROM.USER', NULL, 1, 0, NULL, 'Core:Category', 'User Replied to It\'s Form Submission', 1);
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.FROM.USER.BOUNCED', NULL, 1, 0, NULL, 'Core:Category', 'Form Submission Admin Reply Delivery Failure', 1);
INSERT INTO IdGenerator VALUES ('100');
Index: branches/5.1.x/core/admin_templates/img/toolbar/tool_resend_f2.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/admin_templates/img/toolbar/tool_resend_f3.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/admin_templates/submissions/submissions_list.tpl
===================================================================
diff -u -r12127 -r13390
--- branches/5.1.x/core/admin_templates/submissions/submissions_list.tpl (.../submissions_list.tpl) (revision 12127)
+++ branches/5.1.x/core/admin_templates/submissions/submissions_list.tpl (.../submissions_list.tpl) (revision 13390)
@@ -12,7 +12,8 @@
//do not rename - this function is used in default grid for double click!
function edit()
{
- std_edit_item('formsubs', 'submissions/submission_view');
+ // don't use temp tables, since we can receive user replies while reviewing form submission
+ std_edit_temp_item('formsubs', 'submissions/submission_view');
}
var a_toolbar = new ToolBar();
Index: branches/5.1.x/core/admin_templates/img/itemicons/icon16_replied.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/install/upgrades.sql
===================================================================
diff -u -r13368 -r13390
--- branches/5.1.x/core/install/upgrades.sql (.../upgrades.sql) (revision 13368)
+++ branches/5.1.x/core/install/upgrades.sql (.../upgrades.sql) (revision 13390)
@@ -1710,4 +1710,88 @@
cv.GroupDisplayOrder = (SELECT ca7.GroupDisplayOrder FROM <%TABLE_PREFIX%>ConfigurationAdmin ca7 WHERE ca7.VariableName = cv.VariableName),
cv.`Install` = (SELECT ca8.`Install` FROM <%TABLE_PREFIX%>ConfigurationAdmin ca8 WHERE ca8.VariableName = cv.VariableName);
-DROP TABLE ConfigurationAdmin;
\ No newline at end of file
+DROP TABLE ConfigurationAdmin;
+
+ALTER TABLE Forms
+ ADD RequireLogin TINYINT NOT NULL DEFAULT '0',
+ ADD INDEX (RequireLogin),
+ ADD UseSecurityImage TINYINT NOT NULL DEFAULT '0',
+ ADD INDEX (UseSecurityImage),
+ ADD EnableEmailCommunication TINYINT NOT NULL DEFAULT '0',
+ ADD INDEX (EnableEmailCommunication),
+ ADD ReplyFromName VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyFromEmail VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyCc VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyBcc VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyMessageSignature TEXT,
+ ADD ReplyServer VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyPort INT(10) NOT NULL DEFAULT '110',
+ ADD ReplyUsername VARCHAR(255) NOT NULL DEFAULT '',
+ ADD ReplyPassword VARCHAR(255) NOT NULL DEFAULT ''
+ ADD BounceEmail VARCHAR(255) NOT NULL DEFAULT '',
+ ADD BounceServer VARCHAR(255) NOT NULL DEFAULT '',
+ ADD BouncePort INT(10) NOT NULL DEFAULT '110',
+ ADD BounceUsername VARCHAR(255) NOT NULL DEFAULT '',
+ ADD BouncePassword VARCHAR(255) NOT NULL DEFAULT '';
+
+ALTER TABLE FormFields
+ ADD Visibility TINYINT NOT NULL DEFAULT '1',
+ ADD INDEX (Visibility),
+ ADD EmailCommunicationRole TINYINT NOT NULL DEFAULT '0',
+ ADD INDEX (EmailCommunicationRole);
+
+ALTER TABLE FormSubmissions
+ ADD IPAddress VARCHAR(15) NOT NULL DEFAULT '' AFTER SubmissionTime,
+ ADD ReferrerURL VARCHAR(255) NOT NULL DEFAULT '' AFTER IPAddress,
+ ADD LogStatus TINYINT UNSIGNED NOT NULL DEFAULT '2' AFTER ReferrerURL,
+ ADD LastUpdatedOn INT UNSIGNED NULL AFTER LogStatus,
+ ADD Notes TEXT NULL AFTER LastUpdatedOn,
+ ADD INDEX (LogStatus),
+ ADD INDEX (LastUpdatedOn);
+
+CREATE TABLE SubmissionLog (
+ SubmissionLogId int(11) NOT NULL AUTO_INCREMENT,
+ FormSubmissionId int(10) unsigned NOT NULL,
+ FromEmail varchar(255) NOT NULL DEFAULT '',
+ ToEmail varchar(255) NOT NULL DEFAULT '',
+ Cc text,
+ Bcc text,
+ `Subject` varchar(255) NOT NULL DEFAULT '',
+ Message text,
+ Attachment text,
+ ReplyStatus tinyint(3) unsigned NOT NULL DEFAULT '0',
+ SentStatus tinyint(3) unsigned NOT NULL DEFAULT '0',
+ SentOn int(10) unsigned DEFAULT NULL,
+ RepliedOn int(10) unsigned DEFAULT NULL,
+ VerifyCode varchar(32) NOT NULL DEFAULT '',
+ DraftId int(10) unsigned NOT NULL DEFAULT '0',
+ MessageId varchar(255) NOT NULL DEFAULT '',
+ BounceInfo text,
+ BounceDate int(11) DEFAULT NULL,
+ PRIMARY KEY (SubmissionLogId),
+ KEY FormSubmissionId (FormSubmissionId),
+ KEY ReplyStatus (ReplyStatus),
+ KEY SentStatus (SentStatus),
+ KEY SentOn (SentOn),
+ KEY RepliedOn (RepliedOn),
+ KEY VerifyCode (VerifyCode),
+ KEY DraftId (DraftId),
+ KEY BounceDate (BounceDate),
+ KEY MessageId (MessageId)
+);
+
+CREATE TABLE Drafts (
+ DraftId int(11) NOT NULL AUTO_INCREMENT,
+ FormSubmissionId int(10) unsigned NOT NULL DEFAULT '0',
+ CreatedOn int(10) unsigned DEFAULT NULL,
+ CreatedById int(11) NOT NULL,
+ Message text,
+ PRIMARY KEY (DraftId),
+ KEY FormSubmissionId (FormSubmissionId),
+ KEY CreatedOn (CreatedOn),
+ KEY CreatedById (CreatedById)
+);
+
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.TO.USER', NULL, 1, 0, NULL, 'Core:Category', 'Admin Reply to User Form Submission', 1);
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.FROM.USER', NULL, 1, 0, NULL, 'Core:Category', 'User Replied to It\'s Form Submission', 1);
+INSERT INTO Events (EventId, Event, ReplacementTags, Enabled, FrontEndOnly, FromUserId, Module, Description, Type) VALUES(DEFAULT, 'FORM.SUBMISSION.REPLY.FROM.USER.BOUNCED', NULL, 1, 0, NULL, 'Core:Category', 'Form Submission Admin Reply Delivery Failure', 1);
\ No newline at end of file
Index: branches/5.1.x/core/units/forms/form_submissions/form_submissions_eh.php
===================================================================
diff -u -r13086 -r13390
--- branches/5.1.x/core/units/forms/form_submissions/form_submissions_eh.php (.../form_submissions/form_submissions_eh.php) (revision 13086)
+++ branches/5.1.x/core/units/forms/form_submissions/form_submissions_eh.php (.../forms/form_submissions/form_submissions_eh.php) (revision 13390)
@@ -1,6 +1,6 @@
getSection();
+ $form_id = $this->Application->GetVar('form_id');
+
+ $event->setEventParam('PermSection', $section . ':' . $form_id);
+
return parent::CheckPermission($event);
}
+ /**
+ * Always allow to view feedback form
+ *
+ */
function mapPermissions()
{
parent::mapPermissions();
+
$permissions = Array(
- 'OnEdit' => Array('self' => 'view', 'subitem' => 'view'),
+ 'OnItemBuild' => Array ('self' => true),
+ 'OnEdit' => Array ('self' => 'view', 'subitem' => 'view'),
);
+
$this->permMapping = array_merge($this->permMapping, $permissions);
}
@@ -66,43 +79,66 @@
$conf_grids = $this->Application->getUnitOption($event->Prefix, 'Grids');
$helper =& $this->Application->recallObject('InpCustomFieldsHelper');
+ /* @var $helper InpCustomFieldsHelper */
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'FormFields
WHERE FormId = ' . (int)$form_id . '
ORDER BY Priority DESC';
$fields = $this->Conn->Query($sql, 'FormFieldId');
+ $use_options = Array ('radio', 'select', 'checkbox');
+ $check_visibility = $this->Application->LoggedIn() && !$this->Application->isAdminUser;
+
foreach ($fields as $field_id => $options) {
- $conf_fields['fld_'.$field_id] = Array('type'=>'string', 'default'=>$options['DefaultValue']);
- if ($options['Required']) {
- $conf_fields['fld_'.$field_id]['required'] = 1;
+ $field_visible = $check_visibility ? $options['Visibility'] == FORM_FIELD_EVERYONE : true;
+ $field_options = Array('type' => 'string', 'default' => $options['DefaultValue']);
+
+ if ($options['Required'] && $field_visible) {
+ $field_options['required'] = 1;
}
+
if ($options['Validation'] == 1) {
- $conf_fields['fld_'.$field_id]['formatter'] = 'kFormatter';
- $conf_fields['fld_'.$field_id]['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
+ $field_options['formatter'] = 'kFormatter';
+ $field_options['regexp'] = '/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i';
}
+
if ($options['DisplayInGrid']) {
$title = $options['Prompt'];
- if (substr($title, 0,1) == '+') {
- $this->Application->Phrases->AddCachedPhrase('form_col_title'.$field_id, substr($title,1));
- $title = 'form_col_title'.$field_id;
+
+ if (substr($title, 0, 1) == '+') {
+ $this->Application->Phrases->AddCachedPhrase('form_col_title' . $field_id, substr($title, 1));
+ $title = 'form_col_title' . $field_id;
}
- $conf_grids['Default']['Fields']['fld_'.$field_id] = Array('title'=>$title, 'no_special' => 1, 'nl2br' => 1, 'first_chars' => 200, 'filter_block' => $this->_getFilterBlock($options['ElementType']));
- if ($options['Validation'] == 1)
- {
- $conf_grids['Default']['Fields']['fld_'.$field_id]['data_block'] = 'grid_email_td';
+
+ $conf_grids['Default']['Fields']['fld_' . $field_id] = Array (
+ 'title' => $title, 'no_special' => 1, 'nl2br' => 1, 'first_chars' => 200,
+ 'filter_block' => $this->_getFilterBlock($options['ElementType'])
+ );
+
+ if ($options['Validation'] == 1) {
+ $conf_grids['Default']['Fields']['fld_' . $field_id]['data_block'] = 'grid_email_td';
}
}
- if ($options['ElementType'] == 'radio' || $options['ElementType'] == 'select') {
- $conf_fields['fld_'.$field_id]['options'] = $helper->GetValuesHash( $options['ValueList'] );
- $conf_fields['fld_'.$field_id]['formatter'] = 'kOptionsFormatter';
+
+ if ($options['ElementType'] == 'checkbox' && !$options['ValueList']) {
+ // fix case, when user haven't defined any options for checkbox
+ $options['ValueList'] = '1=la_Yes||0=la_No';
}
+
+ if (in_array($options['ElementType'], $use_options) && $options['ValueList']) {
+ // field type can have options and user have defined them too
+ $field_options['options'] = $helper->GetValuesHash( $options['ValueList'] );
+ $field_options['formatter'] = 'kOptionsFormatter';
+ }
+
if ($options['ElementType'] == 'password') {
- $conf_fields['fld_'.$field_id]['formatter'] = 'kPasswordFormatter';
- $conf_fields['fld_'.$field_id]['encryption_method'] = 'plain';
- $conf_fields['fld_'.$field_id]['verify_field'] = 'fld_'.$field_id.'_verify';
+ $field_options['formatter'] = 'kPasswordFormatter';
+ $field_options['encryption_method'] = 'plain';
+ $field_options['verify_field'] = 'fld_' . $field_id . '_verify';
}
+
+ $conf_fields['fld_' . $field_id] = $field_options;
}
$this->Application->setUnitOption($event->Prefix, 'Fields', $conf_fields);
@@ -116,14 +152,26 @@
$object->addFilter('form_filter','%1$s.FormId = '.$form_id);
}
+ /**
+ * Allows user to see it's last feedback form data
+ *
+ * @param kEvent $event
+ * @return int
+ */
function getPassedID(&$event)
{
- if (!$this->Application->isAdminUser) {
- // no way to see other user's form submission by giving it's ID directly in url
- return 0;
+ if ($event->Special == 'last') {
+ // allow user to see his last submitted form
+ return $this->Application->RecallVar('last_submission_id');
}
- return parent::getPassedID($event);
+ if ($this->Application->isAdminUser) {
+ // don't check ids in admin
+ return parent::getPassedID($event);
+ }
+
+ // no way to see other user's form submission by giving it's ID directly in url
+ return 0;
}
/**
@@ -139,6 +187,12 @@
return ;
}
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ // allows user to view only it's last submission
+ $this->Application->StoreVar('last_submission_id', $object->GetID());
+
$this->Application->EmailEventAdmin('FORM.SUBMITTED');
// $this->Application->EmailEventUser('FORM.SUBMITTED', null, 'to_email' => '');
@@ -153,4 +207,62 @@
$event->redirect = $alias_template ? $alias_template : $template;
}
+
+ /**
+ * Processes Captcha code
+ *
+ * @param kEvent $event
+ */
+ function OnBeforeItemCreate(&$event)
+ {
+ parent::OnBeforeItemCreate($event);
+
+ $object =& $event->getObject();
+ /* @var $object kDBItem */
+
+ $object->SetDBField('IPAddress', $_SERVER['REMOTE_ADDR']);
+ $object->SetDBField('ReferrerURL', $_SERVER['HTTP_REFERER']);
+
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $form =& $form_submission_helper->getForm($object);
+
+ // validate captcha code
+ if ($form->GetDBField('UseSecurityImage') && !$this->Application->LoggedIn()) {
+ $captcha_helper =& $this->Application->recallObject('CaptchaHelper');
+ /* @var $captcha_helper kCaptchaHelper */
+
+ $captcha_helper->validateCode($event, false);
+ }
+ }
+
+ /**
+ * Passes form_id, when using "Prev"/"Next" toolbar buttons
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndGo(&$event)
+ {
+ parent::OnPreSaveAndGo($event);
+
+ if ($event->status == erSUCCESS) {
+ $event->SetRedirectParam('pass', 'm,form,formsubs');
+ }
+ }
+
+ /**
+ * Saves edited item in temp table and goes
+ * to passed tabs, by redirecting to it with OnPreSave event
+ *
+ * @param kEvent $event
+ */
+ function OnPreSaveAndGoToTab(&$event)
+ {
+ parent::OnPreSaveAndGoToTab($event);
+
+ if ($event->status == erSUCCESS) {
+ $event->SetRedirectParam('pass', 'm,form,formsubs');
+ }
+ }
}
\ No newline at end of file
Index: branches/5.1.x/core/units/forms/form_submissions/form_submissions_config.php
===================================================================
diff -u -r13159 -r13390
--- branches/5.1.x/core/units/forms/form_submissions/form_submissions_config.php (.../form_submissions/form_submissions_config.php) (revision 13159)
+++ branches/5.1.x/core/units/forms/form_submissions/form_submissions_config.php (.../forms/form_submissions/form_submissions_config.php) (revision 13390)
@@ -1,6 +1,6 @@
hAFTER,
'Conditional' => false,
- 'HookToPrefix' => 'formsubs', //self
+ 'HookToPrefix' => '',
'HookToSpecial' => '*',
'HookToEvent' => Array('OnAfterConfigRead'),
'DoPrefix' => '',
'DoSpecial' => '',
'DoEvent' => 'OnBuildFormFields',
),
- ),
- 'TitlePresets' => Array(
- 'default' => Array( 'new_status_labels' => Array('form'=>'!la_title_Adding_Form!'),
- 'edit_status_labels' => Array('form'=>'!la_title_Editing_Form!'),
- 'new_titlefield' => Array('form'=>''),
+ // Captcha processing
+ Array (
+ 'Mode' => hAFTER,
+ 'Conditional' => false,
+ 'HookToPrefix' => '',
+ 'HookToSpecial' => '*',
+ 'HookToEvent' => Array('OnAfterConfigRead'),
+ 'DoPrefix' => 'captcha',
+ 'DoSpecial' => '*',
+ 'DoEvent' => 'OnPrepareCaptcha',
+ ),
),
+ 'TitlePresets' => Array(
+ 'default' => Array(
+ 'new_status_labels' => Array('form'=>'!la_title_Adding_Form!'),
+ 'edit_status_labels' => Array('form'=>'!la_title_Editing_Form!'),
+ ),
+
'formsubs_list' => Array (
- 'prefixes' => Array('form', 'formsubs_List'),
- 'format' => "!la_title_FormSubmissions! '#form_titlefield#'",
- 'toolbar_buttons' => Array ('edit', 'delete', 'dbl-click'),
- ),
+ 'prefixes' => Array('form', 'formsubs_List'),
+ 'format' => "!la_title_FormSubmissions! '#form_titlefield#'",
+ 'toolbar_buttons' => Array ('edit', 'delete', 'dbl-click'),
+ ),
'formsubs_view' => Array(
- 'prefixes' => Array('formsubs'),
- 'format' => "!la_title_ViewingFormSubmission!",
- 'toolbar_buttons' => Array ('cancel', 'prev', 'next'),
- ),
+ 'prefixes' => Array('formsubs'),
+ 'format' => "!la_title_ViewingFormSubmission!",
+ 'toolbar_buttons' => Array ('select', 'cancel', 'prev', 'next'),
+ ),
- ),
+ 'submission_edit_logs' => Array (
+ 'prefixes' => Array ('formsubs', 'submission-log_List'),
+ 'format' => "!la_title_ViewingFormSubmission! - !la_title_Messages! (#submission-log_recordcount#)"
+ ),
+ 'submission_log_edit' => Array (
+ 'new_status_labels' => Array ('submission-log' => '!la_title_NewReply!'),
+ 'edit_status_labels' => Array ('submission-log' => '!la_title_ViewingReply!'),
+
+ 'prefixes' => Array ('submission-log'), 'format' => "!la_title_ViewingFormSubmission! - #submission-log_status#"
+ ),
+ ),
+
+ 'EditTabPresets' => Array (
+ 'Default' => Array (
+ Array ('title' => 'la_tab_General', 't' => 'submissions/submission_view', 'priority' => 1),
+ Array ('title' => 'la_tab_Messages', 't' => 'submissions/submission_edit_logs', 'priority' => 2),
+ ),
+ ),
+
'PermSection' => Array('main' => 'in-portal:submissions'),
'IDField' => 'FormSubmissionId',
/*'TitleField' => 'Name',*/
+ 'StatusField' => Array ('LogStatus'),
'TableName' => TABLE_PREFIX.'FormSubmissions',
'ListSQLs' => Array(
''=>' SELECT %1$s.* %2$s FROM %1$s',
@@ -79,27 +110,44 @@
'AutoDelete' => true,
'AutoClone' => true,*/
+ 'SubItems' => Array ('submission-log', 'draft'),
+
'ListSortings' => Array(
'' => Array(
'Sorting' => Array('SubmissionTime' => 'desc'),
)
),
- 'Fields' => Array(
- 'FormSubmissionId' => Array('type' => 'int', 'not_null' => 1,'default' => 0),
- 'FormId' => Array('type' => 'int','not_null' => '1','default' => 0),
- 'SubmissionTime' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
+ 'Fields' => Array(
+ 'FormSubmissionId' => Array('type' => 'int', 'not_null' => 1,'default' => 0),
+ 'FormId' => Array('type' => 'int','not_null' => '1','default' => 0),
+ 'SubmissionTime' => Array('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => '#NOW#'),
+ 'IPAddress' => Array ('type' => 'string', 'max_len' => 15, 'not_null' => 1, 'default' => ''),
+ 'ReferrerURL' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''),
+
+ 'LogStatus' => Array (
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_opt_Replied', 2 => 'la_opt_NotReplied', 3 => 'la_opt_NewEmail', 4 => 'la_opt_Bounce'), 'use_phrases' => 1,
+ 'not_null' => 1, 'required' => 1, 'default' => 2
+ ),
+
+ 'LastUpdatedOn' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL),
+ 'Notes' => Array ('type' => 'string', 'default' => NULL),
),
'VirtualFields' => Array(
),
'CalculatedFields' => Array(
),
'Grids' => Array(
'Default' => Array(
- 'Icons' => Array('default' => 'icon16_item.png'),
+ 'Icons' => Array('default' => 'icon16_item.png', 1 => 'icon16_replied.gif', 2 => 'icon16_not_replied.gif', 3 => 'icon16_new_email.gif', 4 => 'icon16_bounce.gif'),
'Fields' => Array(
'FormSubmissionId' => Array( 'title'=>'la_col_Id', 'data_block' => 'grid_checkbox_td', 'sort_field' => 'FormFieldId', 'filter_block' => 'grid_range_filter', 'width' => 60 ),
'SubmissionTime' => Array( 'title'=>'la_prompt_SumbissionTime', 'filter_block' => 'grid_date_range_filter', 'width' => 145 ),
+ 'IPAddress' => Array ('title' => 'la_col_IPAddress', 'filter_block' => 'grid_like_filter', 'width' => 100 ),
+ 'ReferrerURL' => Array ('title' => 'la_col_ReferrerURL', 'filter_block' => 'grid_like_filter', 'first_chars' => 100, 'width' => 200 ),
+ 'LogStatus' => Array ('title' => 'la_col_Status', 'filter_block' => 'grid_options_filter', 'width' => 100 ),
+ 'LastUpdatedOn' => Array ('title' => 'la_col_LastUpdatedOn', 'filter_block' => 'grid_date_range_filter', 'width' => 145 ),
),
),
),
Index: branches/5.1.x/core/units/forms/form_submissions/form_submission_tp.php
===================================================================
diff -u -r13086 -r13390
--- branches/5.1.x/core/units/forms/form_submissions/form_submission_tp.php (.../form_submissions/form_submission_tp.php) (revision 13086)
+++ branches/5.1.x/core/units/forms/form_submissions/form_submission_tp.php (.../forms/form_submissions/form_submission_tp.php) (revision 13390)
@@ -19,4 +19,28 @@
return $this->Application->Phrase($phrase_name);
}
+
+ /**
+ * Allows to retrieve for submission field by it's name or role in email communications
+ *
+ * @param Array $params
+ * @return string
+ */
+ function FormField($params)
+ {
+ $object =& $this->getObject($params);
+ /* @var $object kDBItem */
+
+ $form_submission_helper =& $this->Application->recallObject('FormSubmissionHelper');
+ /* @var $form_submission_helper FormSubmissionHelper */
+
+ $formatted = !(array_key_exists('db', $params) && $params['db']);
+ $format = $formatted ? (array_key_exists('format', $params) ? $params['format'] : null) : null;
+
+ if (array_key_exists('role', $params)) {
+ return $form_submission_helper->getFieldByRole($object, $params['role'], $formatted, $format);
+ }
+
+ return $form_submission_helper->getFieldByName($params['name'], $formatted, $format);
+ }
}
Index: branches/5.1.x/core/units/forms/drafts/draft_eh.php
===================================================================
diff -u
--- branches/5.1.x/core/units/forms/drafts/draft_eh.php (revision 0)
+++ branches/5.1.x/core/units/forms/drafts/draft_eh.php (revision 13390)
@@ -0,0 +1,43 @@
+getObject();
+ /* @var $object kDBItem */
+
+ $user_id = $this->Application->RecallVar('user_id');
+
+ $object->SetDBField('CreatedById', $user_id);
+ }
+
+ /**
+ * Allows to load draft, that best matches given form submission
+ *
+ * @param kEvent $event
+ * @return int
+ */
+ function getPassedID(&$event)
+ {
+ if ($event->Special == 'related') {
+ $form_submission =& $this->Application->recallObject('formsubs');
+ /* @var $form_submission kDBItem */
+
+ return Array (
+ 'FormSubmissionId' => $form_submission->GetID(),
+ 'CreatedById' => $this->Application->RecallVar('user_id'),
+ );
+ }
+
+ return parent::getPassedID($event);
+ }
+ }
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/img/itemicons/icon16_new_email.gif
===================================================================
diff -u
Binary files differ
Index: branches/5.1.x/core/units/helpers/helpers_config.php
===================================================================
diff -u -r13159 -r13390
--- branches/5.1.x/core/units/helpers/helpers_config.php (.../helpers_config.php) (revision 13159)
+++ branches/5.1.x/core/units/helpers/helpers_config.php (.../helpers_config.php) (revision 13390)
@@ -1,6 +1,6 @@
'JSONHelper', 'class' => 'JSONHelper', 'file' => 'json_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'LanguageImportHelper', 'class' => 'LanguageImportHelper', 'file' => 'language_import_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
Array ('pseudo' => 'SkinHelper', 'class' => 'SkinHelper', 'file' => 'skin_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'SiteConfigHelper', 'pseudo' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'MenuHelper', 'pseudo' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'SiteConfigHelper', 'class' => 'SiteConfigHelper', 'file' => 'site_config_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'MenuHelper', 'class' => 'MenuHelper', 'file' => 'menu_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'InpCustomFieldsHelper', 'pseudo' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'kCountryStatesHelper', 'pseudo' => 'CountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'kBracketsHelper', 'pseudo' => 'BracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'kXMLHelper', 'pseudo' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'kCatDBItemExportHelper', 'pseudo' => 'CatItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'EmailMessageHelper', 'pseudo' => 'EmailMessageHelper', 'file' => 'email_message_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
- Array ('class' => 'ListHelper', 'pseudo' => 'ListHelper', 'file' => 'list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'InpCustomFieldsHelper', 'class' => 'InpCustomFieldsHelper', 'file' => 'custom_fields_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CountryStatesHelper', 'class' => 'kCountryStatesHelper', 'file' => 'country_states_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'BracketsHelper', 'class' => 'kBracketsHelper', 'file' => 'brackets_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'kXMLHelper', 'class' => 'kXMLHelper', 'file' => 'xml_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'CatItemExportHelper', 'class' => 'kCatDBItemExportHelper', 'file' => 'cat_dbitem_export_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'EmailMessageHelper', 'class' => 'EmailMessageHelper', 'file' => 'email_message_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'ListHelper', 'class' => 'ListHelper', 'file' => 'list_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+
+ Array ('pseudo' => 'FormSubmissionHelper', 'class' => 'FormSubmissionHelper', 'file' => 'form_submission_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'MailboxHelper', 'class' => 'MailboxHelper', 'file' => 'mailbox_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'POP3Helper', 'class' => 'POP3Helper', 'file' => 'pop3_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
+ Array ('pseudo' => 'MimeDecodeHelper', 'class' => 'MimeDecodeHelper', 'file' => 'mime_decode_helper.php', 'build_event' => '', 'require_classes' => 'kHelper'),
),
);
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/submissions/submission_view.tpl
===================================================================
diff -u -r12657 -r13390
--- branches/5.1.x/core/admin_templates/submissions/submission_view.tpl (.../submission_view.tpl) (revision 12657)
+++ branches/5.1.x/core/admin_templates/submissions/submission_view.tpl (.../submission_view.tpl) (revision 13390)
@@ -1,8 +1,14 @@
-
+
+
-
+
+
+
+
+
+