Changeset 57102
- Timestamp:
- 30/06/08 16:12:47 (2 months ago)
- Location:
- modules/sapphire/branches/roa/tools
- Files:
-
- 2 modified
-
BulkLoader.php (modified) (2 diffs)
-
CsvBulkLoader.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
modules/sapphire/branches/roa/tools/BulkLoader.php
r56537 r57102 6 6 * You can configure column-handling, 7 7 * 8 * @todo Allow updating of existing records based on user-specified unique criteria/callbacks (e.g. database ID)9 8 * @todo Add support for adding/editing has_many relations. 10 9 * @todo Add support for deep chaining of relation properties (e.g. Player.Team.Stats.GoalCount) 10 * @todo Character conversion 11 11 * 12 12 * @see http://rfc.net/rfc4180.html … … 41 41 * The column count should match the count of array elements, 42 42 * fill with NULL values if you want to skip certain columns. 43 * 44 * You can also combine {@link $hasHeaderRow} = true and {@link $columnMap} 45 * and omit the NULL values in your map. 43 46 * 44 47 * Supports one-level chaining of has_one relations and properties with dot notation -
modules/sapphire/branches/roa/tools/CsvBulkLoader.php
r54730 r57102 39 39 40 40 $return = new DataObjectSet(); 41 42 // assuming that first row is column naming if no columnmap is passed 41 43 42 if($this->hasHeaderRow && $this->columnMap) { 44 43 $columnRow = fgetcsv($file, 0, $this->delimiter, $this->enclosure); 45 $columnMap = $this->columnMap; 44 $columnMap = array(); 45 foreach($columnRow as $k => $origColumnName) { 46 if(isset($this->columnMap[$origColumnName])) { 47 $columnMap[$origColumnName] = $this->columnMap[$origColumnName]; 48 } else { 49 $columnMap[$origColumnName] = null; 50 } 51 52 } 46 53 } elseif($this->columnMap) { 47 54 $columnMap = $this->columnMap; 48 55 } else { 56 // assuming that first row is column naming if no columnmap is passed 49 57 $columnRow = fgetcsv($file, 0, $this->delimiter, $this->enclosure); 50 58 $columnMap = array_combine($columnRow, $columnRow); 51 59 } 52 60 61 $rowIndex = 0; 53 62 while (($row = fgetcsv($file, 0, $this->delimiter, $this->enclosure)) !== FALSE) { 54 $indexedRow = array_combine(array_values($columnMap), array_values($row)); 63 $rowIndex++; 64 65 /* 66 // the columnMap should have the same amount of columns as each record row 67 if(count(array_keys($columnMap)) == count(array_values($row))) { 68 user_error("CsvBulkLoader::processAll(): Columns in row {$rowIndex} don't match the \$columnMap", E_USER_WARNING); 69 } 70 */ 71 72 $indexedRow = array(); 73 foreach($columnMap as $origColumnName => $fieldName) { 74 // in case the row has less fields than the columnmap, 75 // ignore the "leftover" mappings 76 if(!isset($row[count($indexedRow)])) { 77 user_error("CsvBulkLoader::processAll(): Columns in row {$rowIndex} don't match the \$columnMap", E_USER_NOTICE); 78 continue; 79 } 80 81 $indexedRow[$origColumnName] = $row[count($indexedRow)]; 82 } 83 55 84 $return->push($this->processRecord($indexedRow, $columnMap)); 56 85 } … … 71 100 // we can't combine runs, as other columns might rely on the relation being present 72 101 $relations = array(); 73 foreach($record as $key => $val) { 102 foreach($record as $origColumnName => $val) { 103 $fieldName = $columnMap[$origColumnName]; 104 74 105 // don't bother querying of value is not set 75 106 if($this->isNullValue($val)) continue; 76 107 77 108 // checking for existing relations 78 if(isset($this->relationCallbacks[$ key])) {109 if(isset($this->relationCallbacks[$fieldName])) { 79 110 // trigger custom search method for finding a relation based on the given value 80 111 // and write it back to the relation (or create a new object) 81 $relationName = $this->relationCallbacks[$ key]['relationname'];82 $relationObj = $obj->{$this->relationCallbacks[$ key]['callback']}($val, $record);112 $relationName = $this->relationCallbacks[$fieldName]['relationname']; 113 $relationObj = $obj->{$this->relationCallbacks[$fieldName]['callback']}($val, $record); 83 114 if(!$relationObj || !$relationObj->exists()) { 84 115 $relationClass = $obj->has_one($relationName); … … 89 120 $obj->{"{$relationName}ID"} = $relationObj->ID; 90 121 $obj->write(); 91 } elseif(strpos($ key, '.') !== false) {122 } elseif(strpos($fieldName, '.') !== false) { 92 123 // we have a relation column with dot notation 93 list($relationName,$columnName) = split('\.', $ key);124 list($relationName,$columnName) = split('\.', $fieldName); 94 125 $relationObj = $obj->getComponent($relationName); // always gives us an component (either empty or existing) 95 126 $obj->setComponent($relationName, $relationObj); … … 103 134 $id = ($preview) ? 0 : $obj->write(); 104 135 105 106 136 // second run: save data 107 foreach($record as $key => $val) { 108 if($this->isNullValue($val, $key)) continue; 109 110 if($obj->hasMethod("import{$key}")) { 111 $obj->{"import{$key}"}($val, $record); 112 } elseif(strpos($key, '.') !== false) { 137 foreach($record as $origColumnName => $val) { 138 $fieldName = $columnMap[$origColumnName]; 139 140 if($this->isNullValue($val, $fieldName)) continue; 141 142 if($obj->hasMethod("import{$fieldName}")) { 143 $obj->{"import{$fieldName}"}($val, $record); 144 } elseif(strpos($fieldName, '.') !== false) { 113 145 // we have a relation column 114 list($relationName,$columnName) = split('\.', $ key);146 list($relationName,$columnName) = split('\.', $fieldName); 115 147 $relationObj = $obj->getComponent($relationName); 116 148 $relationObj->{$columnName} = $val; 117 149 $relationObj->write(); 118 150 $obj->flushCache(); // avoid relation caching confusion 119 } elseif($obj->hasField($key) || $obj->hasMethod($key)) { 151 //} elseif($obj->hasField($fieldName) || $obj->hasMethod($fieldName)) { 152 } else { 120 153 // plain old value setter 121 $obj->{$ key} = $val;154 $obj->{$fieldName} = $val; 122 155 } 123 156 } … … 150 183 if(is_string($duplicateCheck)) { 151 184 $SQL_fieldName = Convert::raw2sql($duplicateCheck); 152 $SQL_fieldValue = $record[$columnMap[$fieldName]]; 185 186 if(!isset($record[$fieldName])) { 187 user_error("CsvBulkLoader:processRecord: Couldn't find duplicate identifier '{$fieldName}' in columns", E_USER_ERROR); 188 } 189 $SQL_fieldValue = $record[$fieldName]; 153 190 $existingRecord = DataObject::get_one($this->objectClass, "`$SQL_fieldName` = '{$SQL_fieldValue}'"); 154 191 if($existingRecord) return $existingRecord; 155 192 } elseif(is_array($duplicateCheck) && isset($duplicateCheck['callback'])) { 156 $existingRecord = singleton($this->objectClass)->{$duplicateCheck['callback']}($ val, $record);193 $existingRecord = singleton($this->objectClass)->{$duplicateCheck['callback']}($record[$fieldName], $record); 157 194 if($existingRecord) return $existingRecord; 158 195 } else {
