Printer-Friendly Pages 5.x-3.4

chx and Morbus reviewed Printer-Friendly Pages 5.x-3.4 which "allows you to generate printer friendly versions of any node by navigating to www.example.com/print/nid, where nid is the node id of content to render. A link is inserted in the each node (configurable in the content type settings), that opens a version of the page with no sidebars, search boxes, navigation pages, etc."

First-post disclaimers: As the first post, we're still figuring out the best format and approach to distilling the information we proffer. If you have suggestions, concerns, or have eyeballed one of our own mistakes, please let us know by leaving a comment. Likewise, also note that there was no ulterior motive to picking Printer-Friendly Pages as our first review: we literally just browsed through the 5.x taxonomy term until we found a recent release of a module we knew was in actual use. Our reviews are also not necessarily security reviews: if we don't mention any problems, it doesn't mean we assert the module is Security Team approved (of which we're both members). Finally, if you'd like us to review your own (contributed) module code, don't hesitate to let Morbus or chx know and we'll add it to our queue.

The Review

  1. $nodetype should be $node_type. Additionally, the use of $nodetype has a slight problem:

    <?php
    $nodetype
    = isset($node->type) ? $node->type : '';
    $print["submitted"] = theme_get_setting("toggle_node_info_$nodetype") ...
    ?>

    Your use here, and similarly on line 55, allows a theme_get_setting() check on a variable that would never exist ("toggle_node_info_"). It'll be a few more lines of code, but you're better served with an if that checks if $node->type exists, then calls the proper display options. Your final use on line 508 ($print["type"] = $nodetype;) could be moved into the same if.

  2. Coder only caught 3 errors (great job!) involving camelCase variable names (specifically, $queryArr). camelCase and mungedwords should be replaced with lower case variable names, split on word boundaries with a "_".
  3. As the PHP documentation says on strstr(): "If you only want to determine if a particular needle occurs within haystack, use the faster and less memory intensive function strpos()..." Instead of strstr($module, 'book_printer'), use strpos($module, 'book_printer')) !== FALSE instead.
  4. There's plenty of text files shipped with the module, and nearly all of them need work. Besides the standard "string retardation" (the name of the module is listed as "print", the module's filename, as opposed to "Printer-Friendly Pages", the module's actual name), and the README.txt and INSTALL.txt not using core style (in the absence of a style guide, Do What Core Does), they also can't agree on which format they themselves would like to use (README.txt uses numbered lists with either a), b) or i., ii., sub-items, whilst INSTALL.txt uses a dashed-list with i., ii., etc.). More egregious is the lack of hard newlines (depending, instead, on an editor's default word-wrapping capability, which browsers don't have, making these docs difficult to read online). In some cases, the docs are also slightly wrong (suggesting that it only works on nodes when it currently defaults to working on every page, an error that print.info also perpetuates). Finally, there's not a whole lot of rationale to have a CREDITS.txt and a MAINTAINER.txt in a contrib module - certainly, yes, it's "like core", but core is a lot bigger and maintained by far more people, which justifies their existence. Move the contents of your versions into your README.txt and get rid of 'em.
  5. print.css has some missing semi-colons and its formatting could be improved.
  6. Your print.install is great; thanks for deleting your variables. However, it's a bit odd to store most of a module's configuration inside a single variable (print_settings, etc.). Ideally, you'd only do that for things like lists, not for the entire batch of variables offered on a module's admin page. It's entirely possible this was a misstep or misuse of Forms API - there shouldn't ever be a real need to use #tree on a form intended for system_settings_form(). If you get rid of the #tree, you'll also be able to remove/collapse your various "default" functions (like print_robot_settings_default()).
  7. The print.module starts off with a spurious use of a constant - there's no real need for define("PRINT_PATH", "print"), and if one is concerned about having a single place to customize the root path for all printer-friendly pages, move it into a variable for the admin pages. It's only four or five extra lines of code to make the module friendlier, and more inline with what core does (no part of core hardcodes a menu path to a constant).
  8. A module that overrides hook_help() without providing its own help documentation is amusing.
  9. Another bad habit we often see is "string first on equality tests" such as lines 128 and 137:

    <?php
    if ('node_type_form' == $form_id) {
    ?>

    The implication, of course, is that a mistype of == to = would cause an error, since you can never assign anything to a string. The only rationale for using the above "workaround" is to indicate that not enough testing is happening. If a developer tests every line of code, obsessively and iteratively, they'd find "assignment instead of equality" bugs and could write and maintain code that doesn't use lazy tricks like the above. To make it worse, the module isn't consistent in this usage, with $type == 'comment' and count($matches) == 4 elsewhere. Replace these sorts of constructs, and don't rely on them to protect you from yourself - that's what testing is for.

  10. Theme functions (here theme_print_format_link() and theme_print_text()) should never return an array. If you want data or configuration to be override-able, use a hook and module_invoke_all(); developers can decide the ordering of the overrides via the standard module weight capabilities of the system table. In Drupal 6, there's also the new drupal_alter(), which allows you to pass around data and get hooks for free. Theme documentation tends to start with "Generate the themed output", traditionally HTML, not "return a structured array of strings". The true intent of these functions seems to be to control the strings displayed in the generated printer-friendly version, such as on line 466:

    <?php
    $print
    ["printdate"] = $print_sourceurl_settings['date'] ? (" (". $themed['retrieved'] ." ". format_date(time(), 'small') .")") : "";
    ?>

    But this is also considered bad form: one shouldn't ever concatenate strings onto a t() (here, the t() is stored inside the $themed['retrieved'], which was generated with a call to theme('print_text')). Assuming that the above string is assigned to $print["printdate"], you end up with t('retrieved on') . $date. One would think this OK until they consider a language where the date would read before, or in the midst of, the translated "retrieved on" (such as Japanese). Because the date is always appended to the translated string, it would always translate incorrectly. This even assumes translation... in English, one wouldn't be able to rephrase this to "[DATE] (retrieved on)". A much better approach is:

    <?php
    $print
    ["printdate"] = $print_sourceurl_settings['date'] ? t('(retrieved on %date)', array('%date' => format_date(time(), 'small'))) : "";
    ?>

    Besides reading more clearly from a code perspective, it allows translators to put the %date where they need it. One could also argue that this gives themers more control over the strings displayed. While the conceit is nice, it's still wrong: the site's developers should have properly setup a locale toolkit to allow translating of strings stored in Drupal's t() or, in Drupal 6, you could modify the strings inside the revised settings.php (scroll all the way to the bottom for documentation on how to do this). The shortest guideline here is: don't override the theme functionality (or, for that matter, any programming construct that is meant to do only one thing). Theme functions are intended for HTML, not a piggy-back into developmental hooks (as your use of theme_print_format_link(), which replicates hook_link_alter() functionality, promotes).

  11. print_generate_path() has very familiar menu code: this was committed to core for a few days and then rolled back (cf. this issue). This patch was one of those "unfixable" problems that lead to the menu system rewrite in Drupal 6. To sum up, _menu_append_contextual_items() was only ever designed to run once during a single page load: calling it a second time causes unpredictable results. One potential fix would be to set a flag in $_SESSION and do a drupal_goto() instead. Capturing the output passed to theme('page') is not easy in Drupal 5; you'd probably need to implement a phptemplate_variables() function or instruct your users to add your code there and use it to catch the content of theme hook page. You can check Advanced Forum for an example. Another trick you could pull is to provide an entirely new theme called 'print' and change to this theme in hook_menu() !$may_cache by tweaking the global $custom_theme (see Sections for an example).
  12. Something else we see a lot of are bad #descriptions for form elements. Either they're wrong or out-of-date, an exact repetition of the element's #title, or they contain spurious information. There's a little bit of all three in the elements that the module adds to some of Drupal's standard forms:

    <?php
    $form
    ['viewing_options']['print_display_comment'] = array(
     
    '#type' => 'checkbox',
     
    '#title' => t('Show printer-friendly version link in individual comments'),
     
    '#return_value' => 1,
     
    '#default_value' => variable_get('print_display_comment', '0'),
     
    '#description' => t('Displays the link to a printer-friendly version of the comment. Further configuration is available on the !settings.', array('!settings' => l(t('settings page'), 'admin/settings/print' ))),
    );
    ?>

    We'll start with the "Further configuration" sentence, which includes a link to the primary settings page. Not only is this dangerous (there's no check against user_access('administer print'), so a user who can administer comments may receive an "Access denied" message), but there's not a lot of benefit of going to the suggested URL: there's nothing additional that specifically affects the current decision. Removing that entire sentence leaves us with something that repeats the #title in a few more words and serves no useful purpose. This form element, as well as a similar checkbox for node types, should have its #description removed entirely. One final itch: integers don't use quotes (see #default_value).

  13. Core uses "Implementation of hook_NAME()." - you've forgotten the ending period on a few of yours.
  14. Use dangling commas on your arrays (From the coding standards: "Note the comma at the end of the last array element; This is not a typo! It helps prevent parsing errors if another element is placed at the end of the list later."). Some of your arrays do, others don't. Consistency, above all else, is key: if a developer is going to commit to something (mistake or otherwise), commit to it fully. Otherwise, it just looks sloppy.
  15. If the module is named "Printer-Friendly Pages", use that as the title of the admin settings page, not "Printer-friendly". Also, the description should be revised to note that it can now function on more than just nodes. Decide if it's "Printer-Friendly" (the capitalization on drupal.org) or "Printer-friendly" (the more grammatically correct usage, and what most of your documentation properly repeats).
  16. Lowercase AS in the foreach ($links AS $module => $link) on line 89.
  17. Don't use '#return_value' => 1 on boolean checkboxes in Forms API. #return_value is one of those fun and obscure constructs where you can specify what value you want if the checkbox has been clicked. It defaults to 1 already, which is usually what people expect and want.
  18. Standardize your form elements: under admin/settings/printer-friendly, you offer radio buttons ("Enabled" and "Disabled") for the printer-friendly link on nodes, but then change tactics by offering a single checkbox for the same feature, only for non-content pages. Get rid of the radio buttons and use the checkbox - for a decision involving merely "on" or "off" or "yes" and "no", a checkbox is always stronger than two radios.
  19. Drupal core uses TRUE and FALSE not true and false.
  20. Don't use PHP function aliases: use count(), not sizeof().
  21. If an array has only one item, implode() does the right thing (i.e., no joining with the glue string). Don't isset($robots_meta[1]) ? implode(', ', $robots_meta) : $robots_meta[0];, just skip the ternary entirely and use implode() as normal.
  22. The module's function documentation needs work - most functions have a one-line summary (good), but either skimp on the details (a @return string that depends on the one-liner to describe the results; best to remove the @return entirely) or leave them out wholesale (such as missing @params). Function summaries should always be one-line: "The first line of the block should contain a brief description of what the function does, beginning with a verb in the form "Do such and such" (rather than "Does such and such"). A longer description with usage notes may follow after a blank line. Each parameter should be listed with a @param directive, with a description indented on the following line."
  23. We're not entirely sure why the code uses $base_url or $base_path in _print_var_generator() and print_rewrite_urls(). You should be able to do most everything you need with url() and its "absolute URL?" parameter. Part of our confusion lies in the fact that url() is used for some conditions, but not others. Regardless, if you absolutely did require $base_path, use base_path() instead.
  24. $base_url is unused in print_generate_node() and the other _generate functions.

Comments

I'm excited for what you've

I'm excited for what you've started here. Peer review is a good system and will likely become another asset for the hopefully forthcoming module rating/review solution.

Did you (both) purposefully use "you" a lot? After the first paragraph of http://www.disobey.com/node/1828 I thought the use was going to be decreased. Modules can have several maintainers and patch providers but "you" is pretty directed and I know I didn't write any of the code for the print module.

Actually, I personally did a

Actually, I personally did a review for every "you" and "your" - what remains are intentional and should be considered the Eponymous You, i.e., all developers, not just whoever wrote this particular piece of code. Ideally, these reviews are directed at both the module author and, yes, you, the reader (whom we presume is someone interested in coding for Drupal).

Awesome review! I'd like to

Awesome review!

I'd like to add: Some (trivial) points of this list could have been avoided by the module maintainer if he/she had applied the coder_format script (shipped with the Coder module) at least once to the module. Ensuring that your code complies to Drupal Coding Standards is the best and easiest way to attract more developers, who in turn will be able to contribute bug fixes and new features.

I think this web site will

I think this web site will become an invaluable tool for not only new developers, but for seasoned pros. Great idea guys!

Repeating my words from IRC:

Repeating my words from IRC: awesome initiative! Thanks :) When Hierarchical Select 3 is ready, I'll definitely want your review ;) :)

Thanks for starting this. 2

Thanks for starting this.

2 people that are really great for this but chx, how much more can you take on? :)

But anyways, I would love to help you guys. I'm not quite at your level of course but a lot of the stuff you guys mentioned as issues for this review are things I bug my team about so it was great to see the same thoughts come from you guys.

Per #13, Is the period

Per #13, Is the period really a serious consideration for a code review?

From taxonomy.module:

<?php
/**
* Implementation of hook_perm().
*/
function taxonomy_perm() {
*
snip*

/**
* Implementation of hook_theme()
*/
function taxonomy_theme() {
*
snip*
?>

It should be. Its in our

It should be. Its in our coding standards. I hate saying this cause it can be over used but "Post a patch!" This would be a really easy way to help out drupal core. You can say you've helped :-D

i'm sorry, but i really

i'm sorry, but i really don't care about a period or not. and technically it doesn't mention that it *must* have a period in the documentation.

When given an example in the

When given an example in the code style guide, especially one that has /no user-specific variables/, one shouldn't stray from the example.

Patch submitted at

Patch submitted at http://drupal.org/node/245329

Does anyone know why user.module and node.module sometimes include "Implementation of a Drupal action" in the code comments and not include the function name?

Note that, until

Note that, until coder.module came along, core had a /ton/ of code style errors. When in doubt, the code style is always the Guide, and Drupal core, along with contrib, are merely the implementors. Both can fail equally but, naturally, core does so less often because there are so many more eyeballs.

Amen! God bless the coder

Amen! God bless the coder module. It has saved me HOURS for upgrading my modules to 6. I don't know if I could work without it.

:)

haha.. for a sec i misread

haha.. for a sec i misread that. Not all of core is a guide. Drupal core has some -- echm -- dusty corners that remind me of the drupal classic 4.5 styles -- which contained nonsense only slightly less ridiculous then:

<?php
// all you have to do is remember the order of every type of form element!
$output = form_checkboxes($title, $value =0, $description, $options = array(), $required = null, $return_value = 1, $override_name = false);
return
$output;
?>

Hellish memories aside, release, by release, i've found system, node, taxonomy, user to be the solid guides to "the drupal way"'. Although CCK, views, panels tends to better show you how to push the boundries.

Remember that these comments

Remember that these comments are not just for human readability but also are parsed by e.g. api.module and bot.module and for these purposes more consistency is always better.

Actually, the real rule is

Actually, the real rule is that comments simply follow proper typography, and thus that sentences end in periods. 'Implementation of hook_foo' is just a fragment (no verb) and thus needs no period.

Of course this rule requires people to think about what they are writing.

Not entirely true. The

Not entirely true. The proper typography/sentence rule is for non-documentation comments - in other words, inline comments not affected by Doxygen headers. Compare the Doxygen documentation vs. the Comments section of the coding style guide, specifically: "Non-documentation comments should use capitalized sentences with punctuation." No such restriction exists on the Doxygen guide. (And, yes, I'm nitpicking. Obviously, the one-liners and expanded summary should be written intelligently <g>)

haha :) I'm glad we got

haha :) I'm glad we got this settled then. I was half joking on the original comment, but i'm glad to know that there is actual requirements to write in proper capitalization. I heard that the code goes faster when you case properly and end your comments in periods. ;)

Then the guide is wrong or

Then the guide is wrong or ambiguous.

I really like the idea of

I really like the idea of this but would like to see a more open process where we select a single module and review it together over the course of a week or so. we can adding issues to a numbered list either wiki style or in a more structured way ("project" content types that are nodereferenced by "issues" types) and listed below in fulltext using an embedded view on the project. individual issues could be openly editable and comments could contain the discussion on that issue so that we can avoid "re #13" style comments.

It is perhaps thought of best as a project_issue list that is instead printed in fullnode format with wikified issues and discussions.

Id also like to see the tone a little less tough love and a little more plain informative, but for the price and the insight just about any tone will do imo. Perhaps always referencing the code instead of the author might be a good start to avoid accidental perception of ad hominem attacks (then again i may be being too thin skinned). Thank you to you both for starting the initiative i hope to help contribute if you open up the process.

michaelfavia: what you

michaelfavia: what you propose is already entirely possible using the regular Drupal issue queues. You'll note that it hasn't happened; in fact, the absolute lack of /anything even remotely like it/ using the processes that Drupal.org already promotes is why DrupalToughLove.com exists. Opening it up isn't going to make quality, or trusted and vetted coders, suddenly flock to it. If anything, it'll lower the barrier to entry and, quite probably, the inevitable quality of the final result, especially if it were a wiki, where the reviewers combat each other, not the code they're reviewing. As chx says: "you can review if you are in MAINTAINERS.txt at least twice or you have several O'Reilly books on your rap sheet."

"As chx says: "you can

"As chx says: "you can review if you are in MAINTAINERS.txt at least twice or you have several O'Reilly books on your rap sheet.""
Sounds, hopefully unintentionally, elitist and self serving to this contributor and experienced drupal developer. I and many others *do* have the requisite skill and experience to provide code reviews on at least parts of the modules and that was what i was all i was suggesting. "Shallow problems with many eyes." You guys could still organize, delete and or approve the issues raised with each project during that week as seen fit to maintain quality, etc

I was just trying to help you offload some of the work on the community that has clearly expressed an interest in providing assistance. I felt this may help you provide a more valuable tool for the community while involving their participation on a concentrated task for fixed periods of time. Carry on with the show as is if you dont agree. Atlas Telamon!

Once you write the same code review issues (periods following method summaries) a dozen times i hope you might reconsider the help of others on this noble and necessary task. If that time comes please consider me willing to help implement such a framework. I genuinely wish you good luck either way you chose because the value provided is concrete and appreciated.

"Atlas Telamon!"?

"Atlas Telamon!"?

9. Another bad habit we

9. Another bad habit we often see is "string first on equality tests" such as lines 128 and 137:
Why is that a bad habit? I agree that testing is important but isn't anything that helps you catch errors earlier also good?

I had the same thought. It

I had the same thought. It never occurred to me to reverse it that way mostly because of habit but it seems like it would do more good than harm. I don't plan on changing my ways though since I never make that mistake and it just looks odd.

Chx, Morbus.. This is a great idea for the site!

I also think it looks odd

I also think it looks odd and I would never write it that way but that's not really a valid reason for calling it a "bad habit".

This is a fantastic and

This is a fantastic and helpful review and a great idea for a website.

This is really great.

This is really great. Hopefully some of these rules will get seared into my own memory so I don't make the same mistakes.

One thing that I noticed is that your logic for #9 ("string" == $variable) was "don't do this to try and catch your coding errors", but on #14 (trailing comma on an array) the logic is "do this to catch coding errors". Hmmmm.

The difference is this: One

The difference is this:

One is a syntax error. One is a logic error.

One won't really break your site in any way at all, other than completely shutting it down, it will either work, or won't. One will cause erratic behavior that only breaks some functionality some of the time.

One is a good idea, since no one needs to do testing to catch syntax errors. The other encourages users to skip testing of a logic testing function of their application.

That is the difference.

This is a very good idea.

This is a very good idea. botsnacks all around.

One request, can you enable feeds so I don't miss any posts?

Tks

Harry - feeds are enabled.

Harry - feeds are enabled.

I suppose I should pay

I suppose I should pay attention in class %'/

Delete me :)

What a fantastic resource!

What a fantastic resource! Given the expertise of the reviewers, this is a tremendous opportunity for inexpert coders like myself to study up and raise our game. Thank you so much!

The screen shot

The screen shot "print-admin-settings.png" in this article uses markup size constraints to set its width to 500px. However, the actual width of the image of 674 pixels. This is a poor practice in HTML/CSS because it wasts bandwidth (each user must download a large file even though they aren't viewing its full size) and because most browsers do a lousy job of resizing images for display. The text in the image has horrible aliasing in FF and IE that makes it very difficult to read.

Images should be resized in a graphics problem before publication, or with something like imagecache.

I was wondering if someone

I was wondering if someone would catch this. I've been playing with the idea of introducing an error per article, to see if people are really paying attention. I recall that this worked very well for a really difficult college course - by forcing the students to listen, and challenge, the rationale behind the stated facts, the retention became a lot higher. If only I could find that original article...

As the print module

As the print module maintainer, I can't thank you guys enough for such a comprehensive review.. I would have preferred that you had reviewed the print-6.x branch, as that one is my favorite branch, now, but I guess that you shouldn't complain when someone gives you something for free..

I would also like to thank Morbus for telling me about this review (only two weeks later :)..

For your consideration in future reviews:
1. You have access to the code, and you are suggesting changes to be done, so why not provide these changes as a patch? Your review included mostly one-line patch changes, which would have been so much easier to integrate if you provided these patches (and you wouldn't have to describe so much the changes that you're suggesting).
2. Most 'decent' modules now have two versions (5.x and 6.x), it would be nice if you could look at those two versions in parallel.
3. Since we all want Drupal to be lightning-fast, it would be nice to include performance reviews on the code and not only a code review. (i.e. your module is taking up so much in function n. etc. etc). Maybe use a PHP profiler?
4. If I fix it, will you update this review?

My verdict on your review:

Accept and will change it ASAP:
1, 2, 3, 4, 5, 9, 12, 13, 14, 15, 16, 17, 19, 20, 21, 24

Thinking about it...:
6, 8, 10, 22, 23

Not going to do anything about it:
7, 11, 18

Comments:
2. It's because I do periodical runs of Coder, myself..
4. I will leave CREDITS.txt and MAINTAINER.txt there.. The files have been there for 3 1/2 years without hurting anyone.
5. What do you mean formatting can be improved?
6. The tree is on purpose there.. I actually like to be able fetch all default values in a single function, and to do a single variable_get instead of several.. It keeps the code more readable. Note that I have more than one variable: they are more or less grouped by function. If you can prove to me that using an array is slower than calling variable_get several times, then I will happily collapse the arrays.
7. That define is there so that if a developer really needs to change the root path, they can do so easily. However, I don't want to be showered with requests by clueless users that have decided to rename their root path as "files" and can no longer access their uploaded files. So, no.. It will stay as it is.
8. :) In the beginning there really wasn't much help to provide.. Maybe I should add some help now that things are more complicated.
10. These theme functions were asked by users.. They were the ones that specifically asked to be able to "theme" these features.
11. I remember that at one point I removed the "_menu_append_contextual_items()" call, but something stopped working so I had to put it back in.. print_generate_path() is used to create PF versions of non-node pages (views/core/etc.).. Are you telling me that Drupal core should be altered so that I stop using these functions??
18. In the Drupal 6 version, it's a checkbox, as it became a choice between none/text only/icon only/text+icon.. I got permission from the Plone foundation to use their GPLd printer and pdf icons (Thanks Plone Foundation!). I will back-port that into the Drupal 5 branch one of these days, something I prefer to do before "fixing" as you suggested.
22. It's bloody hard work to document everything properly..
23. Sometimes, I really need to create the absolute URL myself, as url() tries to replace the URL with an alias if any is defined. Is there a supported url()-like function that returns a URL in a http://www.example.com/node/nid format?

Thanks again,

João Ventura

Please take it serious. 4. I

Please take it serious.

4. I will leave CREDITS.txt and MAINTAINER.txt there.. The files have been there for 3 1/2 years without hurting anyone.
You should not. README.txt and, if needed, INSTALL.txt are recommended. No more, no less. Please do not make module documentation, installation, and upgrading harder than it is already.

5. What do you mean formatting can be improved?
Use spaces between styles (i.e. foo: bar;), put each style in a separate line, and indent styles with 2 spaces like this:

body {
  margin: 1em;
  background-color: #fff;
  font-family: sans-serif;
}

Additionally, the last semicolon was missing. You should also add comments to make clear on which page/function/output a section of styles will be applied, so themers are able to quickly identify which styles they need to override.

6. The tree is on purpose there.. I actually like to be able fetch all default values in a single function, and to do a single variable_get instead of several.. It keeps the code more readable. Note that I have more than one variable: they are more or less grouped by function. If you can prove to me that using an array is slower than calling variable_get several times, then I will happily collapse the arrays.
The reason for removing #tree has already been outlined above.

7. That define is there so that if a developer really needs to change the root path, they can do so easily. However, I don't want to be showered with requests by clueless users that have decided to rename their root path as "files" and can no longer access their uploaded files. So, no.. It will stay as it is.
You could prevent this in a hook_validate() function. It is a bad practice to force users to change the code of a module, because that will make upgrades to a later version much harder.

8. :) In the beginning there really wasn't much help to provide.. Maybe I should add some help now that things are more complicated.
You definitely should.

10. These theme functions were asked by users.. They were the ones that specifically asked to be able to "theme" these features.
As outlined above, the implementation is wrong.

11. I remember that at one point I removed the "_menu_append_contextual_items()" call, but something stopped working so I had to put it back in.. print_generate_path() is used to create PF versions of non-node pages (views/core/etc.).. Are you telling me that Drupal core should be altered so that I stop using these functions??
No, read the suggested alternatives above again, please.

22. It's bloody hard work to document everything properly..
...but documentation is badly needed for contributors who want to help you out and provide a patch. In reality, you are restricting yourself by being lazy with proper documentation.

23. Sometimes, I really need to create the absolute URL myself, as url() tries to replace the URL with an alias if any is defined. Is there a supported url()-like function that returns a URL in a http://www.example.com/node/nid format?
global $base_url is unused in _print_generate_node(), _print_generate_path(), and _print_generate_book(). If it's unused, it simply shouldn't be there.

I am taking it

I am taking it serious...

Honestly, I maintain (and improve) this module on a part-time basis.. It takes a lot more of me than it has ever given back.. And being called lazy makes me think about calling it quits and moving to Joomla or Plone, where perhaps people will be more diplomatic about stuff.

So, about your suggestions (and I am going to be specially caustic, in light of the above reason):

4. Did you read my comment? The files have been there for 3 1/2 years. They are current, they will remain current as long as I am maintainer of the module. They will remain. End of discussion.

5. Thanks for letting me know what was meant by 'formatting could be improved'. It's the only positive part of your post, I wish you could have limited yourself to write only that.

6. No it wasn't. No reason for not using tree was given. Reading it back it goes like this: Your use of tree is maybe a mistake - I have stated that it is on purpose. If you get rid of it maybe you can collapse your default functions - I like the default functions as they are.. If PHP enabled me to do array constants, I wouldn't use a separate function, but alas I prefer it this way. Nowhere was it said that it would be better to colllapse the default functions().

7. Did you read my comment? That define is not there for the users! No sane user should ever need that.. If an advanced user wants to change it, it is there. But then again, he will have to deal with the consequences (such as changing the define again, when he upgrades).

8. I definitively should.. But then again, my free time only allows me to do so much.. Maybe YOU could submit a patch for that, if you are so interested.

10. The implementation may be wrong, but since I don't have time to research how to do it right, it will have to remain as it is until: a) somebody provides a patch or an explanation on how to do it right; or b) I have to research how to do it right.

11. No, you read my comment again, please. I tried removing the call, and it broke something (note that leaving it in hasn't broken anything). Also, of the suggested solutions, only the theme may be usable, and then again probably it isn't. Since I don't have time to fix something that is not broken just because some people (as respected as they are) tell me they don't like it, I am leaving it as it is.

22. Thanks. Yes I am lazy, working for free on something which I do for kicks. Would you prefer to maintain the module yourself?

23. Your reply has nothing to do with my comment. I asked for a url()-like function that doesn't return alias. I know perfectly well that I need to remove some unused vars (they were not unused at one point, but I have changed the code and forgot to remove the var declaration).

To avoid a flame-war, please contact me directly via drupal.org, if you fell that you need to discuss this further. I would specially appreciate constructive comments or an offer to take over maintenance of the module. Thanks!

João Ventura

Please take it serious. To

Please take it serious.

To me it seemed like he did take it seriously, and you're still giving him a hard time, being unfriendly and not answering the questions raised (like choosing branch or making patches). Keep it up and you might as well make him leave this module. But maybe that's what "tough love" is about...

Well, I have let it go.. I

Well, I have let it go.. I still have some ideas on what I want this module to do before I am ready to pass it on to other hands (one of them being an optional module to send the page via e-mail, using the same output that is built for the web page)..

Besides, one troll does not offset all the users that have repeatedly told me how useful they find the module to be (and the fact that it is used on some of the more important Drupal sites out there is proof enough). I see that 'sun' had also commented before that I should use 'Coder' when if he had thought about the fact that 'Coder' had so few complaints should be an indicator that I actually use it..

So, although I would welcome co-maintainers, I am not abandoning it. Before I took it over (in August 2007), it spent about a year and a half in maintenance limbo, and I wouldn't want it to return to that status. I believe part of the reason why 'my' module was chosen by chx and Morbus is the fact that indeed it is so useful (and most of you haven't even seen the PDF generation capabilities in print-6.x).

João

Hi, Just to let anyone

Hi,

Just to let anyone interested in the progress know how it is going.. I have changed the print-5.x-dev code and the print-6.x-HEAD code to comply with most of the comments.. I still have to do some things, before I release the print-5.x-3.5, specifically:

4. Still to improve README.txt and INSTALL.txt
6. I decided that I like it the way it is, so it will remain as it is. (use of #tree in the admin settings form)
8. Write help documentation (or just include README.txt)
10. Correct strings as suggested (use of %date, etc.) Need to find out what is meant by this hook talk... Specifically, I don't want users to have to install a new module that implements these functions.. These things are a matter of personal taste, about look and feel. I will probably leave it as theme functions after all, or promote them to configuration settings (probably the best choice).
12. In the end I left it as is.. I need to write a better description, not delete it simply..
18. Still to do in print-5.x
22. Need to improve code documentation.
23. Used base_path() instead of $base_path, but the $base_url and $base_root will remain, pending a test using drupal_lookup_path

Also to enlighten others about why some stuff looks weird, the 9th comment (that sometimes constants came before the var in '==' comparisons), while looking at it I remembered that that code was 'borrowed' from the forward module, and that's where part of the blame is.

João Ventura

Great review. I have already

Great review. I have already made some fixes in my own module. I am looking forwards to the next one, when it arrives.

Hi. Version 5.x-3.5 (and

Hi.

Version 5.x-3.5 (and 6.x-1.0-rc3) of the module was released a few minutes ago.

It fixes almost all of the points highlighted in the article. Except:

6. Contrary to what was believed by this article author's, I have used the #tree on purpose. I like to group functionally related variables in the same variable array. Unfortunately, PHP doesn't allow me to create array constants, forcing me to create some _default() functions..
7. As I explained, the define("PRINT_PATH", "print") is not there so that it is configurable by the user.. It is there to improve code readability, and to create a single point where I can change it. Drupal core doesn't do this. But it should. Really :)
11. The _menu_append_contextual_items() call was removed at one point, from 2007-10-24 to 2008-03-11. A user complained that without this call his dynamic menu didn't work properly (see http://drupal.org/node/232650). So, because leaving it in hasn't yet broken anything, I am not going to re-engineer the code just because you don't like it. Sorry :)
12. I still have to write a better description there... (yeah.. lazy and all.)

Best regards,

João Ventura

The line by line feedback is

The line by line feedback is great, but there is precious little feedback about how well the module actually does its intended job. Next time you might provide more input about that and about the code as it relates to the features and usability of the module, not only the readability.

A final comment. I have now

A final comment.

I have now accepted #6 also. The reason was that in the end, when using #tree, one is forced to use the same grouping for fieldsets, etc in the form that one wants to use in the code. At one point, the link-related variables were just too much and I wanted to move them to their own collapsible fieldset, but without moving the rest of the print_html_settings variables..

My advice: don't use #tree for the settings form. It will bite you down the road.

João

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.

More information about formatting options