@param ServerRequestInterface $request
@param Tree                   $tree

@return ResponseInterface
481558
public function getAddNoteAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $note = Note::getInstance($xref, $tree);

        if ($note === null) {
            throw new NoteNotFoundException();
        }

        $options = $this->noteOptions($note);

        $title = I18N::translate('Add %s to the clippings cart', $note->fullName());

        return $this->viewResponse('modules/clippings/add-options', [
            'options' => $options,
            'default' => key($options),
            'record'  => $note,
            'title'   => $title,
            'tree'    => $tree,
        ]);
    }
1304069
public function addSpouse(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $individual = Individual::getInstance($xref, $tree);

        Auth::checkIndividualAccess($individual, true);

        if ($individual->sex() === 'F') {
            $title  = $individual->fullName() . ' - ' . I18N::translate('Add a husband');
            $famtag = 'HUSB';
            $gender = 'M';
        } else {
            $title  = $individual->fullName() . ' - ' . I18N::translate('Add a wife');
            $famtag = 'WIFE';
            $gender = 'F';
        }

        return $this->viewResponse('edit/new-individual', [
            'tree'       => $tree,
            'title'      => $title,
            'nextaction' => 'add_spouse_to_individual_action',
            'individual' => $individual,
            'family'     => null,
            'name_fact'  => null,
            'famtag'     => $famtag,
            'gender'     => $gender,
        ]);
    }
478158
public function place(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $query = $request->get('query', '');
        $data  = [];

        foreach ($this->search_service->searchPlaces($tree, $query) as $place) {
            $data[] = ['value' => $place->gedcomName()];
        }

        if (empty($data) && $tree->getPreference('GEONAMES_ACCOUNT')) {
            // No place found? Use an external gazetteer
            $url =
                'http://api.geonames.org/searchJSON' .
                '?name_startsWith=' . urlencode($query) .
                '&lang=' . WT_LOCALE .
                '&fcode=CMTY&fcode=ADM4&fcode=PPL&fcode=PPLA&fcode=PPLC' .
                '&style=full' .
                '&username=' . $tree->getPreference('GEONAMES_ACCOUNT');

            // try to use curl when file_get_contents not allowed
            if (ini_get('allow_url_fopen')) {
                $json = file_get_contents($url);
            } elseif (function_exists('curl_init')) {
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                $json = curl_exec($ch);
                curl_close($ch);
            } else {
                return response([]);
            }

            $places = json_decode($json, true);
            if (isset($places['geonames']) && is_array($places['geonames'])) {
                foreach ($places['geonames'] as $k => $place) {
                    $data[] = ['value' => $place['name'] . ', ' . $place['adminName2'] . ', ' . $place['adminName1'] . ', ' . $place['countryName']];
                }
            }
        }

        return response($data);
    }
1275685
public function getDescendantsAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $individual = Individual::getInstance($xref, $tree);

        if ($individual !== null && $individual->canShow()) {
            $html = $this->loadSpouses($individual, 1);
        } else {
            $html = '';
        }

        return response($html);
    }
920485
public function addMediaFile(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref  = $request->get('xref', '');
        $media = Media::getInstance($xref, $tree);

        try {
            Auth::checkMediaAccess($media);
        } catch (Exception $ex) {
            return response(view('modals/error', [
                'title' => I18N::translate('Add a media file'),
                'error' => $ex->getMessage(),
            ]));
        }

        return response(view('modals/add-media-file', [
            'max_upload_size' => $this->maxUploadFilesize(),
            'media'           => $media,
            'media_types'     => $this->mediaTypes(),
            'unused_files'    => $this->unusedFiles($tree),
        ]));
    }
515619
public function updateNoteObject(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $note = Note::getInstance($xref, $tree);

        Auth::checkNoteAccess($note, true);

        $NOTE = $request->get('NOTE');

        // "\" and "$" are signficant in replacement strings, so escape them.
        $NOTE = str_replace([
            '\\',
            '$',
        ], [
            '\\\\',
            '\\$',
        ], $NOTE);

        $gedrec = preg_replace(
            '/^0 @' . $note->xref() . '@ NOTE.*(\n1 CONT.*)*/',
            '0 @' . $note->xref() . '@ NOTE ' . preg_replace("/\r?\n/", "\n1 CONT ", $NOTE),
            $note->gedcom()
        );

        $note->updateRecord($gedrec, true);

        return redirect($note->url());
    }
686375
public function mediaList(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        //route is assumed to be 'module'
        $module = $request->get('module');
        $action = $request->get('action');
        
        $formats = GedcomTag::getFileFormTypes();

        $action2   = $request->get('action2');
        $page      = (int) $request->get('page');
        $max       = (int) $request->get('max', 20);
        $folder    = $request->get('folder', '');
        $filter    = $request->get('filter', '');
        $subdirs   = $request->get('subdirs', '');
        $form_type = $request->get('form_type', '');

        $folders = $this->allFolders($tree);

        if ($action2 === '1') {
            $media_objects = $this->allMedia(
                $tree,
                $folder,
                $subdirs === '1' ? 'include' : 'exclude',
                'title',
                $filter,
                $form_type
            );
        } else {
            $media_objects = [];
        }

        // Pagination
        $count = count($media_objects);
        $pages = (int) (($count + $max - 1) / $max);
        $page  = max(min($page, $pages), 1);

        $media_objects = array_slice($media_objects, ($page - 1) * $max, $max);

        return $this->viewResponse('media-list-page', [
            'count'         => $count,
            'filter'        => $filter,
            'folder'        => $folder,
            'folders'       => $folders,
            'formats'       => $formats,
            'form_type'     => $form_type,
            'max'           => $max,
            'media_objects' => $media_objects,
            'page'          => $page,
            'pages'         => $pages,
            'subdirs'       => $subdirs,
            'title'         => I18N::translate('Media'),
            'module'        => $module,
            'action'        => $action,
        ]);
    }
850581
public function rejectChange(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $url       = $request->get('url', '');
        $xref      = $request->get('xref', '');
        $change_id = (int) $request->get('change_id');

        // Reject a change, and subsequent changes to the same record
        DB::table('change')
            ->where('gedcom_id', '=', $tree->id())
            ->where('xref', '=', $xref)
            ->where('change_id', '>=', $change_id)
            ->where('status', '=', 'pending')
            ->update(['status' => 'rejected']);

        return redirect(route('show-pending', [
            'ged' => $tree->name(),
            'url' => $url,
        ]));
    }
760238
public function page(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $query = $request->get('query', '');
        $xref  = $request->get('extra', '');

        $source = Source::getInstance($xref, $tree);

        Auth::checkSourceAccess($source);

        $regex_query = preg_quote(strtr($query, [' ' => '.+']), '/');

        // Fetch all records with a link to this source
        $individuals = DB::table('individuals')
            ->join('link', static function (JoinClause $join): void {
                $join
                    ->on('l_file', '=', 'i_file')
                    ->on('l_from', '=', 'i_id');
            })
            ->where('i_file', '=', $tree->id())
            ->where('l_to', '=', $xref)
            ->where('l_type', '=', 'SOUR')
            ->distinct()
            ->select(['individuals.*'])
            ->get()
            ->map(Individual::rowMapper())
            ->filter(GedcomRecord::accessFilter());

        $families = DB::table('families')
            ->join('link', static function (JoinClause $join): void {
                $join
                    ->on('l_file', '=', 'f_file')
                    ->on('l_from', '=', 'f_id')
                    ->where('l_type', '=', 'SOUR');
            })
            ->where('f_file', '=', $tree->id())
            ->where('l_to', '=', $xref)
            ->where('l_type', '=', 'SOUR')
            ->distinct()
            ->select(['families.*'])
            ->get()
            ->map(Family::rowMapper())
            ->filter(GedcomRecord::accessFilter());

        $pages = [];

        foreach ($individuals->merge($families) as $record) {
            if (preg_match_all('/\n1 SOUR @' . $xref . '@(?:\n[2-9].*)*\n2 PAGE (.*' . $regex_query . '.*)/i', $record->gedcom(), $matches)) {
                $pages = array_merge($pages, $matches[1]);
            }

            if (preg_match_all('/\n2 SOUR @' . $xref . '@(?:\n[3-9].*)*\n3 PAGE (.*' . $regex_query . '.*)/i', $record->gedcom(), $matches)) {
                $pages = array_merge($pages, $matches[1]);
            }
        }

        $pages = array_unique($pages);

        $pages = array_map(static function (string $page): array {
            return ['value' => $page];
        }, $pages);

        return response($pages);
    }
809973
public function acceptChanges(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $record = GedcomRecord::getInstance($xref, $tree);

        Auth::checkRecordAccess($record, false);

        if ($record && Auth::isModerator($tree)) {
            if ($record->isPendingDeletion()) {
                /* I18N: %s is the name of a genealogy record */
                FlashMessages::addMessage(I18N::translate('“%s” has been deleted.', $record->fullName()));
            } else {
                /* I18N: %s is the name of a genealogy record */
                FlashMessages::addMessage(I18N::translate('The changes to “%s” have been accepted.', $record->fullName()));
            }
            FunctionsImport::acceptAllChanges($record->xref(), $record->tree());
        }

        return response();
    }
1060392
public function postRemoveAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

        $cart = Session::get('cart', []);
        unset($cart[$tree->name()][$xref]);
        Session::put('cart', $cart);

        $url = route('module', [
            'module' => $this->name(),
            'action' => 'Show',
            'ged'    => $tree->name(),
        ]);

        return redirect($url);
    }
565146
public function show(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref   = $request->get('xref', '');
        $record = GedcomRecord::getInstance($xref, $tree);

        Auth::checkRecordAccess($record);

        if ($this->hasCustomPage($record)) {
            return redirect($record->url());
        }

        return $this->viewResponse('gedcom-record-page', [
            'facts'         => $record->facts(),
            'families'      => $record->linkedFamilies($record::RECORD_TYPE),
            'individuals'   => $record->linkedIndividuals($record::RECORD_TYPE),
            'meta_robots'   => 'index,follow',
            'notes'         => $record->linkedNotes($record::RECORD_TYPE),
            'media_objects' => $record->linkedMedia($record::RECORD_TYPE),
            'record'        => $record,
            'sources'       => $record->linkedSources($record::RECORD_TYPE),
            'title'         => $record->fullName(),
        ]);
    }
714388
public function editRawFact(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref    = $request->get('xref', '');
        $fact_id = $request->get('fact_id');
        $record  = GedcomRecord::getInstance($xref, $tree);

        Auth::checkRecordAccess($record, true);

        $title = I18N::translate('Edit the raw GEDCOM') . ' - ' . $record->fullName();

        foreach ($record->facts() as $fact) {
            if (!$fact->isPendingDeletion() && $fact->id() === $fact_id) {
                return $this->viewResponse('edit/raw-gedcom-fact', [
                    'pattern' => self::GEDCOM_FACT_REGEX,
                    'fact'    => $fact,
                    'title'   => $title,
                ]);
            }
        }

        return redirect($record->url());
    }
507086
public function getListAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        Auth::checkComponentAccess($this, 'list', $tree, $user);
      
        $listController = new BranchesController(app(ModuleService::class));
        return $listController->list($request, $tree, $user);
    }
1185385
public function getAdminEditAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $this->layout = 'layouts/administration';

        $block_id = (int) $request->get('block_id');

        if ($block_id === 0) {
            // Creating a new faq
            $header  = '';
            $faqbody = '';

            $block_order = 1 + (int) DB::table('block')
                    ->where('module_name', '=', $this->name())
                    ->max('block_order');

            $languages = [];

            $title = I18N::translate('Add an FAQ');
        } else {
            // Editing an existing faq
            $header  = $this->getBlockSetting($block_id, 'header');
            $faqbody = $this->getBlockSetting($block_id, 'faqbody');

            $block_order = DB::table('block')
                ->where('block_id', '=', $block_id)
                ->value('block_order');

            $languages = explode(',', $this->getBlockSetting($block_id, 'languages'));

            $title = I18N::translate('Edit the FAQ');
        }

        $tree_names = ['' => I18N::translate('All')] + Tree::getIdList();

        return $this->viewResponse('modules/faq/edit', [
            'block_id'    => $block_id,
            'block_order' => $block_order,
            'header'      => $header,
            'faqbody'     => $faqbody,
            'languages'   => $languages,
            'title'       => $title,
            'tree'        => $tree,
            'tree_names'  => $tree_names,
        ]);
    }
319332
public function postAddFamilyAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref   = $request->get('xref', '');
        $option = $request->get('option', '');

        $family = Family::getInstance($xref, $tree);

        if ($family === null) {
            throw new FamilyNotFoundException();
        }

        switch ($option) {
            case 'parents':
                $this->addFamilyToCart($family);
                break;

            case 'members':
                $this->addFamilyAndChildrenToCart($family);
                break;

            case 'descendants':
                $this->addFamilyAndDescendantsToCart($family);
                break;
        }

        return redirect($family->url());
    }
1348354
public function treePageBlockUpdate(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $block    = $this->treeBlock($request, $tree, $user);
        $block_id = (int) $request->get('block_id');

        $block->saveBlockConfiguration($request, $block_id);

        return redirect(route('tree-page', ['ged' => $tree->name()]));
    }