Show a form to edit block config options.

@param ServerRequestInterface $request
@param Tree                   $tree
@param UserInterface          $user

@return ResponseInterface
424596
public function treePageBlockEdit(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $block_id = (int) $request->get('block_id');
        $block    = $this->treeBlock($request, $tree, $user);
        $title    = $block->title() . ' — ' . I18N::translate('Preferences');

        return $this->viewResponse('modules/edit-block-config', [
            'block'      => $block,
            'block_id'   => $block_id,
            'cancel_url' => route('tree-page', ['ged' => $tree->name()]),
            'title'      => $title,
            'tree'       => $tree,
        ]);
    }
1164014
public function select2Place(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $page  = (int) $request->get('page');
        $query = $request->get('q', '');

        return response($this->placeSearch($tree, $page, $query, true));
    }
528126
public function messageAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $body    = $request->get('body', '');
        $subject = $request->get('subject', '');
        $to      = $request->get('to', '');
        $url     = $request->get('url', '');

        $to_user = $this->user_service->findByUserName($to);
        $ip      = $request->getClientIp() ?? '127.0.0.1';

        if ($to_user === null || $to_user->getPreference('contactmethod') === 'none') {
            throw new AccessDeniedHttpException('Invalid contact user id');
        }

        if ($body === '' || $subject === '') {
            return redirect(route('message', [
                'body'    => $body,
                'subject' => $subject,
                'to'      => $to,
                'tree'    => $tree,
                'url'     => $url,
            ]));
        }

        if ($this->deliverMessage($tree, $user, $to_user, $subject, $body, $url, $ip)) {
            FlashMessages::addMessage(I18N::translate('The message was successfully sent to %s.', e($to_user->realName())), 'success');

            $url = $url ?: route('tree-page', ['ged' => $tree->name()]);

            return redirect($url);
        }

        FlashMessages::addMessage(I18N::translate('The message was not sent.'), 'danger');

        $redirect_url = route('contact', [
            'body'    => $body,
            'subject' => $subject,
            'to'      => $to,
            'url'     => $url,
        ]);

        return redirect($redirect_url);
    }
655889
public function getChartAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        Auth::checkComponentAccess($this, 'chart', $tree, $user);

        $ajax  = (bool) $request->get('ajax');
        $scale = (int) $request->get('scale', self::SCALE_DEFAULT);
        $scale = min($scale, self::SCALE_MAX);
        $scale = max($scale, self::SCALE_MIN);

        $xrefs = $request->get('xrefs', []);

        // Find the requested individuals.
        $individuals = (new Collection($xrefs))
            ->unique()
            ->map(static function (string $xref) use ($tree): ?Individual {
                return Individual::getInstance($xref, $tree);
            })
            ->filter()
            ->filter(GedcomRecord::accessFilter());

        // Generate URLs omitting each xref.
        $remove_urls = [];

        foreach ($individuals as $exclude) {
            $xrefs_1 = $individuals
                ->filter(static function (Individual $individual) use ($exclude): bool {
                    return $individual->xref() !== $exclude->xref();
                })
                ->map(static function (Individual $individual): string {
                    return $individual->xref();
                });

            $remove_urls[$exclude->xref()] = route('module', [
                'module' => $this->name(),
                'action' => 'Chart',
                'ged'    => $tree->name(),
                'scale'  => $scale,
                'xrefs'  => $xrefs_1->all(),
            ]);
        }

        $individuals = array_map(static function (string $xref) use ($tree): ?Individual {
            return Individual::getInstance($xref, $tree);
        }, $xrefs);

        $individuals = array_filter($individuals, static function (?Individual $individual): bool {
            return $individual instanceof Individual && $individual->canShow();
        });

        if ($ajax) {
            return $this->chart($tree, $xrefs, $scale);
        }

        $ajax_url = route('module', [
            'ajax'   => true,
            'module' => $this->name(),
            'action' => 'Chart',
            'ged'    => $tree->name(),
            'scale'  => $scale,
            'xrefs'  => $xrefs,
        ]);

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

        $zoom_in_url = route('module', [
            'module' => $this->name(),
            'action' => 'Chart',
            'ged'    => $tree->name(),
            'scale'  => min(self::SCALE_MAX, $scale + (int) ($scale * 0.2 + 1)),
            'xrefs'  => $xrefs,
        ]);

        $zoom_out_url = route('module', [
            'module' => $this->name(),
            'action' => 'Chart',
            'ged'    => $tree->name(),
            'scale'  => max(self::SCALE_MIN, $scale - (int) ($scale * 0.2 + 1)),
            'xrefs'  => $xrefs,
        ]);

        return $this->viewResponse('modules/timeline-chart/page', [
            'ajax_url'     => $ajax_url,
            'individuals'  => $individuals,
            'module_name'  => $this->name(),
            'remove_urls'  => $remove_urls,
            'reset_url'    => $reset_url,
            'title'        => $this->title(),
            'scale'        => $scale,
            'zoom_in_url'  => $zoom_in_url,
            'zoom_out_url' => $zoom_out_url,
        ]);
    }
706245
public function addSpouseAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

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

        Auth::checkIndividualAccess($individual, true);

        $sex = $request->get('SEX', 'U');

        $this->glevels = $request->get('glevels', []);
        $this->tag     = $request->get('tag', []);
        $this->text    = $request->get('text', []);
        $this->islink  = $request->get('islink', []);

        $this->splitSource();
        $indi_gedcom = '0 @@ INDI';
        $indi_gedcom .= $this->addNewName($request, $tree);
        $indi_gedcom .= $this->addNewSex($request);
        if (preg_match_all('/([A-Z0-9_]+)/', $tree->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                $indi_gedcom .= $this->addNewFact($request, $tree, $match);
            }
        }
        if ((bool) $request->get('SOUR_INDI')) {
            $indi_gedcom = $this->handleUpdates($indi_gedcom);
        } else {
            $indi_gedcom = $this->updateRest($indi_gedcom);
        }

        $fam_gedcom = '';
        if (preg_match_all('/([A-Z0-9_]+)/', $tree->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                $fam_gedcom .= $this->addNewFact($request, $tree, $match);
            }
        }
        if ((bool) $request->get('SOUR_FAM')) {
            $fam_gedcom = $this->handleUpdates($fam_gedcom);
        } else {
            $fam_gedcom = $this->updateRest($fam_gedcom);
        }

        // Create the new spouse
        $spouse = $tree->createIndividual($indi_gedcom);
        // Create a new family
        if ($sex === 'F') {
            $family = $tree->createFamily("0 @@ FAM\n1 WIFE @" . $spouse->xref() . "@\n1 HUSB @" . $individual->xref() . '@' . $fam_gedcom);
        } else {
            $family = $tree->createFamily("0 @@ FAM\n1 HUSB @" . $spouse->xref() . "@\n1 WIFE @" . $individual->xref() . '@' . $fam_gedcom);
        }
        // Link the spouses to the family
        $spouse->createFact('1 FAMS @' . $family->xref() . '@', true);
        $individual->createFact('1 FAMS @' . $family->xref() . '@', true);

        if ($request->get('goto') === 'new') {
            return redirect($spouse->url());
        }

        return redirect($individual->url());
    }
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();
    }
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,
        ]);
    }
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);
    }
20277
public function postAddIndividualAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref   = $request->get('xref', '');
        $option = $request->get('option', '');

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

        if ($individual === null) {
            throw new IndividualNotFoundException();
        }

        switch ($option) {
            case 'self':
                $this->addRecordToCart($individual);
                break;

            case 'parents':
                foreach ($individual->childFamilies() as $family) {
                    $this->addFamilyAndChildrenToCart($family);
                }
                break;

            case 'spouses':
                foreach ($individual->spouseFamilies() as $family) {
                    $this->addFamilyAndChildrenToCart($family);
                }
                break;

            case 'ancestors':
                $this->addAncestorsToCart($individual);
                break;

            case 'ancestor_families':
                $this->addAncestorFamiliesToCart($individual);
                break;

            case 'descendants':
                foreach ($individual->spouseFamilies() as $family) {
                    $this->addFamilyAndDescendantsToCart($family);
                }
                break;
        }

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

        Auth::checkRecordAccess($record, true);

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

        return $this->viewResponse('edit/raw-gedcom-record', [
            'pattern' => self::GEDCOM_FACT_REGEX,
            'record'  => $record,
            'title'   => $title,
        ]);
    }
632824
public function editBlockConfiguration(Tree $tree, int $block_id): void
    {
        $default_events = implode(',', self::DEFAULT_EVENTS);

        $days      = (int) $this->getBlockSetting($block_id, 'days', self::DEFAULT_DAYS);
        $filter    = $this->getBlockSetting($block_id, 'filter', self::DEFAULT_FILTER);
        $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', self::DEFAULT_STYLE);
        $sortStyle = $this->getBlockSetting($block_id, 'sortStyle', self::DEFAULT_SORT);
        $events    = $this->getBlockSetting($block_id, 'events', $default_events);

        $event_array = explode(',', $events);

        $all_events = [];
        foreach (self::ALL_EVENTS as $event) {
            $all_events[$event] = GedcomTag::getLabel($event);
        }

        $info_styles = [
            /* I18N: An option in a list-box */
            'list'  => I18N::translate('list'),
            /* I18N: An option in a list-box */
            'table' => I18N::translate('table'),
        ];

        $sort_styles = [
            /* I18N: An option in a list-box */
            'alpha' => I18N::translate('sort by name'),
            /* I18N: An option in a list-box */
            'anniv' => I18N::translate('sort by date'),
        ];

        echo view('modules/upcoming_events/config', [
            'all_events'  => $all_events,
            'days'        => $days,
            'event_array' => $event_array,
            'filter'      => $filter,
            'infoStyle'   => $infoStyle,
            'info_styles' => $info_styles,
            'max_days'    => self::MAX_DAYS,
            'sortStyle'   => $sortStyle,
            'sort_styles' => $sort_styles,
        ]);
    }
601732
public function editNameAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

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

        Auth::checkIndividualAccess($individual, true);

        // @TODO - Move the name-specific code to this function?
        return app(EditGedcomRecordController::class)->updateFact($request, $tree);
    }
341206
public function index(ServerRequestInterface $request, UserInterface $user): ResponseInterface
    {
        $filter = $request->getQueryParams()['filter'] ?? '';

        $all_users = $this->user_service->all();

        $page_size = (int) $user->getPreference(' admin_users_page_size', '10');

        $title = I18N::translate('User administration');

        return $this->viewResponse('admin/users', [
            'all_users' => $all_users,
            'filter'    => $filter,
            'page_size' => $page_size,
            'title'     => $title,
        ]);
    }
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,
        ]);
    }
1338005
public function familyList(ServerRequestInterface $request, Tree $tree, UserInterface $user, ?ModuleListInterface $moduleListInterface): ResponseInterface
    {
        return $this->individualOrFamilyList($request, $tree, $user, true, $moduleListInterface);
    }
170041
private function treeBlock(ServerRequestInterface $request, Tree $tree, UserInterface $user): ModuleBlockInterface
    {
        $block_id = (int) $request->get('block_id');

        $block = DB::table('block')
            ->where('block_id', '=', $block_id)
            ->where('gedcom_id', '=', $tree->id())
            ->whereNull('user_id')
            ->first();

        if ($block === null) {
            throw new NotFoundHttpException();
        }

        $module = $this->module_service->findByName($block->module_name);

        if (!$module instanceof ModuleBlockInterface) {
            throw new NotFoundHttpException();
        }

        if ($block->user_id !== $user->id() && !Auth::isAdmin()) {
            throw new AccessDeniedHttpException();
        }

        return $module;
    }
515415
public function rejectChanges(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $xref = $request->get('xref', '');

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

        Auth::checkRecordAccess($record);

        if (Auth::isModerator($tree)) {
            DB::table('change')
                ->where('gedcom_id', '=', $record->tree()->id())
                ->where('xref', '=', $record->xref())
                ->where('status', '=', 'pending')
                ->update(['status' => 'rejected']);

            /* I18N: %s is the name of an individual, source or other record */
            FlashMessages::addMessage(I18N::translate('The changes to “%s” have been rejected.', $record->fullName()));
        }

        return response();
    }