Sandbox Project Page: http://drupal.org/sandbox/jthorson/1073590
Project Summary
ULT stands for 'Ultimate League Tool', a suite of custom modules used to simplify the day-to-day management and operations of amateur sport leagues.
The tool (rather ambitiously) attempts to provide solutions for all aspects of a league; including player registration, team roster management, game creation, scheduling, field assignment, standings, online score submissions, and communications tools.
For a complete planned feature list, please view http://groups.drupal.org/node/115394. (Items marked ‘planned’ have not been included in the current codebase, and are candidates for future feature enhancements.)
History
ULT was first developed in the Spring of 2010 to organize and manage the various leagues put on by the 'Regina Ultimate Flying Disc Club' (also known as RUFDC). The module was put into production on the RUFDC website in April, 2010 and used to manage two four-tier leagues for both the Spring and Summer seasons ... consisting of over 700 players, almost 50 teams, and 431 games. The code posted here is the second generation rewrite of that original module.
Development of the initial ULT module suite was sponsored by RUFDC, on the condition that the finished product be made open-source (to ensure the organization was not left stranded if they lost access to the primary developer). Further inspiration came from the standalone 'LeagueRunner' project current being used by other Ultimate Frisbee leagues across Canada.
Module Listing
The following modules are currently included in the core 'ULT' distribution:
• ult_main:
o Core module
o Creates ult_league and ult_team content types
o Requires cck, views, text, optionwidgets, nodereference, and userreference modules
• ult_divisions:
o Adds support for 'multiple divisions/tiers' per league
o Creates ult_division content type
o Requires ult_main module
• ult_fields:
o Adds support for field/facility assignment and tracking
o Creates ult_fieldsite content type
o Requires ult_main, gmapfield, and location modules
• ult_logos:
o Adds support for league, division, and team logo images
o Requires ult_main, imagecache, and imagefield modules
• ult_matches:
o Adds support for tracking individual matches between teams
o Creates ult_game and ult_gameresult content types
o Requires ult_main and date_popup modules
• ult_profiles:
o Adds support for individual 'player profiles'
o Creates ult_profile content type
o Requires ult_main, content_profile, content_profile_registration, fieldgroup, and date modules
• ult_registration:
o Adds support for tracking status of team registrations
o Adds fields related to registration to the ult_division, ult_league, and ult_team content types
o Requires ult_main and date_popup modules
• ult_rosters:
o Adds support for tracking and management of team rosters
o Adds ult_roster content type
o Requires ult_main module
• ult_scheduling:
o Adds ‘scheduling’ capabilities (creating multiple games and assigning fields/timeslots in a single interface, instead of individual single game creation)
o Requires ult_main, ult_matches, ult_fields, and ult_timeslots modules
• ult_spirit:
o Adds support for ultimate-frisbee 'spirit score' tracking
o Supports 'score out of 10', or customized 'survey' spirit scores
o Requires ult_main and ult_matches modules
• ult_standings:
o Adds support for tracking and displaying ‘league standings’ tables
o Supports mid-season tier shuffles
o Requires ult_main and ult_matches modules
• ult-timeslots:
o Adds ability to create ‘timeslots’ on individual fields, outlining times when a given field is available for games.
o Tracks facility permits/booked times, etc.
o Requires the ult_main, ult_matches, and ult_fields modules.
• ult_waivers:
o Adds display and tracking of player waiver forms before a player is added to a team
o Requires ult_main and ult_roster modules
Additional Module Support
ULT will also utilize functionality from the 'Contact' and 'RealName' modules, if installed.
Existing Modules with Similar Functionality
While there are a few other modules which promise ‘league management’ functionality, any of the options I found before creating ULT required the integration of third party software. I wanted to create a ‘100% Drupal’ solution; where bug fixes and future feature requests could be handled entirely within the Drupal ecosystem, and not depend on external third-party developers and environments.
Existing Module List and Analysis:
LMO – League Manager Online:
Maintenance Status: Unknown
- Third party league management software integration module.
- Last commit over 2 years ago.
- Download link (on the module page) for the LMO software being integrated leads to a ‘server not found’ page – and google results for “League Manager Online” lead to the Drupal pages.
Sports Club Management:
Maintenance Status: Unknown
- An excellent initial framework for creating the sport-related content types and views
- Didn’t go anywhere after the initial commits (last commit November, 2009).
- Contains objects and structure, but doesn’t contain associated logic for the management of a league (ie. No ‘features’ … things like the ‘league standings’ table values need to be manually entered & edited.)
- No documentation.
- Issue queue shows a history of user troubles, namespace conflicts, and
LeagueSite:
Maintenance Status: Active
- Last commit: February, 2011
- Development of Leaguesite started at the same time as ULT – unfortunately, we were unaware of each other’s initiatives.
- The base ‘League’ functionality of LeagueSite has some overlap with ULT, in that both modules allow the creation of a season/league/team structure and creation of games/results between teams. However, the ‘additional’ feature sets differ quite significantly.
Why ULT instead of extending LeagueSite?
I am aware of the desire to curb the proliferation of duplicate modules within the Drupal ecosystem, and fully understand the preference to extend existing modules instead of developing new modules with duplicate functionality.
In this case, I was not aware of the ongoing LeagueSite development until after the completion of my initial ULT module build. In any case, my use case required a solution where the players in a given league were also the Drupal site users; an architecture currently not supported by LeagueSite … and incidently, a common feature request in the LeagueSite issue queue.
ULT is designed to support both the players and administrators of a given league; supporting features such as individual player registration, waiver forms, the ability to apply to or be invited to team rosters, player-submitted game results, and integration with other user-based Drupal modules (such as Contact, Content Profile, and Realname).
Leaguesite, on the other hand, is focused more on a ‘single administrator’ use case, where the site administrator sets up and maintains the League site and structure, manually establishing the teams, players, rosters, and games tracked via the site; then using the site to publish game results. In this case, each player is simply another node; and there is no guarantee (or need) that they actually have an account on the site … which works well for certain use cases, but does not lend itself to certain others.
ULT also provides support for field and facility tracking, with the ability to create individual ‘timeslots’ associated with a given field site or facility. These ‘timeslots’ represent times when the field is available for scheduled games, and can be used both in the initial creation of league schedules, as well as in the rescheduling of rainouts and other postponed games.
Examples of LeagueSite features not present in ULT include the support for detailed match scoring breakdowns as well as tournaments (via integration with the Bracket module). While these would be valuable features within the ULT module, I have consciously avoided adding new ULT features which were already present or under development within the LeagueSite module ... with the goal of minimizing duplication between the modules, and hopefully setting up for the consolidation of the complementary feature sets into a single unified module at some point in the future.
As a result, while the current ULT and LeagueSite modules do share some commonalities, they also support significantly different feature sets and use cases. It is my hope that, in offering ULT as a ‘full project’ module, I can provide an all-in-one solution for the management of amateur sports leagues; and provide a solution for existing use cases not currently met by the D6 version of the LeagueSite module.
Future Plans
Moving forward, however, I do not envision the long-term maintenance of both ULT and the LeagueSite module, and would like to pursue the development of a merged module supporting both feature sets in the future (preferably starting with a D7 release). I know that Alun (LeagueSite maintainer) has been too busy over the last few months to devote much attention to LeagueSite development (and has no plans for a D7 port this year), but I did contact him to let him know about the ULT module and indicate my desire to discuss the possible merger of our codebases at some point in the future. If he is open to the concept, my intent would be to start working on a merged D7 module within the next couple of months, to serve as a single successor to both the ULT and LeagueSite modules moving forward.
In the meantime, I feel that the current ULT feature set is powerful enough (and significantly different than that offered by the LeagueSite module) to justify the existence of both modules in their current D6 forms. I urge any application reviewers who may be concerned about module duplication to consider a hands-on comparison of the two modules, so that they may experience this for themselves; and arrive at the same conclusion. :)
Comments
Comment #1
jthorson commentedOoops ... setting 'needs review' might help. :)
Comment #2
sreynen commentedHi jthorson,
I was just reading about your experience so far at http://groups.drupal.org/node/142464#comment-491239 and thought I might help speed up your review process before it gets started with a simple suggestion: submit only ult_main for review. Asking people to review your entire set of over a dozen modules makes this likely to take a very long time. Just from reading the description, ult_main sounds like it should be functional as a stand-alone module, which is all we need for a review. To focus the review on ult_main, I'd suggest creating a new sandbox with only that module in it. That sandbox needn't be used after your review is complete; it just makes it easier to complete the review. If you'd like a review of your larger set of modules for reasons behind getting full project access, that's great, it's just going to take longer.
Comment #3
jthorson commentedThanks for the input, sreynen. I had asked something along these very lines on IRC, and it was suggested that I should submit the whole package ... perhaps I should have looked for a second opinion. ;)
In this case, ult_main may serve as enough to get a sense of my code style ... but I'm afraid that, on it's own, it would not pass the 'module duplication' test. Ult_main provides the basic 'league->team->game' framework, which can also be accomplished with LeagueSite ... but the value (and justification) for this module lies in the additional modules which extend this base framework.
That said, and recognizing that a smaller contribution might be less daunting to a reviewer, I'd suggest that looking at ult_main, ult_matches, and possibly ult_registration should be sufficient to give a reviewer a solid view of my coding style and the operation of the code ... in addition to providing a fairly substantial chunk of the overall feature set involved in the larger collection.
Incidently (because I know it will come up), the code currently requires the latest -dev version of the Date module as a dependency ... the current 'recommended' Date-2.7 release has some trouble processing 'disabled' fields, which results in mysqli warnings when creating an ULT team (as per #1075530: Adding (or editing) a team after enabling 'ult_registration' results in mysqli_real_escape_string() warning) - this has been addressed in the -dev version of the Date code.
Comment #4
gregglesQuick review of ult_main
* Remove the version = "6.x-0.1-dev" line from your .info files. The packager will add that automatically.
* The message
$message = "The ULT Coreis not translatable and should be formatted so it's one long string (even if broken across lines) instead of concatenated. That makes life easier for translaters.* What is your goal with the check_plain in queries like in
$count = db_result(db_query($sql, check_plain($parentnid)));?* The function _ult_main_getteamsbyleague is never used, but if it is then the node titles need to be check_plained. Maybe add a comment to the docblock above it?
It would be good for you to create a team named
<script>alert('xss');</script>and then browse around the site and make sure everything still works AND that you do not see any popup boxes.Comment #5
gregglesPardon, I see now that ult_meain_getteamsbyleague is used and that in the cases I saw it was as part of a form api select which will not do a check_plain on the option keys and elements so you will need to add that.
See details on handling user input in select boxes and other places.
Comment #6
jthorson commentedThanks for your input, greggles. Currently running through the module to add missing t() functions and ensuring I've got proper output filtering inplace. Also removed the extraneous $Id and version tags.
Regarding your last comment, the linked page indicates that the Form API will run check_plain on #default_value and #options elements when the type is a select box ... which is actually causing me issues, as I already ran check_plain when I pulled the data out of the database. Rather than hunt down all the locations that call the ult_main_getteamsbyleague function to determine which result in direct output versus in a select box, is there a recommended way to "reverse" the check_plain encoding, so that the FAPI select box items are not double-encoded?
Comment #7
jthorson commentedFound drupal_html_to_text(), which seems to be doing the trick.
That said, the referenced page still contradicts itself.
Comment #8
jthorson commentedTranslation, xss prevention, and removal of extraneous check_plain() commands in db_query commands have been applied to ult_main and ult_divisions ... remaining modules still need to be updated.
Setting to 'needs work' until they're done.
Comment #9
jthorson commentedTranslation, sanitized output, and other code cleanup now completed on all included modules.
Setting back to 'needs review'.
Comment #10
jthorson commentedGiven the sheer size of this module, and the associated effort that would be required to give it a proper and thorough review, I have decided to withdraw this application ... and have instead created a new application with my D7 'IP Address Entity' module (Application link: http://drupal.org/node/1172058).
In the meantime, I'd like to express my thanks to sreynen and greggles for their time, effort, and feedback regarding this application and the associated module.
Comment #11
jthorson commented