Source for file billing.php

Documentation is available at billing.php

  1. <?php
  2. /**
  3. * Send billing data by email
  4. *
  5. * @author    Stuart Prescott
  6. * @copyright  Copyright Stuart Prescott
  7. * @license    http://opensource.org/licenses/gpl-license.php GNU Public License
  8. * @version    $Id$
  9. * @package    Bumblebee
  10. * @subpackage Actions
  11. *
  12. *  path (bumblebee root)/inc/actions/billing.php
  13. */
  14.  
  15. /** Load ancillary functions */
  16. require_once 'inc/typeinfo.php';
  17.  
  18. require_once 'inc/bb/configreader.php';
  19.  
  20. /** parent object */
  21. require_once 'inc/actions/export.php';
  22. /** ExportType and formatting */
  23. require_once 'inc/export/exporttypes.php';
  24. /** Export formatting codes */
  25. require_once 'inc/exportcodes.php';
  26. /** db interrogation object */
  27. require_once 'inc/formslib/dblist.php';
  28.  
  29. /**
  30. * Send billing data by email
  31. *
  32. *  Find out what sort of report is required and generate it
  33. *
  34. * @package    Bumblebee
  35. * @subpackage Actions
  36. */
  37. class ActionBilling extends ActionExport {
  38.   /**
  39.   * should all group leaders be send the email or just the logged in user
  40.   * @var boolean 
  41.   */
  42.   var $emailIndividuals = false;
  43.   /**
  44.   * mail error message (if sending mail went wrong)
  45.   * @var string 
  46.   */
  47.   var $mail_error = NULL;
  48.   /**
  49.   * enable additional debugging information for PDF generation
  50.   * @var boolean 
  51.   */
  52.   var $DEBUG_PDF = false;
  53.  
  54.   /**
  55.   * Initialising the class
  56.   *
  57.   * @param  BumblebeeAuth $auth  Authorisation object
  58.   * @param  array $pdata   extra state data from the call path
  59.   * @return void nothing
  60.   */
  61.   function ActionBilling($auth, $pdata) {
  62.     parent::ActionExport($auth, $pdata);
  63.     //$this->format = EXPORT_FORMAT_VIEW;
  64.     $this->format = EXPORT_FORMAT_PDF;
  65.     $this->_verb = 'billing';
  66.     $this->PD['what'] = 'billing';
  67.     $this->reportSet = array('group' => 'users',
  68.                              'bookingbilling' => 'groups',
  69.                              'consumablegroup' => 'users',
  70.                              'billing' => '');
  71.   }
  72.  
  73.   function mungeInputData() {
  74.     $this->emailIndividuals = issetSet($_POST, 'emailToGroups');
  75.     //echo $this->emailIndividuals ? 'true' : 'false';
  76.     parent::mungeInputData();
  77.   }
  78.  
  79.   /**
  80.   * convenience function to generate a submit button
  81.   */
  82.   function _goButton() {
  83.     echo '<label>'
  84.           .'<input type="radio" name="emailToGroups" value="0" checked="checked" /> '
  85.           .T_('Email report to me').' ('.xssqw($this->auth->email).')'
  86.         .'</label><br/>';
  87.     echo '<label>'
  88.           .'<input type="radio" name="emailToGroups" value="1" /> '
  89.           .T_('Email report to each group leader')
  90.         .'</label><br/><br/>';
  91.     parent::_goButton();
  92.   }
  93.  
  94.   /**
  95.   * get all the data and send it back to the user
  96.   */
  97.   function returnExport() {
  98.     #$this->DEBUG=10;
  99.     $lists = array();
  100.     $pdfs = array();
  101.     $nopdfs = array();
  102.     foreach ($this->reportSet as $report => $pivot) {
  103.       $this->PD['pivot'] = $pivot;
  104.       $lists[] = $this->_getDataList($report);
  105.       # preDump($lists);
  106.     }
  107.     $groups = $this->_limitationSet(array('groups'), count($this->reportSet)-1, false);
  108.     #preDump($groups);
  109.     $noData = true;
  110.     foreach ($groups['groups'] as $g) {
  111.       $noGroupData = true;
  112.       $exportArray = new ArrayExport($lists[0], '');
  113.       $exportArray->header = $this->_reportHeader();
  114.       $exportArray->author = $this->auth->name;
  115.       for ($r = 0; $r < count($lists); $r++) {
  116.         // put a restriction on what to return for this incarnation
  117.         $l = clone($lists[$r]);
  118.         $l->unionrestriction[] = 'groups.id = '.$g;   // $g is already qw($g)
  119.         $l->restriction[] = 'groups.id = '.$g;   // $g is already qw($g)
  120.         $l->fill();
  121.         $noData = $noData && ! count($l->data);
  122.         $noGroupData = $noGroupData && ! count($l->data);
  123.         $this->log('Found '. count($l->data) .' rows');
  124.  
  125.         if (count($l->data)) {
  126.           // start rendering the data
  127.           $l->outputFormat = $this->format;
  128.           $l->formatList();
  129.           $this->log('Creating new AE');
  130.           //preDump($lists[$r]);
  131.           $ea = new ArrayExport($l, $l->breakfield);
  132.           $ea->header = $this->_reportHeader();
  133.           $ea->makeExportArray();
  134.           $this->log('Appending EA');
  135.           #preDump(count($exportArray->export));
  136.           $exportArray->appendEA($ea);
  137.           #preDump(count($exportArray->export));
  138.         }
  139.       }
  140.       //preDump($exportArray);
  141.       $who = quickSQLSelect('groups', 'id', unqw($g));
  142.       if (! $noGroupData) {
  143.         $filename = $this->_getReportFilename($who['name']);
  144.         $pdfExport = $this->_preparePDFExport($exportArray);
  145.         $pdfExport->filename = $filename;
  146.         $pdfExport->useBigTable = false;
  147.         if ($this->DEBUG_PDF) {
  148.           $pdfExport->writeToFile = true;
  149.         } else {
  150.           $pdfExport->writeToFile = false;
  151.         }
  152.         $pdfExport->makePDFBuffer();
  153.         $pdfs[] = array('filename'  => $filename,
  154.                         'mimetype'  => $this->mimetype,
  155.                         'data'      => $pdfExport->export,
  156.                         'groupdata' => $who);
  157.       } else {
  158.         // if there was no data, then record that fact for later reporting.
  159.         $nopdfs[] = array('groupdata' => $who);
  160.       }
  161.     }
  162.     if ($noData) {
  163.       return $this->unbufferForError('<p>'.T_('No data found for those criteria').'</p>');
  164.     } else {
  165.       // dump out the files via email or a zip file....
  166.       $this->unbuffer();
  167.       if ($this->emailIndividuals) {
  168.         $success = 1;
  169.         for ($group=0; $group<count($pdfs); $group++) {
  170.           $success &= $this->_sendPDFbyEmail($pdfs[$group]['groupdata']['name'],
  171.                                             $pdfs[$group]['groupdata']['email'],
  172.                                             $pdfs[$group]['groupdata'],
  173.                                             array($pdfs[$group]));
  174.         }
  175.       } else {
  176.         $grouplist = array();
  177.         for ($group=0; $group<count($pdfs); $group++) {
  178.           $grouplist[] = $pdfs[$group]['groupdata']['longname'];
  179.         }
  180.         $gpinfo = array('name' => $this->auth->name, 'longname' => "\n".join($grouplist, "\n"));
  181.         $success = $this->_sendPDFbyEmail($this->auth->name, $this->auth->email, $gpinfo, $pdfs);
  182.       }
  183.       if ($success) {
  184.         $s = '<div class="msgsuccess">'
  185.             .T_('Reports sent by email.').'</div>';
  186.         echo $s;
  187.       } else {
  188.         $s = '<div class="msgerror">'
  189.             .T_('An error occured sending reports by email.').' '
  190.             .(empty($this->mail_error)
  191.                   ? T_('An unknown error occured.')
  192.                   : sprintf(T_('The mail function said: <pre>%s</pre>'), $this->mail_error))
  193.             .'</div>';
  194.         echo $s;
  195.       }
  196.       if (count($nopdfs)) {
  197.         $s = '<div class="msgerror">'
  198.             .T_('<b>Note:</b> no billing data was found for some groups.').'<br/><br/>';
  199.         foreach ($nopdfs as $group) {
  200.           $s .= xssqw($group['groupdata']['name']).': '
  201.                .xssqw($group['groupdata']['longname']).'<br/>';
  202.         }
  203.         $s .= '</div>';
  204.         echo $s;
  205.       }
  206.       echo '<div>'.T_('Regenerate reports:').'<br/><br/>';
  207.       $this->_goButton();
  208.       echo '</div>';
  209.     }
  210.   }
  211.  
  212.   /**
  213.   * obtain an appropriate filename for the data export
  214.   */
  215.   function _getReportFilename($who) {
  216.     $conf = ConfigReader::getInstance();
  217.     $name = $conf->value('billing', 'filename');
  218.     $this->mimetype = 'application/pdf';
  219.     $who = urlencode($who);
  220.     $name = preg_replace('/__date__/', strftime('%Y%m%d-%H%M%S', time()), $name);
  221.     $name = preg_replace('/__who__/', $who, $name);
  222.     return $name;
  223.   }
  224.  
  225.   /**
  226.   * send the PDF to the appropriate person by email
  227.   * the logged in user is always included in the To list for their records
  228.   *
  229.   * @param string $toName  name of the person to receive the email
  230.   * @param string $toEmail  email addr of recipient
  231.   * @param string $group   name of the group for which this report is being generated
  232.   * @param string $data    PDF data to be sent
  233.   */
  234.   function _sendPDFbyEmail($toName, $toEmail, $group, $data) {
  235.     $conf = ConfigReader::getInstance();
  236.     $eol = "\r\n";
  237.     //$from = $conf->value('billing', 'emailFromName').' <'.$conf->value('main','SystemEmail').'>';
  238.     $from = $conf->value('main', 'SystemEmail');
  239.     $returnpath = $conf->value('main', 'SystemEmail');
  240.     $replyto = $this->auth->name.' <'.$this->auth->email.'>';
  241.     $cc   = $this->auth->name.' <'.$this->auth->email.'>';    // CC a copy to the sender
  242.     $to   = $toName.' <'.$toEmail.'>';
  243.     $recipient_list = array($this->auth->email, $toEmail);
  244.     srand(time());
  245.     $id   = '<bumblebee-'.time().'-'.rand().'@'.$_SERVER['SERVER_NAME'].'>';
  246.  
  247.     // Try to work around various PHP bugs in sending mail
  248.     // see: http://marc.theaimsgroup.com/?l=php-dev&m=109286883222906&w=2
  249.     //      http://bugs.php.net/bug.php?id=28976
  250.     if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && ! ini_get("sendmail_from")){
  251.       ini_set("sendmail_from", $from);
  252.       $server = $conf->value('email', 'smtp_server');
  253.       if ($server) ini_set('SMTP', $server);
  254.       $port = $conf->value('email', 'smtp_port');
  255.       if ($port) ini_set('smtp_port', $port);
  256.     }
  257.  
  258.     $headers  = 'Return-path: '.$returnpath .$eol;
  259.     $headers .= 'From: '.$from .$eol;
  260.     //$headers .= 'To: '.$to .$eol;    // automatically added by mail()
  261.     //$headers .= 'Cc: '.$cc .$eol;    // automatically added by mail() ?
  262.     $headers .= 'Reply-To: '.$replyto.$eol;
  263.     $headers .= 'Message-id: ' .$id .$eol;
  264.  
  265.     $start = $this->_daterange->getStart();
  266.     $stop  = $this->_daterange->getStop();
  267.  
  268.     $textmessage = $this->_getEmailText($group, $start->dateString(), $stop->dateString());
  269.  
  270.     //$textmessage = 'Please find attached PDF billing summaries for instrument usage.';
  271.     $subject = ($conf->value('billing', 'emailSubject')
  272.                     ? $conf->value('billing', 'emailSubject') : T_('Instrument usage summary'));
  273.  
  274.     //Having read in the data for the file attachment,
  275.     //we need to set up the message headers to send a multipart/mixed message:
  276.  
  277.     // Generate a boundary string
  278.     $semi_rand = md5(time());
  279.     $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
  280.  
  281.     // Add the headers for a file attachment
  282.     $headers .= 'MIME-Version: 1.0'.$eol
  283.                .'Content-Type: multipart/mixed;'.$eol
  284.                .' boundary="'.$mime_boundary.'"'.$eol;
  285.  
  286.     // Add a multipart boundary above the plain message
  287.     $message = 'This is a multi-part message in MIME format.'.$eol .$eol
  288.                .'--'.$mime_boundary.$eol
  289.                .'Content-Type: text/plain; charset="iso-8859-1"'.$eol
  290.                .'Content-Transfer-Encoding: 7bit' .$eol.$eol
  291.                .$textmessage .$eol.$eol;
  292.  
  293.     for ($att=0; $att<count($data); $att++) {
  294.       //echo strlen($data[$att]['data']);
  295.       // Base64 encode the file data
  296.       $attdata = chunk_split(base64_encode($data[$att]['data']));
  297.  
  298.       // Add file attachment to the message
  299.       $message .= '--'.$mime_boundary . $eol
  300.                  .'Content-Type: '.$data[$att]['mimetype'].';'.$eol
  301.                  .' name="'.$data[$att]['filename'].'"'.$eol
  302.                  .'Content-Disposition: attachment;'.$eol
  303.                  .' filename="'.$data[$att]['filename'].'"'.$eol
  304.                  .'Content-Transfer-Encoding: base64'.$eol.$eol
  305.                  .$attdata . $eol.$eol;
  306.     }
  307.     $message .= '--'.$mime_boundary.'--'.$eol;
  308.  
  309.     // Send the message
  310. /*    $fh = fopen('/tmp/mail.mbox', 'w');
  311.     fwrite($fh, $headers.$eol.$message);
  312.     fclose($fh);
  313.     return 1;*/
  314.  
  315.     // try to get more useful error messages from the mail() function
  316.     ini_set('track_errors', true);
  317.     $php_errormsg = '';
  318.     $ok =  mail(join(', ', $recipient_list), $subject, $message, $headers);
  319.     if ($ok === false) {   // error sending mail
  320.       $this->mail_error = $php_errormsg;
  321.     }
  322.     #print "sent mail to $to, $cc\n";
  323.     return $ok;
  324.   }
  325.  
  326.   /**
  327.   * Reads the boilerplate text for the email and customise it for this email
  328.   *
  329.   * @param string $group   name of the group for which this report is being generated
  330.   * @param string $start   the start date for the report
  331.   * @param string $stop    the stop date for the report
  332.   */
  333.   function _getEmailText($group, $start, $stop) {
  334.     $conf = ConfigReader::getInstance();
  335.     $fh = fopen($conf->value('billing', 'emailTemplate'), 'r');
  336.     $txt = fread($fh, filesize($conf->value('billing', 'emailTemplate')));
  337.     fclose($fh);
  338.     $replace = array(
  339.             '/__name__/'      => $group['name'],
  340.             '/__groupname__/' => $group['longname'],
  341.             '/__start__/'     => $start,
  342.             '/__stop__/'      => $stop,
  343.             '/__host__/'      => makeAbsURL()
  344.                     );
  345.     $txt = preg_replace(array_keys($replace),
  346.                         array_values($replace),
  347.                         $txt);
  348.     return $txt;
  349.   }
  350.  
  351. } // ActionBilling
  352.  
  353. ?>

Documentation generated on Tue, 06 Mar 2007 10:00:43 +0000 by phpDocumentor 1.3.0