I created a slim4 action to send more than one email.
The two emails get their output from views and sends two separate emails.
The first email is sent ok, But the second one is sent with the body of the first (The recipient and subject is correct.)
I have excluded the email library by debuging and tracing the values being received. I can confirm the same response body is being set,
I tried making a copy of $response. That did not change things.
The code below is a summary
public function actionContact(RequestInterface $request, ResponseInterface $response, array $args): ResponseInterface
$form_data = (array)$request->getParsedBody();
$notify_view_ = $this->renderer->render(
$response,
'emails/contactus_notify.php',
['form_data' => $form_data]
);
$notify_message = $response->getBody();
$notify_mail = new Email('user1#domain.com, 'Subject 1', $notify_message)->send();
// Send second email
$thankyou_view_ = $this->renderer->render(
$response,
'emails/contactus_thankyou.php',
['form_data' => $form_data]
);
$thankyou_message = $response->getBody();
$thankyou_mail = new Email('user2#domain.com, 'Subject 2', $thankyou_message)->send();
}
I figured after further debugging that the second getBody() was actually concatenating the results of the two render()s.
I tried resetting the body
$response->getBody()->write('');
but this had no effect. The second email is the concatenation of the two writes by render.
The issues was fixed by using the fetch() method, which renders the template and returns the result instead of writing it to the response. (Unfortunate name for the method, I think.)
Replace
$notify_view_ = $this->renderer->render(
$response,
'emails/contactus_notify.php',
['form_data' => $form_data]
);
$notify_message = $response->getBody();
by
$notify_message = $this->renderer->fetch(
'emails/contactus_notify.php',
['form_data' => $form_data]
);
Related
I created some enveloppe custom fields in the admin of Docusign.
So I'd to know how to set their value when I create an enveloppe from the docusign Ruby API.
I've tried to set there like this, but it doesn't work. When I send the envelope the custom fields are not filled.
envelope_definition = DocuSign_eSign::EnvelopeDefinition.new
custom_fields = DocuSign_eSign::CustomFieldsEnvelope.new(
{"name":"enveloppe_annee","value":"2019"}
)
envelope_definition.custom_fields = [custom_fields]
The envelope_definition.custom_fields attribute takes a single instance of custom_fields. (Not an array)
custom_fields is an object that has two attributes:
list_custom_fields wants an array of ListCustomField
text_custom_fields wants an array of TextCustomField
Based on the above, can you redo your request?
envelope_definition = DocuSign_eSign::EnvelopeDefinition.new({status: 'sent', templateId:'a19dXXXX-XXXX-4ce7-XXXX-56cXXXX83364', emailSubject: 'Example Document Signing'})
signer = DocuSign_eSign::TemplateRole.new({email: 'email#eample.com', name: 'Johny Walker', roleName: 'signer'})
text = DocuSign_eSign::Text.new
text.tab_label = 'label_id of the custom field'
text.value = 'value for the custom field'
tabs = DocuSign_eSign::Tabs.new
tabs.text_tabs = [text]
signer.tabs = tabs
envelope_definition.template_roles = [signer]
This should work for you
So I have a field in state bullet_points: [] that is an array of elements.
I have a function in my component that adds/removes elements from this array. To save the changes, clicking submit will sent product: this.state as an argument in a POST request to my backend.
The backend only receives bullet_points if the array IS NOT empty. If I clear the field of all elements, it is never sent to the backend.
What would cause this? Below are the relevant code snippets.
1) Function for add/remove of elements (notice arrow, this is where elements are removed)
updateList(evt) {
evt.preventDefault();
let elements = this.state[evt.target.dataset.type];
let idx = parseInt(evt.target.dataset.index);
let new_element = evt.target.dataset.type == "durations" ? 30 : "";
if (isNaN(idx)) {
elements.push(new_element);
} else {
if (evt.target.dataset.delete) { <----------
elements.splice(idx, 1);
}
else {
elements[idx] = evt.target.value;
}
}
this.setState({ [evt.target.dataset.type]: elements });
}
2) POST request to backend
API.put(`coach/products/${this.props.params.id}`, {
product: this.state
}, function(res) {
this.closeModal();
Alert.success('<p class="small-body-text">Your changes have been saved</p>', {
position: "top-right",
effect: "scale",
timeout: 5000
});
}.bind(this));
Many libraries that serialize and post data do not send key/value pairs if the value is an empty array. For example: jQuery has this behavior. There are essentially two ways you can handle this:
1) On the backend, check for the existence of the key in the post parameters. If it doesn't exist, treat it like an empty array.
2) If you really want to send an empty array (maybe there's a difference between sending an empty array and not sending the key/value at all?), then send the array with a single empty string or some other value that cannot possibly be valid input but that you will check for to mean that the array is empty.
One tricky thing I've run into before - if you're testing with rspec, rspec's post method does not remove the key/value if the value is an empty array; it sends the data as is. So you may want to add additional tests that represent what the client data looks like after it has been serialized.
ZF2 docs show the following example in terms of using Db\RecordExists validator with multiple columns.
$email = 'user#example.com';
$clause = $dbAdapter->quoteIdentifier('email') . ' = ' . $dbAdapter->quoteValue($email);
$validator = new Zend\Validator\Db\RecordExists(
array(
'table' => 'users',
'field' => 'username',
'adapter' => $dbAdapter,
'exclude' => $clause
)
);
if ($validator->isValid($username)) {
// username appears to be valid
} else {
// username is invalid; print the reason
$messages = $validator->getMessages();
foreach ($messages as $message) {
echo "$message\n";
}
}
I’ve tried this using my own Select object containing a more complex where condition. However, isValid() must be called with a value parameter.
In the example above $username is passed to isValid(). But there seems to be no according field definition.
I tried calling isValid() with an empty string, but this does not produce the desired result, since Zend\Validator\Db\AbstractDb::query() always adds the value to the statement:
$parameters = $statement->getParameterContainer();
$parameters['where1'] = $value;
If I remove the seconds line above, my validator produces the expected results.
Can someone elaborate on how to use RecordExists with the where conditions in my custom Select object? And only those?
The best way to do this is probably by making your own validator that extends one of Zend Framework's, because it doesn't seem like the (No)RecordExists classes were meant to handle multiple fields (I'd be happy to be proven wrong, because it'd be easier if they did).
Since, as you discovered, $parameters['where1'] is overridden with $value, you can deal with this by making sure $value represents what the value of the first where should be. In the case of using a custom $select, $value will replace the value in the first where clause.
Here's a hacky example of using RecordExists with a custom select and multiple where conditions:
$select = new Select();
$select->from('some_table')
->where->equalTo('first_field', 'value1') // this gets overridden
->and->equalTo('second_field', 'value2')
;
$validator = new RecordExists($select);
$validator->setAdapter($someAdapter);
// this overrides value1, but since isValid requires a string,
// the redundantly supplied value allows it to work as expected
$validator->isValid('value1');
The above produces the following query:
SELECT `some_table`.* FROM `some_table` WHERE `first_field` = 'value1' AND `second_field` = 'value2'
...which results in isValid returning true if there was a result.
I want to email form responses to a help desk email once they are "approved" and a "work order #" is assigned, meaning I open the spreadsheet and assign initials to the approved column and assign a work order number to the new work order column. I've modified many scripts to try to achieve this. I do not want the responses sent immediately upon form submission, as they need at least a work order attached. Below is the script I've attempted to modify (shown below without any modification). It works fine IF I want the form submissions to go directly to the email when a user hits submit. Again, I need them emailed ONLY when a work order is attached to the respective line item in the spreadsheet.
function nl2br_(input_string){
return input_string.replace(/(\r\n|\r|\n)/g,'<br />');
}
function RequestNWOMailer(e) {
try {
var recipient = 'test-area#efriends44221.org';
var timestamp = e.values[0];
var name = e.values[1];
var contactmethod = e.values[2];
var emailphone = e.values[3];
var building = e.values[4];
var room = e.values[5];
var reason = e.values[6];
var description = e.values[7];
var approval = e.values[8];
var nwo = e.values[9];
var subject = building+' <'+reason+'> <'+name+'>';
var body = name+' <'+emailphone+'> sent the following: '+description;
var bodyHTML = '\
<p>NWO #: '+nwo+'</p>\
<p>'+name+' sent the following: </p>\
<p>Contact Method: '+contactmethod+'</p>\
<p>Email of Phone#: '+emailphone+'</p>\
<p>Building: '+building+'</p>\
<p>Room #: '+room+'</p>\
<p>Reason for NWO: '+reason+'</p>\
<p>Description: '+nl2br_(description)+'</p>';
var advancedArgs = {htmlBody:bodyHTML , replyTo:emailphone};
MailApp.sendEmail(recipient, subject, body, advancedArgs);
} catch(e){MailApp.sendEmail(recipient, "Error - Request for New Work Order Form", e.message);
}
}
I am having an issue with ZF2 trying to use the table gateways and getting result sets:
I am trying to query two result sets (from two different tables/two different gateways) and send them to the view to be iterated through and placed on the screen.
(Simplified example):
function viewAction() {
$table1 = $this->getServiceLocator()->get('Model\Table\Table1');
$table2 = $this->getServiceLocator()->get('Model\Table\Table2');
return new ViewModel([
'table1' => $table1->fetchAll(),
'table2' => $table2->fetchAll()
]);
}
With the Model\Table\Table1 and Model\Table\Table2 having a fetch all:
public function fetchAll() {
return $this->tableGateway->select();
}
Then in my view:
...
<?php
foreach($table1 as $row) {
echo "<tr><td>{$row['col1']}</td><td>{$row['col2']}</td></tr>";
}
?>
...
<?php
foreach($table2 as $row) {
echo "<tr><td>{$row['col1']}</td><td>{$row['col2']}</td></tr>";
}
?>
...
The problem is, $table1 will have no data when looping. However, if I instead do something like this (in the controller, instead of passing the result set to the view, passing $results1 and $results2 to the view):
$fetchAll = $table1->fetchAll();
$results1 = [];
foreach($fetchAll as $row) {
$results1[] = $row;
}
$fetchAll = $table2->fetchAll();
$results2 = [];
foreach($fetchAll as $row) {
$results2[] = $row;
}
Then all works fine. I don't want to have to loop through the same set of data twice. So why does ZF2 prevent me from using two different ResultSets before all the data in a ResultSet has been accessed?
Since I was querying to different record sets one after the other, the database was still waiting for action to take place on the first query. I could only have one action record set at a time.
There first solution was what I presented in the question, get a record set and loop through all the rows that are available before trying to query again. This frees the record set as we have all the data.
The second solution (the one I have adapted), is to enable Multiple Active Record Sets (MARS) for the database connection.
I was able to do this by adding MARS_Connection=yes to the dsn connection string for MSSQL.