~fabiocbalbuquerque/sahana-agasti/web-services

« back to all changes in this revision

Viewing changes to apps/frontend/lib/util/agImportHelper.class.php

  • Committer: Clayton Kramer
  • Date: 2011-06-02 20:32:55 UTC
  • mto: (1.26.1 push-trunk) (7.1.1 mayon)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: clayton.kramer@mail.cuny.edu-20110602203255-jibrhvvu4193e0sa
Staff import working. Still needs to be hooked to indexer.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
  const CONN_TEMP_READ = 'import_temp_read';
20
20
  const CONN_TEMP_WRITE = 'import_temp_write';
21
21
 
22
 
  protected   $fileInfo,
23
 
              $tempTable,
24
 
              $tempTableOptions = array(),
25
 
              $importSpec = array(),
26
 
              $requiredImportColumns = array(),
27
 
              $successColumn = '_import_success',
28
 
              $idColumn = 'id',
29
 
              $excelImportBatchSize = 2500,
30
 
              $dynamicFieldType,
31
 
              $importHeaderStrictValidation = FALSE,
32
 
              $iterData;
33
 
 
 
22
  protected $fileInfo,
 
23
  $tempTable,
 
24
  $tempTableOptions = array(),
 
25
  $importSpec = array(),
 
26
  $requiredImportColumns = array(),
 
27
  $successColumn = '_import_success',
 
28
  $idColumn = 'id',
 
29
  $excelImportBatchSize = 2500,
 
30
  $dynamicFieldType,
 
31
  $importHeaderStrictValidation = FALSE,
 
32
  $iterData;
34
33
  /**
35
34
   * @var agEventHandler An agEventHandler instance
36
35
   */
37
 
  protected   $eh;
 
36
  protected $eh;
38
37
 
39
38
  abstract protected function setImportSpec();
40
39
 
74
73
 
75
74
    $adapter = Doctrine_Manager::connection()->getDbh();
76
75
    $this->_conn[self::CONN_TEMP_READ] = Doctrine_Manager::connection($adapter, self::CONN_TEMP_READ);
77
 
    $this->_conn[self::CONN_TEMP_WRITE] = Doctrine_Manager::connection($adapter, self::CONN_TEMP_WRITE);
 
76
    $this->_conn[self::CONN_TEMP_WRITE] = Doctrine_Manager::connection($adapter,
 
77
                                                                       self::CONN_TEMP_WRITE);
78
78
  }
79
79
 
80
80
  /**
84
84
  {
85
85
    // the parent's destructor will rollback any oustanding open transactions and close conns
86
86
    parent::__destruct();
87
 
    
88
 
    // removes the temporary file
89
 
    $file = $this->fileInfo['dirname'] . DIRECTORY_SEPARATOR . $this->fileInfo['basename'];
90
 
    if (!@unlink($file)) {
 
87
 
 
88
    /*
 
89
 
 
90
      // removes the temporary file
 
91
      $file = $this->fileInfo['dirname'] . DIRECTORY_SEPARATOR . $this->fileInfo['basename'];
 
92
      if (!@unlink($file)) {
91
93
      $this->eh->logAlert('Failed to delete the {' . $this->fileInfo['basename'] . '} import file.');
92
 
    } else {
 
94
      } else {
93
95
      $this->eh->logInfo('Successfully deleted the {' . $this->fileInfo['basename'] . '} import file.');
94
 
    }
 
96
      }
 
97
     * 
 
98
     */
95
99
  }
96
100
 
97
101
  /**
116
120
        $this->importSpec[$cleanColumn] = $value;
117
121
 
118
122
        $eventMsg = 'Import spec column name {' . $column . '} was not clean and was ' .
119
 
        'automatically renamed to {' . $cleanColumn . '}. It is recommended you correct this in' .
120
 
        'your import spec declaration.';
 
123
            'automatically renamed to {' . $cleanColumn . '}. It is recommended you correct this in' .
 
124
            'your import spec declaration.';
121
125
        $this->eh->logWarning($eventMsg);
122
126
      }
123
127
    }
169
173
    $this->getFileInfo($importFile);
170
174
    if (strtolower($this->fileInfo['extension']) <> 'xls') {
171
175
      $errMsg = '{' . $this->fileInfo['basename'] .
172
 
        '} is not a Microsoft Excel 2003 ".xls" workbook.';
 
176
          '} is not a Microsoft Excel 2003 ".xls" workbook.';
173
177
      $this->eh->logEmerg($errMsg);
174
178
    }
175
179
 
197
201
      $sheetName = $xlsObj->boundsheets[$sheet]['name'];
198
202
 
199
203
      // We don't import sheets named "Lookup" so we'll skip the remainder of this loop
200
 
      if (strtolower($sheetName) == 'lookup')
201
 
      {
 
204
      if (strtolower($sheetName) == 'lookup') {
202
205
        $this->eh->logInfo('Ignoring {' . $sheetName . '} worksheet');
203
206
        continue;
204
207
      }
208
211
 
209
212
      // clean the column headers to ensure consistency
210
213
      $this->eh->logInfo('Cleaning worksheet headers');
211
 
      foreach ($currentSheetHeaders as $index => &$header)
212
 
      {
 
214
      foreach ($currentSheetHeaders as $index => &$header) {
213
215
        $header = $this->cleanColumnName($header);
214
216
      }
215
217
      unset($header);
241
243
        $this->createTempTable();
242
244
      }
243
245
 
244
 
      $this->eh->logInfo('Validating column headers for sheet {' . $sheetName .'}.');
245
 
      if ($this->validateColumnHeaders($currentSheetHeaders, $sheetName))
246
 
      {
 
246
      $this->eh->logInfo('Validating column headers for sheet {' . $sheetName . '}.');
 
247
      if ($this->validateColumnHeaders($currentSheetHeaders, $sheetName)) {
247
248
        $this->eh->logInfo('Valid column headers found!');
248
 
      }
249
 
      else
250
 
      {
251
 
        if ($this->importHeaderStrictValidation)
252
 
        {
 
249
      } else {
 
250
        if ($this->importHeaderStrictValidation) {
253
251
          $errMsg = 'Unable to import file due to failed validation of import headers. (Strict ' .
254
 
            'header validation is currently enforced!)';
 
252
              'header validation is currently enforced!)';
255
253
          $this->eh->logEmerg($errMsg);
256
 
        }
257
 
        else
258
 
        {
 
254
        } else {
259
255
          $errMsg = 'Import sheet {' . $sheetName . '} failed column header validation. Skipping ' .
260
 
            'import of this sheet. (Strict header validation is not currently enforced!)' ;
 
256
              'import of this sheet. (Strict header validation is not currently enforced!)';
261
257
          $this->eh->logErr($errMsg);
262
258
          continue;
263
259
        }
275
271
      }
276
272
 
277
273
      // start by looping our batches
278
 
      for ($batch = 1; $batch <= $batches; $batch++)
279
 
      {
 
274
      for ($batch = 1; $batch <= $batches; $batch++) {
280
275
        $this->eh->logInfo('Processing batch {' . $batch . '} of {' . $batches . '}.');
281
276
        // each batch clears the import data array
282
277
        $importFileData = array();
283
278
 
284
279
        // begin adding rows and continue to the end for this batch
285
 
        for ($row = $batchStart; $row <= $batchEnd; $row++)
286
 
        {
 
280
        for ($row = $batchStart; $row <= $batchEnd; $row++) {
287
281
          $this->eh->logDebug('Reading row {' . $row . '} into import data array.');
288
282
 
289
283
          // used to tell if the row is empty
307
301
              $val = NULL;
308
302
            } elseif (strlen(strval($val)) > $this->importSpec[$currentSheetHeaders[$col]]['length']) {
309
303
              $eventMsg = 'Value in sheet {' . $sheet . '} row {' . $row . '} column {' .
310
 
                $currentSheetHeaders[$col] . '} is too long and was set to NULL.';
 
304
                  $currentSheetHeaders[$col] . '} is too long and was set to NULL.';
311
305
              $this->eh->logWarning($eventMsg);
312
306
              $val = NULL;
313
307
            } else {
320
314
          }
321
315
 
322
316
          // check for empty rows early to prevent
323
 
          if (! $notNull)
324
 
          {
 
317
          if (!$notNull) {
325
318
            $this->eh->logWarning('Empty row found at sheet {' . $sheet . '} row {' . $row . '}. Skipping.');
326
 
          }
327
 
          else
328
 
          {
 
319
          } else {
329
320
            $importFileData[$row] = $importRow;
330
321
          }
331
322
        }
332
323
 
333
324
        // process this batch
334
325
        $this->eh->logInfo('Successfully loaded batch {' . $batch . '} from file, now inserting into ' .
335
 
          'temp table {' . $this->tempTable . '}');
 
326
            'temp table {' . $this->tempTable . '}');
336
327
 
337
328
        $inserted = $this->saveImportTempIter($importFileData, $query);
338
329
        $this->iterData['tempCount'] += $inserted;
348
339
 
349
340
    // Log our success and return T/F based on whether or not any non-fatal errors occurred
350
341
    $okMsg = 'Completed insertion of ' . $this->iterData['tempCount'] . ' rows from the import ' .
351
 
      'file to the temporary table.';
 
342
        'file to the temporary table.';
352
343
    $this->eh->logNotice($okMsg);
353
344
 
354
 
    return ($this->eh->getErrCount() == 0) ? TRUE : FALSE ;
 
345
    return ($this->eh->getErrCount() == 0) ? TRUE : FALSE;
355
346
  }
356
347
 
357
348
  /**
395
386
                                      Doctrine_Connection_Statement $insertQuery)
396
387
  {
397
388
    // first check to see if it's even worth running
398
 
    if (empty($importDataSet))
399
 
    {
 
389
    if (empty($importDataSet)) {
400
390
      $this->eh->logWarning('Cannot save empty dataset to temp table.');
401
 
     return 0;
 
391
      return 0;
402
392
    }
403
393
 
404
394
    // beginning a transaction should improve performance
417
407
      } catch (Exception $e) {
418
408
        // in the event of an insert error, don't continue
419
409
        $errMsg = 'Failed to insert to temp table with data (' . implode(',', $row) . '). ' .
420
 
          "\n\n" . $e->getMessage();
 
410
            "\n\n" . $e->getMessage();
421
411
        $this->eh->logErr($errMsg, count($importDataSet));
422
412
        $err = TRUE;
423
413
        break;
463
453
      // log this info event
464
454
      $eventMsg = 'Dropped temporary table {' . $this->tempTable . '}';
465
455
      $this->eh->logNotice($eventMsg);
466
 
    }
467
 
    catch(Doctrine_Connection_Exception $e)
468
 
    {
 
456
    } catch (Doctrine_Connection_Exception $e) {
469
457
      // we only want to silence 'no such table' errors
470
 
      if ($e->getPortableCode() !== Doctrine_Core::ERR_NOSUCHTABLE)
471
 
      {
 
458
      if ($e->getPortableCode() !== Doctrine_Core::ERR_NOSUCHTABLE) {
472
459
        $this->eh->logEmerg('Failed to drop temp table {' . $this->tempTable . '}');
473
 
      }
474
 
      else
475
 
      {
 
460
      } else {
476
461
        $this->eh->logInfo('Temp table {' . $this->tempTable . '} does not exist. Skipping drop.');
477
462
      }
478
463
    }
496
481
    try {
497
482
      // uses the Doctrine_Export methods see Doctrine_Export api for more details
498
483
      $conn->export->createTable($this->tempTable, $importSpec, $this->tempTableOptions);
499
 
      $this->eh->logNotice('Successfully created temp table {' . $this->tempTable .'}.');
500
 
    }
501
 
    catch (Doctrine_Exception $e)
502
 
    {
 
484
      $this->eh->logNotice('Successfully created temp table {' . $this->tempTable . '}.');
 
485
    } catch (Doctrine_Exception $e) {
503
486
      $this->eh->logEmerg('Error creating temp table ({' . $this->tempTable . '} for import.');
504
487
    }
505
488
  }
530
513
    // return true / false and return info as appropriate
531
514
    if (empty($importSpecDiff)) {
532
515
      return TRUE;
533
 
    }
534
 
    else
535
 
    {
 
516
    } else {
536
517
      $this->eh->logErr('Error processing sheet headers: Missing required columns.');
537
 
      
538
 
      foreach ($importSpecDiff as $missing)
539
 
      {
 
518
 
 
519
      foreach ($importSpecDiff as $missing) {
540
520
        $this->eh->logWarning('Column header {' . $missing . '} is missing.');
541
521
      }
542
522
      return FALSE;