HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/ivs.kaunokolegija.lt/laravel/app/Imports/ScientistsSheetOneImport.php
<?php

namespace App\Imports;

use Carbon\Carbon;
use App\Models\Publisher;
use App\Models\Scientist;
use App\Models\InstProject;
use App\Models\ProjectType;
use App\Models\ScienceArea;
use App\Models\ResearchField;
use App\Models\ExpertActivity;
use App\Models\WorkExperience;
use App\Models\ResearcherGroup;
use App\Models\ScienceDirection;
use App\Models\StudyPublication;
use App\Models\IntScienceProject;
use App\Models\NatScienceProject;
use App\Models\ResearcherSubGroup;
use Illuminate\Support\Collection;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use Maatwebsite\Excel\Concerns\ToCollection;

class ScientistsSheetOneImport implements ToCollection
{
    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function collection(Collection $rows)
    {
        // Optionally, skip the header row if needed.
        foreach ($rows->skip(3) as $row) {
            // Assume:
            // Scientist
            // $row[1] = name
            // $row[2] = ???
            // $row[3] = email

            // Research Fields /research-fields
            // $row[4] = science-areas /science-areas
            // $row[5] = science-directions /science-directions
            // $row[6] = title
            // $row[7] = input_time

            // Researcher Groups
            // $row[8] = title

            // Researcher Sub Groups
            // $row[9] = title

            // /work-experiences Work Experiences
            // $row[10] = period_from period_to
            // $row[11] = institution
            // $row[12] = position

            // $row[13] = ???

            // Expert activities /expert-activities
            // $row[14] = activity_type option from (App\Models\ExpertActivity::ACTIVITY_TYPE_SELECT )
            // $row[15] = ???
            // $row[16] = period_from period_to
            // $row[17] = institution
            // $row[18] = position

            // Int Science Projects /int-science-projects
            // $row[19] = period_from period_to
            // $row[20] = title
            // $row[21] = number
            // $row[22] = budget
            // $row[23] = leader
            // Truksta leaded_participated pasirinkimo

            // Nat Science Projects /nat-science-projects
            // $row[24] = period_from period_to
            // $row[25] = title
            // $row[26] = number
            // $row[27] = budget
            // $row[28] = leader
            // Truksta leaded_participated pasirinkimo

            // Inst Projects /inst-projects
            // $row[29] = period_from period_to
            // $row[30] = to project_type_id create from /project-types
            // $row[31] = title
            // $row[32] = number
            // $row[33] = budget
            // $row[34] = leader
            // add leaded_participated always value leaded

            // Study Publications /study-publications
            // $row[35] = year
            // $row[36] = /science-direction find or create
            // $row[37] = title
            // $row[38] = input_time
            // $row[39] = authorship_field
            // $row[40] = page_count
            // $row[41] = /publishers firstorcreate
            // $row[42] = isbn
            // $row[43] = doi

            
            // Use updateOrCreate to create or update scientist
            if (empty($row[1])) {
                continue;
            }

            $scientist = Scientist::updateOrCreate(
                [
                    'name' => trim($row[1]),
                ],
                [
                    'email' => $row[2] ?? null,
                    'phone' => $row[3] ?? null,
                ]
            );
            // dd($row);
            $this->syncResearchFields($scientist, $row);
            $this->syncResearcherGroups($scientist, $row);
            $this->syncResearcherSubGroups($scientist, $row);
            $this->syncWorkExperiences($scientist, $row);
            $this->syncExpertActivities($scientist, $row);
            $this->syncIntScienceProjects($scientist, $row); //leaded_participated ka naudoti?
            $this->syncNatScienceProjects($scientist, $row); //leaded_participated ka naudoti?
            $this->syncInstProjects($scientist, $row);
            $this->syncStudyPublications($scientist, $row);
        }
    }

    protected function syncResearchFields(Scientist $scientist, $row)
    {
        // dd($row[2], $row[6], $row[7]);

        $researchTitle = trim($row[6] ?? '');
        $inputTime = trim($row[7] ?? '');

        if (empty($researchTitle) || empty($inputTime)) {
            return;
        }
        
        $researchField = ResearchField::updateOrCreate(
            [
                'title' => $researchTitle,
            ],
            [
                'input_time' => $inputTime,
            ]
        );

        $areaNames = array_filter(array_map('trim', explode(',', $row[4] ?? '')));
        foreach ($areaNames as $areaName) {
            if (!empty($areaName)) {
                $scienceArea = ScienceArea::firstOrCreate(['name' => $areaName]);
                $researchField->science_areas()->syncWithoutDetaching($scienceArea->id);
            }
        }

        $directionNames = array_filter(array_map('trim', explode(',', $row[5] ?? '')));
        foreach ($directionNames as $directionName) {
            if (!empty($directionName)) {
                $scienceDirection = ScienceDirection::firstOrCreate(['name' => $directionName]);
                $researchField->science_directions()->syncWithoutDetaching($scienceDirection->id);
            }
        }

        $scientist->scientistResearchFields()->syncWithoutDetaching($researchField->id);
    }

    protected function syncResearcherGroups(Scientist $scientist, $row)
    {
        $groupTitles = array_filter(array_map('trim', explode(',', $row[8] ?? '')));

        if (empty($groupTitles)) {
            return;
        }

        foreach ($groupTitles as $groupTitle) {
            $researcherGroup = ResearcherGroup::firstOrCreate([
                'title' => $groupTitle,
            ]);

            $scientist->groups()->syncWithoutDetaching($researcherGroup->id);
        }
    }

    protected function syncResearcherSubGroups(Scientist $scientist, $row)
    {
        $subGroupTitles = array_filter(array_map('trim', explode(',', $row[9] ?? '')));

        if (empty($subGroupTitles)) {
            return;
        }

        foreach ($subGroupTitles as $subGroupTitle) {
            $researcherSubGroup = ResearcherSubGroup::firstOrCreate([
                'title' => $subGroupTitle,
            ]);

            $scientist->subgroups()->syncWithoutDetaching($researcherSubGroup->id);
        }
    }

    protected function syncWorkExperiences(Scientist $scientist, $row)
    {
        $periodCell  = trim($row[10] ?? '');
        $institution = trim($row[11] ?? '');
        $position    = trim($row[12] ?? '');
    
        if (empty($periodCell) || empty($institution)) {
            return;
        }
    
        $periodParts = preg_split('/\s+/', $periodCell);
        if (count($periodParts) < 1) {
            return;
        }
    
        $period_from = $periodParts[0];
        $period_to   = isset($periodParts[1]) ? $periodParts[1] : null;

        if (empty($period_from)) {
            return;
        } elseif (is_numeric($period_from)) {
            $period_from = Date::excelToDateTimeObject($period_from)->format('Y-m-d');
        }
    
        $workExperience = WorkExperience::updateOrCreate(
            [
                'institution' => $institution,
                'period_from' => $period_from,
            ],
            [
                'position' => $position,
                'period_to'   => $period_to,
            ]
        );
    
        $scientist->scientistWorkExperiences()->syncWithoutDetaching($workExperience->id);
    }
    
    protected function syncExpertActivities(Scientist $scientist, $row)
    {
        $activityType = null;
    
        $row14 = trim($row[14] ?? '');
        $row15 = trim($row[15] ?? '');
        
        $positiveValues = ['taip', '+'];
        
        if (!empty($row14) && in_array(strtolower($row14), array_map('strtolower', $positiveValues))) {
            $activityType = 'courses';
        } elseif (!empty($row15) && in_array(strtolower($row15), array_map('strtolower', $positiveValues))) {
            $activityType = 'memership';
        }  

        if (empty($activityType)) {
            return;
        }

        $period = trim($row[16] ?? '');
        $institution = trim($row[17] ?? '');
        $position = trim($row[18] ?? '');

        if (empty($period) || empty($institution) || empty($position)) {
            return;
        }

        $periodParts = preg_split('/\s+/', $period);
        if (count($periodParts) < 1) {
            return;
        }

        $period_from = trim($periodParts[0] ?? '');
        $period_to = trim(isset($periodParts[1]) ? $periodParts[1] : null ?? '');

        if (empty($period_from)) {
            return;
        } elseif (is_numeric($period_from)) {
            $period_from = Date::excelToDateTimeObject($period_from)->format('Y-m-d');
        }

        $expertActivity = ExpertActivity::updateOrCreate(
            [
                'activity_type' => $activityType,
                'institution'   => $institution,
                'position'      => $position,
            ],
            [
                'period_from'   => $period_from,
                'period_to'     => $period_to,
            ]
        );

        $scientist->scientistExpertActivities()->syncWithoutDetaching($expertActivity->id);
    }

    protected function syncIntScienceProjects(Scientist $scientist, $row)
    {
        // $row[19] = period, $row[20] = title, $row[21] = number, $row[22] = budget, $row[23] = leader
        $period = trim($row[19] ?? '');
        $title = trim($row[20] ?? '');
        $number = trim($row[21] ?? '');
        $budget = trim($row[22] ?? '');
        $leader = trim($row[23] ?? '');

        if (empty($period) || empty($title)) {
            return;
        }

        $periodParts = explode(' ', $period);
        $period_from = trim($periodParts[0] ?? '');
        $period_to = trim(isset($periodParts[1]) ? $periodParts[1] : null ?? '');

        if (empty($period_from)) {
            return;
        } elseif (is_numeric($period_from)) {
            $period_from = Date::excelToDateTimeObject($period_from)->format('Y-m-d');
        }
        $leadedParticipated = $scientist->name == $leader || empty($leader) ? 'leaded' : 'participated';

        $intScienceProject = IntScienceProject::updateOrCreate(
            [
                'number' => $number,
            ],
            [
                'period_from'         => $period_from,
                'period_to'           => $period_to,
                'budget'              => $budget,
                'leader'              => $leader,
                'title'               => $title,
                'leaded_participated' => $leadedParticipated
            ]
        );

        $scientist->scientistIntScienceProjects()->syncWithoutDetaching($intScienceProject->id);
    }

    protected function syncNatScienceProjects(Scientist $scientist, $row)
    {
        // $row[24] = period, $row[25] = title, $row[26] = number, $row[27] = budget, $row[28] = leader
        $period = trim($row[24] ?? '');
        $title = trim($row[25] ?? '');
        $number = trim($row[26] ?? '');
        $budget = trim($row[27] ?? '');
        $leader = trim($row[28] ?? '');

        if (empty($period) || empty($title)) {
            return;
        }

        $periodParts = explode(' ', $period);
        $period_from = trim($periodParts[0] ?? '');
        $period_to = trim($periodParts[1] ?? '');

        if (empty($period_from)) {
            return;
        } elseif (is_numeric($period_from)) {
            $period_from = Date::excelToDateTimeObject($period_from)->format('Y-m-d');
        }

        $leadedParticipated = $scientist->name == $leader || empty($leader) ? 'leaded' : 'participated';

        $natScienceProject = NatScienceProject::updateOrCreate(
            [
                'number'      => $number,
            ],
            [
                'title'        => $title,
                'period_from' => $period_from,
                'period_to'   => $period_to,
                'budget'      => $budget,
                'leader'      => $leader,
                'leaded_participated' => $leadedParticipated,
            ]
        );

        $scientist->scientistNatScienceProjects()->syncWithoutDetaching($natScienceProject->id);
    }

    protected function syncInstProjects(Scientist $scientist, $row)
    {
        // $row[29] = period, $row[30] = project type, $row[31] = title, $row[32] = number, $row[33] = budget, $row[34] = leader
        $period = trim($row[29] ?? '');
        $projectTypeName = trim($row[30] ?? '');
        $title = trim($row[31] ?? '');
        $number = trim($row[32] ?? '');
        $budget = trim($row[33] ?? '');
        $leader = trim($row[34] ?? '');

        if (empty($period) || empty($projectTypeName) || empty($title)) {
            return;
        }

        $periodParts = explode(' ', $period);
        $period_from = trim($periodParts[0] ?? '');
        $period_to = trim($periodParts[1] ?? '');

        if (empty($period_from)) {
            return;
        } elseif (is_numeric($period_from)) {
            $period_from = Date::excelToDateTimeObject($period_from)->format('Y-m-d');
        }

        // Create or find the project type
        $projectType = ProjectType::firstOrCreate([
            'name' => $projectTypeName,
        ]);

        $leadedParticipated = $scientist->name == $leader || empty($leader) ? 'leaded' : 'participated';

        $instProject = InstProject::updateOrCreate(
            [
                'number'       => $number,
            ],
            [
                'title'               => $title,
                'period_from'         => $period_from,
                'period_to'           => $period_to,
                'project_type_id'     => $projectType->id,
                'budget'              => $budget,
                'leader'              => $leader,
                'leaded_participated' => $leadedParticipated,          
            ]
        );

        $scientist->scientistInstProjects()->syncWithoutDetaching($instProject->id);
        
    }

    protected function syncStudyPublications(Scientist $scientist, $row)
    {
        // $row[35] = year, $row[36] = science-direction, $row[37] = title,
        // $row[38] = input_time, $row[39] = authorship_field, $row[40] = page_count,
        // $row[41] = publisher, $row[42] = isbn, $row[43] = doi
        $yearRaw = trim($row[35] ?? '');
        $scienceDirectionName = trim($row[36] ?? '');
        $title = trim($row[37] ?? '');
        $inputTime = trim($row[38] ?? '');
        $authorshipField = trim($row[39] ?? '');
        $pageCount = trim($row[40] ?? '');
        $publisherName = trim($row[41] ?? '');
        $isbn = trim($row[42] ?? '');
        $doi = trim($row[43] ?? '');

        if (empty($yearRaw) || empty($title) || empty($inputTime)) {
            return;
        }

        $scienceDirection = ScienceDirection::firstOrCreate([
            'name' => $scienceDirectionName,
        ]);

        $publisher = Publisher::firstOrCreate([
            'name' => $publisherName,
        ]);    


        if (is_numeric($yearRaw)) {
            $year = Date::excelToDateTimeObject($yearRaw)->format('Y-m-d');
        } else {
            $year = Carbon::parse($yearRaw)->toDateString();
        }

        $studyPublication = StudyPublication::updateOrCreate(
            [
                'isbn'                => $isbn,
            ],
            [
                'year'                => Carbon::parse($year)->toDateString(),
                'title'               => $title,
                'input_time'          => $inputTime,
                'authorship_field'    => $authorshipField,
                'page_count'          => $pageCount,
                'doi'                 => $doi,
                'publisher_id'        => $publisher->id,
            ]
        );

        $studyPublication->science_directions()->syncWithoutDetaching($scienceDirection->id);
        $scientist->scientistStudyPublications()->syncWithoutDetaching($studyPublication->id);   
    }

/**
 * Attempts to match the given input to a valid activity type key.
 *
 * @param string $input The raw activity type value from the Excel file.
 * @return string|null  Returns the matched key from ACTIVITY_TYPE_SELECT or null if none found.
 */
    // protected function matchActivityType(string $input, $validTypes)
    // {
    //     $inputLower = strtolower($input);

    //     $bestMatch   = null;
    //     $minDistance = PHP_INT_MAX;

    //     foreach ($validTypes as $key => $value) {
    //         // Calculate the Levenshtein distance between the input and the current key.
    //         $distance = levenshtein($inputLower, strtolower($key));

    //         // Check if this is an exact match.
    //         if ($distance === 0) {
    //             return $key;
    //         }

    //         // If this distance is smaller than any we've seen so far, record it.
    //         if ($distance < $minDistance) {
    //             $minDistance = $distance;
    //             $bestMatch = $key;
    //         }
    //     }

    //     // Optional: set a threshold to avoid matching completely off values.
    //     // For example, if the distance is too high, consider no match.
    //     $threshold = 3; // Adjust this threshold as needed.
    //     if ($minDistance > $threshold) {
    //         return null;
    //     }

    //     return $bestMatch;
    // }


}