Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Annotation/ImportIndex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Avro\CsvBundle\Annotation;

/**
* @Annotation
*/
class ImportIndex
{
}
13 changes: 8 additions & 5 deletions Controller/ImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ImportController extends ContainerAware
*/
public function uploadAction($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);

$form = $this->container->get('form.factory')->create(new ImportFormType(), null, array('field_choices' => $fieldChoices));

Expand All @@ -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()) {
Expand Down Expand Up @@ -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()) {
Expand All @@ -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.');

Expand Down
51 changes: 40 additions & 11 deletions Import/Importer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 "<pre> fields = "; var_dump($fields);
//echo "<pre> fieldIndexes = "; var_dump($fieldIndexes);
//echo "<pre> row = "; var_dump($row);

$criteria = array();
foreach ($fieldIndexes as $k => $v)
{
$criteria[lcfirst($v)] = $row[$k];
}
//echo "<pre> 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 "<pre> entity not found<br/>\n";
// Create new entity
$entity = new $this->class();
}
//else
//{
// echo "<pre> id = ".$entity->getId() . "<br/>\n";
//}
if (in_array('Id', $fields)) {
$key = array_search('Id', $fields);
if ($this->metadata->hasField('legacyId')) {
Expand All @@ -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']) {
Expand Down
5 changes: 4 additions & 1 deletion Resources/views/Import/mapping.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@
{{ form_row(form.delimiter) }}
{{ form_row(form.filename) }}
</div>
<table class="table-styled table-bordered table-striped table-rounded">
{{ form_widget(form._token) }}
</div>
<div class="form-actions">
<button type="submit" class="btn btn-large btn-primary"><i class="icon-ok icon-white"></i> Import CSV</button>
<a href="{{ path('avro_csv_import_upload', {'alias': alias}) }}" class="btn"><i class="icon-arrow-left"></i> Back</a>
</div>
</form>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$(document).ready(function() {
var headers = {{ headersJson | raw }};
Expand All @@ -68,3 +70,4 @@
});
</script>
{% endblock %}

Binary file removed Util/.AbstractBase.php.swp
Binary file not shown.
Binary file removed Util/.Writer.php.swp
Binary file not shown.
10 changes: 8 additions & 2 deletions Util/FieldRetriever.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Doctrine\Common\Annotations\AnnotationReader;

use Avro\CsvBundle\Annotation\ImportExclude;
use Avro\CsvBundle\Annotation\ImportIndex;
use Avro\CaseBundle\Util\CaseConverter;

/**
Expand Down Expand Up @@ -35,20 +36,24 @@ 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)
{
$reflectionClass = new \ReflectionClass($class);
$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) {
Expand All @@ -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);
}
}
12 changes: 8 additions & 4 deletions Util/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Reader
protected $enclosure;
protected $line;
protected $headers;
protected $lineLength;

/**
* Open a CSV file
Expand All @@ -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();
Expand All @@ -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;
}

/**
Expand Down