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

PA robot’s picture

Status: Needs review » Needs work

There 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.

swirt’s picture

Status: Needs work » Needs review

I 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.

swirt’s picture

Issue summary: View changes
gisle’s picture

Status: Needs review » Needs work

Automated Review

PAReview complained about:

FILE: ...ar/www/drupal-7-pareview/pareview_temp/codit_blocks/codit_blocks.module
--------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
--------------------------------------------------------------------------------
183 | WARNING | Only string literals should be passed to t() where possible
--------------------------------------------------------------------------------

The problem line:

'info' => t(ucwords($human_readable)),

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 through check_plain.

swirt’s picture

Hi 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:

  1. This is not user submitted and does not require simple sanitization.
  2. These are the friendly names of blocks that are being generated dynamically from file names. There is never an instance in time when this is a string literal.
  3. While it is true that the translation would never be grabbed when t() is parsed as described here " the text inside t() calls is added to the database of strings to be translated. " It is not true that the t function would not allow possible translation. Lets take for example a block named "Loved Ones". Getting passed into t(ucwords($human_readable)), would never make it get added to the database of translatables. But let say I was running this on a site where I had both Engilsh and French Admins and I needed that bloc's name to appear in French for my french admins. I simply need to add "t('Loved Ones');" to codit_local/codit_local_function_definitions.inc and now that block name is fully translatable to 'proches'.
  4. Others might suggest the following as a coding option which would make pareview happy:
    $human_read_cap = ucwords($human_readable)
    t('@human', array('@human' => $human_read_cap));
    

    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.

swirt’s picture

Status: Needs work » Needs review
gisle’s picture

Status: Needs review » Needs work

OK, 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(), since t() 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.inc with the literal strings suitable encapsulated in calls to t() (or even better: equivalent local .po files 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.)

swirt’s picture

Status: Needs work » Needs review

Thank 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.

joachim’s picture

Status: Needs review » Needs work

This 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.

swirt’s picture

Thank 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.

  1. Code - Boxes is kind of the antithesis of the submodule Codit: Blocks (included with Codit). 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)
  2. Caching - Boxes offers none other than standard Drupal anonymous page caching. Codit: Blocks offers simple yet highly capable caching ranging from sitewide to per user or per page, or even per-user-per-subpath on a block by block basis.
  3. Individual Block User Access - Boxes offers none by itself. All the blocks it creates are publicly visible to any user unless controlled by context or panels. Codit: Blocks have easy to define access based on role or user.
  4. Editing Blocks - Boxes = anyone with account privileges || Codit: Blocks = Anyone with developer access. There are pros and cons to each method, but they are definitely different.
  5. Heavy PHP Processing - I'm not sure where this resides in Boxes other than in the db and then exported. In Codit: Blocks it resides safe from collisions in an anonymous callback function.
  6. Output - With Boxes it is all by code and html in a text field. Codit: Blocks has a block specific tpl.php that can be moved to theme if needed to have different output on sites with multiple themes.

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:

  • A site needs a wee bit of custom php code, a few functions. Where does it live? Codit:Local
  • A site with multiple themes needs a bit of consistent JS across those themes, Where does it live? Codit: Local
  • A site needs a few hooks registered specific to the site, as opposed to a specific module, Where does it live? Codit: Local
  • A site has a bunch of custom blocks created by Codit: Blocks. Where does the code live? Codit: Local

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.

gisle’s picture

About 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.

swirt’s picture

Thank 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

swirt’s picture

Status: Needs work » Needs review
joachim’s picture

> 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.

gisle’s picture

Joachim, 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:

  1. acknowledges the existence of similar projects; and
  2. briefly explain how they are different.

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.

swirt’s picture

Thank 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.

gisle’s picture

I 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.

swirt’s picture

Thanks for the update gisle. Have a good vacation.

swirt’s picture

Issue summary: View changes
gisle’s picture

Status: Needs review » Needs work

README.md

hook_help in 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:

cp codit_local/blocks/block_bin/_a_sample_block codit_local/blocks/block_bin/cool_block

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.

  • Docblock for hook_init() in codit.module claims it is hook_boot().
  • (*) codit_blocks.module line 256 : 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.

swirt’s picture

Thanks gisle,
I will get these changes made soon.

swirt’s picture

Status: Needs work » Needs review

Greetings gisle,
I have made both the required and the recommended changes.

gwprod’s picture

I 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 sanitize validate user input coming in and sanitize going out. What you are doing does not accomplish this.

gisle’s picture

I 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:

  1. Remove the t() wrapper around the variable, thus making PAreview and us reviewers happy; or:
  2. Flesh it out into something that makes these strings localizable by the user in a non-hackish fashion.

(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.

swirt’s picture

Thank 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?

gisle’s picture

swirt, my remark about sanitizing "best practices" was primarily intended for gwprod, not you.

gwprod’s picture

gisle 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.

swirt’s picture

gisle and gwprod,
Thank you for clarifying. ;)

gisle’s picture

Please keep in mind though that PAreview was happy.

While 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.)

gisle’s picture

Status: Needs review » Reviewed & tested by the community

Automated 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

Individual user account
Yes: Follows the guidelines for individual user accounts.
No duplication
Yes. Similar Projects and how they differ is adequately addressed on project page.
Master Branch
Yes: Follows the guidelines for master branch.
Licensing
Yes: Follows the licensing requirements
3rd party code/content
Yes: Follows the guidelines for 3rd party code.
README.md
Yes: Follows the guidelines for in-project documentation. It is named README.md, which we have a policy of accepting.
Code long/complex enough for review
Yes: Follows the guidelines for project length and complexity.
Secure code
Yes: Follows guidelines for writing secure code.
Coding style & Drupal API usage
Yes. All issues that have been reported are fixed.

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.

swirt’s picture

Thank 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.

dstol’s picture

Status: Reviewed & tested by the community » Fixed

Thanks 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.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.