CVS edit link for mcstrother

I made a shift scheduler module for Drupal that I am currently hosting on google code at: http://code.google.com/p/drupal-shift-scheduler/ . A handbook and introductory videos to the module can be found in the GettingStarted page in the google code wiki.

I was prompted to make the module for the use of my EMS service (http://est.wustl.edu/shift_scheduler) after finding no modules that implemented the same functionality. I am still not aware of any module or combination of modules--I briefly considered trying to use a combination of Event and Sign Up-- that could replace the shift scheduler in any effective way.

There has been some use and adoption of the module as evidenced by the number of times it has been downloaded. It is currently on its 2.0 release, and I have not had a single new issue reported since it was released from beta.

I would like CVS access because I have received several requests to move the project to drupal.org: 1, 2. I am also looking for a new module maintainer, as I am too busy for feature improvements. I am, however, committed to updating the module for drupal 7 and fixing any critical bugs.

I realize that the Google code site states that the module is released under the BSD license and that there is a file in the hg repository that states the same. Obviously the license file will be removed before the code is committed to CVS, and I am happy to have the code re-licensed under the GPLv2, assuming I had the right to release it under the BSD license to begin with.

Comments

mcstrother’s picture

Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new14.48 KB

Attaching proposed contribution. The attached file is the same as the 6.x.2.0 download on the google code site but without the LICENSE.txt file or any of the mercurial-related files.

avpaderno’s picture

Status: Needs review » Needs work
Issue tags: +Module review

Hello, and thank you for applying for a CVS account. I am adding the review tags, and some volunteers will review the code, pointing out what it needs to be changed.

As per requirements, the motivation message should be expanded to contain more features of the proposed project. For themes, it should include also a screenshot of the theme, and (when possible) a link to a working demo site; for modules, it should include also a comparison with the existing solutions.

Scyther’s picture

There is many "Control Structures" faults, so read http://drupal.org/coding-standards and correct those.

mcstrother’s picture

StatusFileSize
new13.9 KB

Ok. A version with the coding style problems resolved--according to Coder and Grammar Parser--is attached.

avpaderno’s picture

See comment #2; the motivation message should include a description of the module features, and a comparison with the existing projects.

mcstrother’s picture

Sorry, I was in the middle of responding to your comment and was called away.

I can't seem to find a link to edit the original motivation statement, so for now I'll add the requested details here.

Module features:
* Maintains a schedule of employees/volunteers (see http://est.wustl.edu/shift_scheduler for an example on a working site)
* Easy access to historical shift information (see http://est.wustl.edu/shift_scheduler/old_shifts for a working example)
* Shifts on the schedule appear as links to users with appropriate permissions allowing users to edit a shift (change who is signed up for a shift, split shifts between two people, close a shift so no one needs to take it etc), "relinquish" a shift (set a shift that the user previously was signed up for to be "open"), or "claim" an open shift. Shift editing is optimized for certain repetitive tasks (e.g. copying physical sign-up sheets into the module)
* The "slot" concept allows users/administrators with the appropriate permissions to define different positions that should be filled at any given time. (E.g. "driver", "EMT-B", and "Paramedic" for an ambulance corps or "manager", "register 1", "register 2" for a small store would all be different "slots".) Which users can be assigned to which slots can be defined with standard drupal "roles".
* Users/administrators also define "default shifts" for each slot, which is in line with the way many organizations make their schedules and helps with speed of input and clarity and consistency of presentation. (See more detailed discussion in the manual.)

Comparison with existing solutions:
To my knowledge, there is no module that makes any real attempt to tackle the issue of managing regular schedules for employees or volunteers. One thread that consistently comes up on related searches contains comments from a lot of people seeking similar functionality since 2007, with no resolution. There is a weak suggestion of using a combination of Event, Signup, Date, CCK, Views, and Calendar, but that hardly seems as efficient as a dedicated module and my research on the Event module (which admittedly was done about a year ago) suggested that it is not intended for managing 10-50 events a day with one participant each. The users on the same thread (and the coop group, I believe) have made noises about developing similar modules, but it looks like nothing has materialized from any of those efforts. Recent posts on the coop group indicate that people are still looking for a solution. I was also contacted by a user who did some fairly extensive research into drupal and non-drupal options and didn't come up with anything satisfying from drupal either.

Hope that clears things up.

avpaderno’s picture

Status: Needs work » Needs review

Thank you for your reply.

Scyther’s picture

Status: Needs review » Needs work

1.

  update_sql('INSERT INTO {shift_scheduler_slot_roles} (slot_id, rid) VALUES ('. $row->slot_id .', 2)');

Not secure!! Read this http://drupal.org/writing-secure-code and change the code to avoid SQL injection attacks.

2.

      'primary key' => array('shift_id'), //TODO: figure out a way to index using the start time for fast lookups.  This table is going to get big, and we can't do linear time searches all over the place
Please, when applying for a CVS account supply code that you believe is complete.

So I don't think there should be todo:s.

3. shift_scheduler.module is missing CVS header "// $Id$".

4.

function _write_date_row(&$schedule_rows, $slot_cells, $timestamp, $slot_ids) {
function _schedule_format_name($uid) {
function _can_claim($user_uid, $shift_id) {
function _schedule_format_shift_text($uid, $shift_id, $start_time_t, $end_time_t) {
Functions and variables should be named using lowercase, and words should be separated with an underscore. Functions should in addition have the grouping/module name as a prefix, to avoid name collisions between modules.

5.

  $options_query = "SELECT {users}.uid, {users}.name, {users_roles}.rid FROM {users} INNER JOIN {users_roles} ON {users_roles}.uid = {users}.uid INNER JOIN {shift_scheduler_slot_roles} ON {users_roles}.rid = {shift_scheduler_slot_roles}.rid WHERE {shift_scheduler_slot_roles}.slot_id = %d ORDER BY {users}.name";

This is not wrong. But if you want to shorten it you can do like this instead

  $options_query = "SELECT u.uid, u.name, ur.rid FROM {users} AS u INNER JOIN {users_roles} AS ur ON ur.uid = u.uid INNER JOIN {shift_scheduler_slot_roles} AS sssr ON ur.rid = sssr.rid WHERE sssr.slot_id = %d ORDER BY u.name";

- - - - -

Havn't checked all the code, so there could be more similar errors in more places so please look over all your code and correct them.

mcstrother’s picture

Status: Needs work » Needs review
StatusFileSize
new13.88 KB

Thanks a lot for reviewing my code. A new version of the module is attached with the issues you raised addressed with the one exception mentioned in my comment on #1 below.

1. This API page says that update_sql doesn't support %-substitution, and I'm not using something like check_plain because I don't see how it would be possible for someone who doesn't already have access to the database to change the value of $row-->slot_id to be something malicious.

2. Good point. I removed the TODO from the code and opened a proper issue on the google code site. There aren't any other TODOs, although you can see there are plenty of open issues on google code. The module is "complete", but as with all software, there is (documented) room for improvement.

3. Ack. Sorry. Thanks for the catch.

4. Sorry again. The offending functions have been properly prefixed.

5. Thanks for the tip. I used it to shorten all of the longer statements in the .module file.

For all of the above comments, I checked the rest of the code to ensure that similar errors were not made elsewhere (and corrected them if they were).

Thanks again.

rbrownell’s picture

+1 Subscribe (Watching this in anticipation of the startup of the Drupal Shift Scheduler module.)

rbrownell’s picture

So what is happening with this? Is the application process almost finished?

avpaderno’s picture

Status: Needs review » Needs work
  1.       $form[$i -1] = array(
            '#type' => 'select',
            '#title' => t('Role ' . $i),
            '#options' => $role_array,
            '#default_value' => $row->rid,
          );
    

    The first argument of t() is a literal string, not a dynamic value obtained from a function, a PHP variable, or concatenating two strings (even if they are two literal strings). If the first argument is not a literal string, then the script that extracts the string to translate will not add the string to the translation template, and the string will not be translated. Use t()-placeholders instead of concatenating strings.

  2. Menu descriptions and titles (as well as schema descriptions) should not be passed to t().
  3. The module doesn't implement hook_uninstall() to remove the Drupal variables it defines. Don't delete them using a SQL query that match any Drupal variable with a name starting with the module name.
  4.   $row_data[] = array(
        'data' => '<b><p>' . date('l', $timestamp) . '</p><p>' . date('n/j/Y', $timestamp) . '</p></b>',
        'valign' => 'center',
      );
    
      if ($uid == 0 || $uid == NULL) {
        //if it's still an open shift, make it red and bold
        $shift_text = '<b><font  color="Red">' . $shift_text . '</font></b>';
      }
    

    <b> should be replaced by <strong>, and <font> should be replaced by a CSS style.

  5. Dependencies from Drupal core modules that are not optional should not be declared. The module should report its dependencies from modules that need to be enabled before the module is enabled (it is not possible to disable user.module).
  6. The project is not hosted on drupal.org; the update functions should be removed.
  7. I am not sure why the database should have a field for each weekday when it would be enough to have a single field.
  8.     $form[$i -1] = array(
          '#type' => 'select',
          '#title' => t('New Eligible Role'),
          '#description' => t('To add a new eligible role, select one from this menu.'),
          '#options' => $role_array,
        );
    

    Form field titles should be in sentence case, not title case.

  9.     db_query("INSERT INTO {shift_scheduler_slots} (display_name, status) VALUES ('%s', 0)", $form_state['values']['name']);
        $slot_info = db_fetch_object(db_query("SELECT slot_id FROM {shift_scheduler_slots} WHERE display_name ='%s'", $form_state['values']['name']));
    

    Why isn't the code using drupal_write_record()?

  10.   $form['slot_id'] = array(
        // use 'value' rather than 'hidden'
        '#type' => 'value',
        '#value' => $slot_id,
      );
    

    Comments should be written as sentences, with a final period.

  11.     drupal_set_message(t('New default shift added'));
    

    Shown messages should have a final period.

  12. function shift_scheduler_configure_submit($form, &$form_state) {
      variable_set('shift_scheduler_claim_open_shifts', (int) $form_state['values']['claim_open_shifts']);
      variable_set('shift_scheduler_relinquish_shifts', (int) $form_state['values']['relinquish_shifts']);
      variable_set('shift_scheduler_link_to_profile', (int) $form_state['values']['link_to_profile']);
    }
    

    That code would be not necessary, if the form would use system_settings_form().

mcstrother’s picture

Ok. Thanks a lot for the review. The next time I will be able to work on it is December 19th, and I should be able to resolve all of the issues then.

I'll do my best with #4, although I haven't done any work with CSS and was deliberately avoiding it, so I hope it isn't a deal-breaker if that doesn't get resolved.

Also, is there any harm in leaving the leaving the update functions? Though it isn't currently hosted on drupal.org, there are people running the module on production websites, so I'd prefer not to delete the update functions if it isn't necessary. Also, if I end up making changes to the database as you suggest, I'm going to need to give people a way to update from the version they're currently running to the version that is eventually hosted on drupal.org.

mcstrother’s picture

StatusFileSize
new13.98 KB

Thanks again for the review. Your feedback was very helpful.

Attached is an updated version of the module will all of the issues addressed except for:

#4 - I'm working on it. (See my last comment.)
#6 - See my last comment. I'd like to leave the update functions in if possible
#7 - I agree that there is probably a better way to do this, but changing it would be a lot of work and could very easily introduce new bugs, which I'd like to avoid. The module is very stable now and is being used by a good number of people, so I'd like to be able to move it to d.o without starting a whole new development/release cycle.
#10 - Working on it, but I'd rather not spend hours adding periods and capital letters to every single comment unless it is absolutely necessary.

Is there a way for someone to give me an idea of how much more work is necessary for the module to be accepted? (For starters, which if any of the 4 issues above must absolutely be resolved for the module to be accepted.) As I said, one of the reasons I'm applying to move the module to d.o is that I'm not able to commit the time to making the module perfect.

avpaderno’s picture

Status: Needs work » Needs review
lorinpda’s picture

Status: Needs review » Needs work

Hi,
This is not a complete review. I installed your module on a fresh Drupal 6.20 installation. A few issues:

  • Coder (Code Review) reports formatting issues.
  • Please see the following http://drupal.org/node/539608 . In particular:

    Code like db_query('SELECT * FROM {table} t WHERE t.name = ' . $_GET['user'])
    is an open gate to security issues, as the content of $_GET['user'] could be ' OR 1, and would cause the query to show all the rows contained in the table.

    Please change the following statements located in shift_scheduler.module, method shift_scheduler_schedule() :

    if ($_GET['claim'] && $_GET['uid'] == $user->uid && $_GET['shift_id']
           && variable_get('shift_scheduler_claim_open_shifts', FALSE)
           && _shift_scheduler_can_claim($user->uid, $_GET['shift_id'])) {
        db_query('UPDATE {shift_scheduler_shifts} SET uid=%d WHERE shift_id=%d', $user->uid, (int) $_GET['shift_id']);
      }
      // Handle relinquishing shifts.
      elseif ($_GET['relinquish'] && $_GET['shift_id']
               && variable_get('shift_scheduler_relinquish_shifts', FALSE)) {
        $shift_info = db_fetch_object(db_query('SELECT uid FROM {shift_scheduler_shifts} WHERE shift_id = %d', $_GET['shift_id']));
        // Ensure that user is trying to relinquish his own shift.
        if ($shift_info->uid == $user->uid) {
          //Set to open shift.
          db_query('UPDATE {shift_scheduler_shifts} SET uid=%d WHERE shift_id=%d', NULL, $_GET['shift_id']);
        }
      }
    
  • Please consider replacing the hard-coded database table values located in file listing shift_scheduler.module, method _shift_scheduler_schedule_format_name() :
    $last_name_row  = db_fetch_object(db_query("SELECT value FROM {profile_values} WHERE fid=2 AND uid=%d", $uid));
    $first_name_row = db_fetch_object(db_query("SELECT value FROM {profile_values} WHERE fid=1 AND uid=%d", $uid));
    

    What happens if first and last name are not mapped to fid 1 and 2 ?

Hope that helps.

mcstrother’s picture

StatusFileSize
new14.4 KB

Hi lorinpda. Thank you very much for the review.

The formatting issues have been resolved.

Good catch on the use of the fid. I thought that those profile fields were present in drupal with those fids by default-- and therefore were unlikely to change-- but you're right.

As for the use of values from $_GET in the database query, I understand that one needs to be careful with that, but I've taken a hard look at the code, and I don't see any actual security holes. The database access functions are there protect against SQL injections, no? And I've tried to write the rest of the code that anyone could put whatever they want in the URL and the module will not let you do anything you aren't supposed to be able to do (e.g. "relinquish" someone else's shift).

mcstrother’s picture

Status: Needs work » Needs review
evelien’s picture

Component: Miscellaneous » miscellaneous

+1 Subscribe

lorinpda’s picture

Hi,
I reviewed the version posted in comment #17 on Drupal 6.20 installation.

First, my sincere apology. My comment #16 , referring to use of $_GET vars and SQL was incorrect. Please disregard, you aren't concatenating, my mistake,

A couple other issues:

  • Please set Coder's Selection form to "minor" and "Internationalization". Coder still reports some formatting issues and issues with usage of t().
  • You do not have README.txt or a INSTALL.txt file in your package. I suppose you could notify folks who install your module that they have the option of configuring the profile module with the following field names, etc (in either the README.txt or INSTALL.txt files). In other words, you are still assuming that are profile fields defines with the name of profile_last_name and profile_first_name. As an alternative. please consider adding a configuration setting for an administrator that allows mapping of the profile fields.
  • From reading other reviews, implementing hook_update_6xxx() in your install file is not appropriate for a package that is not currently available on Drupal.org. Obviously, once your project is hosted on Drupal,org, updates are fine.

Nice job! Really close.

Hope that helps.
Lorin

mcstrother’s picture

StatusFileSize
new14.72 KB

Hi Lorin,

Thank you so much for the your review, encouragement, and patience with me through this process.

An updated version of the module is attached.

  • No need to apologize. I'm glad to hear there isn't an (obvious) security problem.
  • Ah, I'm sorry. I didn't see those settings in coder before now. Thank you for pointing them out. Coder reports no errors for me now.
  • I've added a README.txt file will installation notes. I've gone with adding notes to the README file about configuring the Profile module for now. Such configuration only enables a very minor aesthetic improvement of the module, so it isn't a big deal if no one bothers to do it. I agree that making this configurable is a much better solution, and it should be easy enough to implement, but I'm still trying to avoid adding new features in these updates as much as possible.
  • Ok. I removed the hook_update function and added some documentation in the README file to warn my current users. I will add other documentation as appropriate.
  • Issue #4 from comment #12 has also been resolved. I'm not sure about the style of the solution, but it seems work.

    Thanks!

  • arianek’s picture

    Status: Needs review » Postponed

    Hi. Please read all the following and the links provided as this is very important information about your CVS Application:

    Drupal.org has moved from CVS to Git! This is a very significant change for the Drupal community and for your application. Please read the following documentation on how this affects and benefits you and the application process:
    Migrating from CVS Applications to (Git) Full Project Applications

    • The status of this application will be put to "postponed" and by following the instructions in the above link, you will be able to reopen it.
    • Or if your application has been "needs work" for more than 5 weeks, your application will be marked as "closed (won't fix)". You can still reopen it, by reading the instructions above.
    mcstrother’s picture

    Project: Drupal.org CVS applications » Drupal.org security advisory coverage applications
    Status: Postponed » Needs review

    Changing from CVS application to "full project" application.
    Link to sandbox project page: http://drupal.org/sandbox/mcstrother/1075572

    berdir’s picture

    Just skimming over the code, writing down what I'm noticing. These are mostly just suggestions, you don't need to implement everything...

    - ; $Id$
    You don't need this line anymore, git doesn't use it.

    - function shift_scheduler_schema() {
    You should add a "Implementation of hook_schema()." docblock to all hook implementations. Note that it has changed to "Implements hook_schema()." in D7, which I prefer and usually also use in my D6 modules.

    - $output = '< p >' . t("Displays the shift schedule managed by shift_scheduler") . '< /p >'; // Not too sure about this line. Does it need to be enclosed in a paragraph?
    That is a good question, I don't know. I do know that the comment should be on a separate line however ;)

    - That huge conditional thing in function _shift_scheduler_can_claim() is hard to read. My suggestion would be to split them into separate lines, store in a temporary variable and then just check these. Or write some api/helper functions. Also, you shouldn't select multiple columns nor use db_fetch_object() (use db_result() instead) when you just want to know if there is such a row or now. If these queries can return many rows, you also might want to use db_query_range() and only select a single row at most.

    - " date_default_timezone_set('CST');"
    That shouldn't be there I think. Not everyone lives in that timezone :)

    - There is a huge amount of code in your .module file. Maybe you could move admin/pages callbacks to their own file to make it easier to read and save some memory.

    - There are many many different queries all over the place. Wondering if that could be simplified a bit by creating some helper/api functions to re-use some of these. Haven't checked if they are different though.

    - $volunteer_options_query = "SELECT uid, name FROM {users} WHERE uid > 1 ORDER BY name"; (in shift_scheduler_old_shifts_form)
    That looks like a problematic think if a site has many users. Also, excluding uid 1 looks like a site-specific thing to me.

    - function shift_scheduler_old_shifts_results()
    You are mixing php and HTML in that function, should be moved to a separate theme function. Or maybe theme_table() could be used?

    - function shift_scheduler_admin_slots() {
    if (!arg(4)) {
    Any reason why that is not a normal argument defined in hook_menu() ? Will make it easer to port to D7, because the number of path elements will likely be different.

    - $items['admin/settings/shift_scheduler/slot'] = array(
    This and a few others below admin/settings/shift_scheduler are all normal menu_items, is there a reason that they aren't local_tasks? I think that's more common when you have multiple settings pages.

    Overall, the code looks good, it's just a huge amount of that.

    berdir’s picture

    Status: Needs review » Needs work
    mcstrother’s picture

    Hi. Thanks a lot for the very prompt and thorough review. I'm very sorry I didn't see it until just now. Apparently I somehow stopped getting emails about updates to this thread.

    I really appreciate all the comments. I won't have the opportunity to work on them for another two weeks or so, but when I do, I imagine I'll be able to address most of them.

    sreynen’s picture

    Component: miscellaneous » new project application
    tim.plunkett’s picture

    Component: new project application » module
    Status: Needs work » Closed (won't fix)

    Closing, feel free to re-open if this was a mistake.

    avpaderno’s picture

    Issue summary: View changes
    Issue tags: -Module review