3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
36 * This class provides the functionality to email a group of
39 class CRM_Contribute_Form_Task_Invoice
extends CRM_Contribute_Form_Task
{
41 * Are we operating in "single mode", i.e. updating the task of only
42 * one specific contribution?
46 public $_single = FALSE;
49 * gives all the statues for conribution
53 public $_contributionStatusId;
56 * gives the HTML template of PDF Invoice
60 public $_messageInvoice;
63 * This variable is used to assign parameters for HTML template of PDF Invoice
67 public $_invoiceTemplate;
72 public $_selectedOutput;
75 * build all the data structures needed to build the form
80 function preProcess() {
81 $id = CRM_Utils_Request
::retrieve('id', 'Positive', $this, FALSE);
83 $this->_contributionIds
= array($id);
84 $this->_componentClause
= " civicrm_contribution.id IN ( $id ) ";
85 $this->_single
= TRUE;
86 $this->assign('totalSelectedContributions', 1);
92 // check that all the contribution ids have status Completed, Pending, Refunded.
93 $this->_contributionStatusId
= CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
94 $status = array('Completed', 'Pending', 'Refunded');
96 foreach ($this->_contributionStatusId
as $key => $value) {
97 if (in_array($value, $status)) {
101 $Id = implode(",", $statusId);
102 $query = "SELECT count(*) FROM civicrm_contribution WHERE contribution_status_id NOT IN ($Id) AND {$this->_componentClause}";
103 $count = CRM_Core_DAO
::singleValueQuery($query);
105 CRM_Core_Error
::statusBounce(ts('Please select only contributions with Completed, Pending, Refunded status.'));
108 // we have all the contribution ids, so now we get the contact ids
109 parent
::setContactIDs();
110 $this->assign('single', $this->_single
);
112 $qfKey = CRM_Utils_Request
::retrieve('qfKey', 'String', $this);
113 $urlParams = 'force=1';
114 if (CRM_Utils_Rule
::qfKey($qfKey)) {
115 $urlParams .= "&qfKey=$qfKey";
118 $url = CRM_Utils_System
::url('civicrm/contribute/search', $urlParams);
122 'title' => ts('Search Results'),
126 CRM_Utils_System
::appendBreadCrumb($breadCrumb);
128 $this->_selectedOutput
= CRM_Utils_Request
::retrieve('select', 'String', $this);
129 $this->assign('selectedOutput', $this->_selectedOutput
);
131 if ($this->_selectedOutput
== 'email') {
132 CRM_Utils_System
::setTitle(ts('Email Invoice'));
135 CRM_Utils_System
::setTitle(ts('Print Contribution Invoice'));
146 public function buildQuickForm() {
147 $session = CRM_Core_Session
::singleton();
148 if (CRM_Core_Permission
::check('administer CiviCRM')) {
149 $this->assign('isAdmin', 1);
151 $contactID = $session->get('userID');
152 $contactEmails = CRM_Core_BAO_Email
::allEmails($contactID);
154 $fromDisplayName = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Contact',
155 $contactID, 'display_name'
157 foreach ($contactEmails as $emailId => $item) {
158 $email = $item['email'];
160 $emails[$emailId] = '"' . $fromDisplayName . '" <' . $email . '> ';
162 if (isset($emails[$emailId])) {
163 $emails[$emailId] .= $item['locationType'];
164 if ($item['is_primary']) {
165 $emails[$emailId] .= ' ' . ts('(preferred)');
167 $emails[$emailId] = htmlspecialchars($emails[$emailId]);
170 $fromEmailAddress = CRM_Core_OptionGroup
::values('from_email_address');
171 foreach ($fromEmailAddress as $key => $email) {
172 $fromEmailAddress[$key] = htmlspecialchars($fromEmailAddress[$key]);
174 $fromEmail = CRM_Utils_Array
::crmArrayMerge($emails, $fromEmailAddress);
175 $this->add('select', 'from_email_address', ts('From Email Address'), array('' => '- select -') +
$fromEmail);
176 if ($this->_selectedOutput
!= 'email') {
177 $this->addElement('radio', 'output', NULL, ts('Email Invoice'), 'email_invoice');
178 $this->addElement('radio', 'output', NULL, ts('PDF Invoice'), 'pdf_invoice');
179 $this->addRule('output', ts('Selection required'), 'required');
180 $this->addFormRule(array('CRM_Contribute_Form_Task_Invoice', 'formRule'));
183 $this->addRule('from_email_address', ts('From Email Address is required'), 'required');
186 $this->addWysiwyg('email_comment', ts('If you would like to add personal message to email please add it here. (If sending to more then one receipient the same message will be sent to each contact.)'), array(
191 if (in_array("email", $this->urlPath
)) {
192 $this->addButtons(array(
195 'name' => ts('Email Invoice'),
200 'name' => ts('Cancel'),
206 $this->addButtons(array(
209 'name' => ts('Process Invoice(s)'),
214 'name' => ts('Cancel'),
222 * global validation rules for the form
226 * @internal param array $fields posted values of the form
228 * @return array list of errors to be posted back to the form
232 static function formRule($values) {
235 if ($values['output'] == 'email_invoice' && empty($values['from_email_address'])) {
236 $errors['from_email_address'] = ts("From Email Address is required");
243 * process the form after the input has been submitted and validated
249 public function postProcess() {
250 $params = $this->controller
->exportValues($this->_name
);
251 $this->printPDF($this->_contributionIds
, $params, $this->_contactIds
);
256 * process the PDf and email with activity and attachment
257 * on click of Print Invoices
259 * @param array $contribIDs Contribution Id
260 * @param array $params for pdf or email invoices
261 * @param array $contactIds Contact Id
265 static function printPDF($contribIDs, $params, $contactIds) {
266 // get all the details needed to generate a invoice
267 $messageInvoice = array();
268 $invoiceTemplate = CRM_Core_Smarty
::singleton();
269 $invoiceElements = CRM_Contribute_Form_Task_PDF
::getElements($contribIDs, $params, $contactIds);
271 // gives the status id when contribution status is 'Refunded'
272 $contributionStatusID = CRM_Contribute_PseudoConstant
::contributionStatus(NULL, 'name');
273 $refundedStatusId = CRM_Utils_Array
::key('Refunded', $contributionStatusID);
275 // getting data from admin page
276 $prefixValue = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::CONTRIBUTE_PREFERENCES_NAME
, 'contribution_invoice_settings');
278 foreach ($invoiceElements['details'] as $contribID => $detail) {
279 $input = $ids = $objects = array();
280 if (in_array($detail['contact'], $invoiceElements['excludeContactIds'])) {
284 $input['component'] = $detail['component'];
286 $ids['contact'] = $detail['contact'];
287 $ids['contribution'] = $contribID;
288 $ids['contributionRecur'] = NULL;
289 $ids['contributionPage'] = NULL;
290 $ids['membership'] = CRM_Utils_Array
::value('membership', $detail);
291 $ids['participant'] = CRM_Utils_Array
::value('participant', $detail);
292 $ids['event'] = CRM_Utils_Array
::value('event', $detail);
294 if (!$invoiceElements['baseIPN']->validateData($input, $ids, $objects, FALSE)) {
295 CRM_Core_Error
::fatal();
298 $contribution = & $objects['contribution'];
300 $input['amount'] = $contribution->total_amount
;
301 $input['invoice_id'] = $contribution->invoice_id
;
302 $input['receive_date'] = $contribution->receive_date
;
303 $input['contribution_status_id'] = $contribution->contribution_status_id
;
304 $input['organization_name'] = $contribution->_relatedObjects
['contact']->organization_name
;
306 $objects['contribution']->receive_date
= CRM_Utils_Date
::isoToMysql($objects['contribution']->receive_date
);
308 $addressParams = array('contact_id' => $contribution->contact_id
);
309 $addressDetails = CRM_Core_BAO_Address
::getValues($addressParams);
311 // to get billing address if present
312 $billingAddress = array();
313 foreach ($addressDetails as $key => $address) {
314 if ((isset($address['is_billing']) && $address['is_billing'] == 1) && (isset($address['is_primary']) && $address['is_primary'] == 1) && $address['contact_id'] == $contribution->contact_id
) {
315 $billingAddress[$address['contact_id']] = $address;
318 elseif (($address['is_billing'] == 0 && $address['is_primary'] == 1) ||
(isset($address['is_billing']) && $address['is_billing'] == 1) && $address['contact_id'] == $contribution->contact_id
) {
319 $billingAddress[$address['contact_id']] = $address;
323 if (!empty($billingAddress[$contribution->contact_id
]['state_province_id'])) {
324 $stateProvinceAbbreviation = CRM_Core_PseudoConstant
::stateProvinceAbbreviation($billingAddress[$contribution->contact_id
]['state_province_id']);
327 $stateProvinceAbbreviation = '';
330 if ($contribution->contribution_status_id
== $refundedStatusId) {
331 $creditNoteId = CRM_Utils_Array
::value('credit_notes_prefix', $prefixValue) . "" . $contribution->id
;
333 $invoiceId = CRM_Utils_Array
::value('invoice_prefix', $prefixValue) . "" . $contribution->id
;
335 //to obtain due date for PDF invoice
336 $contributionReceiveDate = date('F j,Y', strtotime(date($input['receive_date'])));
337 $invoiceDate = date("F j, Y");
338 $dueDate = date('F j ,Y', strtotime($contributionReceiveDate . "+" . $prefixValue['due_date'] . "" . $prefixValue['due_date_period']));
340 if ($input['component'] == 'contribute') {
342 $etable = 'contribution';
345 $eid = $contribution->_relatedObjects
['participant']->id
;
346 $etable = 'participant';
349 //TO DO: Need to do changes for partially paid to display amount due on PDF invoice
350 $amountDue = ($input['amount'] - $input['amount']);
352 // retreiving the subtotal and sum of same tax_rate
353 $lineItem = CRM_Price_BAO_LineItem
::getLineItems($eid, $etable);
354 $dataArray = array();
356 foreach ($lineItem as $entity_id => $taxRate) {
357 if (isset($dataArray[(string) $taxRate['tax_rate']])) {
358 $dataArray[(string) $taxRate['tax_rate']] = $dataArray[(string) $taxRate['tax_rate']] + CRM_Utils_Array
::value('tax_amount', $taxRate);
361 $dataArray[(string) $taxRate['tax_rate']] = CRM_Utils_Array
::value('tax_amount', $taxRate);
363 $subTotal +
= CRM_Utils_Array
::value('subTotal', $taxRate);
366 // to email the invoice
367 $mailDetails = array();
369 if ($contribution->_component
== 'event') {
370 $daoName = 'CRM_Event_DAO_Event';
371 $pageId = $contribution->_relatedObjects
['event']->id
;
372 $mailElements = array(
375 'confirm_from_email',
379 CRM_Core_DAO
::commonRetrieveAll($daoName, 'id', $pageId, $mailDetails, $mailElements);
380 $values['title'] = CRM_Utils_Array
::value('title', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
381 $values['confirm_from_name'] = CRM_Utils_Array
::value('confirm_from_name', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
382 $values['confirm_from_email'] = CRM_Utils_Array
::value('confirm_from_email', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
383 $values['cc_confirm'] = CRM_Utils_Array
::value('cc_confirm', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
384 $values['bcc_confirm'] = CRM_Utils_Array
::value('bcc_confirm', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
386 $title = CRM_Utils_Array
::value('title', $mailDetails[$contribution->_relatedObjects
['event']->id
]);
388 elseif ($contribution->_component
== 'contribute') {
389 $daoName = 'CRM_Contribute_DAO_ContributionPage';
390 $pageId = $contribution->contribution_page_id
;
391 $mailElements = array(
394 'receipt_from_email',
398 CRM_Core_DAO
::commonRetrieveAll($daoName, 'id', $pageId, $mailDetails, $mailElements);
400 $values['title'] = CRM_Utils_Array
::value('title', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
401 $values['receipt_from_name'] = CRM_Utils_Array
::value('receipt_from_name', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
402 $values['receipt_from_email'] = CRM_Utils_Array
::value('receipt_from_email', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
403 $values['cc_receipt'] = CRM_Utils_Array
::value('cc_receipt', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
404 $values['bcc_receipt'] = CRM_Utils_Array
::value('bcc_receipt', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
406 $title = CRM_Utils_Array
::value('title', CRM_Utils_Array
::value($contribution->contribution_page_id
, $mailDetails));
408 $source = $contribution->source
;
410 $config = CRM_Core_Config
::singleton();
411 if (!isset($params['forPage'])) {
412 $config->doNotAttachPDFReceipt
= 1;
415 // get organization address
416 $domain = CRM_Core_BAO_Domain
::getDomain();
417 $locParams = array('contact_id' => $domain->id
);
418 $locationDefaults = CRM_Core_BAO_Location
::getValues($locParams);
419 if (isset($locationDefaults['address'][1]['state_province_id'])) {
420 $stateProvinceAbbreviationDomain = CRM_Core_PseudoConstant
::stateProvinceAbbreviation($locationDefaults['address'][1]['state_province_id']);
423 $stateProvinceAbbreviationDomain = '';
425 if (isset($locationDefaults['address'][1]['country_id'])) {
426 $countryDomain = CRM_Core_PseudoConstant
::country($locationDefaults['address'][1]['country_id']);
432 // parameters to be assign for template
435 'component' => $input['component'],
436 'id' => $contribution->id
,
438 'invoice_id' => $invoiceId,
439 'imageUploadURL' => $config->imageUploadURL
,
440 'defaultCurrency' => $config->defaultCurrency
,
441 'amount' => $contribution->total_amount
,
442 'amountDue' => $amountDue,
443 'invoice_date' => $invoiceDate,
444 'dueDate' => $dueDate,
445 'notes' => CRM_Utils_Array
::value('notes', $prefixValue),
446 'display_name' => $contribution->_relatedObjects
['contact']->display_name
,
447 'lineItem' => $lineItem,
448 'dataArray' => $dataArray,
449 'refundedStatusId' => $refundedStatusId,
450 'contribution_status_id' => $contribution->contribution_status_id
,
451 'subTotal' => $subTotal,
452 'street_address' => CRM_Utils_Array
::value('street_address', CRM_Utils_Array
::value($contribution->contact_id
, $billingAddress)),
453 'supplemental_address_1' => CRM_Utils_Array
::value('supplemental_address_1', CRM_Utils_Array
::value($contribution->contact_id
, $billingAddress)),
454 'supplemental_address_2' => CRM_Utils_Array
::value('supplemental_address_2', CRM_Utils_Array
::value($contribution->contact_id
, $billingAddress)),
455 'city' => CRM_Utils_Array
::value('city', CRM_Utils_Array
::value($contribution->contact_id
, $billingAddress)),
456 'stateProvinceAbbreviation' => $stateProvinceAbbreviation,
457 'postal_code' => CRM_Utils_Array
::value('postal_code', CRM_Utils_Array
::value($contribution->contact_id
, $billingAddress)),
458 'is_pay_later' => $contribution->is_pay_later
,
459 'organization_name' => $contribution->_relatedObjects
['contact']->organization_name
,
460 'domain_organization' => $domain->name
,
461 'domain_street_address' => CRM_Utils_Array
::value('street_address', CRM_Utils_Array
::value('1', $locationDefaults['address'])),
462 'domain_supplemental_address_1' => CRM_Utils_Array
::value('supplemental_address_1', CRM_Utils_Array
::value('1', $locationDefaults['address'])),
463 'domain_supplemental_address_2' => CRM_Utils_Array
::value('supplemental_address_2', CRM_Utils_Array
::value('1', $locationDefaults['address'])),
464 'domain_city' => CRM_Utils_Array
::value('city', CRM_Utils_Array
::value('1', $locationDefaults['address'])),
465 'domain_postal_code' => CRM_Utils_Array
::value('postal_code', CRM_Utils_Array
::value('1', $locationDefaults['address'])),
466 'domain_state' => $stateProvinceAbbreviationDomain,
467 'domain_country' => $countryDomain,
468 'domain_email' => CRM_Utils_Array
::value('email', CRM_Utils_Array
::value('1', $locationDefaults['email'])),
469 'domain_phone' => CRM_Utils_Array
::value('phone', CRM_Utils_Array
::value('1', $locationDefaults['phone'])),
471 if (isset($creditNoteId)) {
472 $tplParams['creditnote_id'] = $creditNoteId;
474 $sendTemplateParams = array(
475 'groupName' => 'msg_tpl_workflow_contribution',
476 'valueName' => 'contribution_invoice_receipt',
477 'contactId' => $contribution->contact_id
,
478 'tplParams' => $tplParams,
479 'PDFFilename' => 'Invoice.pdf',
481 $session = CRM_Core_Session
::singleton();
482 $contactID = $session->get('userID');
483 $contactEmails = CRM_Core_BAO_Email
::allEmails($contactID);
485 $fromDisplayName = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Contact',
486 $contactID, 'display_name'
489 foreach ($contactEmails as $emailId => $item) {
490 $email = $item['email'];
492 $emails[$emailId] = '"' . $fromDisplayName . '" <' . $email . '> ';
495 $fromEmail = CRM_Utils_Array
::crmArrayMerge($emails, CRM_Core_OptionGroup
::values('from_email_address'));
497 // from email address
498 if (isset($params['from_email_address'])) {
499 $fromEmailAddress = CRM_Utils_Array
::value($params['from_email_address'], $fromEmail);
501 // condition to check for download PDF Invoice or email Invoice
502 if ($invoiceElements['createPdf']) {
503 list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate
::sendTemplate($sendTemplateParams);
504 if (isset($params['forPage'])) {
509 'subject' => $subject,
514 $messageInvoice[] = $mail['html'];
517 $messageInvoice[] = nl2br($mail['body']);
521 elseif ($contribution->_component
== 'contribute') {
522 $email = CRM_Contact_BAO_Contact
::getPrimaryEmail($contribution->contact_id
);
524 $sendTemplateParams['tplParams'] = array_merge($tplParams, array('email_comment' => $invoiceElements['params']['email_comment']));
525 $sendTemplateParams['from'] = $fromEmailAddress;
526 $sendTemplateParams['toEmail'] = $email;
527 $sendTemplateParams['cc'] = CRM_Utils_Array
::value('cc_receipt', $values);
528 $sendTemplateParams['bcc'] = CRM_Utils_Array
::value('bcc_receipt', $values);
530 list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate
::sendTemplate($sendTemplateParams);
531 // functions call for adding activity with attachment
532 $fileName = self
::putFile($html);
533 self
::addActivities($subject, $contribution->contact_id
, $fileName, $params);
535 elseif ($contribution->_component
== 'event') {
536 $email = CRM_Contact_BAO_Contact
::getPrimaryEmail($contribution->contact_id
);
538 $sendTemplateParams['tplParams'] = array_merge($tplParams, array('email_comment' => $invoiceElements['params']['email_comment']));
539 $sendTemplateParams['from'] = $fromEmailAddress;
540 $sendTemplateParams['toEmail'] = $email;
541 $sendTemplateParams['cc'] = CRM_Utils_Array
::value('cc_confirm', $values);
542 $sendTemplateParams['bcc'] = CRM_Utils_Array
::value('bcc_confirm', $values);
544 list($sent, $subject, $message, $html) = CRM_Core_BAO_MessageTemplate
::sendTemplate($sendTemplateParams);
545 // functions call for adding activity with attachment
546 $fileName = self
::putFile($html);
547 self
::addActivities($subject, $contribution->contact_id
, $fileName, $params);
550 CRM_Core_DAO
::setFieldValue('CRM_Contribute_DAO_Contribution', $contribution->id
, 'invoice_id', $invoiceId);
551 if ($contribution->contribution_status_id
== $refundedStatusId) {
552 CRM_Core_DAO
::setFieldValue('CRM_Contribute_DAO_Contribution', $contribution->id
, 'creditnote_id', $creditNoteId);
554 $invoiceTemplate->clearTemplateVars();
557 if ($invoiceElements['createPdf']) {
558 if (isset($params['forPage'])) {
562 CRM_Utils_PDF_Utils
::html2pdf($messageInvoice, 'Invoice.pdf', FALSE, array(
567 // functions call for adding activity with attachment
568 $fileName = self
::putFile($html);
569 self
::addActivities($subject, $contactIds, $fileName, $params['output']);
571 CRM_Utils_System
::civiExit();
575 if ($invoiceElements['suppressedEmails']) {
576 $status = ts('Email was NOT sent to %1 contacts (no email address on file, or communication preferences specify DO NOT EMAIL, or contact is deceased).', array(1 => $invoiceElements['suppressedEmails']));
577 $msgTitle = ts('Email Error');
581 $status = ts('Your mail has been sent.');
582 $msgTitle = ts('Sent');
583 $msgType = 'success';
585 CRM_Core_Session
::setStatus($status, $msgTitle, $msgType);
591 * This function is use for adding activity for
592 * Email Invoice and the PDF Invoice
594 * @param string $subject Activity subject
595 * @param array $contactIds Contact Id
596 * @param string $fileName gives the location with name of the file
597 * @param array $output for invoices
602 static public function addActivities($subject, $contactIds, $fileName, $output) {
603 $session = CRM_Core_Session
::singleton();
604 $userID = $session->get('userID');
605 $config = CRM_Core_Config
::singleton();
606 $config->doNotAttachPDFReceipt
= 1;
607 if ($output['output'] == 'email_invoice' ||
(is_array($output) && array_key_exists("from_email_address", $output))) {
608 $activityTypeID = CRM_Core_OptionGroup
::getValue('activity_type',
614 $activityTypeID = CRM_Core_OptionGroup
::getValue('activity_type',
615 'Downloaded Invoice',
619 $activityParams = array(
620 'subject' => $subject,
621 'source_contact_id' => $userID,
622 'target_contact_id' => $contactIds,
623 'activity_type_id' => $activityTypeID,
624 'activity_date_time' => date('YmdHis'),
625 'attachFile_1' => array(
627 'type' => 'application/pdf',
628 'location' => $fileName,
629 'upload_date' => date('YmdHis'),
632 CRM_Activity_BAO_Activity
::create($activityParams);
637 * This function is use for creating the Invoice file in upload folder
640 * @param $html content for pdf in html format
642 * return $fileName of file which is in pdf format
645 static public function putFile($html) {
646 require_once("packages/dompdf/dompdf_config.inc.php");
647 spl_autoload_register('DOMPDF_autoload');
649 $doc->load_html($html);
651 $html = $doc->output();
652 $config = CRM_Core_Config
::singleton();
653 $fileName = $config->uploadDir
. 'Invoice.pdf';
654 file_put_contents($fileName, $html);