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)-1false);
  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_OS03)) === 'WIN' && ini_get("sendmail_from")){
  251.       ini_set("sendmail_from"$from);
  252.       $server $conf->value('email''smtp_server');
  253.       if ($serverini_set('SMTP'$server);
  254.       $port $conf->value('email''smtp_port');
  255.       if ($portini_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($fhfilesize($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