/**
  * Handler to view a generated report file
  *
  * @param type $data
  * @param type $form
  */
 public function viewreport($request)
 {
     $item = 1;
     $allowed = array('html', 'pdf', 'csv');
     $ext = $request->getExtension();
     if (!in_array($ext, $allowed)) {
         return $this->httpError(404);
     }
     $reportID = (int) $request->param('ID');
     $fileID = (int) $request->param('OtherID');
     $report = AdvancedReport::get()->byID($reportID);
     if (!$report || !$report->canView()) {
         return $this->httpError(404);
     }
     $file = $report->{strtoupper($ext) . 'File'}();
     if (!$file || !strlen($file->Content)) {
         return $this->httpError(404);
     }
     $mimeType = HTTP::get_mime_type($file->Name);
     header("Content-Type: {$mimeType}; name=\"" . addslashes($file->Name) . "\"");
     header("Content-Disposition: attachment; filename=" . addslashes($file->Name));
     header("Content-Length: {$file->getSize()}");
     header("Pragma: ");
     session_write_close();
     ob_flush();
     flush();
     // Push the file while not EOF and connection exists
     echo base64_decode($file->Content);
     exit;
 }
 public function getSettingsFields()
 {
     $fields = parent::getSettingsFields();
     $types = ClassInfo::subclassesFor('DataObject');
     array_shift($types);
     ksort($types);
     $fields->insertAfter(new DropdownField('ReportOn', _t('AdvancedReport.REPORT_ON', 'Report on'), $types), 'Title');
     return $fields;
 }
 public function getCMSFields($params = null)
 {
     $fields = new FieldList();
     // tabbed or untabbed
     $fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
     $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
     $reports = array();
     $reportObjs = AdvancedReport::get()->filter(array('ReportID' => 0));
     if ($reportObjs && $reportObjs->count()) {
         foreach ($reportObjs as $obj) {
             if ($obj instanceof CombinedReport) {
                 continue;
             }
             $reports[$obj->ID] = $obj->Title . '(' . $obj->ClassName . ')';
         }
     }
     $fields->addFieldsToTab('Root.Main', array(new DropdownField('ReportID', 'Related report', $reports), new TextField('Title'), new KeyValueField('Parameters', 'Parameters to pass to the report'), new NumericField('Sort')));
     return $fields;
 }
 /**
  * @return AdvancedReport
  */
 public function getReport()
 {
     return AdvancedReport::get()->byID($this->reportID);
 }
 /**
  * Overwrites SiteTree.getCMSFields.
  *
  * This method creates a customised CMS form for back-end user.
  *
  * @return fieldset
  */
 function getCMSFields()
 {
     $fields = parent::getCMSFields();
     $fields->removeFieldsFromTab("Root.Main", array("Pages"));
     return $fields;
 }
 /**
  * Restructures the data objects according to the settings of the report.
  *
  * @todo this method is too complex and should be refactored into smaller methods
  */
 protected function reformatDataObjects()
 {
     $this->data = array();
     $dataObjects = $this->report->getDataObjects();
     $colsToBlank = $this->report->getDuplicatedBlankingFields();
     $i = 0;
     $previousVals = array();
     $tableName = self::DEFAULT_TABLE_NAME;
     $paginateBy = $this->report->dottedFieldToUnique($this->report->PaginateBy);
     $headerTemplate = $this->report->PageHeader ? $this->report->PageHeader : '$name';
     $addCols = null;
     if ($this->report->AddInRows && count($this->report->AddInRows->getValues())) {
         $addCols = $this->report->AddInRows->getValues();
     }
     if (!$dataObjects) {
         $this->data[$tableName] = array();
         return;
     }
     foreach ($dataObjects as $item) {
         // lets check to see whether this item has the paginate variable, if so we want to be
         // adding this result to that table entry
         if ($paginateBy) {
             $pageVar = is_object($item) ? $item->{$paginateBy} : $item[$paginateBy];
             if ($pageVar) {
                 $tableName = str_replace('$name', $pageVar, $headerTemplate);
             } else {
                 $tableName = sprintf(_t('ReportFormatter.NO_PAGINATE_VALUE', 'No %s'), $paginateBy);
             }
         }
         $row = array();
         $addToTable = isset($this->data[$tableName]) ? $this->data[$tableName] : array();
         $rowSum = 0;
         foreach ($this->headers as $field => $display) {
             // Account for our total summation of things.
             if ($field == self::ADD_IN_ROWS_TOTAL) {
                 if (is_object($item)) {
                     $item->{$field} = $rowSum;
                 } else {
                     $item[$field] = $rowSum;
                 }
             }
             // check if the value is coming from an object or is an element of an array
             $value = 0;
             if (is_object($item)) {
                 // if this is an object we need to check if the field we are looking for is a method or a value
                 if (method_exists($item, $field)) {
                     $value = $item->{$field}();
                 } else {
                     $value = $item->{$field};
                 }
             } else {
                 $value = $item[$field];
             }
             if (in_array($field, $colsToBlank)) {
                 if (!isset($previousVals[$field]) || $previousVals[$field] != $value) {
                     $row[$field] = $value;
                     // if this value that has changed is the 'first' value, then we need to reset all the other
                     // 'previous' values from left to right from this position
                     $previousVals = $this->resetPreviousVals($previousVals, $field);
                     $previousVals[$field] = $value;
                 } else {
                     $row[$field] = '';
                 }
             } else {
                 $row[$field] = $value;
             }
             if ($addCols && in_array($field, $addCols)) {
                 $rowSum += $value;
             }
         }
         $addToTable[] = $row;
         $this->data[$tableName] = $addToTable;
         $i++;
     }
     // now that the tables have been created, need to do column summation on each. We could do this during
     // the above looping, but because we don't FORCE the items to be properly sorted first, we can't guarantee
     // that the columns that need summation are in the right places
     $addCols = $this->report->AddCols ? $this->report->AddCols->getValues() : array();
     if (count($addCols)) {
         // if we had a row total, we'll add it in by default; it only makes sense!
         if (isset($this->headers[self::ADD_IN_ROWS_TOTAL])) {
             $addCols[] = self::ADD_IN_ROWS_TOTAL;
         }
         foreach ($this->data as $tableName => $data) {
             $sums = array();
             $titleColumn = null;
             foreach ($data as $row) {
                 $prevField = null;
                 foreach ($row as $field => $value) {
                     if (in_array($field, $addCols)) {
                         // if we haven't already figured it out, we now know that we want the field BEFORE
                         // this as the column we put the Total text into
                         if (!$titleColumn) {
                             $titleColumn = $prevField;
                         }
                         $cur = isset($sums[$field]) ? $sums[$field] : 0;
                         // use a report custom method for adding up or count/sum it up
                         //  based on the best possible assumptions we can make
                         if (method_exists($this->report, 'columnAdder')) {
                             $sums[$field] = $this->report->columnAdder($field, $cur, $value);
                         } else {
                             // summing up totals makes only sense if it is a number
                             // otherwise we count the number of items
                             if (is_numeric($value)) {
                                 $sums[$field] = $cur + $value;
                             } else {
                                 $sums[$field] = $cur + 1;
                             }
                         }
                     } else {
                         $sums[$field] = '';
                     }
                     $prevField = $field;
                 }
             }
             // figure out the name of the field we want to stick the Total text
             $sums[$titleColumn] = _t('ReportFormatter.ROW_TOTAL', 'Total');
             $data[] = $sums;
             $this->data[$tableName] = $data;
         }
     }
 }
 /**
  * Creates a report in a specified format, returning a string which contains either
  * the raw content of the report, or an object that encapsulates the report (eg a PDF).
  *
  * @param string $format
  * @param boolean $store
  *				Whether to store the created report.
  * @param array $parameters
  *				An array of parameters that will be used as dynamic replacements
  */
 public function createReport($format = 'html', $store = false)
 {
     Requirements::clear();
     $convertTo = null;
     $renderFormat = $format;
     if (isset(AdvancedReport::config()->conversion_formats[$format])) {
         $convertTo = 'pdf';
         $renderFormat = AdvancedReport::config()->conversion_formats[$format];
     }
     $reports = $this->ChildReports();
     if (!$reports->count()) {
         return _t('AdvancedReport.NO_REPORTS_SELECTED', 'No reports selected');
     }
     $contents = array();
     foreach ($reports as $report) {
         if (!$report->ReportID) {
             continue;
         }
         $params = $report->Parameters;
         $report = $report->Report();
         if ($params) {
             $params = $params->getValues();
             $baseParams = $report->ReportParams->getValues();
             $params = array_merge($baseParams, $params);
             $report->ReportParams = $params;
         }
         $formatter = $report->getReportFormatter($renderFormat);
         if ($formatter) {
             $contents[] = $report->customise(array('ReportContent' => $formatter->format()));
         } else {
             $contents[] = new ArrayData(array('ReportContent' => "Formatter for '{$renderFormat}' not found."));
         }
     }
     $templates = array(get_class($this) . '_' . $renderFormat);
     $date = DBField::create_field('SS_Datetime', time());
     $this->Description = nl2br($this->Description);
     $reportData = array('Reports' => new ArrayList($contents), 'Format' => $format, 'Now' => $date);
     $output = $this->customise($reportData)->renderWith($templates);
     if (!$output) {
         // put_contents fails if it's an empty string...
         $output = " ";
     }
     if (!$convertTo) {
         if ($store) {
             // stick it in a temp file?
             $outputFile = tempnam(TEMP_FOLDER, $format);
             if (file_put_contents($outputFile, $output)) {
                 return new AdvancedReportOutput(null, $outputFile);
             } else {
                 throw new Exception("Failed creating report in {$outputFile}");
             }
         } else {
             return new AdvancedReportOutput($output);
         }
     }
     // hard coded for now, need proper content transformations....
     switch ($convertTo) {
         case 'pdf':
             if ($store) {
                 $filename = singleton('PdfRenditionService')->render($output);
                 return new AdvancedReportOutput(null, $filename);
             } else {
                 singleton('PdfRenditionService')->render($output, 'browser');
                 return new AdvancedReportOutput();
             }
             break;
         default:
             break;
     }
 }
 /**
  * Restructures the data objects according to the settings of the report. 
  */
 protected function reformatDataObjects()
 {
     $this->data = array();
     $dataObjects = $this->report->getDataObjects();
     $colsToBlank = $this->report->getDuplicatedBlankingFields();
     $mapping = $this->report->getFieldMapping();
     $i = 0;
     $previousVals = array();
     $tableName = self::DEFAULT_TABLE_NAME;
     $paginateBy = $this->report->PaginateBy;
     $headerTemplate = $this->report->PageHeader ? $this->report->PageHeader : '$name';
     $addCols = $this->report->AddInRows && count($this->report->AddInRows->getValues()) ? $this->report->AddInRows->getValues() : null;
     if (!$dataObjects) {
         $this->data[$tableName] = array();
         return;
     }
     foreach ($dataObjects as $item) {
         // lets check to see whether this item has the paginate variable, if so we want to be
         // adding this result to that table entry
         if ($paginateBy) {
             $pageVar = is_object($item) ? $item->{$paginateBy} : $item[$paginateBy];
             if ($pageVar) {
                 $tableName = str_replace('$name', $pageVar, $headerTemplate);
             } else {
                 $tableName = sprintf(_t('ReportFormatter.NO_PAGINATE_VALUE', 'No %s'), $paginateBy);
             }
         }
         $row = array();
         $addToTable = isset($this->data[$tableName]) ? $this->data[$tableName] : array();
         $rowSum = 0;
         foreach ($this->headers as $field => $display) {
             // Account for our total summation of things.
             if ($field == self::ADD_IN_ROWS_TOTAL) {
                 if (is_object($item)) {
                     $item->{$field} = $rowSum;
                 } else {
                     $item[$field] = $rowSum;
                 }
             }
             $rawValue = is_object($item) ? $item->{$field} : $item[$field];
             $value = '';
             // based on the field name we've been given, lets
             // see if we can resolve it to a value on our data object
             if (isset($mapping[$field]) && $rawValue) {
                 $format = $mapping[$field];
                 eval('$value = ' . $format . ';');
             } else {
                 if ($rawValue) {
                     $value = $rawValue;
                 }
             }
             if (in_array($field, $colsToBlank)) {
                 if (!isset($previousVals[$field]) || $previousVals[$field] != $value) {
                     $row[$field] = $value;
                     // if this value that has changed is the 'first' value, then we need to reset all the other
                     // 'previous' values from left to right from this position
                     $previousVals = $this->resetPreviousVals($previousVals, $field);
                     $previousVals[$field] = $value;
                 } else {
                     $row[$field] = '';
                 }
             } else {
                 $row[$field] = $value;
             }
             if ($addCols && in_array($field, $addCols)) {
                 $rowSum += $value;
             }
         }
         $addToTable[] = $row;
         $this->data[$tableName] = $addToTable;
         $i++;
     }
     // now that the tables have been created, need to do column summation on each. We could do this during
     // the above looping, but because we don't FORCE the items to be properly sorted first, we can't guarantee
     // that the columns that need summation are in the right places
     $addCols = $this->report->AddCols ? $this->report->AddCols->getValues() : array();
     if (count($addCols)) {
         // if we had a row total, we'll add it in by default; it only makes sense!
         if (isset($this->headers[self::ADD_IN_ROWS_TOTAL])) {
             $addCols[] = self::ADD_IN_ROWS_TOTAL;
         }
         foreach ($this->data as $tableName => $data) {
             $sums = array();
             $titleColumn = null;
             foreach ($data as $row) {
                 $prevField = null;
                 foreach ($row as $field => $value) {
                     if (in_array($field, $addCols)) {
                         // if we haven't already figured it out, we now know that we want the field BEFORE
                         // this as the column we put the Total text into
                         if (!$titleColumn) {
                             $titleColumn = $prevField;
                         }
                         $cur = isset($sums[$field]) ? $sums[$field] : 0;
                         $sums[$field] = $cur + $value;
                     } else {
                         $sums[$field] = '';
                     }
                     $prevField = $field;
                 }
             }
             // figure out the name of the field we want to stick the Total text
             $sums[$titleColumn] = _t('ReportFormatter.ROW_TOTAL', 'Total');
             $data[] = $sums;
             $this->data[$tableName] = $data;
         }
     }
 }