Your IP : 216.73.217.78


Current Path : /home/seto/indexator.pm/src/Import/
Upload File :
Current File : /home/seto/indexator.pm/src/Import/ImportService.php.bak-20260722-183427

<?php

namespace App\Import;

use App\Core\Database;
use App\Core\Request;
use App\Urls\UrlNormalizer;
use App\Urls\UrlRepository;
use App\Urls\UrlValidator;

class ImportService
{
    private UrlValidator  $validator;
    private UrlNormalizer $normalizer;
    private UrlRepository $urlRepo;

    public function __construct(private Database $db)
    {
        $this->validator  = new UrlValidator();
        $this->normalizer = new UrlNormalizer();
        $this->urlRepo    = new UrlRepository($db);
    }

    /**
     * Import URLs into a project from the given source.
     *
     * @return array{imported: int, duplicates: int, invalid: int}
     * @throws \RuntimeException on sitemap fetch / file read failure
     */
    public function import(int $projectId, string $sourceType, Request $request): array
    {
        $rawUrls    = $this->extractRaw($sourceType, $request);
        $sourceType = in_array($sourceType, ['manual', 'file', 'sitemap'], true)
            ? $sourceType : 'manual';

        return $this->processAndInsert($projectId, $rawUrls, $sourceType);
    }

    // ── Private ──────────────────────────────────────────────────────────────

    private function extractRaw(string $sourceType, Request $request): array
    {
        return match($sourceType) {
            'file'    => $this->fromFile($request),
            'sitemap' => $this->fromSitemap($request),
            default   => $this->fromManual($request),
        };
    }

    private function fromManual(Request $request): array
    {
        $text = (string) $request->post('urls_manual', '');
        return (new ManualImporter())->parse($text);
    }

    private function fromFile(Request $request): array
    {
        $file = $request->file('urls_file');

        if (!$file) {
            return [];
        }

        return (new FileImporter())->parse($file);
    }

    private function fromSitemap(Request $request): array
    {
        $sitemapUrl = trim((string) $request->post('sitemap_url', ''));

        if ($sitemapUrl === '') {
            return [];
        }

        $config   = $GLOBALS['config'];
        $importer = new SitemapImporter($config);
        return $importer->fetch($sitemapUrl);
    }

    private function processAndInsert(int $projectId, array $rawUrls, string $sourceType): array
    {
        $report = ['imported' => 0, 'duplicates' => 0, 'invalid' => 0];

        if (empty($rawUrls)) {
            return $report;
        }

        // Deduplicate raw input first
        $seen    = [];
        $toInsert = [];

        foreach ($rawUrls as $raw) {
            $raw = trim($raw);

            if (!$this->validator->isValid($raw)) {
                $report['invalid']++;
                continue;
            }

            $normalized = $this->normalizer->normalize($raw);

            if (isset($seen[$normalized])) {
                $report['duplicates']++;
                continue;
            }

            $seen[$normalized]  = true;
            $toInsert[]         = ['url' => $raw, 'normalized_url' => $normalized];
        }

        // Count how many already exist in DB (will be ignored by INSERT OR IGNORE)
        $beforeCount = $this->urlRepo->countByProject($projectId);
        $this->urlRepo->bulkInsert($projectId, $toInsert, $sourceType);
        $afterCount  = $this->urlRepo->countByProject($projectId);

        $inserted            = $afterCount - $beforeCount;
        $dbDuplicates        = count($toInsert) - $inserted;

        $report['imported']   = $inserted;
        $report['duplicates'] += $dbDuplicates;

        return $report;
    }
}