Skip to content

Commit

Permalink
Add CSV imports via CLI
Browse files Browse the repository at this point in the history
Summary:
- Add CSV imports via CLI
- Add Import Usecase
- Fix typo in Console\Command
- Use camelCase for console command actions
- Better validation errors

Refs T272

Test Plan:
- `./bin/ushahidi import list` - to see possible formats.
- `./bin/ushahidi import run -f ../primary-schools-2007-top50.csv -m ../primary-schools-map.json --values ../primary-schools-values.json`
Where map.json is a json file of source-destination mappings like
```
{
	"[Id]" : "[values][school-id][0]",
	"[Name_of_School]": "[title]"
}
```
and values.json is a json file of fixed values like
```
{
	"status":"published",
	"form":2
}
```

Reviewers: will, lkamau, jasonmule

Subscribers: jasonmule, will, rjmackay, lkamau

Maniphest Tasks: T272

Differential Revision: https://phabricator.ushahidi.com/D874
  • Loading branch information
rjmackay committed Aug 5, 2015
1 parent d17fd43 commit 5920050
Show file tree
Hide file tree
Showing 22 changed files with 858 additions and 45 deletions.
6 changes: 3 additions & 3 deletions application/classes/Ushahidi/Console/Dataprovider.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected function get_providers(InputInterface $input, OutputInterface $output
return $providers;
}

protected function execute_list(InputInterface $input, OutputInterface $output)
protected function executeList(InputInterface $input, OutputInterface $output)
{
$providers = $this->get_providers($input, $output);

Expand All @@ -66,7 +66,7 @@ protected function execute_list(InputInterface $input, OutputInterface $output)
return $list;
}

protected function execute_incoming(InputInterface $input, OutputInterface $output)
protected function executeIncoming(InputInterface $input, OutputInterface $output)
{
$providers = $this->get_providers($input, $output);
$limit = $input->getOption('limit');
Expand All @@ -84,7 +84,7 @@ protected function execute_incoming(InputInterface $input, OutputInterface $outp
return $totals;
}

protected function execute_outgoing(InputInterface $input, OutputInterface $output)
protected function executeOutgoing(InputInterface $input, OutputInterface $output)
{
$providers = $this->get_providers($input, $output);
$limit = $input->getOption('limit');
Expand Down
4 changes: 4 additions & 0 deletions application/classes/Ushahidi/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public static function init()
$di->params['Ushahidi\Factory\ValidatorFactory']['map']['posts'] = [
'create' => $di->lazyNew('Ushahidi_Validator_Post_Create'),
'update' => $di->lazyNew('Ushahidi_Validator_Post_Create'),
'import' => $di->lazyNew('Ushahidi_Validator_Post_Create'),
];
$di->params['Ushahidi\Factory\ValidatorFactory']['map']['tags'] = [
'create' => $di->lazyNew('Ushahidi_Validator_Tag_Create'),
Expand Down Expand Up @@ -434,6 +435,9 @@ public static function init()
'repo' => $di->lazyGet('repository.post')
];

$di->set('transformer.mapping', $di->lazyNew('Ushahidi_Transformer_MappingTransformer'));
$di->set('filereader.csv', $di->lazyNew('Ushahidi_FileReader_CSV'));

/**
* 1. Load the plugins
*/
Expand Down
48 changes: 48 additions & 0 deletions application/classes/Ushahidi/FileReader/CSV.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php defined('SYSPATH') or die('No direct script access');

/**
* Ushahidi CSV File Reader
*
* @author Ushahidi Team <[email protected]>
* @package Ushahidi\Application
* @copyright 2014 Ushahidi
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3)
*/

use \ArrayIterator;
use League\Csv\Reader;
use Ushahidi\Core\Tool\FileReader;

class Ushahidi_FileReader_CSV implements FileReader
{

protected $limit;
public function setLimit($limit) {
$this->limit = $limit;
}

protected $offset;
public function setOffset($offset) {
$this->offset = $offset;
}

public function process($filename) {
// @todo inject factory function to get Reader
$reader = Reader::createFromFileObject(new SplFileObject($filename));

// Filter out empty rows
$nbColumns = count($reader->fetchOne());
$reader->addFilter(function($row) use ($nbColumns) {
return count($row) == $nbColumns;
});

if ($this->offset) {
$reader->setOffset($this->offset);
}
if ($this->limit) {
$reader->setLimit($this->limit);
}

return new ArrayIterator($reader->fetchAssoc());
}
}
3 changes: 2 additions & 1 deletion application/classes/Ushahidi/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ abstract class Ushahidi_Repository implements
Usecase\ReadRepository,
Usecase\UpdateRepository,
Usecase\DeleteRepository,
Usecase\SearchRepository
Usecase\SearchRepository,
Usecase\ImportRepository
{

use CollectionLoader;
Expand Down
47 changes: 47 additions & 0 deletions application/classes/Ushahidi/Transformer/MappingTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php defined('SYSPATH') or die('No direct script access');

/**
* Ushahidi Mapping Transformer
*
* A user defined transform, transforms records based on
* - a source-destination mapping
* - a set of fixed destination values
*
* Uses the MappingStep from ddeboer/import to process
* the transformation
*
* @author Ushahidi Team <[email protected]>
* @package Ushahidi\Application
* @copyright 2014 Ushahidi
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3)
*/

use Ushahidi\Core\Tool\MappingTransformer;
use Ddeboer\DataImport\Step\MappingStep;

class Ushahidi_Transformer_MappingTransformer implements MappingTransformer
{
protected $map;
// MappingTransformer
public function setMap(Array $map)
{
$this->map = new MappingStep($map);
}

protected $fixedValues;
// MappingTransformer
public function setFixedValues(Array $fixedValues)
{
$this->fixedValues = $fixedValues;
}

// Tranformer
public function interact(Array $data)
{
$this->map->process($data);

$data = array_merge($data, $this->fixedValues);

return $data;
}
}
2 changes: 1 addition & 1 deletion application/classes/Ushahidi/Validator/Post/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public function checkValues(Validation $validation, $attributes, $data)
}
elseif ($error = $validator->check($values))
{
$validation->error('values', $error, [$key]);
$validation->error('values', $error, [$key, $values]);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// Note: this doesn't actually implement Ushahidi\Core\Tool\Validator
abstract class Ushahidi_Validator_Post_ValueValidator
{
protected $default_error_source = 'post';


protected $config;
public function setConfig(Array $config = null)
Expand Down
16 changes: 15 additions & 1 deletion application/messages/post.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,19 @@
'exists' => 'The role you are publishing to ":value" does not exist'
],
'stageDoesNotExist' => 'Stage ":param1" does not exist',
'stageRequired' => 'Stage ":param1" is required before publishing'
'stageRequired' => 'Stage ":param1" is required before publishing',

'values' => [
'date' => ':field.:param1 must be a date, Given: :param2',
'decimal' => ':field.:param1 must be a decimal with :param2 places, Given: :param2',
'digit' => ':field.:param1 must be a digit, Given: :param2',
'email' => ':field.:param1 must be an email address, Given: :param2',
'exists' => ':field.:param1 must be a valid post id, Post id: :param2',
'max_length' => ':field.:param1 must not exceed :param2 characters long, Given: :param2',
'invalidForm' => ':field.:param1 has the wrong post type, Post id: :param2',
'numeric' => ':field.:param1 must be numeric, Given: :param2',
'scalar' => ':field.:param1 must be scalar, Given: :param2',
'point' => ':field.:param1 must be an array of lat and lon',
'url' => ':field.:param1 must be a url, Given: :param2',
]
];
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@
"ext-gd": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-mcrypt": "*"
"ext-mcrypt": "*",
"league/csv": "~7.1@dev",
"ddeboer/data-import": "dev-master",
"symfony/property-access": "~2.5"
},
"require-dev": {
"behat/behat": "~2.5.2",
Expand Down
Loading

0 comments on commit 5920050

Please sign in to comment.