Integrate workout data from Garmin Connect into Drupal.

This project uses the Garmin Connect REST API to download your workout data from Garmin Connect and provides mechanisms for rendering and comparing workout data.

Data summary and presentation functions are provided:

  • A block that lists your last X key workouts
  • A block that rewards you for completing workouts that you hate
  • A "quick view" of pace, heart rate, power, and other workout metrics
  • A calendar-type view that summarizes this month's and last month's workout activity

You can use the Garmin Connector 'Compare Workouts' page to create lists of key workouts, ready to show to your coach or training partners. You can create sets of these workouts to make comparing key workouts easier.

Important notes:

  • Although sample data is provided, you really need an account with Garmin Connect for best results. The current version of this software allows only one Garmin Connect user per drupal instance but plans are in place to extend this to multi-Garmin Connect users.
  • No other project successfully interfaces with Garmin Connect in a complete way.
  • I heavily used this code when training for Ironman Coeur D'Alene 2013 and Ironman Lake Placid 2013. You can see different demos on Ironman training website ironman.teamchad.ca. You can start by checking out the project demo page there

Important Links

  • Git: git clone --branch 7.x-1.x http://git.drupal.org/sandbox/candotri/1816816.git garmin_connector
  • Repository Viewer
  • Git: git.drupal.org:sandbox/candotri/1816816.git
  • Project page: here
  • pareview results: here
  • Reviews of other projects

    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://ventral.org/pareview/httpgitdrupalorgsandboxcandotri1816816git

    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.

    candotri’s picture

    I attended to many of the issues described in the automated review process. I consider the review complete.

    PA robot’s picture

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

    Closing due to lack of activity. Feel free to reopen if you are still working on this application.

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

    candotri’s picture

    Status: Closed (won't fix) » Fixed
    klausi’s picture

    Status: Fixed » Needs review

    This is not fixed? See https://drupal.org/node/532400

    sreynen’s picture

    Title: garmin_connector » [D7] garmin_connector
    Status: Needs review » Needs work

    http://pareview.sh/pareview/httpgitdrupalorgsandboxcandotri1816816git still shows thousands of code formatting errors. None of those are individually blockers, but there's so many that it's going to be difficult for anyone to read the code to review.

    Much of that is likely due to the 3rd party libraries you have included directly in your module. Those need to be changed to a library include to prevent errors with other modules using the same libraries. See: https://drupal.org/node/422996

    ygerasimov’s picture

    More points to improve:
    - use 7.x-1.x branch instead of master
    - remove all dpm() (found them in .install file)

    candotri’s picture

    Compliance with the style robot complete. I'll work on using the flot library in a different way. Is there anything that can be done while I'm working on that?

    candotri’s picture

    Anyone?

    klausi’s picture

    You need to set the status to "needs review" if you are ready and want to get a review, see https://drupal.org/node/532400

    candotri’s picture

    Status: Needs work » Needs review

    Thanks, @klausi. Oops.

    candotri’s picture

    OK, I did a bunch of work to suppress unused variable errors. All that's left are errors because I use vim modelines

    I get "3526 | WARNING | There must be no blank line following an inline comment" when the last line of the file is this:
    3526 // vim: syntax=php ts=2

    Is there an appropriate way to suppress that?

    kscheirer’s picture

    Title: [D7] garmin_connector » [D7] Garmin Connector
    Status: Needs review » Needs work
    Master Branch
    It appears you are working in the "master" branch in git. You should really be working in a version specific branch. The most direct documentation on this is Moving from a master branch to a version branch. For additional resources please see the documentation about release naming conventions and creating a branch in git.
    README.txt
    Please take a moment to make your README.txt follow the guidelines for in-project documentation.
    • You can remove the commented out lines from garmin_connector.info, they're always in the git repo if you need them back.
    • In garmin_connector_install(), I'm not sure what's going on with those empty conditional blocks, can you remove or finish them?
    • In garmin_connector_schema() you have a user column set as varchar 40, do you want to use uid instead?
    • You should remove garmin_connector_update_7002() - assume your users have not installed this module before.
    • Remove the commented out dpm() calls if you can.
    • I'm not sure what's in the Makefile - can you delete that file?
    • What is garmin_connector.test testing? I'd remove it until you're ready to flesh out the tests.
    • In garmin_connector.module, don't use bare php, and definitely don't change any php ini values. Assume the user has their PHP configured the way they want it.
    • Is it possible to remove the new global $_garmin_connector_cf? A function with a static variable is an easier way to reuse a single connection.
    • If your project requires the flot module, add it to the list of dependencies in the .info file.
    • Don't use hook_init() if you can, just load your javascript/css when it's actually needed.
    • In garmin_connector_block_view() - all your code blocks ends the same way with
        // ...
        $renderer['content'] = array('#markup' => $returner);
        return $renderer;
      

      You could abstract that out from all 3 code blocks and just put it at the bottom of the function.

    • In garmin_connector_permission() you don't seem to be using the $descriptions array at all, deleteable?

    That's as far as I've gotten, this is not a complete review. The module seems very ambitious and potentially useful, but right now there are a lot of unfinished parts and debug code.

    My suggestion is to limit the scope down to what's absolutely necessary (or what you actually have time to build), and delete everything else for now. You can always add it back in later :) Otherwise you'll never get out of "needs work" if there are unfinished bits hanging around.

    Let's work on getting this approved, and then you can add new features in the next version.

    ----
    Top Shelf Modules - Crafted, Curated, Contributed.

    candotri’s picture

    @kscheirer Thank you so much for clearly spending a lot of time twlling me what I need to do. I'll get on this and report back.

    I have a couple of questions:
    1. Regarding deleting dpms that are commented out: Is this an asthetic thing? Clearly there is no functional penalty for commenting out code. Given the complexity of some of the things I have to do it would be super irritating if, at a later date, Garmin changes something (very common) and I have to figure out how to debug the code.
    2. garmin_connector_update_7002 was for me. I have had people check code out of the git to help me debug and that's why that update is there. Is there any harm in leaving it there?
    3. removed stuff from .info
    4. removed stuff from .install
    5. Regarding varchar(40) for user, no I don't want to use uid. It's an experimental feature that I'm working on. I could delete it but I want to work on it moving forward.
    6. The Makefile and the testing stuff was me trying to learn to use the Drupal testing framework and to automate some drush commands for maintaining databases with hook_cron. I'll remove them but I'd like to eventually make it work.
    6. regarding hook_init: I can't persuade Libraries to load the javascript for flot. It is, apparently, a 'feature' in Drupal's flot. I tried really really hard. Really I did.
    7. Added flot to dependencies
    8. Removed ini calls. Silly question: What is bare php?
    9. hook_block_view, did what you suggested. It was, of course, a better way.
    10. Regarding $_garmin_connector_cf: There were so many things that I needed to keep track of. I could remove the global and call a method to return a key. Is this, in your view, cleaner or are you concerned about the global variable. I'm going to assume that the method call is just cleaner:

    $directory = garmin_connector_get_config('dir_tcx_cycling');
    

    11. Deleted descriptions array. You are quite right.

    I just committed the things I described and I'll go through the code looking for dpm()s. The issue I'm having at the moment is that I made *so* many changes to make things comply with pareview that I feel I need to test things thorough to make sure that things still work. For that I'll need the dpms. I'll work on that testing as quick as I can and then remove whatever I can.

    Thank you again for your review.

    candotri’s picture

    Did the following things:

    1. I automated the creation of a brand new drupal (7.3) on PHP 5.2 and 5.4 to test clean installs. All is well.
    2. Removed references to json_encode($object,JSON_PRETTY_PRINT) because that was not supported in PHP 5.2 (SURPRISE!)
    3. Cleaned up README
    4. Cleaned up references to $cf as described previously.
    5. Removed Makefile as described previously
    6. Fixed commented lines, cleaned up conditionals in .install
    7. Created branch in git
    8. Removed test
    9. Removed php.ini calls
    10. Added dependency on flot
    11. Deleted descriptions as described previously

    I also did a lot of general cleanup. There are still dpm()s while I debug performance given the large amount of rennovating I've been doing.

    candotri’s picture

    Changed hook_menu to add the path 'garmin-connector/' where I've added pages. Testing functionality and repairing where necessary.

    candotri’s picture

    I added a demo page to showcase what the components do. Everything is working correctly.

    kscheirer’s picture

    Status: Needs work » Needs review

    Are you ready for another review?

    candotri’s picture

    Yes, please.

    kscheirer’s picture

    Sorry, I didn't see that list of questions!

    Regarding deleting dpms that are commented out: Is this an asthetic thing?

    Yes, just aesthetic. If you feel strongly about it it's fine to leave them in.

    garmin_connector_update_7002

    It's ok to leave that in, just not usual for a new module.

    What is bare php?

    It's PHP code that's not contained in any function, hence "bare". When Drupal loads your file as part of it's normal process, any bare PHP is always executed - so it's on every page request, regardless of whether it's useful or not. Can be bad for performance, and just a general bad practice.

    $_garmin_connector_cf

    We try and avoid globals wherever possible. Generally you can get the same functionality with variable_get/set (for permanent storage) or drupal_static (for storage throughout a single request).

    kscheirer’s picture

    Status: Needs review » Needs work
    Master Branch
    It appears you are working in the "master" branch in git. You should really be working in a version specific branch. The most direct documentation on this is Moving from a master branch to a version branch. For additional resources please see the documentation about release naming conventions and creating a branch in git.
    • What is disabled.js? Doesn't jquery already have a get() function?
    • I think you can get rid of hook_init() now that you've got a dependency on flot?
    • garmin_connector_purge_workout() does not seem like it's working?
    • In garmin_connector_spill_locals() you should use file_directory_temp() to get the temp path.
    • All variables used in your module should be removed in hook_uninstall.
    • variable_get can accept default values. So instead of $days = variable_get('garmin_connector_reward_number_of_days') ? variable_get('garmin_connector_reward_number_of_days') : 7; use $days = variable_get('garmin_connector_reward_number_of_days', 7)
    • "// Make the pareview warning go away." - I appreciate trying to make the automated script happy, but sometimes it does give false positives. In this case I bet it was telling you the $key variable is not used in your function. Instead of creating a dummy use (if (is_array($key)) {}), change your foreach to foreach ($workouts as $workout) {. No $key variable needed :)
    • All user-facing text should be run through t(), like $message. Try and keep HTML tags out of the translation string if possible. So instead of <h2>Did you complete the workouts you hate?</h2> use '<h2>' . t('Did you complete the workouts you hate?') . '</h2>'

    This is another partial review.

    candotri, I think you have the same problem of having too much debug/test code to get this project approved. I think what's happening (as you mentioned earlier) is that you're still in the debugging process of your module, and it's not polished yet. It's understandable that you still want debug code, and it's fine in a sandbox as well, but for a Drupal module, users expect to download a working, finished module. That's not to say it has to be bug-free, but the basics have to be covered.

    I think the best solution is for you to create a local branch to work from (git checkout -b 7.x-1.x-debug or something). Don't push it to origin, just keep it local (if you do accidentally push it, no big deal). You can keep your debug code in there for checking stuff out, and the main 7.x-1.x branch to keep the finished code. Then keep the 7.x-1.x branch clean and tidy. You can use git merge to easily move changes from one branch to another. This is a good simple guide to git if you're not used to it: http://rogerdudler.github.io/git-guide/.

    Or you could make the debug stuff "official". What I mean by that is, create a hook_menu entry for it, put permissions around it, render the output like you would any other Drupal function, and move the code out of your .module file. Some modules provide test pages like this, like a page where you can test that your garmin connection is working, or that it's parsing a dummy data file correctly.

    From #13:

    limit the scope down to what's absolutely necessary (or what you actually have time to build), and delete everything else for now. You can always add it back in later :)

    Instead of deleting, you can keep that code in a different branch.

    Also, take a look at Tips for ensuring a smooth review - that covers a lot of common things we look for when reviewing a module.

    Hope that helps!

    ----
    Top Shelf Modules - Crafted, Curated, Contributed.

    candotri’s picture

    I hear what you are saying about the debugging. The thing is, I trust the code. But I don't particularly trust Garmin. That's the problem with interoperability without accountability - they can change anything at anytime.

    I've removed almost all of the debugging code that prints to the screen. I've left the debugging code that prints to files. I feel that this way anybody who wants to know what's going on will know and those that are not able to help won't be bothered by weird output.

    I use this code every day for things that matter to me so I feel that it's reliable and useful.

    I hope you agree that this would be useful to other people. I certainly don't see code like this out in the wild.

    Regarding specific issues:

    • I am working in a branch - 7.x-1.x
    • I removed disabled.js
    • Regarding drupal_init, I explained earlier in this thread (it was with a bunch of stuff and you must have missed it, I'm sorry about that):
    • I cannot get rid of drupal_init because I can't persuade Libraries to load the javascript for flot. It is, apparently, a 'feature' in Drupal's flot. I tried really really hard. Really I did.
    • garmin_connector_purge_workout was moved to garmin_connector.drush.inc just now. Thank you for the reminder. I will be improving the garmin_connector_list_workouts drush next.
    • Used file_directory_temp() in garmin_connector_spill_locals(). Good point.
    • Implemented hook_uninstall and deleted variables
    • Regarding variable_get: You are quite right. Fixed.
    • Regarding t() - I've converted almost all strings presented to the user with t().

    I'd like to note that debug code is still present in the code that calls garmin. I feel that this will be necessary moving forward.

    Thanks for the patience.

    candotri’s picture

    Here's another reason why I'm leaving a bit of debugging code in. From my last commit:
    4 files changed, 250 insertions(+), 480 deletions(-)

    As the review progresses, the code is getting leaner and meaner but I'm continually testing that it still works.

    candotri’s picture

    candotri’s picture

    Status: Needs work » Needs review
    candotri’s picture

    Issue summary: View changes

    added link to project page

    kscheirer’s picture

    Issue summary: View changes

    Candotri, this queue is for use to review finished, working modules to grant you the 'git vetted user' status. Unfortunately, it's not intended to help you learn coding best practices. Additional workload for reviewers results in longer wait times for everyone in the queue. I'm setting this issue to postponed, please feel free to reopen it when you think it's ready for review again.

    Take a look at Tips for ensuring a smooth review for a list of common issues if you haven't already.

    kscheirer’s picture

    Status: Needs review » Postponed
    candotri’s picture

    Status: Postponed » Needs review

    To the best of my knowledge I do not require further assistance in learning coding best practices.

    This is a finished, working module that meets standards described here:
    https://drupal.org/node/1187664

    This module is ready for review.

    If there are specific requirements that I am not meeting, please let me know and I will meet them immediately.

    heddn’s picture

    @candotri, What are you trying to do with flot that you can't use the flot module? I've used it fairly extensively and never had problems with its loading using libraries.

    klausi’s picture

    Status: Needs review » Needs work
    Issue tags: +PAreview: security

    There is still a master branch, make sure to set the correct default branch: http://drupal.org/node/1659588 . Then remove the master branch, see also step 6 and 7 in http://drupal.org/node/1127732
    Review of the 7.x-1.x branch:

    • DrupalPractice has found some issues with your code, but could be false positives.
      
      FILE: /home/klausi/pareview_temp/garmin_connector.module
      --------------------------------------------------------------------------------
      FOUND 0 ERROR(S) AND 4 WARNING(S) AFFECTING 4 LINE(S)
      --------------------------------------------------------------------------------
        795 | WARNING | Variable $message is undefined.
       1382 | WARNING | Unused variable $by_date.
       1670 | WARNING | Unused variable $type.
       2305 | WARNING | Variable $_garmin_connector_debug is undefined.
      --------------------------------------------------------------------------------
      

    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.

    I agree with kscheirer that a full project should be production-ready and not contain site-breaking debug code. If you must do that do it in a debugging git branch or add a conditional debug mode.

    manual review:

    1. garmin_connector_show_workout_set(): this is vulnerable to XSS exploits. You need to sanitize user provided text before printing, you are taking arbitrary stuff from $_GET and printing it directly to HTML, allowing for a reflected XSS attack. Make sure to read https://drupal.org/node/28984 again. And please don't remove the security tag, we keep that for statistics and to show examples of security problems.
    2. The project page should mention that this module should not be used on a production site right now, because it will throw fatal errors if the devel module is not present. Users should be aware that is not ready to be used yet at all.
    3. garmin_connector.info: why do you need the JS and CSS on every single page? Why can't you add it when your module produces output? Please add a comment.
    candotri’s picture

    @heddn I repaired the issue. Thanks for the comment.

    candotri’s picture

    @klausi Thank you for your time!

    1. There is no master branch at this time. It's possible that I deleted it after you wrote your comments.
    2. pareview is fulfilled except for errors related to my // vim: modeline at the end of each module. I constantly run pareview so any errors are either temporary or spurious
    3. thank you for the catch on garmin_connector_show_workout_set(). Fixed that and several other places where user input could be found. This includes workout sets. I carefully read that material and implemented as well as I could. Comments are welcome.
    4. "Users should be aware that is not ready to be used yet at all.". I'm aware that I'm new at this but a more constructive comment was "will throw fatal errors if the devel module is not present". I removed all dpm and replaced them, where necessary, with drupal_set_message calls. Does that mean that I don't need to inform the users that "[it] is not ready to be used yet at all"?
    5. 4. I removed garmin_connector.js from .info and placed drupal_add_js calls where necessary. I will do the same for the css.

    I'm not sure if you've seen the number and volume of commits that I'm putting into this project in order to comply with the comments. I think that they speak to the amount of work that I'm doing. I appreciate the fact that we are trying to build a solid code base and I appreciate your time.

    I will now go and try to get review bonus points.

    candotri’s picture

    Status: Needs work » Needs review
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue tags: +PAreview: review bonus
    candotri’s picture

    Status: Needs review » Needs work

    Broke something while repairing sorting. Will update when ready.

    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    Issue summary: View changes
    candotri’s picture

    This module is complete and ready for review.

    I test this module two ways:

    1. a scripted, clean install of the latest drupal7 followed by a scripted, clean install of garmin_connector.
    2. an existing site with git pull

    The automated site operates using php5.3 and the existing site uses php5.4.

    I suggest you download the sample data something like this:


    sudo -u www-data drush -r $DRUPAL_ROOT garmin-connector-sample-data

    Obviously that this assumes LAMP and the apache user www-data. It's ok to not sudo but remember to change permissions when required.

    candotri’s picture

    Status: Needs work » Needs review
    candotri’s picture

    Issue summary: View changes

    Repaired broken link. Updated with git checkout command.

    candotri’s picture

    Issue summary: View changes

    Added project review.

    klausi’s picture

    Status: Needs review » Needs work
    Issue tags: -PAreview: review bonus

    manual review:

    1. garmin_connector_permission(): do not line-break translatable strings.
    2. garmin_connector_activity_manager(): that hook_menu() callabck is completely unprotected and can be accessed by anonymous users, right? Why is there no permission guarding that page and the others? I fear that this could be vulerable to DoS attacks if garmin_connector_ajax_run_cron_form is an expensive operation.
    3. garmin_connector_activity_manager(): don't call drupal_render() here, just return a complete return array, drupal will render it later for you. Same in garmin_connector_admin() and garmin_connector_get_contextual_links(), just return a render array.
    4. Your module file has nearly 4000 lines of code which is loaded on every single page request on a Drupal site, and of course this is hard to maintain. The module file should only include hook implementations for such huge modules and the rest should be loaded from include files when needed.
    5. "'#options' => module_invoke_all('strength_workout_types'),": all hooks defines by your module need to be prefixed with your module's name + docs in garmin_connector.api.php.
    6. garmin_connector_admin_validate(): do not use check_plain() here. "When handling data, the golden rule is to store exactly what the user typed. When a user edits a post they created earlier, the form should contain the same things as it did when they first submitted it. This means that conversions are performed when content is output, not when saved to the database." from https://drupal.org/node/28984
    7. You are not using any theme functions or templates as far as I can see? So nobody can override the markup on a site?
    8. garmin_connector_process_purge(): "// Pareview is satisfied": what does that mean? Why do you need an empty if-statement here? What is Pareview? pareview.sh? Why would that want an empty if statement?
    9. garmin_connector_purge_single(): why do you check permissions here? If the user does not have access to that functionality then the ajax form to trigger that should have never been displayed in the first place? /garmin-connector/purge.html should not be accessible by non-admin users, correct? Then there should be a permission in hook_menu()?

    Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.

    candotri’s picture

    Thank you for the comments @klausi,

    • All line breaks on translatable strings removed
    • No permissions added to garmin_connector_activity_manager. This is because the forms are only added when viewing the page as an authorized user. There is no rise to a DOS attack due to the amount of data rendered on that page because for an unauthorized viewer no forms are loaded.
    • garmin_connector_activity_manager now returns render array. My mistake.
    • it appears that garmin_connector_admin() returns a render array already via system_settings_form($form).
    • added permission 'view activity data' to allow administrators to prevent viewing of activity graphs when required
    • split .module into several .inc files
    • changed the name of the hooks and corrected missing documentation in api.inc for one hook.
    • repaired garmin_connector_admin_validate() - removed check_plain
    • regarding theme functions:
    • at the time of @klausi's comment there were two theme functions defined. I added another.
    • changed comments regarding pareview. I use global variables in drush.inc that are not used in drush.inc but in the called function. these generate an 'unused' error. is is best to just live with that as a false positive or to use an 'islet' to suppress the error?
    • regarding purge_single: good point. I think I was being excessively cautious.

    Notes about my feelings on permissions:

    I'm unsatisfied with the generic "Permission Denied" errors when one uses access callbacks in hook_menu. I prefer to check access in the page callback and when permission is denied, provide the user with the *reason* permission is denied. Is there a best practice somewhere that recommends against this? The only risk that I can see is in the case of a DOS attack on that page there is a small amount of overhead in activating the callback.

    candotri’s picture

    Issue summary: View changes

    Added review.

    candotri’s picture

    Issue summary: View changes

    Added a review.

    candotri’s picture

    Issue summary: View changes

    Added a review.

    candotri’s picture

    Issue summary: View changes

    Added a review

    candotri’s picture

    Status: Needs work » Needs review
    Issue tags: +PAreview: review bonus
    klausi’s picture

    Status: Needs review » Needs work

    The usual Drupal philosophy is to not display any links to pages where the user does not have access to in the first place. Also that pages should not leak any information what is behind them, so anyone that does not have access should just get a generic 403.

    manual review:

    1. garmin_connector_permission(): permissions usually don't use dashes, just separate the words with spaces.
    2. garmin_connector_cron(): if corn runs often, then this will run often. Are you sure that you need to do this stuff every 5 minutes?
    3. garmin_connector_post_activity_upload(): why do you need cURL and cannot use drupal_http_request()? Please add a comment.
    4. garmin_connector_post_activity_upload(): that function is not used anywhere, or am I overlooking something? And the doc block says this implements a hook, so it should be garmin_connector_garmin_connector_post_activity_upload(), right?
    5. garmin_connector_post_activity_upload(): this looks vulnerable to XSS exploits. $result2 comes from an untrusted third party source, so it has to be sanitized before printing into HTML. Make sure to read https://drupal.org/node/28984 again.
    6. garmin_connector_purge_activities_form: that page callback is not defined in the module file and the hook_menu() entry does not specify a file either, so does that even work?
    7. garmin_connector_admin(): don't call drupal_render() here, just add another item to your render array. Same in garmin_connector_activity_manager(), just return nested render arrays.
    8. '#markup' => "<h3>Workout set with name $set</h3>",: all user facing text should run through t() for translation.
    9. garmin_connector_get_compare_results(): Are you sure that $this_activity->activityName is sanitized already? Is that user provided text?
    10. There are still lots of functions that return un-themable raw markup like garmin_connector_activity_manager().

    So the potential XSS issue is a blocker right now, otherwise this looks quite ok.

    candotri’s picture

    Status: Needs work » Needs review
    • Removed dashes from permissions names
    • Regarding hook_cron: you are quite right. Renamed garmin_connector_cron to garmin_connector_cron and created a new blank garmin_connector_cron with detailed information on why it's a bad idea. Refactored drush methods to call the new method. Removed all references to 'cron' throughout the code.
    • Added comment regarding drupal_http_request in garmin_connector_post_activity_upload. The reason is that I was able to get it to work with cURL and not with drupal_http_request. I can try again, but it's certainly a @todo.
    • Improved error handling when no Garmin Connect username is set
    • Improved error handling when Garmin Connect username/password results in a 403 with Garmin Connect.
    • Regarding post_activity_upload, the hook is defined in garmin_connector.api.php and implemented in garmin_connector.module. I now filter with check_plain. The result that is supposed to come back from Garmin Connect is json - is there a drupal function to sanitize json?
    • Regarding garmin_connector_purge_activities_form: I made an error and failed to include the 'file' parameter. This is fixed.
    • Regarding garmin_connector_admin() - I'm returning a form. Isn't that ok?
    • Regarding garmin_connector_activity_manager() - I'm returning a render array at this time.
    • $this_activity->activityName() comes from Garmin Connect so it should be ok but I added check_plain to make sure.
    • Regarding lots of functions that return unthemeable raw markup - there are indeed a few. I would like to make this a @todo, given that the majority of important functions returning rows of output are themeable. I've made the most likely targets themeable and I will improve the rest.
    klausi’s picture

    Status: Needs review » Needs work

    manual review:

    1. garmin_connector_admin(): instead of using drupal_add_css() you should use #attached in the render array. See https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.h...
    2. garmin_connector_admin(): it is ok to return a form render array, but you should not call drupal_render() on any nested elements in it. The whole array tree of elements will be rendered later for you and it is easier for other modules to alter the form when not rendered yet.
    3. no, there is no Drupal function to sanitize JSON that I'm aware of. I think it would not make sense to sanitize JSON, only if you print stuff from that third party supplied JSON then you should make use of the usual check_plain() and friends.
    4. garmin_connector_strength_done(): it does not make sense here to call check_plain(), since you are not printing anything to the user here? And $title is sanitized correctly in the hook implementation with the "@" placeholder, so that would be double escaping, which is bad.
    5. t("Workout set with name") . " $set</h3>": do not concatenate variables into translatable strings, use placeholders with t() instead.
    6. garmin_connector_get_compare_results(): why do you call check_plain() on the $selected array keys? I don't exactly see where they are printed to the user, but the sanitization should happen as late as possible (right before printing or adding to a render array). That way the internal data structures stay intact as long as possible and check_plain() only happens if needed.
    7. garmin_connector_compare_activities_form(): $ignore_regex is never printed to the user, why do you run check_plain() on it?
    8. "return "Id $id was not found in the garmin connector catalogue";": all user facing text must run through t() for translation, please check all your strings.
    9. garmin_connector_add_to_workout_set(): "When handling data, the golden rule is to store exactly what the user typed. When a user edits a post they created earlier, the form should contain the same things as it did when they first submitted it. This means that conversions are performed when content is output, not when saved to the database" from https://drupal.org/node/28984 . Don't run check_plain() on variables that are inserted into the database.

    The use of check_plain() is a blocker right now, you need to know when to use it and when not. Otherwise this would get a green light from me, so don't give up just yet, I think you are almost there!

    candotri’s picture

    Status: Needs work » Needs review

    Thank you for your time, @klausi !!

    • replaced drupal_add_css in garmin_connector_admin with #attached. I will look for other opportunities to do the same.
    • removed drupal_render in garmin_connector_admin(). oops.
    • The purpose of garmin_connector_strength_done is to send a message to Garmin Connect that you want to change the GarminConnectAcvitivy->activityName to that specified in $form_state['values']['type']. It does that by passing $title to garmin_connector_post_Activity_upload(). It's theoretically possible that that $form_state['values']['type'] was hijacked and replaced with something harmful, that's why I check_plain when getting the value to put in $title. Theoretically, it would be the responsibility of the software running at Garmin to ensure the sanity and clenliness of any proposed new activityName but I did it here because it seemed reasonable. I would like to leave it here because although $title is not being displayed to the user it is being sent to Garmin Connect. I moved check_plain into hook_garmin_connector_post_activity_upload and updated api.php to inform the coder to not sanitize before passing it here. I also changed @title to !title in the message.
    • workout_set_name $set requiring t() - absolutely you are correct. I seem to have missed that one. I've extensively used translatable strings throughout this project but sometimes I miss them. Thanks!
    • garmin_connector_compare_activities_form had an illegitimate check_plain. I think in previous versions I *was* displaying the regex.
    • Fixed everything else that was mentioned.

    I did additional review looking for untranslated strings and as far as I can tell the check_plain usage is legitimate.

    I sincerely appreciate your time. I will continue to review projects to help you and the community.

    candotri’s picture

    candotri’s picture

    klausi’s picture

    Assigned: Unassigned » kscheirer
    Status: Needs review » Reviewed & tested by the community

    manual review:

    1. "Small improvements" aas git commit message all the time is not very helpful, see https://drupal.org/node/52287
    2. "<p>" . t("Purging") . $location . ":" . "$status</p>";: do not concatenate variables into translatable strings, use placeholders with t() instead.
    3. garmin_connector_show_workout_set(): The check_plain() for $set is not needed, because the "@" placeholder is used in the t() message, and I cannot see where else it would be printed?

    Bu otherwise I think this should be now sufficient, so RTBC from me.

    Assigning to kscheirer as he might have time to take a final look at this.

    candotri’s picture

    Thank you for your time @klausi . I worked hard to help by reviewing other projects.

    • vowed to improve commit messages
    • repaired several strings where it was possible to avoid concatenating translatable strings. I had to do that when wanting to insert links into a themed string in order to have the target translatable.
    • made plot containers themeable
    kscheirer’s picture

    Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

    What is the latex directory for? Is it something that the user needs to install? I don't see anything about it in the README or hook_requirements().

    candotri’s picture

    Sorry about the latex directory. Removed the latex directory and other unused files including debug-tcx.tcx, tcx.tcx, logtail.js, and logtail.html

    klausi’s picture

    Status: Postponed (maintainer needs more info) » Reviewed & tested by the community

    Cool, back to RTBC.

    klausi’s picture

    Status: Reviewed & tested by the community » Fixed

    no other objections for more than a week, so ...

    Thanks for your contribution, candotri!

    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.

    avpaderno’s picture