Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev/core#1855 - Allow different output formats for CiviReport results and untangle code #17901

Merged
merged 1 commit into from
Jul 21, 2020

Conversation

demeritcowboy
Copy link
Contributor

Overview

https://lab.civicrm.org/dev/core/-/issues/1855

The code to output csv/pdf/etc is hardcoded and hard to follow - I've previously struggled looking through the code a few times - but there's also several uses for being able to allow extensions to provide their own output formats or alter the core ones. I've expanded on this a bit in the lab ticket.

Inspired by and borrows from #17145 and #17693.

There's no change to existing report functions proposed here. A stock install should function the same as before.

There's a docs PR coming. It adds two varTypes to hook_civicrm_alterReportVar.

Before

CiviReports

After

Still CiviReports, but you can add your own formats. They also automatically become available as formats for the mail_report scheduled job.

If you want to get fancy, it's flexible enough to let you provide different output handlers for different report instances, or different report classes.

Technical Details

Since it looks big, here's a walkthrough:

  1. Three of the files are for tests. I also recently added several tests here, here, and here to cover existing functionality.

  2. There's three files in the Civi/Report folder:

  • One is an interface, so by definition is boilerplate.
  • One is a base class, which is identical to the interface but implements some defaults.
  • The other is the factory, which is mostly just a hook for you to advertise your extension's outputhandler(s), with some fluff around it. On its own without the hook it just helps replace the big "if/else/if/then" that was hardcoded in the form by instead registering builtin types for 'pdf', 'csv', 'print'.
  1. There's three files in the CRM/Report/OutputHandler folder, which are all copy/paste from the base class except for the parts that are different for the specific type, which are copy/paste from the if blocks. A key simplification here was that emailing a report and downloading a report start with the same thing: getting the output string.

  2. That just leaves CRM_Report_Form itself.

  • There's some getters added.
  • It's hard to see from the github UI but if you look at the function endPostProcess before, you'll see it's this big nested if statement. By using the simplification above and moving the code into the outputhandler files, the if reduces mostly to:
if ($this->_sendmail) {
  $this->sendEmail();
}
elseif (!empty($this->outputHandler)) {
  $this->outputHandler->download();
  CRM_Utils_System::civiExit();
}
function examplereportoutputhandler_civicrm_alterReportVar($type, &$vars, $form) {
switch ($type) {
case 'actions':
  $vars['report_instance.excel2007'] = ['title' => ts('Export to Excel')];
  break;
}

Comments

There's an example outputhandler extension which implements an "emoji" format at https://lab.civicrm.org/DaveD/examplereportoutputhandler

On the civireports instance listing pages, there are some links on the righthand side. This PR doesn't automatically alter those links, but there is already a hook for those that you could implement in your extension (hook_links with $op = 'view.report.links').

This PR does not fully address the hardcoding of the email body text when using the mail_report job - it's the same as before - but this might make it easier to make that more configurable via UI later since it's now out of the big if block. Even without a UI, you can now override it by extending one of the core outputhandlers and changing just the related function(s). You could do it before with hook_alterMailParams, but it wasn't very robust since you had to guess if the email was a civireport.

@civibot
Copy link

civibot bot commented Jul 20, 2020

(Standard links)

@demeritcowboy
Copy link
Contributor Author

The test fail is because that test uses a dataprovider that calculates time-sensitive things, which is a no-no because it does the calculation at a different unknown time from the run of the test. I'm just surprised it hasn't come up before. Could be done via callback instead, or just not a dataprovider. Will make a ticket.

@eileenmcnaughton
Copy link
Contributor

OK - gonna kick off tests again - here is the old link https://test.civicrm.org/job/CiviCRM-Core-PR/35526/

@eileenmcnaughton
Copy link
Contributor

test this please

@demeritcowboy
Copy link
Contributor Author

MySQL server has gone away. Jenkins test this please.

@eileenmcnaughton
Copy link
Contributor

Yay it's passing - @seamuslee001 wanna check this fully replaces your PR?

@homotechsual
Copy link
Contributor

homotechsual commented Jul 21, 2020

WIP docsPR @ civicrm/civicrm-dev-docs#834

@seamuslee001
Copy link
Contributor

I tested this by testing the original actions and confirmed that they were all working with this change. I also tested sending a report via email and confirmed that the base64 encoded content was correct and the mail_report job works correctly

@seamuslee001 seamuslee001 merged commit 5b9deab into civicrm:master Jul 21, 2020
@demeritcowboy
Copy link
Contributor Author

Wow less than 24 hours. Thanks for testing!

@demeritcowboy demeritcowboy deleted the outputhandler2 branch July 21, 2020 22:52
@eileenmcnaughton
Copy link
Contributor

Thanks for the work @demeritcowboy !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants