diff --git a/Annotation/ImportIndex.php b/Annotation/ImportIndex.php new file mode 100644 index 0000000..d173f7e --- /dev/null +++ b/Annotation/ImportIndex.php @@ -0,0 +1,10 @@ +container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); + list($fieldChoices, $fieldIndexes) = $this->container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); $form = $this->container->get('form.factory')->create(new ImportFormType(), null, array('field_choices' => $fieldChoices)); @@ -49,8 +49,10 @@ public function uploadAction($alias) */ public function mappingAction(Request $request, $alias) { - $fieldChoices = $this->container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); + list($fieldChoices, $fieldIndexes) = $this->container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); + // prepend blank choice into choices array + array_unshift($fieldChoices, ''); $form = $this->container->get('form.factory')->create(new ImportFormType(), null, array('field_choices' => $fieldChoices)); if ('POST' == $request->getMethod()) { @@ -94,8 +96,9 @@ public function mappingAction(Request $request, $alias) */ public function processAction(Request $request, $alias) { - $fieldChoices = $this->container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); - + list($fieldChoices, $fieldIndexes) = $this->container->get('avro_csv.field_retriever')->getFields($this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias)), 'title', true); + // prepend blank choice into choices array + array_unshift($fieldChoices, ''); $form = $this->container->get('form.factory')->create(new ImportFormType(), null, array('field_choices' => $fieldChoices)); if ('POST' == $request->getMethod()) { @@ -106,7 +109,7 @@ public function processAction(Request $request, $alias) $importer->init(sprintf('%s%s', $this->container->getParameter('avro_csv.tmp_upload_dir'), $form['filename']->getData()), $this->container->getParameter(sprintf('avro_csv.objects.%s.class', $alias), $form['delimiter']->getData())); - $importer->import($form['fields']->getData()); + $importer->import($form['fields']->getData(), $fieldIndexes); $this->container->get('session')->getFlashBag()->set('success', $importer->getImportCount().' items imported.'); diff --git a/Import/Importer.php b/Import/Importer.php index 138fb0a..d1cd626 100644 --- a/Import/Importer.php +++ b/Import/Importer.php @@ -72,17 +72,22 @@ public function init($file, $class, $delimiter = ',', $headerFormat = 'title') * * @return true if successful */ - public function import($fields) + public function import($fields, $fieldIndexes) { $fields = array_unique($this->caseConverter->toPascalCase($fields)); + $indexes = array_unique($this->caseConverter->toPascalCase($fieldIndexes)); + + // make keys for both arrays match + $fieldIndexes = array(); + foreach ($indexes as $k => $v) + { + $i = array_search($v, $fields); + $fieldIndexes[$i] = $v; + } while ($row = $this->reader->getRow()) { - if (($this->importCount % $this->batchSize) == 0) { - $this->addRow($row, $fields, true); - } else { - $this->addRow($row, $fields, false); - } - $this->importCount++; + ++$this->importCount; + $this->addRow($row, $fields, $fieldIndexes, (($this->importCount % $this->batchSize) == 0)); } // one last flush to make sure no persisted objects get left behind @@ -98,11 +103,35 @@ public function import($fields) * @param array $fields An array of the fields to import * @param boolean $andFlush Flush the ObjectManager */ - private function addRow($row, $fields, $andFlush = true) + private function addRow($row, $fields, $fieldIndexes, $andFlush = true) { - // Create new entity - $entity = new $this->class(); + // If we have indexes, try to find a record that matches and load it... + if (count($fieldIndexes) > 0) + { + //echo "
 fields = "; var_dump($fields);
+            //echo "
 fieldIndexes = "; var_dump($fieldIndexes);
+            //echo "
 row = "; var_dump($row);
+
+            $criteria = array();
+            foreach ($fieldIndexes as $k => $v)
+            {
+                $criteria[lcfirst($v)] = $row[$k];
+            }
+            //echo "
 criteria = "; var_dump($criteria);
+            $entity = $this->objectManager->getRepository($this->class)->findOneBy($criteria);
+        }
 
+        // if we don't have indexes, or we didn't get a match, create a new entity.        
+        if (!isset($entity))
+        {
+            //echo "
 entity not found
\n"; + // Create new entity + $entity = new $this->class(); + } + //else + //{ + // echo "
 id = ".$entity->getId() . "
\n"; + //} if (in_array('Id', $fields)) { $key = array_search('Id', $fields); if ($this->metadata->hasField('legacyId')) { @@ -114,7 +143,7 @@ private function addRow($row, $fields, $andFlush = true) // loop through fields and set to row value foreach ($fields as $k => $v) { if ($this->metadata->hasField(lcfirst($v))) { - $entity->{'set'.$fields[$k]}($row[$k]); + $entity->{'set'.$v}($row[$k]); } else if ($this->metadata->hasAssociation(lcfirst($v))) { $association = $this->metadata->associationMappings[lcfirst($v)]; switch ($association['type']) { diff --git a/Resources/views/Import/mapping.html.twig b/Resources/views/Import/mapping.html.twig index 5accd86..19adbf5 100644 --- a/Resources/views/Import/mapping.html.twig +++ b/Resources/views/Import/mapping.html.twig @@ -34,7 +34,6 @@ {{ form_row(form.delimiter) }} {{ form_row(form.filename) }} - {{ form_widget(form._token) }}
@@ -42,6 +41,9 @@ Back
+{% endblock %} +{% block javascripts %} +{{ parent() }} {% endblock %} + diff --git a/Util/.AbstractBase.php.swp b/Util/.AbstractBase.php.swp deleted file mode 100644 index 5306f30..0000000 Binary files a/Util/.AbstractBase.php.swp and /dev/null differ diff --git a/Util/.Writer.php.swp b/Util/.Writer.php.swp deleted file mode 100644 index 813fb72..0000000 Binary files a/Util/.Writer.php.swp and /dev/null differ diff --git a/Util/FieldRetriever.php b/Util/FieldRetriever.php index 486b92e..110505d 100644 --- a/Util/FieldRetriever.php +++ b/Util/FieldRetriever.php @@ -5,6 +5,7 @@ use Doctrine\Common\Annotations\AnnotationReader; use Avro\CsvBundle\Annotation\ImportExclude; +use Avro\CsvBundle\Annotation\ImportIndex; use Avro\CaseBundle\Util\CaseConverter; /** @@ -35,7 +36,7 @@ public function __construct($annotationReader, CaseConverter $caseConverter) * @param string $format The desired field case format * @param boolean $copyToKey Copy the field values to their respective key * - * @return array $fields + * @return array(array $fields, array $indexFields) */ public function getFields($class, $format = 'title', $copyToKey = false) { @@ -43,12 +44,16 @@ public function getFields($class, $format = 'title', $copyToKey = false) $properties = $reflectionClass->getProperties(); $fields = array(); + $fieldIndexes = array(); foreach ($properties as $property) { $addField = true; foreach ($this->annotationReader->getPropertyAnnotations($property) as $annotation) { if ($annotation instanceof ImportExclude) { $addField = false; } + if ($annotation instanceof ImportIndex) { + $fieldIndexes[] = $this->caseConverter->convert($property->getName(), $format); + } } if ($addField) { @@ -58,8 +63,9 @@ public function getFields($class, $format = 'title', $copyToKey = false) if ($copyToKey) { $fields = array_combine($fields, $fields); + $fieldIndexes = array_combine($fieldIndexes, $fieldIndexes); } - return $fields; + return array($fields, $fieldIndexes); } } diff --git a/Util/Reader.php b/Util/Reader.php index 6584e72..d30d7bd 100644 --- a/Util/Reader.php +++ b/Util/Reader.php @@ -15,6 +15,7 @@ class Reader protected $enclosure; protected $line; protected $headers; + protected $lineLength; /** * Open a CSV file @@ -25,12 +26,13 @@ class Reader * @param string $enclosure The enclosure * @param boolean $hasHeaders Does the CSV have any headers? */ - public function open($file, $delimiter = ',', $mode = 'r+', $enclosure = '"', $hasHeaders = true) + public function open($file, $delimiter = ',', $mode = 'r+', $enclosure = '"', $hasHeaders = true, $lineLength = 0) { $this->handle = fopen($file, $mode); $this->delimiter = $delimiter; $this->enclosure = $enclosure; $this->line = 0; + $this->lineLength = $lineLength; if ($hasHeaders) { $this->headers = $this->getRow(); @@ -44,13 +46,15 @@ public function open($file, $delimiter = ',', $mode = 'r+', $enclosure = '"', $h */ public function getRow() { - if (($row = fgetcsv($this->handle, 1000, $this->delimiter, $this->enclosure)) !== false) { + while (($row = fgetcsv($this->handle, $this->lineLength, $this->delimiter, $this->enclosure)) !== false) { $this->line++; + // a blank line returns array of one null. if found, skip it. + if ((count($row) == 1) && ($row[0] == NULL)) + continue; return $row; - } else { - return false; } + return false; } /**