Commit 0b57f9b0 authored by Jack Stupple's avatar Jack Stupple
Browse files

import resource categories and resources

parent daee56fd
Loading
Loading
Loading
Loading
+170 −0
Original line number Diff line number Diff line
<?php

namespace App\Console\Commands;

use App\Language;
use App\Resource;
use App\ResourceCategory;
use Illuminate\Console\Command;

/**
 * Class ImportResources
 * @package App\Console\Commands
 * @see https://laravel.com/docs/5.6/artisan
 */
class ImportResourceCategories extends Command
{

    protected $signature = 'import:resource-categories {csv_file_name}';
    protected $description = 'Import resource categories into the API via a CSV file.';

    protected $csv_file_name = null;
    protected $csv_file_pathinfo = [];

    protected $csv_headers = null;
    protected $csv_data = [];

    protected static $required_headers = [
        'resource category',
        'resource category parent'
    ];

    protected static $cached_categories = [];

    public function handle()
    {
        ini_set('auto_detect_line_endings', true);

        $this->csv_file_name = $this->argument('csv_file_name');

        try {
            // exception will be thrown if file is invalid
            $this->csv_file_pathinfo = $this->checkFileProperties($this->csv_file_name);
        } catch (\Exception $exception) {
            $this->output->writeln("<error>Error encountered:</error> {$exception->getMessage()}");
            return false;
        }

        list($this->csv_headers, $this->csv_data) = $this->getFileData($this->csv_file_name);
        $this->checkHeaders($this->csv_headers); // throws exception if fails

        // we now have the resources list
        foreach ($this->csv_data as $csv_row_number => $_category) {
            $resource_category = ResourceCategory::firstOrCreate([
                'name' => $_category['resource category'],
                'parent_category' => $_category['resource category parent']
            ]);

            if (!$resource_category->exists()) {
                $resource_category->save();
            }
        }
    }

    protected function checkHeaders($csv_headers)
    {
        foreach (static::$required_headers as $required_header) {
            if (in_array($required_header, $csv_headers) === false) {
                throw new \Exception ("Missing required header in CSV: {$required_header}");
            }
        }
    }

    protected function getFileData($csv_file_name)
    {
        $file_handle = fopen($csv_file_name, 'r');
        $csv_headers = null;
        $csv_data = [];

        $row_number = 0;
        $empty_rows = 0; // if 3 empty rows are encountered we just break the loop- assumed end of data
        while (($csv_row = fgetcsv($file_handle)) !== false) {
            $row_number++; // the header is also a row in the CSV

            if ($csv_headers === null) {
                $_csv_headers = [];

                foreach ($csv_row as $header) {
                    $_csv_headers[] = trim(strtolower($header));
                }

                $csv_headers = $_csv_headers;

                unset($_csv_headers);
                continue;
            }

            // skip empty rows
            if (array_filter(array_unique($csv_row)) === []) {
                $empty_rows++;

                if ($empty_rows >= 3) {
                    // assume we have reached the end of the data
                    $this->output->writeln("<comment>Assumed end of data:</comment> {$row_number}");
                    break;
                } else {
                    $this->output->writeln("<comment>Skip empty row:</comment> {$row_number}");
                    continue;
                }
            }

            $_csv_data = [];
            foreach ($csv_headers as $header_index => $header) {
                $_csv_data[$header] = trim($csv_row[$header_index]); // we trim to ensure no additional spaces

                // ensure the data is expected - primarily for the URL's
                $validation_method = camel_case('validate ' . $header);
                if (method_exists($this, $validation_method) && !empty($_csv_data[$header])) {
                    if (!$this->$validation_method($_csv_data[$header])) {
                        throw new \Exception("Issue with {$header} on row: {$row_number}");
                    }
                }
            }

            $csv_data[$row_number] = $_csv_data; // add the row to the data with same row number as that in the CSV
            unset($_csv_data);
        }

        return [$csv_headers, $csv_data];
    }

    protected function checkFileProperties($csv_file_name)
    {
        if (file_exists($csv_file_name) === false) {
            throw new \Exception('File does not exist');
        }

        $csv_file_pathinfo = pathinfo($csv_file_name);
        // extension is only defined if one is provided, eg /etc/hosts will have no extension
        if (!isset($csv_file_pathinfo['extension']) || $csv_file_pathinfo['extension'] !== 'csv') {
            throw new \Exception('File is not CSV');
        }

        return $csv_file_pathinfo;
    }

    protected function validateUkAsset($uk_asset)
    {
        return $this->validateUrl($uk_asset);
    }

    protected function validateFrAsset($asset)
    {
        return $this->validateUrl($asset);
    }

    protected function validateDeAsset($asset)
    {
        return $this->validateUrl($asset);
    }

    protected function validateNoAsset($asset)
    {
        return $this->validateUrl($asset);
    }

    protected function validateUrl($asset)
    {
        return filter_var($asset, FILTER_VALIDATE_URL);
    }
}
 No newline at end of file
+25 −26
Original line number Diff line number Diff line
@@ -56,29 +56,29 @@ class ImportResources extends Command

        // we now have the resources list
        foreach ($this->csv_data as $csv_row_number => $_resource) {
            $language = null;
            $resource_link = null;

            // add here cases for the different kinds of resources we are importing
            if (!empty($_resource['uk asset'])) {
                $language = $this->getLanguageFor('uk');
                $resource_link = $_resource['uk asset'];
            } else if (!empty($_resource['nl asset'])) {
                $language = $this->getLanguageFor('nl');
                $resource_link = $_resource['nl asset'];
            } else if (!empty($_resource['de asset'])) {
                $language = $this->getLanguageFor('de');
                $resource_link = $_resource['de asset'];
            } else if (!empty($_resource['no asset'])) {
                $language = $this->getLanguageFor('no');
                $resource_link = $_resource['no asset'];
            } else if (!empty($_resource['sl asset'])) {
                $language = $this->getLanguageFor('sl');
                $resource_link = $_resource['sl asset'];
            } else {
                $this->output->writeln("<comment>Could not determine language</comment> {$csv_row_number}");
                continue;
            }
            $language = $this->getLanguageFor($_resource['language']);
            $resource_link = $_resource['url'];

//            // add here cases for the different kinds of resources we are importing
//            if (!empty($_resource['uk asset'])) {
//                $language = $this->getLanguageFor('uk');
//                $resource_link = $_resource['uk asset'];
//            } else if (!empty($_resource['nl asset'])) {
//                $language = $this->getLanguageFor('nl');
//                $resource_link = $_resource['nl asset'];
//            } else if (!empty($_resource['de asset'])) {
//                $language = $this->getLanguageFor('de');
//                $resource_link = $_resource['de asset'];
//            } else if (!empty($_resource['no asset'])) {
//                $language = $this->getLanguageFor('no');
//                $resource_link = $_resource['no asset'];
//            } else if (!empty($_resource['sl asset'])) {
//                $language = $this->getLanguageFor('sl');
//                $resource_link = $_resource['sl asset'];
//            } else {
//                $this->output->writeln("<comment>Could not determine language</comment> {$csv_row_number}");
//                continue;
//            }

            // check for duplicates
            if ($this->isDuplicateResource($language->id, $resource_link)) {
@@ -100,15 +100,14 @@ class ImportResources extends Command
        }
    }

    protected function getResourceCategory($category, $parent_category)
    protected function getResourceCategory($category)
    {
        if (isset(static::$cached_categories[$category])) {
            return static::$cached_categories[$category];
        }

        $resource_category = ResourceCategory::firstOrCreate([
            'name' => $category,
            'parent_category' => $parent_category
            'name' => $category
        ]);

        if (!$resource_category->exists()) {
+2 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace App\Console;

use App\Console\Commands\AddCurrency;
use App\Console\Commands\ImportResourceCategories;
use App\Console\Commands\ImportResources;
use App\Console\Commands\Make\MakeAdminUser;
use Illuminate\Console\Scheduling\Schedule;
@@ -17,6 +18,7 @@ class Kernel extends ConsoleKernel
     */
    protected $commands = [
        ImportResources::class,
        ImportResourceCategories::class,
        AddCurrency::class,
        MakeAdminUser::class
    ];
+4 −0
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@ class ImportEmilyQuestions extends CharacterMigration
     */
    public function up()
    {
        if (!\App\ResourceCategory::count()) {
            throw new \Exception('Import resources first.');
        }

        $this->created_at = date('Y-m-d H:i:s');

        $this->character = new \App\Character();
+4 −2
Original line number Diff line number Diff line
@@ -187,9 +187,11 @@ class CharacterMigration extends Migration
                foreach ($_answer['resource_categories'] as $_resource_category) {
                    $category = \App\ResourceCategory::where('name', 'LIKE', $_resource_category)->first();

                    if ($category) {
                        $answer->resourceCategories()->syncWithoutDetaching($category);
                    if (!$category) {
                        throw new \Exception('Resource category not found: ' . $_resource_category);
                    }

                    $answer->resourceCategories()->syncWithoutDetaching($category);
                }
            }
        }
Loading