CVS edit link for Spiked

I wrote an interface for the DirectAdmin API, providing multiple hooks for other developers. This module allows other modules to access and administer a DirectAdmin server. Possibilities include:
- Creation of accounts
- Checking users and configurations
- Administering domains
- Stats control
Missing features will be implemented on request, as well as bug fixes.

Links:
- DirectAdmin http://www.directadmin.com/
- DirectAdmin API http://www.directadmin.com/search_versions.php?query=CMD_API_%25

Comments

Spiked’s picture

Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new4.43 KB
avpaderno’s picture

Status: Needs review » Needs work
Issue tags: +Module review
  1.       watchdog('DirectAdmin', 'Error: ' . $result['error'] . ' - <em>' . $result['details'] . '</em> <pre>' . print_r($result, true) . '</pre>', array(), WATCHDOG_WARNING);
    

    It should be better to use placeholders, rather than concatenating strings.

  2. ; $Id$
    name = "Directadmin API"
    description = "Allows Drupal contributions to communicate with a DirectAdmin server"
    core = 6.x
    

    The module doesn't declare its dependency from PHP 5.

  3. /*
     * Implementation of hook_requirements()
     */
    function directadmin_api_requirements($phase) {
      
    }
    

    There is no code.

  4. require_once(drupal_get_path('module', 'directadmin_api').'/forms.inc');
    require_once(drupal_get_path('module', 'directadmin_api').'/directadmin/directadmin.class.php');
    

    There is another way to include PHP code; if then you are always including those files, it would be better to incorporate them into the module file.

  5.     'title' => 'DirectAdmin data',
        'description' => 'DirectAdmin data.',
    

    The description should be more descriptive.

  6. function directadmin_api_perm() {
      return array('administer directadmin_api');
    }
    

    The permission string should be something more descriptive (see administer nodes, administer users, etc...).

  7. /*
     * Custom hooks
     */
    function directadmin_api_cmd($cmd, $headers = array(), $method = 'GET', $data = NULL) {
      return DirectAdmin::cmd($cmd, $headers, $method, $data);
    }
    
    function directadmin_api_get_free_ips() {
      return DirectAdmin::getFreeIPS();
    }
    
    function directadmin_api_get_random_free_ip() {
      return DirectAdmin::getRandomFreeIp();
    }
    

    The custom class is used just to define static methods, which are then also exposed through functions; in that case, it should be better to not define such class.

  8.   $form['directadmin_api_reseller_password'] = array(
          '#type' => 'password',
          '#title' => t('Reseller password'),
          '#description' => t('The resellers password, as described above.'),
          '#required' => true,
          '#size' => 30,
          '#default_value' => '', // variable_get('directadmin_api_reseller_password', '')
      );
    

    The code should use the value of the Drupal variable, not an empty string.

  9. function directadmin_api_data_form_validate($form, &$form_items) {
      
    }
    
    function directadmin_api_data_form_submit($form, &$form_items)
    {
      variable_set('directadmin_api_host', $form_items['values']['directadmin_api_host']);
      variable_set('directadmin_api_port', $form_items['values']['directadmin_api_port']);
      variable_set('directadmin_api_reseller_username', $form_items['values']['directadmin_api_reseller_username']);
      variable_set('directadmin_api_reseller_password', $form_items['values']['directadmin_api_reseller_password']);
      
      drupal_set_message('Settings saved', 'status');
    }
    

    An empty validate function is not useful. If the form values are used to set Drupal variables, it should be better to call system_settings_form().

  10.     $tests[] = array(
          'test' => "CMD_API_PACKAGES_USER",
          'result' => "<strong>passed</strong>",
          'info' => "{$count} packages available",
        );
    

    The strings result, and info should be translatable.

  11. See the Drupal coding standards to understand how a module code should be written.
Spiked’s picture

Status: Needs work » Needs review
StatusFileSize
new2.63 KB

Changelog:
- Cleaned up the code, removed the class and moved everything into functions
- Applied t() to several strings
- Removed php5 dependency (removed the (static) class)
- Removed .install file (empty hook_requirements())
- Removed require_once(), merged everything after a cleanup
- Changed several descriptions
- Changed permission to "configure directadmin api"
- Removed function around static class->static function, and made the functions directly available
- Removed empty #default_value from #password (#password doesn't support #default_value at all)
- Added validation and added system_settings_form()
- Satisfied the Coder module at highest severity level.

Spiked’s picture

I have also changed function names in comments, but after I archived it. Would be a bit overhead to post a new archive for changed comments, but I thought I'd let you know.

avpaderno’s picture

Status: Needs review » Needs work
  1.   $port = (int) $form_items['directadmin_api_port'];
    
      if (!is_numeric($port) || $port < 0 || $port > 65535) {
        form_set_error('directadmin_api_port', 'Invalid port number.');
      }
    

    As the value is converted in an integer, it's probable that is_numeric() will return TRUE.

  2. 
      variable_set('directadmin_api_host', check_plain($form_items['values']['directadmin_api_host']));
      variable_set('directadmin_api_port', check_plain($form_items['values']['directadmin_api_port']));
      variable_set('directadmin_api_reseller_username', check_plain($form_items['values']['directadmin_api_reseller_username']));
    

    check_plain() and similar functions are used when the value is rendered, not when it is saved in a database table.

  3.   drupal_set_message(t('Settings saved'), 'status');
    

    It should be better to use the same string used by Drupal; in that way, the translation people would have a string less to translate.

  4. function directadmin_api_data_test() {}
    

    Why doesn't the code use simpletest.module, for the testing?

Spiked’s picture

Status: Needs work » Needs review
StatusFileSize
new3.04 KB

1: You're right, I've changed the if-statement (and variable) to
2: Never thought about that. Moved them from set_variable() to get_variable(), but only at the hostname. (port is checked to be numeric, and username+password may contain special characters.) Might be a (small) security issue, and needs some thought.
3: Fixed.
4: The user doesn't need to test the Drupal module/installation, but the connection to the external DirectAdmin server. I'm not completely sure SimpleTest can do this, but I will look into this. It does add a requirement, unfortunately.

Changelog:
- Fixed function names in comments.
- Fixed form validation of the DirectAdmin configuration.
- Moved check_plain from variable_set to variable_get on needed variables.
- Changed "Settings saved" message.
- Added .install file for hook_uninstall() to remove set variables.

avpaderno’s picture

Status: Needs review » Needs work
  1.       '#default_value' => check_plain(variable_get('directadmin_api_host', '')),
    

    The call to check_plain() is not necessary, as it is already done from the form API; calling it twice creates some problems.

  2.   if ($key === FALSE) {
        return TRUE;
      }
      else {
        return FALSE;
      }
    

    The code can be simplified.

Spiked’s picture

Status: Needs work » Needs review
StatusFileSize
new3.02 KB

Changelog:
- Removed check_plain
- Simplified the if statement.

Is there a default README.txt format, or should I base it on another README.txt? (Like drupal's)

avpaderno’s picture

Status: Needs review » Fixed
  1.   if (isset($result['valid'])) {
        switch ($result['valid']) {
          case '0':
            return FALSE;
            break;
          case '1':
            return TRUE;
            break;
        }
    

    It could be simply

      if (isset($result['valid'])) {
        return (boolean) $result['valid'];
      }
    
  2. There isn't a format specific for the README.txt; you can look at the file included with other modules.

Status: Fixed » Closed (fixed)
Issue tags: -Module review

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

avpaderno’s picture

Component: Miscellaneous » new project application
Assigned: Unassigned » avpaderno
Issue summary: View changes
Status: Closed (fixed) » Fixed

Status: Fixed » Closed (fixed)

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