CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion (Moderator: Donald Lobo) »
  • Found a couple of issues (maybe) with cli.class.php in making a quick subclass
Pages: [1]

Author Topic: Found a couple of issues (maybe) with cli.class.php in making a quick subclass  (Read 568 times)

britebyte

  • I post occasionally
  • **
  • Posts: 70
  • Karma: 2
  • CiviCRM version: Several 3.4+, 4.1+
  • CMS version: Drupal 6, Drupal7
  • MySQL version: Several 5.1+
  • PHP version: Several 5.2+
Found a couple of issues (maybe) with cli.class.php in making a quick subclass
October 19, 2012, 02:31:12 pm
I may have found a couple of issues with cli.class.php in making a quick and dirty extension:
  • _additional_arguments array values are always added to params
  • _additional_arguments have to be passed to the script in the order of declaration

My quick and dirty subclass is a script to import directly from a SQL query on so that we don't have to fool with wrapped lines in CSV files and so on. It chauvinistically assumes we are using MySQL. There are some obvious things I could improve here. As a relatively new PHP programmer I would appreciate some pointers to some examples that I could copy from to make it use the the Civi generic db api or a better generalization.

Code: [Select]
class civicrm_cli_sql extends civicrm_cli {
  var $header;
  var $separator = ',';

  function __construct() {
    $this->_required_arguments = array('entity');
    $this->_additional_arguments = array(
        'f' => 'file',
        'h' => 'host',
        'd' => 'database',
        'b' => 'dbuser',
        'w' => 'dbpassword'
    );
    if(!parent::initialize()) {
      die("Could not initialize CLI SQL importer");
    }
  }

  function run() {
    $this->row = 1;
    $sqlhandle = fopen($this->_file, "r");

    if (!$sqlhandle) {
      die("Could not open file: " . $this->_file . ". Please provide an absolute path.\n");
    }

    //header
    $sql =  file_get_contents($this->_file);
    $mysqli = new mysqli($this->_host, $this->_dbuser, $this->_dbpassword, $this->_database);
    if ($mysqli->connect_errno) {
      die("Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error);
    }
    $results = $mysqli->query($sql);
    if(!$results) {
      die("SQL query failed: (" . $mysqli->errno . ") " . $mysqli->error);
    }
   
    //header
    $headerfields = $results->fetch_fields();
    $header = array();
    foreach($headerfields as $fld) {
      $header[] = $fld->name;
    }
    // TODO: ErrorChecking   

    $this->header = $header;
    for ($row_no = 0; $row_no < $results->num_rows; $row_no++) {
      $results->data_seek($row_no);
      $data = $results->fetch_assoc();

      $this->row++;
      $params = $this->convertLine($data);
      $this->processLine($params);
    }
    fclose($sqlhandle);
    return;
  }
  /* return a params as expected */
  function convertLine($data) {
    $params = array();
    foreach ($this->header as $i => $field) {
      $params[$field] = $data[$field];
    }
    $params['version'] = 3;
    return $params;
  }
}

class civicrm_cli_sql_importer extends civicrm_cli_sql {
  function processline($params) {
    $result = civicrm_api($this->_entity, 'Create', $params);
    if ($result['is_error']) {
      echo "\nERROR line " . $this->row . ": " . $result['error_message'] . "\n";
    }
    else {
      echo "\nline " . $this->row . ": created " . $this->_entity . " id: " . $result['id'] . "\n";
    }
  }
}

Here are the changes to cli.class.php I needed to make to get my _additional_arguments working and order independent (around line 166):
Code: [Select]
      else {
        $isproperty = FALSE;
        foreach ($this->_additional_arguments as $short => $long) {
          if ($arg == '-' . $short || $arg == '--' . $long) {
            $property = '_' . $long;
            $this->$property = $value;
            $isproperty = TRUE;
            break;
          }
        }
        // all other arguments are parameters
        if(!$isproperty) {
          $key = ltrim($arg, '--');
          $this->_params[$key] = $value;
        }
      }

instead of
Code: [Select]
else {
        while(list($short, $long) = each ($this->_additional_arguments)) {
          if ($arg == '-' . $short || $arg == '--' . $long) {
            $property = '_' . $long;
            $this->$property = $value;
            continue;
          }
        }
        // all other arguments are parameters
        $key = ltrim($arg, '--');
        $this->_params[$key] = isset($value) ? $value : NULL;
      }
    }
    return TRUE;
  }
It seems that with the each call the array pointer is being advanced so that the arguments have to be handled in order.  Notice that even if an addtional argument is found it gets added to the parameters. I am wondering whether I should submit this as an issue. I realize the cli.class.php is used in multiple places and I am not sure what the implications of changing the parent class would be.

« Last Edit: October 19, 2012, 02:41:24 pm by britebyte »

Pages: [1]
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion (Moderator: Donald Lobo) »
  • Found a couple of issues (maybe) with cli.class.php in making a quick subclass

This forum was archived on 2017-11-26.