Codit and Codit Local form a framework to support a series of submodules that all have a common need. The common need is to have some immutable code that resides as part of a distribution, a git submodule, or in sites/all and some code that is site specific and needs to reside in sites/mysite.com
For the sake of keeping this initial review as tight as possible, I am only including 1 of the 3 submodules. (If Codit is cleared for release, the submodule will be moved out into its own project to make issue tracking and documentation easier.)
This inital review request includes the submodule Codit Blocks which provides a powerful method of creating blocks only in through code and no admin settings. It is an alternative to the standard Drupal block admin and the Custom Page module https://www.drupal.org/project/custompage
In its simplest use case for Codit Blocks, you copy a sample directory in codit_local//blocks/block_bin then rename the directory and tpl inside with the name (delta) of the block you are building. Flush cache and your block is now registered for placement with Context, Panels, or the block admin. Add some content to the tpl and you have your block. (drush will handle this soon)
Beyond making a simple block, add some code to the callback function within the directory and whatever it returns will be available to the tpl. This is useful for doing the heavy lifting and keeping PHP out of the tpl.
If your callback is doing so much heavy lifting that you need to cache the results, Have the Caching callback pass it a unique cache id and the block can be cached on a page by page, user by user or entire site basis.
Need the block to only show for certain permissions. Process the permissions in the permissions callback.
Each block created can be as simple or as robust as needed, without having to create a new module just to build a block for a site.
The blocks are also portable. Copy the block directory and move it to another site using Codit Local, flush the cache and now that block is present on that site too, ready for placement with Context, Panels or the block admin.
Codit Sandbox Page: https://www.drupal.org/sandbox/swirtmiles/2164945
Codit Git Repo:
git clone --branch 7.x-1.x http://git.drupal.org/sandbox/swirtMiles/2164945.git codit
Codit Local Sandbox Page: https://www.drupal.org/sandbox/swirtmiles/2164951
Codit Local Git Repo:
git clone --branch 7.x-1.x http://git.drupal.org/sandbox/swirtMiles/2164951.git codit_local
Comments
Comment #1
PA robot commentedThere are some errors reported by automated review tools, did you already check them? See http://pareview.sh/pareview/httpgitdrupalorgsandboxswirtMiles2164945git
We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and put yourself on the high priority list, then we will take a look at your project right away :-)
Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).
I'm a robot and this is an automated message from Project Applications Scraper.
Comment #2
swirtI have cleaned up a handful of issues found by Pareeview. The 2 warnings found by Pareview that remain are unavoidable and fall into allowable cases for the warning.
Comment #3
swirtComment #4
gisleAutomated Review
PAReview complained about:
The problem line:
One of the purposes of the
t()function is to facilitate extraction of string literals for localization. This does not work with a function call or a variable. If you need to sanitize the string, you should run it throughcheck_plain.Comment #5
swirtHi gisle,
Thank you for taking a look.
I believe this does fall into one of the very rare cases where passing a variable to t() is allowable and while not ideal, is better than the alternative of not passing it to t(). Here I respectfully plead the case:
This would make the human readable variable by-pass translation so it would remain untranslatable.
Wrapping it in the t() as I have done does not make any block name getting registered automatically translatable as that is impossible, but it does leave the door open to make specific block names translatable if needed. If, as you suggested, I removed it from the t() then translation would forever be impossible.
Comment #6
swirtComment #7
gisleOK, I buy your premise that there is a use-case for passing this variable through
t().I also agree that having a string with only a placeholder to make PAReview happy, is silly (and doing this is the same as not using
t(), sincet()does not translate the stuff passed it by means of an array assigned to a placeholder).However, given that the whole point of passing this through
t()is to allow admins to create translations of these "friendly names of blocks that are being generated dynamically from file names", admins need to be told about this feature and how to use it. The method you describe for making use of these strings for translation is IMHO far from intuitive.So to support this use-case, you will need to, as a minimum requirement, document this (e.g. in README.txt). Documenting it will have the additional benefit of making reviewers (like me) aware of why you do such non-standard things as passing a variable through
t().The following is not a requirement, but just ideas:
To provide better support the translation, the "friendly names of blocks that are being generated dynamically from file names" should be exposed to admins on some page, so that admins can see what these names are and what they shall be able to translate. For even better support, you could generate the
codit_local/codit_local_function_definitions.incwith the literal strings suitable encapsulated in calls tot()(or even better: equivalent local.pofiles that can be imported into the translation interface), to spare admins from the task of having to do this themselves.Btw - are users allowed to create the files the names are derived from, and if so, are the file names sanitized? I have Drupal sites that allows file uploads, and I've seen names of uploaded files that are clearly intended to be various forms of injection attacks. (I could find out by reading your code, but it is quicker to ask than scrutinizing the code.)
Comment #8
swirtThank you Gisle,
On your suggestion, I have added directions to the README for the submodule Codit Blocks.
http://cgit.drupalcode.org/sandbox-swirtMiles-2164945/commit/?id=8416f71
I have also added a designated area for string literals in t() and an example to the block config file in the Codit Local module.
http://cgit.drupalcode.org/sandbox-swirtMiles-2164951/commit/?id=b08374c
I like your suggestion of having the string literal written automatically by the code but I think that will run into a handful of issues on properly hardened sites that restrict php files from altering other php files on the site. I do think it would be a great job for Drush to handle in the future so I have added that to my long term plans.
And thanks for your concerns over user submitted block names. The blocks being built are not from anything user submitted. They are 100% from the developer(s) working on the site's code. They come from code and live in code and have no admin whatsoever.
Thank you again for your time and I appreciate any further review.
Comment #9
joachim commentedThis sounds very ambitious and thought-out, but unfortunately, it seems to me like it's reinventing the wheel, sorry:
> In its simplest use case for Codit Blocks, you copy a sample directory in codit_local//blocks/block_bin then rename the directory and tpl inside with the name (delta) of the block you are building. Flush cache and your block is now registered for placement with Context, Panels, or the block admin. Add some content to the tpl and you have your block. (drush will handle this soon)
Why not use Boxes module to create a Box block, and then export it to a Feature, which can then be added to the codebase?
> Beyond making a simple block, add some code to the callback function within the directory and whatever it returns will be available to the tpl. This is useful for doing the heavy lifting and keeping PHP out of the tpl.
Boxes lets you define custom box types, which are CTools plugins. Within those, you can use PHP to create the output.
Comment #10
swirtThank you Joachim,
I think there are some significant differences between Codit and Boxes (which is quite similar to Custom Page module). Hopefully I can convince you. Here are areas where they differ dramatically.
Separate from the submodule Codit:Blocks, Codit can do so much more for consolidating all the unique one-off customizations that we do for sites. Use cases:
I am sure you have worked on sites where you spend lots of time figuring out where the unique customizations that don't merit their own module reside. How often have you seen other developers on your team spend time trying to find other unique customizations scattered throughout a Drupal build. Wouldn't it be nice to have a single place where those things reside? A single place where you can find them? A single place where other members of your team can find them? Most sites get by fine with 90% of the site coming from contributed modules. Codit is for the 10% that usually finds itself scattered in various corners of the site.
Joachim, I hope I have persuaded you to consider that the submodule Codit: Blocks is not a repeat of Boxes and that the Codit framework of modules is worth considering for release.
Comment #11
gisleAbout duplication:
To me, it looks like Codit has enough unique features to justify its place as a module of its own. I really like the idea of being able to manage this through code rather than trough the database.
However, the subject of duplication (i.e. similar projects and how they are different) need to be addressed on the project page, and not only in this issue summary or as comments in this issue queue. It should not be as long and comprehensive as #10. All that is required is a link to the similar project and a line or two that highlights the main difference.
I think there are at least exists two similar project:
Please take a moment to make your project page follow tips for a great project page.
Comment #12
swirtThank you Gisle,
That is an excellent suggestion. I have updated the module page with a section on Similar modules and wrote a breakdown on the pros and cons of each.
https://www.drupal.org/sandbox/swirtmiles/2164945
Comment #13
swirtComment #14
joachim commented> Boxes is nearly entirely admin based. Codit: Blocks are 100% code based. The only admin is whatever tool you use to place them (block admin, Context, Panels)
Boxes are admin based, but can then be exported to code with Features. So the above is misleading.
I still think you're going to great lengths to reinvent the wheel, when Features is already the defacto standard for this sort of thing. But gisle disagrees, which is fair enough. I'm just going to unfollow this.
Comment #15
gisleJoachim, I don't think that it is only in rare cases overlap with an existing module should be a blocking issue.
I don't think we should block a project just because it does the same job as another project. If we have that as a rule, we may prevent better solutions from ever entering the Drupal ecosystem.
The way I interpret § 1.2 of the Project application checklist, is that we only block if the "differences between your modules are not too fundamental for patching an existing one". IMHO, it makes no sense "patching" Boxes to contain Codit.
What we (as reviewers) instead should require in the cases of functional overlap, is that the project page:
The way I see it, this requirement has been fulfilled in this case.
I haven't looked carefully at the code net, so I need to do a code review before setting status, but unless there are issues in the code, as far as I am concerned, this is close to completion.
Comment #16
swirtThank you gisle for your clarity of focus and continuing with the review of Codit. I realize and appreciate that it is a time commitment on your part.
Comment #17
gisleI am going away on a week-long vacation today, so there will not be a code review from me anytime soon. I hope somebody else takes a look at the code in the meantime.
Comment #18
swirtThanks for the update gisle. Have a good vacation.
Comment #19
swirtComment #20
gisleREADME.md
hook_helpin all modules sniffs for the markdown filter module. It should be mentioned in README.md that the presence of this module alters the behaviour of the modules.To create a new block the following shell command is suggested:
This does not work on most Unix-like platforms. cp need the -r option to copy directories.
There are other minor inaccuracies in these instructions as well. Please proofread.
Code review.
hook_init()in codit.module claims it ishook_boot().empty($_access($user))- PHP function empty needs a variable, not a function, as argument.hook_help()sniffs for the markdown filter module. No online help is displayed if the filter is found. This is probably not the intended behavior.The starred items (*) are fairly big issues and warrant going back to Needs Work. The rest of the comments in the code walkthrough are recommendations.
Comment #21
swirtThanks gisle,
I will get these changes made soon.
Comment #22
swirtGreetings gisle,
I have made both the required and the recommended changes.
Comment #23
gwprod commentedI personally disagree with what was said earlier about the use of t() with a variable.
I (personally) would suggest rewriting this to allow the custom strings to be localized, while at the same time not opening yourself up to security holes.
You could accomplish this by using t() as an example localization workflow, while making sure to sanitize everything passed to it.
The thing to remember is that the best practice in drupal is to
sanitizevalidate user input coming in and sanitize going out. What you are doing does not accomplish this.Comment #24
gisleI think I am going to reverse my earlier decision and go with gwprod on this one. I never really liked the hackish approach where the user is supposed to create corresponding wrapped strings in
codit_local/codit_local_function_definitions.inc.For the purposes of this review you could either:
t()wrapper around the variable, thus making PAreview and us reviewers happy; or:(What you do after having passed review is up to you.)
Now, regarding best practices in Drupal I think you should always "store exactly what the user typed". (Source: Handle text in a secure fashion.)
In other words: Preserve user input coming in and sanitize going out.
Comment #25
swirtThank you gisle and gwprod,
I understand that having a blockname up for possible translation is more troubling than not having it translatable at all. So I have taken the route of the core Block module and Custom Page module and Boxes module and just made the friendly name of the block completely non-translatable by simply removing the t(). Please keep in mind though that PAreview was happy. In its warning it makes allowances for such things "183 | WARNING | Only string literals should be passed to t() where possible" (emphasis mine)
What I am not clear on is why you both referenced sanitizing or validating user input. The text being processed is not user input, it is a filename from a developer with keys to the codebase. Is there a risk here I am missing?
Comment #26
gisleswirt, my remark about sanitizing "best practices" was primarily intended for gwprod, not you.
Comment #27
gwprod commentedgisle is completely correct, I misspoke. The standards require that what the user types is preserved, and that your code be designed in such a way that it doesn't matter what they type, it will not cause a security breach.
Comment #28
swirtgisle and gwprod,
Thank you for clarifying. ;)
Comment #29
gisleWhile warnings does not throw PAReview into a state of chronic depression of the kind that inflicts its cousin Marvin, it becomes mildly melancholic after issuing a warning. (But IMHO the t() wrapper around the variable is not a blocker.)
Comment #30
gisleAutomated Review
PAReview complained about a few long lines. These are not substantial and fixing all issues is not a requirement for getting through the application process.
Manual Review
README.md, which we have a policy of accepting.There are IMHO no more blockers. Moving to RTBC. Note that promotion will not happen until a git administrator has given this a second set of eyeballs.
Comment #31
swirtThank you gisle,
I appreciate your time and guidance (and humor) on this. I know what looked like a single module review turned into three module reviews and I appreciate your not running away. I hope it was not too painful.
Comment #32
dstolThanks for your contribution, swirt!
I updated your account so you can 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 stay 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.