About the Project / Submission:
This is a SIMPLE and straight forward module that creates a block which can either already contain a QR code from the google charts API, or render the QR code on click (reduces HTTP requests, not always needed).
The need for this struck me on a recent freelance project for an apartment complex where they wanted to be able to have QR codes on all of their pages for staff so as they could quickly copy and paste QR codes from the website into promotional material they were creating.
There are infact other modules that deliver QR codes. I documented them in my project page. They do not deliver a simple solution, one of them was never ported from D6, and one of them delivers barcode functionality as well and again introduces complexity.
Project Page: http://drupal.org/sandbox/jnicola/1872858
git clone --recursive --branch 7.x-1.x jnicola@git.drupal.org:sandbox/jnicola/1872858.git google_qr_code_generator
Reviews of other projects:
Comment 1 - Pretty Pager(?) - http://drupal.org/node/1871644#comment-6872054
-learned about L() function
-Learned about not wanting to output HTML directly.
-Learned about theme_image() on my own to avoid typing html directly.
Comment 2 - Views Node Edit - http://drupal.org/node/1872452#comment-6872084
-Learned how to actually setup 7.x.1.x branch. and delete "master" thanks to a link I saw.
-Learned about http://ventral.org/pareview . Used this to bring my module from 100 plus errors down to just 4 total!
Review 3 - Delayed Ownership - http://drupal.org/node/1803114#comment-6872164
-Didn't learn anything new, but was impressed! Best module so far. Good code! Cool functionality!
-Saw some things that made me ask and discuss security.
Comments
Comment #1
jnicola CreditAttribution: jnicola commentedSubmit for bonus review. I thought it would be somewhat bothersome to do but I learned a lot from it all!
Heads up:
I know I have these errors from PAreview.sh. I don't know how to fix though... please advise :)
1 | ERROR | End of line character is invalid; expected "\n" but found "\r\n"
I've tried fixing this repeatedly. No idea what is causing this.
60 | ERROR | Constants must be uppercase; expected GOOGLE_QR_CURRENT_URL but
I don't believe I'm setting this up as a constant? I don't understand this.
162 | ERROR | Files must end in a single new line character
My document just has a single new line character for the end?
Comment #2
htumanyan CreditAttribution: htumanyan commentedHi! I reviewed your module manually and didn't find any major issues apart from a few comments below:
a. I've noticed that you set the caching policy for the block as DRUPAL_CACHE_PER_ROLE, which implies that the block will be regenerated each time a user with a new role is accessing a page, where it resides. Looking at the block content I did not spot anything user/role specific. Would it make sense to use DRUPAL_CACHE_GLOBAL for better performance. Again, I don't think this is a major issue/point given that the generation of the block is not resource consuming.
b. Would it make sense to sanitize user-supplied configuration parameters before they are used for generation of end-user visible content? I do see that you have your custom validators upon submission of configuration parameters, but, nevertheless, felt it is reasonable to implement sanitization on the output.
Just my 2c. I hope you find this useful.
Comment #3
jnicola CreditAttribution: jnicola commentedGood points, thanks for mentioning them :)
A- Didn't know this. I grabbed some sample code somewhere and that was leftover. I removed this line of code. It's been commited again sans that line.
B: I hadn't considered sanitizing, and don't know enough about it to consider what to do anyways. What would you advise (or some one else perhaps who sees this)
Further notes on my own admissions of errors:
-Fixed the constants issue. Forgot a $ on a variable. I do this sometimes because I am back and fourth between javascript so often!
-Went into VIM and tried adding the first line break and also the final line character... and it still throws those errors. Anyone with a solution?
Comment #4
jnicola CreditAttribution: jnicola commentedNow that I think about the sanitation comment, I'm forcing the only values that can be changed to be integers, and constricting their values. Not sure what else could even really get through there? I don't think sanitation is a concern, but again... some one may know more than I do :)
Comment #5
sonnym CreditAttribution: sonnym commentedForemost, I would like to let you know that the
git clone
line above is incorrect - you want to use http://git.drupal.org/sandbox/jnicola/1872858.git as the URL, not the one provided by drupal.org with your username specified.It looks like you can also remove some TODOs, as you have both participated in the Review Bonus Program and applied to create full projects!
Now for some actual review of the code. Overall, it looks really solid, the following are some minor tweaks.
google_qr_code_block_info
andgoogle_qr_code_block_view
.#attached
key in the return value from an implementation ofhook_block_view
when caching is enabled. See: this comment re: hook_block_viewIn closing, I would like to reiterate that this module is very cleanly implemented and looks solid!
Comment #6
jnicola CreditAttribution: jnicola commentedGood points :)
I have removed my todo list (cause I am doing it!). I also adjusted the following:
1- Added code for global cache. Makes sense to cache in such a fashion since it's the same no matter where it is.
2- I used #attached to attach the Javascript. This should only load the JS when the block is called, and will function with cacheing. Good read thanks for linking!
Could some one explain the implements comments or link me to an article on writing strong commenting?
Comment #7
htumanyan CreditAttribution: htumanyan commentedThe easiest to ensure that unsafe content never reaches the user is to use Drupal's sanitization functions (http://api.drupal.org/api/drupal/includes!common.inc/group/sanitization/7) when producing the output, i.e. instead of
do
Comment #8
sonnym CreditAttribution: sonnym commentedThis is the specific documentation for hook implementations, but the entire document is worth a read.
Documenting hook implementations and theme preprocess functions
Comment #9
esbenvb CreditAttribution: esbenvb commentedYou still have issues with windows-style line endings:
FILE: ...ew/sites/all/modules/pareview_temp/test_candidate/google_qr_code.module
--------------------------------------------------------------------------------
FOUND 3 ERROR(S) AFFECTING 3 LINE(S)
--------------------------------------------------------------------------------
1 | ERROR | End of line character is invalid; expected "\n" but found "\r\n"
82 | ERROR | break statement indented incorrectly; expected 6 spaces, found 4
184 | ERROR | Files must end in a single new line character
--------------------------------------------------------------------------------
This is also the reason why line 184 fails. Fix it by setting your editor's text format to unix.
Also, there's a space after <?php
I guess the break at line 82 should be removed since your return command already breaks the switch.
All your ON_PAGELOAD and ON_CLICK constants are not defined anywhere, this is not valid and PHP complains about that.
I also think these names are a little to generic for a module like yours, so you should consider just having the strings 'on_pageload' and 'on_click' instead...
Comment #10
esbenvb CreditAttribution: esbenvb commentedComment #11
jnicola CreditAttribution: jnicola commentedI was aware of the EOL issue and it was boggling my mind as I couldn't fix it by editing the file in VIM. I Googled how to fix this in notepad++, and I for those interested in how to convert files to UNIX end of line in Notepad++, simply go to Edit > EOL conversion > Unix.
I switched from constants to strings. Thanks for pointing that out. Learned something new there. I was running off of an example I saw online for handling selects.
I added the check_url() function to both the image output AND the alt output since it includes the URL.
I updated the commenting to the best of my understanding on the topic. Can't say I found the documentation it overly informative, but I feel what I have for comments will help me through it. If I'm not writing them correct, please provide what I should write and a short explanation as to why so I can learn how this all works better, please :)
I am no longer showing any errors, and I beleive this should address everything anyone has said thus far. Module still works as advertised, project page is good. I'm feeling pretty darn solid about this module at this point. Thanks everyone for contributing to my learning experience with this.
Comment #12
Jordan_Fei CreditAttribution: Jordan_Fei commentedHi jnicola,
Review issues for google.qrcode-execute.js:
1. "if(moduleBlock)" code line is redundant.
For the "$('#block-google-qr-code-qr-code').html()", jQuery will always return an object. Therefore the if statement will always be true and never be false. Just use "moduleBlock.length > 0" is ok
2. "return false;" in click event to prevent the default behavior.
I don't believe there is a W3C specification for this. All the ancient JavaScript interfaces like this have been given the nickname "DOM 0", and are mostly unspecified. You may have some luck reading old Netscape 2 documentation. The modern way of achieving this effect is to call event.preventDefault(), and this is specified in the DOM 2 Events specification.
Comment #13
jnicola CreditAttribution: jnicola commentedGood point on the object always existing in jQuery, even if it contains nothing. Again, mixing up my PHP and JavaScript :)
Fixed the unnecessary IF and committed. Changes nothing functionally though... not sure you really needed to flag as "needs work" since it affect nothing, but hey, why not save a dash on file size!
Additionally... you are incorrect on return false, but only in this particular instance!
"return false from within a jQuery event handler is effectively the same as calling both e.preventDefault and e.stopPropagation on the passed jQuery.Event object."
http://stackoverflow.com/questions/1357118/event-preventdefault-vs-retur...
Full discussion and details available there. Outside of a jQuery event handler you are quite correct, but not inside of a jQuery event handler, which my .click() is. So, now it's my turn to share something with you :)
Comment #14
klausiThis sounds like a feature that should live in the existing qr_codes project. Module duplication and fragmentation is a huge problem on drupal.org and we prefer collaboration over competition. Please open an issue in the qr_codes issue queue to discuss what you need. You should also get in contact with the maintainer(s) to offer your help to move the project forward. If you cannot reach the maintainer(s) please follow the abandoned project process.
I'm sure that a port to Drupal 7 would be very welcome.
If that fails for whatever reason please get back to us and set this back to "needs review".
Comment #15
jnicola CreditAttribution: jnicola commentedI'm well aware of collaboration over competition, and I'm aware of the alternatives and I documented it in my module. I chose to continue with this module despite all of this, for reasons beyond competition.
How's this:
I'll move this back to "needs review" as I want further code review. Even if the module goes nowhere I'll learn something.
While getting further (and hopefully final) code review, I am going to follow up with the abandoned projects process for the following reasons:
1- The original module never even left Beta.
2- There is an open issue for a D7 port, It's been open for a year and nothing functional has been delivered. The last comment from a month and a half ago is calling for reporting the module as abandoned.
3- Their module is NOT the same as this to begin with. It offers functionality beyond what my module offers and is therefore more time consuming to install and configure, and does not work right out of the box. Theirs is also NODE FIELDS dependent, while this is URL dependent (plays better with panel pages, Taxonomy term pages, views pages, etc etc). Theirs won't retain view arguments (or views at all) while this does. Adjusting their module to deliver this functionality would be a complete departure...
Comment #16
klausiSo I propose this: since there is no D7 version yet you can simply rename your module accordingly and push it to a 7.x branch in qr_codes. Just follow the abandoned module process and you will become the maintainer. You can clearly state on the project page then that the 7.x version is a simple minimum implementation and that you are willing to accept patches that port features from 6.x. Benefits: no duplicate project and qr_codes finally gets a first 7.x version.
In the meantime I'm setting this to postponed to keep the project application issue queue organized. Feel free to come back to us anytime you have a new project that does not exist yet and you want to promote.
If that fails for whatever reason please get back to us and set this back to "needs review".
Comment #17
jnicola CreditAttribution: jnicola commentedJust placing a comment here to document my progress:
If I don't hear back from him in another week I intend to re-open this as "needs review". My module is a significant departure from theirs, the maintainer in question who post up hasn't committed in a long time and isn't communicating very well, although they're communicating just enough that the module probably would not be classified as abandoned.
Overall, I'd like to get this module out there as I think people would benefit from it. It's a quick and simple solution that works (it's on two production sites and on two soon to be released sites) and I'm proud of :)
So... see you guys in a week!
Comment #18
jnicola CreditAttribution: jnicola commentedOkay, I am reopening this. Here's the situation on the possibility of getting involved with the QR Codes project:
1- I tried to get the module marked as abandoned. A maintainer responded, so it can't get marked as abandoned.
2- I discussed collaborating my module and integrating it with theirs. Radio silence ensued and I heard nothing else. I sent a private message at that time as well... and still nothing... for two weeks straight now.
So, I am reopening this module. I have tried to mark the module abandoned, but the contributors are just active enough it won't get marked abandoned. I tried to get involved and work with them possibly... but nothing, no a word back.
So i tried, neither option is in the cards, and my module is inherently different anyways for all the aforementioned reasons.
Comment #19
klausiOk, so let's continue with this application then.
Review of the 7.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. You have to get a review bonus to get a review from me.
manual review:
Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.
Comment #20
jnicola CreditAttribution: jnicola commentedAll good things to know. I'll implement those changes and put it back in the queue.
Comment #21
jnicola CreditAttribution: jnicola commented"variable_get('google_qr_code_height', '250'))": all variables defined by your module must be deleted in hook_uninstall().Done. Added uninstall function.google_qr_code_block_view(): why do you call drupal_add_js() four times? Just call it once with the whole array()?Done. Didn't know you could do this. Did some reseach, did some tooling around... and got it to work!"'url' => $_SERVER['PATH_INFO']))": why do you need that? Please add a comment.No idea how I got this mixed up. I meant to use $_SERVER['REQUEST_URI']. Switched to $_SERVER['REQUEST_URI']google_qr_code_contents(): the check_url() calls are not necessary since theme_image() will sanitize it for you.Removing. It was added per the recommendation of a previous poster on here. I think you're a bit more senior than them though so I'll go with what yousay here!theme_image(): do not call that directly, use theme('image' ...) instead.Switched. Good to know!"'access arguments' => array('administer users'),": that permissions does not make sense? Better use "administer site configuration" instead or create your own permission?Good point. I hadn't really thought about this before. Adjusted per your advice!Notice: Undefined index: PATH_INFO in google_qr_code_block_view() (line 41 of google_qr_code.module). Please enable PHP notices in your development environment.Not sure where this came from. Notices and warnings are enabled! Anyways, this is fixed.Questions regarding two other items you wrote:
"'QR Code for ' . check_url($google_qr_current_url)": all user facing text must run through t() for translation. Do not put variables into t(), use string literals and placeholders where possible. Same in google_qr_code_max_total_px().
So I understand moving any text heading out in the t() function... but I don't understand the rest of what you wrote, and I wasn't able to find a good answer on this, probably due to not knowing enough to ask the question properly. Could you please elaborate?
"$GLOBALS['base_url'] . $_SERVER['REQUEST_URI']": why can't you use url(current_path(), array('absolute' => TRUE)) or something similar ?
Alternatives do exist... but is there a particularly compelling reason NOT to use request_uri that I am unaware of? Unless this introduces a flaw or security issue, I don't understand why it would matter. If it does though, please enlighten me, I need to know if I'm doing something wrong!
Comment #22
klausi"'QR Code for ' . check_url($google_qr_current_url)"
should bet('QR Code for @url', array('@url' => $google_qr_current_url));
The PHP super globals for paths, URLs etc might not be reliable, so it is recommended to use the appropriate Drupal functions to avoid issues with sites that don't have clean URLs enabled, where the Drupal installation lives in a subdirectory etc.
Comment #23
jnicola CreditAttribution: jnicola commentedGood to know about PHP super globals.
Okay, implemented the placeholder for url's, and also implemented the new method for getting the current path. Pushed changes to a few freelance jobs I have going on and works across all in staging, will hit Prod later this week. I feel pretty confident about most of what I've done thus far.
I am a little bit uncertain about my adding the uninstall code for the module without actually adding install code... but it works so uh... there must be something I don't know? I found the documentation on all of this to be a bit minimal, but it works and throws no errors anywhere. Please let me know if I missed anything though!
Comment #24
jnicola CreditAttribution: jnicola commentedI did three more reviews. I tried going to the back of the list but a lot of the modules were pretty much abandoned in the process. Is there a way to mark module submissions abandoned?
Anyways, 3 reviews!
Comment #1 - Etsy Treasury
http://drupal.org/node/1889102#comment-6958038
Comment #2 - Contact Plus
http://drupal.org/node/1822068#comment-6958060
Comment #3 - Pretty Pagination
http://drupal.org/node/1871644#comment-6958108
Comment #25
klausiThank you for your reviews. When finishing your review comment also set the issue status either to "needs work" (you found some problems with the project) or "reviewed & tested by the community" (you found no major flaws). Every application that is in the "needs review" state is not abandoned and needs feedback. And you can ignore the "needs work" applications, they have been reviewed already and need some fixes from the maintainer.
manual review:
Although you should definitively fix those issues I think they are not major application blockers, so I guess this is RTBC. Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.
Comment #26
jnicola CreditAttribution: jnicola commentedI really appreciate you pointing that all out. I suppose I didn't consider that I was unnecessarily sanitizing some input. Reviewing it all conceptually it now makes a lot of sense.
I'm going to mark "Needs review" again as I made the changes you state, and I'm not sure it would be appropriate to leave the status as is. I apologize profusely if this results in wasting your time :(
I'll review a few more modules to get back into the bonus review, and this time I'll try and tackle some that are further back in the queue.
Comment #27
jnicola CreditAttribution: jnicola commentedI did three more reviews. I even dug pretty far back for Turn.js. Not sure why that one has set ignored for so long. It's mostly there actually, and unlike some other stuff I've tested, it actually worked when enabled!
#1 - JS Spellcheck
http://drupal.org/node/1860736#comment-6960602
#2 - FileField Mail
http://drupal.org/node/1885736#comment-6960752
#3 Turn.js
http://drupal.org/node/1802112#comment-6960786
Comment #28
sprocketman CreditAttribution: sprocketman commentedRegarding commenting, refer to Doxygen and comment formatting conventions.
Comment #29
klausiBack to RTBC.
Comment #30
klausino objections for more than a week, so ...
Thanks for your contribution, jnicola!
I updated your account to let you promote this to a full project and also create new projects as either a sandbox or a "full" project.
Here are some recommended readings to help with excellent maintainership:
You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and get involved!
Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.
Thanks to the dedicated reviewer(s) as well.
Comment #31.0
(not verified) CreditAttribution: commentedAdding review notes