Repository
8.x-4.x branch in Git
Original intro
Drupal 8 is now in its second beta. API changes are still happening, but it should be fine to start converting modules now.
First, I have to clean up Drupal 7 to get it into a state ready for porting. If I postpone this cleanup to Drupal 8, it will probably be much harder.
There are many features I wanted to get into Drupal 7 but did not have time to do, and I didn't receive any patches that added these. Hopefully, these will be easier in Drupal 8 or will at least follow more standardized patterns (making FillPDF templates into entities, filling with data from any entity and not just nodes/webforms, etc.).
(edit: Yep! I've done both of those so far! Wasn't able to dump the query string from the URL format, though.)
Goal
Launch a full Drupal 8 version. (pretty much achieved; touch-ups remain)
Original Goal
Launch a Drupal 8 version that has approximate feature parity with Drupal 7; no new features, no new Drupal APIs (conceptually, since obviously the APIs have changed) used. This will be 8.x-3.x.
Remaining tasks
- Fix FillPdfFormFieldForm (edit PDF field mapping form) forms to look like D7 version
- Fix display of token tree (see #2473259: Token tree is not a tree)
- Fix file usage for FillPdfForm entity (no need to add it manually; the file field actually does this). Implement proper entity access controller and use it for entity forms.
- Same thing re. entity access for FillPdfFormField. Right now the routes are using a custom access controller (which in itself could probably be made into a base class or repurposed somehow).
- Complete HandlePdfController::populatePdf()
actually use token-to-PDF field mappingsimplement real access checkingmake post-generation action plugins as well (sending to user's browser, saving, saving and redirecting to, etc.). These would just return a Response (or RedirectResponse, etc.) to the controller.support saving result to file — and: - Forward-port private files support recently added to Drupal 7, since it's kinda silly to re-iterate on this latersupport redirecting to resulttransform valuesprefix/suffix
- Make token replacement work better when there are multiple tokens in the same string and multiple input sources. See @todo in-module. This should be the same logic for tokens in the title. And should probably be a utility function eventually (just make it a controller helper for now).
- Convert field mapping import/export form
- Allow updating the PDF (similar logic to export/import)
- Fill from the default entity.
- Add rest of FillPdfForm fields (transformations, etc.)
- Implement fillpdf_backend plugins for JavaBridge and pdftk
- Ensure module works with dynamic_page_cache: https://www.drupal.org/documentation/modules/dynamic_page_cache
- Delete legacy code and files
Roadmap, but not necessarily first version
- Check code with Coder Review #2624090: Fix Coder violations for Drupal ruleset.
- TESTS TESTS TESTS. For access checking, PDF generation, the various FillPdfForm/FillPdfFormField settings, etc. #1393056: [Meta] Write tests
- Figure out how to show actual file locations for private, uploaded PDFs shown using the file field in the fillpdf_forms view. #2624120: Show actual file locations in FillPDF Forms view
- Create a class to hold FillPdfLinkContext information. This will replace the job of the $context array because I can make an interface and document it, then point people there instead of telling them to look at FillPdfManipulator::parseLink(). #2624122: Create ValueObject-pattern class to replace $context array
- Add check for xmlrpc module (moved to contrib in D8) to FillPdfSettingsForm — the overview page already has one #2624138: Add ModuleHandler::moduleExists() check for xmlrpc to FillPdfSettingsForm
- Rename classes to be less redundant, e.g. DownloadAction vs. FillPdfDownloadAction, etc. They're already namespaced. Ref: https://www.drupal.org/node/608152#naming #2624144: Revisit naming convention for classes
- Refactor \Drupal\fillpdf\Controller\HandlePdfController to contain less original logic. It should almost exclusively use services. Note: This is related to having a canonical FillPdfForm route. #2624156: Move all original logic in HandlePdfController into services
- Integrate with D8 Rules #2624162: Rules integration (D8)
- FillPdfForm field type (@FieldType) for entities, maybe themeable as a button or link #2343507: FillPDF field
Follow-up
Port the Drupal 8 version to use Drupal 8 concepts more correctly. I don't know what those are, yet, so I'm not going to open follow-up issues until I'm farther along here. Actually, I pretty much had to do this, so I'm just going to use this section for roadmap stuff that I don't wind up getting done.
Want to help?
Leave a comment here :)
Comments
Comment #1
wizonesolutionsI went way farther on this than anticipated. Anyway, I'm opening a GitHub repository shortly so I can work openly on this. The GitHub repository is temporary; if you just want to use the stable Drupal 7 version of the module, you should download it from Drupal.org.
Repository: https://github.com/wizonesolutions/fillpdf
Comment #2
wizonesolutionsComment #3
wizonesolutionsJust an update several months later; still working on this, and it's not as blocked by #2359209 as I thought. I'll be continuing to work on this gradually and might even have an almost-release by the time D8 comes out...but that's far from a promise. My main purpose doing the port is to learn D8. But that doesn't mean the code won't be usable.
Comment #4
wizonesolutionsChanging title to join #d8cx.
Comment #5
wizonesolutionsMoving module tasks from my to-do app to the issue summary.
Comment #6
wizonesolutionsComment #7
wizonesolutionsComment #9
wizonesolutionsComment #10
wizonesolutionsComment #12
wizonesolutionsYay, token replacement is working with real tokens and the new entity-based FillPDF Link format. Not everything's perfect, but it works the same way as Drupal 7 (including how it doesn't always handle multiple tokens from different sources in the same fill pattern well yet).
Comment #13
wizonesolutionsComment #15
wizonesolutionsAccess checking done! Next: saving to file.
Comment #16
wizonesolutionsComment #17
wizonesolutionsStrategy to port saving to file, etc.:
-
Add configuration for fillpdf.scheme to FillPdfAdminForm-
Add configuration for saved-file scheme to FillPdfFormField/FillPdfFormForm-
Port file scheme support for uploading PDF form (save path for the template)- Enforce that file is subdirectory
fillpdf/prefix in saved file paths- Port file saving from Drupal 7 (the latest 7.x-1.x code) — including private file support
- Port redirecting
Comment #18
wizonesolutionsComment #19
wizonesolutionsComment #20
wizonesolutionsBrain freeze on porting file saving, so writing out my thoughts:
Drupal 7 implementation:
- Determine
$action:'default'by default, which uses the PDF form settings to determine what to do. This is already ported to Drupal 8.- Actually save the file. To do this, we pass the PDF metadata, a filename, and whether to redirect/redirect to the file/override the destination directory.
- We process those arguments, particularly destination path — we run that through token_replace.
- We ensure the destination directory exists. We error out if it doesn't, or well — do nothing and log it.
- If we're all good, then we save the file and add usage data (including the generation context). We return the file.
Drupal 8 implementation ideas:
- Determine
$actionin the same way.- Create a standalone FillPdfGenerationContext class that will play the role of D7's
$fillpdf_object(stdClassin D8 is icky)- Instantiate one, and pass the other arguments as they are now.
$destination_path_overridemight not be needed, since a third-party caller could just mess with the FillPdfGenerationContext.- Still process tokens in the destination path and ensure it exists
- Save the file, add file usage in the same way
-- Challenge: Currently, I use a $fillpdf_context (the passed-in $context) to determine which entities the PDF references and check access accordingly. I store that in a database table and the use the ID of the record in the file usage entry. This is no problem in D8, but I'm not sure if it should be a ContentEntity or not. It seems excessive to use a ContentEntity since it has no UI, but I want to ask around first.
- Return the file, and in the parent function return the appropriate RedirectResponse.
Comment #21
wizonesolutionsAlso, considering a FillPdfActions standalone class. Main initial function would just be to provide a standard way to save to file. I think a service would be overkill because there isn't that much to inject. Well, I do log an error if the path doesn't exist...so I guess it would be a service. Anyway, yeah. Should be reusable. But not to the point of being a plugin or anything...yet. That's actually a future idea, since it would let people do stuff with PDF results that I haven't thought about. But they have other ways to do that for now.
Comment #22
wizonesolutionsComment #23
wizonesolutionsDecided to implement action plugins now. Bite-size chunks are easier for me to wrap my head around.
Comment #25
wizonesolutionsComment #26
wizonesolutionsAlright, finally got action plugins wired up! Now I can finish porting file saving, and the length of HandlePdfController::handlePopulatedPdf() won't drive me crazy anymore. Need to make a service that actually handles saving the PDF (so that other modules can do it independently). I might move some of the logic for doing stuff to PDFs generally into that service; the controller shouldn't be the owner of so much functionality. Well, one thing at a time. I also want to turn most of the options arrays into objects, but I'm not going to get held up on that.
Comment #28
wizonesolutionsRealized I've named a lot of things redundantly, so added that to the roadmap. Also, I figured out an easy solution to fixing token replacement (which I should backport to D7): http://drupal.stackexchange.com/questions/177891/most-efficient-way-to-r... (replacing them in reverse order, progressively).
Comment #30
wizonesolutionsMade some decent progress this weekend. There's much re-architecting going on, and this slows things down, but there's no way around it. Most of the hard-hitting features are in or ready to be added pretty easily, though. Some major remaining parts are import/export of mappings (actually, I'd like to upgrade this to import/export of entire
FillPdfFormrecords +FillPdfFormFieldmappings, substitutions (transformations), updating the PDF, and redirecting to the PDF.Also...tests.
Comment #33
wizonesolutionsComment #37
wizonesolutionsFinally using file fields instead of entity references for files. While I'm in this mode, I'm going to go through and write proper entity access classes for the entity types I define and make the forms use these.
PDF generation, due to its nature (being a link not clearly-connected to any form or route), will still use
FillPdfAccessController::checkLink()...at least, I think it will. I have to separate the access-checking functionality out into a service that takes a$contextand tells me if access is granted. I need that forFillPdfFileContextAccessControlHandler::checkAccess(), which basically does the exact same thing, just withFillPdfLinkManipulator::parseLink()(instead of::parseRequest(), and it uses thefillpdf_file_context.contextfield.Comment #38
wizonesolutionsComment #39
wizonesolutionsFile saving and handling of private files is DONE! There are general tweaks to be made that will affect this, but the functionality itself is working.
I also updated the issue summary. i haven't written it there, but I've written up a timeline in my own notes, and I think I can get this done during DrupalCamp Oslo (Nov 14 or 15). If so, I'll release an rc1. So if you are watching this issue, keep an eye out for that! (I'll tweet and such.)
Comment #41
wizonesolutionsAdding a real
FillPdfLinkContextobject to roadmap.Comment #42
wizonesolutionsHuh, switching to file fields broke my fillpdf_forms view. Need to look into this and see if I can format it as a file URI again somehow. Maybe there's some other widget I can use somehow in contrib.
Comment #43
wizonesolutionsComment #44
wizonesolutionsComment #45
wizonesolutionsUpdating remaining action items. Getting there!
Comment #48
wizonesolutionsIf you didn't notice, there's an alpha out now. See the project page if you want to try it out. I'll be continuing to work on it and move towards making it feature-complete according to the must-port features in the issue summary.
Comment #49
wizonesolutionsComment #57
wizonesolutionsHi, I'm at a Drupal 8 release party in Trondheim. During the party, I finished the module. Time to release!
Symbolically changing to Needs Work because I need to open follow-up issues.
#D8CX promise: FULFILLED.
Comment #58
wizonesolutionsComment #59
wizonesolutionsComment #60
wizonesolutionsComment #64
wizonesolutionsComment #65
wizonesolutionsAbandoning Coder fixing until I figure out #2624076: Support namespace aliases in /** @var */ definitions or it's resolved.
Comment #67
wizonesolutionsComment #68
wizonesolutionsComment #69
wizonesolutionsFollow-ups created. See you there!
Comment #71
quietone commented