xref: /webtrees/app/Http/RequestHandlers/SynchronizeTrees.php (revision e93a8df2f8d797005750082cc3766c0e80799688)
16fd01894SGreg Roach<?php
26fd01894SGreg Roach
36fd01894SGreg Roach/**
46fd01894SGreg Roach * webtrees: online genealogy
5*d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
66fd01894SGreg Roach * This program is free software: you can redistribute it and/or modify
76fd01894SGreg Roach * it under the terms of the GNU General Public License as published by
86fd01894SGreg Roach * the Free Software Foundation, either version 3 of the License, or
96fd01894SGreg Roach * (at your option) any later version.
106fd01894SGreg Roach * This program is distributed in the hope that it will be useful,
116fd01894SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
126fd01894SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
136fd01894SGreg Roach * GNU General Public License for more details.
146fd01894SGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
166fd01894SGreg Roach */
176fd01894SGreg Roach
186fd01894SGreg Roachdeclare(strict_types=1);
196fd01894SGreg Roach
206fd01894SGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
216fd01894SGreg Roach
226fd01894SGreg Roachuse Fig\Http\Message\StatusCodeInterface;
236fd01894SGreg Roachuse Fisharebest\Webtrees\FlashMessages;
246fd01894SGreg Roachuse Fisharebest\Webtrees\I18N;
256b9cb339SGreg Roachuse Fisharebest\Webtrees\Registry;
266fd01894SGreg Roachuse Fisharebest\Webtrees\Services\AdminService;
276fd01894SGreg Roachuse Fisharebest\Webtrees\Services\TimeoutService;
286fd01894SGreg Roachuse Fisharebest\Webtrees\Services\TreeService;
2900c45d23SGreg Roachuse League\Flysystem\FilesystemException;
3000c45d23SGreg Roachuse League\Flysystem\UnableToReadFile;
3100c45d23SGreg Roachuse League\Flysystem\UnableToRetrieveMetadata;
326fd01894SGreg Roachuse Psr\Http\Message\ResponseInterface;
336fd01894SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
346fd01894SGreg Roachuse Psr\Http\Message\StreamFactoryInterface;
356fd01894SGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
366fd01894SGreg Roach
376fd01894SGreg Roachuse function redirect;
386fd01894SGreg Roachuse function route;
396fd01894SGreg Roach
406fd01894SGreg Roach/**
416fd01894SGreg Roach * Synchronize GEDCOM files with trees.
426fd01894SGreg Roach */
436fd01894SGreg Roachclass SynchronizeTrees implements RequestHandlerInterface
446fd01894SGreg Roach{
45c4943cffSGreg Roach    private AdminService $admin_service;
466fd01894SGreg Roach
47b55cbc6bSGreg Roach    private StreamFactoryInterface $stream_factory;
48b55cbc6bSGreg Roach
49c4943cffSGreg Roach    private TimeoutService $timeout_service;
506fd01894SGreg Roach
51c4943cffSGreg Roach    private TreeService $tree_service;
526fd01894SGreg Roach
536fd01894SGreg Roach    /**
546fd01894SGreg Roach     * @param AdminService        $admin_service
55b55cbc6bSGreg Roach     * @param StreamFactoryInterface $stream_factory
566fd01894SGreg Roach     * @param TimeoutService      $timeout_service
576fd01894SGreg Roach     * @param TreeService         $tree_service
586fd01894SGreg Roach     */
596fd01894SGreg Roach    public function __construct(
606fd01894SGreg Roach        AdminService $admin_service,
61b55cbc6bSGreg Roach        StreamFactoryInterface $stream_factory,
626fd01894SGreg Roach        TimeoutService $timeout_service,
636fd01894SGreg Roach        TreeService $tree_service
646fd01894SGreg Roach    ) {
656fd01894SGreg Roach        $this->admin_service   = $admin_service;
66b55cbc6bSGreg Roach        $this->stream_factory  = $stream_factory;
676fd01894SGreg Roach        $this->timeout_service = $timeout_service;
686fd01894SGreg Roach        $this->tree_service    = $tree_service;
696fd01894SGreg Roach    }
706fd01894SGreg Roach
716fd01894SGreg Roach    /**
726fd01894SGreg Roach     * @param ServerRequestInterface $request
736fd01894SGreg Roach     *
746fd01894SGreg Roach     * @return ResponseInterface
756fd01894SGreg Roach     */
766fd01894SGreg Roach    public function handle(ServerRequestInterface $request): ResponseInterface
776fd01894SGreg Roach    {
786b9cb339SGreg Roach        $data_filesystem = Registry::filesystem()->data();
796fd01894SGreg Roach
806fd01894SGreg Roach        $gedcom_files = $this->admin_service->gedcomFiles($data_filesystem);
816fd01894SGreg Roach
826fd01894SGreg Roach        foreach ($gedcom_files as $gedcom_file) {
836fd01894SGreg Roach            // Only import files that have changed
84f0448b68SGreg Roach            try {
85f7cf8a15SGreg Roach                $filemtime = (string) $data_filesystem->lastModified($gedcom_file);
866fd01894SGreg Roach
876fd01894SGreg Roach                $tree = $this->tree_service->all()->get($gedcom_file) ?? $this->tree_service->create($gedcom_file, $gedcom_file);
886fd01894SGreg Roach
896fd01894SGreg Roach                if ($tree->getPreference('filemtime') !== $filemtime) {
906fd01894SGreg Roach                    $resource = $data_filesystem->readStream($gedcom_file);
91b55cbc6bSGreg Roach                    $stream   = $this->stream_factory->createStreamFromResource($resource);
921c6adce8SGreg Roach                    $this->tree_service->importGedcomFile($tree, $stream, $gedcom_file, '');
936fd01894SGreg Roach                    $stream->close();
946fd01894SGreg Roach                    $tree->setPreference('filemtime', $filemtime);
956fd01894SGreg Roach
966fd01894SGreg Roach                    FlashMessages::addMessage(I18N::translate('The GEDCOM file “%s” has been imported.', e($gedcom_file)), 'success');
976fd01894SGreg Roach
986fd01894SGreg Roach                    if ($this->timeout_service->isTimeNearlyUp(10.0)) {
999991924fSGreg Roach                        return redirect(route(self::class), StatusCodeInterface::STATUS_TEMPORARY_REDIRECT);
1006fd01894SGreg Roach                    }
1016fd01894SGreg Roach                }
10228d026adSGreg Roach            } catch (FilesystemException | UnableToRetrieveMetadata | UnableToReadFile) {
103f0448b68SGreg Roach                // Can't read the file - skip it.
104f0448b68SGreg Roach            }
1056fd01894SGreg Roach        }
1066fd01894SGreg Roach
1076fd01894SGreg Roach        foreach ($this->tree_service->all() as $tree) {
1086fd01894SGreg Roach            if (!$gedcom_files->containsStrict($tree->name())) {
1096fd01894SGreg Roach                $this->tree_service->delete($tree);
1106fd01894SGreg Roach                FlashMessages::addMessage(I18N::translate('The family tree “%s” has been deleted.', e($tree->title())), 'success');
1116fd01894SGreg Roach
1126fd01894SGreg Roach                if ($this->timeout_service->isTimeNearlyUp(10.0)) {
1139991924fSGreg Roach                    return redirect(route(self::class), StatusCodeInterface::STATUS_TEMPORARY_REDIRECT);
1146fd01894SGreg Roach                }
1156fd01894SGreg Roach            }
1166fd01894SGreg Roach        }
1176fd01894SGreg Roach
1186fd01894SGreg Roach        return redirect(route(ManageTrees::class, ['tree' => $this->tree_service->all()->first()->name()]));
1196fd01894SGreg Roach    }
1206fd01894SGreg Roach}
121