Import::import()   B
last analyzed

Complexity

Conditions 9
Paths 24

Size

Total Lines 55
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 29
nc 24
nop 1
dl 0
loc 55
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Http\Controllers\GrampsXml;
4
5
use App\Models\Family;
6
use App\Models\Person;
7
use Illuminate\Http\Request;
8
use Illuminate\Routing\Controller;
9
use Illuminate\Support\Facades\Storage;
10
use Illuminate\Support\Facades\Validator;
11
12
class Import extends Controller
13
{
14
    /**
15
     * Import family tree as GRAMPS XML file
16
     * - Accepts XML file
17
     * - Validates data and shows error if there is any.
18
     */
19
    public function import(Request $request)
20
    {
21
        $request->validate([
22
            'file' => ['required', 'file', 'mimes:xml'],
23
        ]);
24
25
        // save file as temp and convert to json
26
        $res = $this->fileToJson($request);
27
28
        $fileName = $res[0];
29
        $families = $res[1]['family'];
30
31
        if (array_key_exists('husband', $families) || array_key_exists('wife', $families)) {
32
            $families = [$families];
33
        }
34
35
        $errors = [];
36
        foreach ($families as $key => $family) {
37
            // Validate family
38
            $error = $this->validateFamily($family);
39
40
            if ((is_countable($error) ? count($error) : 0) > 0) {
41
                $errors['Family-'.$key + 1] = $error;
42
                continue;
43
            }
44
45
            $description = $family['description'];
46
47
            $husband = $this->createPerson($family['husband'], null, 'M');
48
            $wife = $this->createPerson($family['wife'], null, 'F');
49
50
            $fam = Family::where('husband_id', $husband->id)->where('wife_id', $wife->id)->first();
51
52
            if (! $fam) {
53
                $fam = Family::create([
54
                    'description' => $description,
55
                    'husband_id' => $husband->id,
56
                    'wife_id' => $wife->id,
57
                ]);
58
            }
59
60
            foreach ($family['child'] as $child) {
61
                $this->createPerson($child, $fam->id);
62
            }
63
        }
64
65
        // remove temp file after importing
66
        Storage::delete('files/temp/'.$fileName);
67
68
        if ($errors !== []) {
69
            return ['errors' => $errors];
70
        }
71
72
        return json_encode([
73
            'message' => 'File imported successfully',
74
        ]);
75
    }
76
77
    protected function fileToJson($request)
78
    {
79
        $fileName = 'temp'.uniqid().'.xml';
80
81
        $request->file('file')->storeAs('/files/temp', $fileName);
82
83
        $xmlDataString = file_get_contents(storage_path('app/files/temp/'.$fileName));
84
        $xmlObject = simplexml_load_string($xmlDataString);
85
86
        $json = json_encode($xmlObject, JSON_THROW_ON_ERROR);
87
88
        return [$fileName, json_decode($json, true, 512, JSON_THROW_ON_ERROR)];
89
    }
90
91
    protected function validateFamily($family)
92
    {
93
        return Validator::make($family, [
94
            'description' => 'sometimes|string',
95
            'husband.birthday' => 'required|date',
96
            'husband.name.first_name' => 'required|string',
97
            'husband.name.last_name' => 'required|string',
98
            'wife.birthday' => 'required|date',
99
            'wife.name.first_name' => 'required|string',
100
            'wife.name.last_name' => 'required|string',
101
            'child.*.birthday' => 'required|date',
102
            'child.*.name.first_name' => 'required|string',
103
            'child.*.name.last_name' => 'required|string',
104
            'child.*.gender' => 'required|string',
105
        ])->errors();
106
    }
107
108
    protected function createPerson($arr, $parentId = null, $defaultGender = null)
109
    {
110
        $p = Person::where('givn', $arr['name']['first_name'])->where('surn', $arr['name']['last_name'])->where('birthday', $arr['birthday'].' 00:00:00')->first();
111
112
        if ($p) {
113
            if ($parentId) {
114
                $p->child_in_family_id = $parentId;
115
                $p->save();
116
            }
117
118
            return $p;
119
        }
120
121
        return Person::create([
122
            'givn' => $arr['name']['first_name'],
123
            'surn' => $arr['name']['last_name'],
124
            'sex' => $arr['gender'] ?? null ? substr((string) $arr['gender'], 0, 1) : $defaultGender,
125
            'birthday' => $arr['birthday'],
126
            'child_in_family_id' => $parentId,
127
        ]);
128
    }
129
}
130