Works up until actual import.

This commit is contained in:
James Cole
2016-07-02 23:08:47 +02:00
parent 162c762973
commit ae768a8525
12 changed files with 444 additions and 71 deletions

View File

@@ -33,6 +33,27 @@ class ImportController extends Controller
View::share('title', trans('firefly.import_data'));
}
/**
* This is the last step before the import starts.
*
* @param ImportJob $job
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws FireflyException
*/
public function complete(ImportJob $job)
{
Log::debug('Now in complete()', ['job' => $job->key]);
if (!$this->jobInCorrectStep($job, 'complete')) {
return $this->redirectToCorrectStep($job);
}
$importer = $this->makeImporter($job);
$subTitle = trans('firefy.import_complete');
$subTitleIcon = 'fa-star';
return view('import.complete', compact('job', 'subTitle', 'subTitleIcon'));
}
/**
* This is step 3.
* This is the first step in configuring the job. It can only be executed
@@ -45,7 +66,10 @@ class ImportController extends Controller
*/
public function configure(ImportJob $job)
{
Log::debug('Now at start of configure()');
if (!$this->jobInCorrectStep($job, 'configure')) {
Log::debug('Job is not in correct state for configure()', ['status' => $job->status]);
return $this->redirectToCorrectStep($job);
}
@@ -59,6 +83,35 @@ class ImportController extends Controller
return view('import.' . $job->file_type . '.configure', compact('data', 'job', 'subTitle', 'subTitleIcon'));
}
/**
* Generate a JSON file of the job's config and send it to the user.
*
* @param ImportJob $job
*
* @return mixed
*/
public function download(ImportJob $job)
{
Log::debug('Now in download()', ['job' => $job->key]);
$config = $job->configuration;
$config['column-roles-complete'] = false;
$config['column-mapping-complete'] = false;
$result = json_encode($config, JSON_PRETTY_PRINT);
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
return response($result, 200)
->header('Content-disposition', 'attachment; filename=' . $name)
->header('Content-Type', 'application/json')
->header('Content-Description', 'File Transfer')
->header('Connection', 'Keep-Alive')
->header('Expires', '0')
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', strlen($result));
}
/**
@@ -68,6 +121,7 @@ class ImportController extends Controller
*/
public function index()
{
Log::debug('Now at index');
$subTitle = trans('firefly.import_data_index');
$subTitleIcon = 'fa-home';
$importFileTypes = [];
@@ -91,9 +145,11 @@ class ImportController extends Controller
*/
public function postConfigure(Request $request, ImportJob $job)
{
Log::debug('Now in postConfigure()', ['job' => $job->key]);
if (!$this->jobInCorrectStep($job, 'process')) {
return $this->redirectToCorrectStep($job);
}
Log::debug('Continue postConfigure()', ['job' => $job->key]);
// actual code
$importer = $this->makeImporter($job);
@@ -122,6 +178,7 @@ class ImportController extends Controller
*/
public function postSettings(Request $request, ImportJob $job)
{
Log::debug('Now in postSettings()', ['job' => $job->key]);
if (!$this->jobInCorrectStep($job, 'store-settings')) {
return $this->redirectToCorrectStep($job);
}
@@ -143,29 +200,32 @@ class ImportController extends Controller
*/
public function settings(ImportJob $job)
{
Log::debug('Now in settings()', ['job' => $job->key]);
if (!$this->jobInCorrectStep($job, 'settings')) {
Log::debug('Job should not be in settings()');
return $this->redirectToCorrectStep($job);
}
Log::debug('Continue in settings()');
$importer = $this->makeImporter($job);
$subTitle = trans('firefy.settings_for_import');
$subTitleIcon = 'fa-wrench';
// now show settings screen to user.
if ($importer->requireUserSettings()) {
Log::debug('Job requires user config.');
$data = $importer->getDataForSettings();
$view = $importer->getViewForSettings();
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
}
Log::debug('Job does NOT require user config.');
$job->status = 'settings_complete';
$job->save();
// if no more settings, save job and continue to process thing.
echo 'now in settings (done)';
exit;
// actual code
return redirect(route('import.complete', [$job->key]));
// ask the importer for the requested action.
// for example pick columns or map data.
@@ -182,6 +242,7 @@ class ImportController extends Controller
*/
public function upload(ImportUploadRequest $request, ImportJobRepositoryInterface $repository)
{
Log::debug('Now in upload()');
// create import job:
$type = $request->get('import_file_type');
$job = $repository->create($type);
@@ -232,6 +293,7 @@ class ImportController extends Controller
*/
private function jobInCorrectStep(ImportJob $job, string $method): bool
{
Log::debug('Now in jobInCorrectStep()', ['job' => $job->key, 'method' => $method]);
switch ($method) {
case 'configure':
case 'process':
@@ -241,6 +303,9 @@ class ImportController extends Controller
case 'store-settings':
return $job->status === 'import_configuration_saved';
break;
case 'complete':
return $job->status === 'settings_complete';
break;
}
return false;
@@ -272,13 +337,23 @@ class ImportController extends Controller
*/
private function redirectToCorrectStep(ImportJob $job)
{
Log::debug('Now in redirectToCorrectStep()', ['job' => $job->key]);
switch ($job->status) {
case 'import_status_never_started':
Log::debug('Will redirect to configure()');
return redirect(route('import.configure', [$job->key]));
break;
case 'import_configuration_saved':
Log::debug('Will redirect to settings()');
return redirect(route('import.settings', [$job->key]));
break;
case 'settings_complete':
Log::debug('Will redirect to complete()');
return redirect(route('import.complete', [$job->key]));
break;
}
throw new FireflyException('Cannot redirect for job state ' . $job->status);

View File

@@ -229,6 +229,8 @@ Route::group(
Route::post('/import/configure/{importJob}', ['uses' => 'ImportController@postConfigure', 'as' => 'import.process_configuration']);
Route::get('/import/settings/{importJob}', ['uses' => 'ImportController@settings', 'as' => 'import.settings']);
Route::post('/import/settings/{importJob}', ['uses' => 'ImportController@postSettings', 'as' => 'import.postSettings']);
Route::get('/import/complete/{importJob}', ['uses' => 'ImportController@complete', 'as' => 'import.complete']);
Route::get('/import/download/{importJob}', ['uses' => 'ImportController@download', 'as' => 'import.download']);
/**

View File

@@ -158,13 +158,16 @@ class CsvImporter implements ImporterInterface
*/
public function requireUserSettings(): bool
{
// does the job have both a 'map' array and a 'columns' array.
$config = $this->job->configuration;
if (isset($config['map']) && isset($config['columns'])) {
return false;
}
Log::debug('doColumnMapping is ' . ($this->doColumnMapping() ? 'true' : 'false'));
Log::debug('doColumnRoles is ' . ($this->doColumnRoles() ? 'true' : 'false'));
if ($this->doColumnMapping() || $this->doColumnRoles()) {
Log::debug('Return true');
return true;
return true;
}
Log::debug('Return false');
return false;
}
/**
@@ -216,25 +219,52 @@ class CsvImporter implements ImporterInterface
*/
public function storeSettings(Request $request)
{
$config = $this->job->configuration;
$count = $config['column-count'];
$all = $request->all();
$roleSet = 0;
for ($i = 0; $i < $count; $i++) {
$selectedRole = $all['role'][$i] ?? '_ignore';
$doMapping = isset($all['map'][$i]) && $all['map'][$i] == '1' ? true : false;
if ($selectedRole == '_ignore' && $doMapping === true) {
$doMapping = false; // cannot map ignored columns.
$config = $this->job->configuration;
$all = $request->all();
if ($request->get('settings') == 'roles') {
$count = $config['column-count'];
$roleSet = 0; // how many roles have been defined
$mapSet = 0; // how many columns must be mapped
for ($i = 0; $i < $count; $i++) {
$selectedRole = $all['role'][$i] ?? '_ignore';
$doMapping = isset($all['map'][$i]) && $all['map'][$i] == '1' ? true : false;
if ($selectedRole == '_ignore' && $doMapping === true) {
$doMapping = false; // cannot map ignored columns.
}
if ($selectedRole != '_ignore') {
$roleSet++;
}
if ($doMapping === true) {
$mapSet++;
}
$config['column-roles'][$i] = $selectedRole;
$config['column-do-mapping'][$i] = $doMapping;
}
if ($selectedRole != '_ignore') {
$roleSet++;
if ($roleSet > 0) {
$config['column-roles-complete'] = true;
$this->job->configuration = $config;
$this->job->save();
}
if ($mapSet === 0) {
// skip setting of map:
$config['column-mapping-complete'] = true;
}
$config['column-roles'][$i] = $selectedRole;
$config['column-do-mapping'][$i] = $doMapping;
}
if ($roleSet > 0) {
$config['column-roles-complete'] = true;
$this->job->configuration = $config;
if ($request->get('settings') == 'map') {
foreach ($all['mapping'] as $index => $data) {
$config['column-mapping-config'][$index] = [];
foreach ($data as $value => $mapId) {
$mapId = intval($mapId);
if ($mapId !== 0) {
$config['column-mapping-config'][$index][$value] = intval($mapId);
}
}
}
// set thing to be completed.
$config['column-mapping-complete'] = true;
$this->job->configuration = $config;
$this->job->save();
}
}
@@ -260,8 +290,9 @@ class CsvImporter implements ImporterInterface
*/
private function getDataForColumnMapping(): array
{
$config = $this->job->configuration;
$data = [];
$config = $this->job->configuration;
$data = [];
$indexes = [];
foreach ($config['column-do-mapping'] as $index => $mustBeMapped) {
if ($mustBeMapped) {
@@ -271,9 +302,11 @@ class CsvImporter implements ImporterInterface
$mapperName = '\FireflyIII\Import\Mapper\\' . config('csv.import_roles.' . $column . '.mapper');
/** @var MapperInterface $mapper */
$mapper = new $mapperName;
$indexes[] = $index;
$data[$index] = [
'name' => $column,
'mapper' => $mapperName,
'index' => $index,
'options' => $mapper->getMap(),
'values' => [],
];
@@ -281,15 +314,25 @@ class CsvImporter implements ImporterInterface
}
}
// in order to actually map we also need all possible values from the CSV file.
$content = $this->job->uploadFileContents();
$reader = Reader::createFromString($content);
$results = $reader->fetch();
echo '<pre>';
var_dump($data);
var_dump($config);
exit;
foreach ($results as $row) {
//do something here
foreach ($indexes as $index) {
$value = $row[$index];
if (strlen($value) > 0) {
$data[$index]['values'][] = $row[$index];
}
}
}
foreach ($data as $index => $entry) {
$data[$index]['values'] = array_unique($data[$index]['values']);
}
return $data;
}
/**

View File

@@ -0,0 +1,46 @@
<?php
/**
* Bills.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Mapper;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
/**
* Class Bills
*
* @package FireflyIII\Import\Mapper
*/
class Bills implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$result = $repository->getBills();
$list = [];
/** @var Bill $bill */
foreach ($result as $bill) {
$list[$bill->id] = $bill->name . ' [' . $bill->match . ']';
}
asort($list);
$list = [0 => trans('csv.do_not_map')] + $list;
return $list;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Budgets.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Mapper;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
/**
* Class Budgets
*
* @package FireflyIII\Import\Mapper
*/
class Budgets implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$result = $repository->getBudgets();
$list = [];
/** @var Budget $budget */
foreach ($result as $budget) {
$list[$budget->id] = $budget->name;
}
asort($list);
$list = [0 => trans('csv.do_not_map')] + $list;
return $list;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Categories.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Mapper;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
/**
* Class Categories
*
* @package FireflyIII\Import\Mapper
*/
class Categories implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
/** @var CategoryRepositoryInterface $repository */
$repository = app(CategoryRepositoryInterface::class);
$result = $repository->getCategories();
$list = [];
/** @var Category $category */
foreach ($result as $category) {
$list[$category->id] = $category->name;
}
asort($list);
$list = [0 => trans('csv.do_not_map')] + $list;
return $list;
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
* Tags.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import\Mapper;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
/**
* Class Tags
*
* @package FireflyIII\Import\Mapper
*/
class Tags implements MapperInterface
{
/**
* @return array
*/
public function getMap(): array
{
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
$result = $repository->get();
$list = [];
/** @var Tag $tag */
foreach ($result as $tag) {
$list[$tag->id] = $tag->tag;
}
asort($list);
$list = [0 => trans('csv.do_not_map')] + $list;
return $list;
}
}