Image Compression TinyPNG/JPG is designed for users to integrate easily with an image compression tool that will make your image suitable for the web. It uses TinyPNG.com’s API which means no complex installation on your server.

This module will reduce the size of your png and jpg files significantly and make Google's PageSpeed Insights happy along reducing your server bandwidth. You will have the options to enable auto compression or keep it manual. You will also be able to bulk compress images that are already on you website.

This module is different from others at it offers simplicity by not presenting the user with any configuration options for images. This module will allow you to compress you historical images on your website using the bulk compression feature and will also give you a way to manually compress you images if you choose too. It provides a close integration with Scald which will also you to see if an image is already compressed or requires compression.

Link to project page: https://www.drupal.org/sandbox/chenderson/2457559

git clone --branch 7.x-1.x http://git.drupal.org/sandbox/chenderson/2457559.git image_compresssion_tinypng_jpg

Manual reviews of other projects:
https://www.drupal.org/node/2495539#comment-9969555
https://www.drupal.org/node/2475755#comment-9969849
https://www.drupal.org/node/2495891#comment-9970057

https://www.drupal.org/node/2496507#comment-9972201
https://www.drupal.org/node/2496997#comment-9972329
https://www.drupal.org/node/2497023#comment-9972703

https://www.drupal.org/node/2498097#comment-9979415
https://www.drupal.org/node/2460777#comment-9986993
https://www.drupal.org/node/2499307#comment-9987823
https://www.drupal.org/node/2499307#comment-9991251 Second review from previous

Minor reviews
https://www.drupal.org/node/2500371#comment-9994307
https://www.drupal.org/node/2499307#comment-9994433
https://www.drupal.org/node/2493817#comment-9974353

Comments

mr_infinity’s picture

Automated Review

[pareview.sh / drupalcs / coder] Tests are good:Pareview

Manual Review

Individual user account
[Yes: Follows] the guidelines for individual user accounts.
No duplication
[Yes: Does not cause] module duplication and/or fragmentation.
Master Branch
[Yes: Follows] the guidelines for master branch.
Licensing
[Yes: Follows] the licensing requirements.
3rd party assets/code
[Yes: Follows] the guidelines for 3rd party assets/code.
README.txt/README.md
[Yes: Follows] the guidelines for in-project documentation and/or the README Template.
Code long/complex enough for review
[Yes: Follows] the guidelines for project length and complexity.
Secure code
[Yes: Meets the security requirements
Coding style & Drupal API usage
  1. The code looks good, the only thing i would recommend is to use less empty lines ( in function hook_menu for example).
  2. Recommended is to use elements requirements, installation, configuration on the project page to turn it into something like this.

This review uses the Project Application Review Template.

chenderson’s picture

Thanks for the feedback.

I have changed the project page to only include the requirements, installation and configuration section (with an intro). I have also included two screenshots of the configuration section.

I have also removed some extra blanks spaces to make the code more compact but anymore and I think it starts to become unreadable.

darol100’s picture

Status: Needs review » Reviewed & tested by the community

In the past I was looking for this integration. I personally, love TinyPNG. There is a place holder that you should consider asking the developer if I can give you the name of this project - https://www.drupal.org/project/tinypng.

I believe this is a Duplication of a module - ImageAPI Optimize (or Image Optimize) have a patch to integrate their module with TinyPNG services. Duplication is not a blocker; however, the Drupal community holds a strong "collaboration rather than competition" ethos, which values joining forces on improving one awesome project rather than building several sub-standard ones that overwhelm end users with choices.

Here are few minor warning from coder:

  • tinypngjpg.scald.manual.inc
    Line 19: in most cases, replace the string function with the drupal_ equivalent string functions
      if (!empty($key) && strlen($key) > 0) {
  • tinypngjpg.inc
    Line 41: in most cases, replace the string function with the drupal_ equivalent string functions
        $headers = substr($response, 0, curl_getinfo($request, CURLINFO_HEADER_SIZE));
    Line 43: in most cases, replace the string function with the drupal_ equivalent string functions
          if (substr($header, 0, 10) === "Location: ") {
    Line 46: in most cases, replace the string function with the drupal_ equivalent string functions
              CURLOPT_URL => substr($header, 10),
    Line 102: in most cases, replace the string function with the drupal_ equivalent string functions
      $json_undecoded = str_replace(substr($response, 0, curl_getinfo($request, CURLINFO_HEADER_SIZE)), '', $response);
    Line 143: in most cases, replace the string function with the drupal_ equivalent string functions
        if (substr($header, 0, 19) === "Compression-Count: ") {
    Line 144: in most cases, replace the string function with the drupal_ equivalent string functions
          variable_set('tinypngjpg_api_key_allowance', substr($header, 19));
  • tinypngjpg.scald.batch.inc
    Line 112: in most cases, replace the string function with the drupal_ equivalent string functions
      if (!empty($key) && strlen($key) > 0) {

No complains from Pareview.sh - http://pareview.sh/pareview/httpgitdrupalorgsandboxchenderson2457559git

I do not see any blockers; however, consider to integrate this module with the ImageAPI Optimize (or Image Optimize) instead of creating your own project.

chenderson’s picture

Issue summary: View changes
chenderson’s picture

Thank for the feedback darol100, it is appreciated and I will look at those issues shortly.

I agree that ImageAPI Optimize is already in existence and there is room to integrate. However I did encounter issues with ImageAPI Optimize that I felt warranted something different. Also I want specifically to allow the user to compress there existing images on the server which ImageAPI Optimize does not offer.

I defiantly agree that there is room to merge once I complete the list of wants for this module.

darol100’s picture

@chenderson,

Sounds great, if you wish to promote your own project due the differences between your project and the ImageAPI Optimize, try to talk to the developer that took the tinypng name to see if would give you that URL.

chenderson’s picture

Issue summary: View changes
Issue tags: +PAreview: review bonus
chenderson’s picture

@darol100,

I made the changes you mentioned in #3. I could not see the minors issues you picked up using Coder. When I type in terminal the code below it shows no suggestions.

phpcs --standard=Drupal --extensions=php,module,inc,install,test,profile,theme tinypngjpg/

Does Coder do a better job at finding out minors or am I missing something from the command? I went through the steps outlined in the guide at https://www.drupal.org/node/1419988 and I can pick up errors just not the few you found. Is it a case of me not using the correct standards rules?

Any advice is appreciated.

chenderson’s picture

Issue summary: View changes
darol100’s picture

@chenderson,

I usually use Coder module alone without Sniffer because it show different warnings and errors from Coder Sniffer. In addition, Coder Sniffer is integrate with Pareview.sh so there is need for me to used it locally. If you want to get those warning, you would have to install the coder module, then find your module in the modules page (admin/modules) and click Code Review. From there you would have to click on SELECTION FORM and select the check box "minor (most)". This would make your review very picky and it would show you those warning.

chenderson’s picture

Issue summary: View changes

Adding three more reviews

chenderson’s picture

Issue summary: View changes
chenderson’s picture

Issue summary: View changes
darol100’s picture

@chenderson,

Apparently, there is another project trying integrate Drupal with TinyPng #2471060: [D7] TinyPNG On Upload, which is also been under-review.

chenderson’s picture

@darol100,

Yes the other module does seems to be doing the same tasks.

I have put a lot of time into other reviews here and I am reluctant to abandoned the review process. However I am equally willing not to promote this project to a full project. It would be good if a administrators could advise on the way forward here.

mpdonadio’s picture

Assigned: Unassigned » mpdonadio

Next up on my review queue.

mpdonadio’s picture

Assigned: mpdonadio » Unassigned
Issue tags: +PAreview: security

Automated Review

Review of the 7.x-1.x branch (commit a5a9241):

  • No automated test cases were found, did you consider writing Simpletests or PHPUnit tests? This is not a requirement but encouraged for professional software development.

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

Secure code

(*) There is a security problem with this module. As part of project review mentoring, I am assigning this to @darol100 to find it.

Coding style & Drupal API usage
Remove the .gitignore from the repo. This like this should go in your global ignore.

Why cURL and not drupal_http_request()?

All of your variable_get() should have a default value.

Why the exif_imagetype() and not use the MIME type that is in the $file object? Comment needed.

tinypngjpg_compress_for_batch(), don't concatenate with t(). Use placeholders.

tinypngjpg_bulk_import_form() has untranslated strings. Use t() w/ placeholders.

tinypngjpg_bulk_import_form_submit(), you don't need the leading slash in the drupal_goto().

In general single quoted strings are preferred over double-quoted ones.

tinypngjpg_start_batch_process(). Avoid using header() and die() directly. See http://drupal.stackexchange.com/questions/91011/can-a-batch-process-be-s...

tinypngjpg_process_finished(), the check_plain is superflous here. There is no user input.

In the .module file you shouldn't have any logic at the top level. You need to move these includes somewhere else.

The starred items (*) are fairly big issues and warrant going back to Needs Work. Items marked with a plus sign (+) are important and should be addressed before a stable project release. The rest of the comments in the code walkthrough are recommendations.

The security problem is the blocker. Otherwise, I didn't see anything.

If added, please don't remove the security tag, we keep that for statistics and to show examples of security problems.

This review uses the Project Application Review Template.

mpdonadio’s picture

Status: Reviewed & tested by the community » Needs work
mpdonadio’s picture

OK, no response about the security problem.

In tinypngjpg_admin_settings(), line 15, the variable_get() is used directly in #markup without sanitization. This is user input and considered unsafe. Use t() w/ a placeholder. See https://www.drupal.org/node/28984

chenderson’s picture

Thanks for the review mpdonadio.

I have went through the issues you have highlighted.

Remove the .gitignore from the repo. This like this should go in your global ignore.

Done.

Why cURL and not drupal_http_request()?

Main reason was there was already a snippet available for the cURL from tinypng.com. I have changed it over to drupal_http_request() now.

All of your variable_get() should have a default value.

Done.

Why the exif_imagetype() and not use the MIME type that is in the $file object? Comment needed.

I think my original concern was dealing with jpg, jpeg and what they would return, I thought they would return different mime type of image/jpeg and image/jpg and that lead me in the wrong direction. I changed the check to $file->filemime == 'image/jpeg' || $file->filemime == 'image/png'.

tinypngjpg_compress_for_batch(), don't concatenate with t(). Use placeholders.

Done.

tinypngjpg_bulk_import_form() has untranslated strings. Use t() w/ placeholders.

Done.

tinypngjpg_bulk_import_form_submit(), you don't need the leading slash in the drupal_goto().

Done.

In general single quoted strings are preferred over double-quoted ones.

Changed to single quotes.

tinypngjpg_start_batch_process(). Avoid using header() and die() directly.

Removed header() and die() to use $context['finished'] = 1

tinypngjpg_process_finished(), the check_plain is superflous here. There is no user input.

Removed the check_plain.

In the .module file you shouldn't have any logic at the top level. You need to move these includes somewhere else.

Sorry I am not sure what you are suggesting here.

In tinypngjpg_admin_settings(), line 15, the variable_get() is used directly in #markup without sanitization. This is user input and considered unsafe. Use t() w/ a placeholder. See https://www.drupal.org/node/28984

I have made the change but I would just like to follow up for better clarification on my part.

I understand not sanitising user code is unsafe however this variable is set by the function tinypngjpg_update_tinypng_allowance_info() and is uses the response for the tinypng.com api.

Are you suggesting that I should always consider third party responses unsafe and on the same level as a user? Or is it about future maintenance and a potential for the variable to change use and be exposed to a user?

chenderson’s picture

Status: Needs work » Needs review
mpdonadio’s picture

Assigned: Unassigned » mpdonadio

Sorry for the delay. The review admins have a big queue to go through, and we do it by age. I will check the security fix tonight (which was the only blocker).

And to answer your question, third-party content is considered unsafe. In general, we require sanitization here.

mpdonadio’s picture

Assigned: mpdonadio » er.pushpinderrana
Status: Needs review » Reviewed & tested by the community

I read `git diff a5a9241`, and my security issue was addressed via proper use of t() w/ an @arg placeholder. Nothing else jumped out at me. Setting RTBC and assigning to @er.pushpinderrana, if he has time.

er.pushpinderrana’s picture

Assigned: er.pushpinderrana » Unassigned
Status: Reviewed & tested by the community » Needs work

Automated Review

Best practice issues identified by pareview.sh / drupalcs / coder. None

Review of the 7.x-1.x branch (commit 1884ed5):

  • No automated test cases were found, did you consider writing Simpletests or PHPUnit tests? This is not a requirement but encouraged for professional software development.

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

Coding style & Drupal API usage

(*) tinypngjpg_bulk_import_form(): doc block is wrong, this is not a hook. See https://www.drupal.org/coding-standards/docs#forms. Same applies for tinypngjpg_bulk_import_form_submit(), tinypngjpg_compress_form_submit() and tinypngjpg_batch(). Need a proper doc block with @param and @return, check for other functions too.

(+) tinypngjpg_batch(): BatchAPI code looks wired to me. That's not the right way to do this at all. Use the batch sandbox to store details from one batch iteration to the next, it's what it's there to do.

foreach ($images as $image) {
    $batch['operations'][] = array(
      'tinypngjpg_process',
      array($image),
    );
  }

You should only add the operation once, and let the operation iterate over a set number of results, using the sandbox to mark how far it got each time. If you go with sandbox then there is no need to use $_SESSION to hold batch results.

tinypngjpg_bulk_import_form_submit(): IMO do NOT use drupal_goto() in form submit handlers, $form_state['redirect'] is the correct way.

tinypngjpg_extract_error_message(): Instead of using json_decode(), should use drupal_json_decode().

tinypngjpg_save_error(): Instead of using time(), should use REQUEST_TIME.

(*) tinypngjpg_compress(): drupal_set_message(check_plain('Compression failed: ' . $error['Error'] . ', ' . $error['Message']), 'error');The check_plain does not suit for static text. Use t() with "@" or "%" instead, see https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7

tinypngjpg_init(): hook_init() is run on every single page request and even on drush invocations. Could you add a comment here why you can't use hook_page_build() or others?

The starred items (*) are fairly big issues and warrant going back to Needs Work. Items marked with a plus sign (+) are important and should be addressed before a stable project release. The rest of the comments in the code walkthrough are recommendations.

PA robot’s picture

Status: Needs work » Closed (won't fix)

Closing due to lack of activity. If you are still working on this application, you should fix all known problems and then set the status to "Needs review". (See also the project application workflow).

I'm a robot and this is an automated message from Project Applications Scraper.