Perform an update

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

@return ResponseInterface
331349
public function postAdminAction(ServerRequestInterface $request, UserInterface $user, Tree $tree = null): ResponseInterface
    {
        // We need a tree to work with.
        if ($tree === null) {
            throw new NotFoundHttpException();
        }

        // Admins only.
        if (!Auth::isAdmin($user)) {
            throw new AccessDeniedHttpException();
        }

        $plugin = $request->get('plugin', '');
        $update = $request->get('update', '');
        $xref   = $request->getParsedBody()['xref'] ?? '';

        $plugins = $this->getPluginList();
        $plugin  = $plugins[$plugin] ?? null;

        if ($plugin === null) {
            throw new NotFoundHttpException();
        }
        $plugin->getOptions($request);

        $all_data = $this->allData($plugin, $tree);

        $parameters = $request->getParsedBody();
        unset($parameters['csrf']);
        unset($parameters['update']);

        switch ($update) {
            case 'one':
                $record = $this->getRecord($all_data[$xref], $tree);
                if ($plugin->doesRecordNeedUpdate($record)) {
                    $new_gedcom = $plugin->updateRecord($record);
                    $record->updateRecord($new_gedcom, false);
                }

                $parameters['xref'] = $this->findNextXref($plugin, $xref, $all_data, $tree);
                break;

            case 'all':
                foreach ($all_data as $xref => $value) {
                    $record = $this->getRecord($value, $tree);
                    if ($plugin->doesRecordNeedUpdate($record)) {
                        $new_gedcom = $plugin->updateRecord($record);
                        $record->updateRecord($new_gedcom, false);
                    }
                }
                $parameters['xref'] = '';
                break;
        }

        $url = route('module', $parameters);

        return redirect($url);
    }
583611
public function edit(Tree $tree, UserInterface $user): ResponseInterface
    {
        $my_individual_record = Individual::getInstance($tree->getUserPreference(Auth::user(), 'gedcomid'), $tree);
        $contact_methods      = FunctionsEdit::optionsContactMethods();
        $default_individual   = Individual::getInstance($tree->getUserPreference(Auth::user(), 'rootid'), $tree);
        $installed_languages  = FunctionsEdit::optionsInstalledLanguages();
        $show_delete_option   = !$user->getPreference('canadmin');
        $themes               = $this->themeOptions();
        $timezone_ids         = DateTimeZone::listIdentifiers();
        $timezones            = array_combine($timezone_ids, $timezone_ids);
        $title                = I18N::translate('My account');

        return $this->viewResponse('edit-account-page', [
            'contact_methods'      => $contact_methods,
            'default_individual'   => $default_individual,
            'installed_languages'  => $installed_languages,
            'my_individual_record' => $my_individual_record,
            'show_delete_option'   => $show_delete_option,
            'themes'               => $themes,
            'timezones'            => $timezones,
            'title'                => $title,
            'user'                 => $user,
        ]);
    }
416766
public function getListAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        Auth::checkComponentAccess($this, 'list', $tree, $user);
      
        $listController = new ListController(app(IndividualListService::class), app(LocalizationService::class));
        return $listController->individualList($request, $tree, $user, $this);
    }
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,
        ]);
    }
1363642
public function update($id, UpdateUserRequest $request)
    {
        $this->user->updatewithRoles($request->all(), $request->roles, $id);

        flash(trans('core::messages.resource.resource updated', ['name' => trans('user::users.title.user')]));

        return redirect()->route('backend::user.user.index');
    }
491786
public function editName(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $fact_id = $request->get('fact_id', '');
        $xref    = $request->get('xref', '');

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

        Auth::checkIndividualAccess($individual, true);

        // Find the fact to edit
        foreach ($individual->facts() as $fact) {
            if ($fact->id() === $fact_id && $fact->canEdit()) {
                return $this->viewResponse('edit/new-individual', [
                    'tree'       => $tree,
                    'title'      => I18N::translate('Edit the name'),
                    'nextaction' => 'update',
                    'individual' => $individual,
                    'family'     => null,
                    'name_fact'  => $fact,
                    'famtag'     => '',
                    'gender'     => $individual->sex(),
                ]);
            }
        }

        throw new NotFoundHttpException();
    }
1221120
public function getChartAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $ajax       = (bool) ($request->getQueryParams()['ajax'] ?? false);
        $xref       = $request->getQueryParams()['xref'] ?? '';
        $individual = Individual::getInstance($xref, $tree);

        Auth::checkIndividualAccess($individual);
        Auth::checkComponentAccess($this, 'chart', $tree, $user);

        $show_spouse = (bool) ($request->getQueryParams()['show_spouse'] ?? false);
        $generations = (int) ($request->getQueryParams()['generations'] ?? self::DEFAULT_GENERATIONS);
        $generations = min($generations, self::MAXIMUM_GENERATIONS);
        $generations = max($generations, self::MINIMUM_GENERATIONS);

        // Generations of ancestors/descendants in each mini-tree.
        $book_size = (int) ($request->getQueryParams()['book_size'] ?? 2);
        $book_size = min($book_size, 5);
        $book_size = max($book_size, 2);

        if ($ajax) {
            return $this->chart($individual, $generations, $book_size, $show_spouse);
        }

        $ajax_url = $this->chartUrl($individual, [
            'ajax'        => true,
            'book_size'   => $book_size,
            'generations' => $generations,
            'show_spouse' => $show_spouse,
        ]);

        return $this->viewResponse('modules/family-book-chart/page', [
            'ajax_url'            => $ajax_url,
            'book_size'           => $book_size,
            'generations'         => $generations,
            'individual'          => $individual,
            'maximum_generations' => self::MAXIMUM_GENERATIONS,
            'minimum_generations' => self::MINIMUM_GENERATIONS,
            'module_name'         => $this->name(),
            'show_spouse'         => $show_spouse,
            'title'               => $this->chartTitle($individual),
        ]);
    }
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()]));
    }
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);
    }
691124
public function getChartAction(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $xref = $request->get('xref', '');

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

        Auth::checkIndividualAccess($individual);
        Auth::checkComponentAccess($this, 'chart', $tree, $user);

        $tv = new TreeView('tv');

        [$html, $js] = $tv->drawViewport($individual, 4);

        return $this->viewResponse('interactive-tree-page', [
            'html'       => $html,
            'individual' => $individual,
            'js'         => $js,
            'title'      => $this->chartTitle($individual),
            'tree'       => $tree,
        ]);
    }
815552
public function replaceAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $search  = $request->get('search', '');
        $replace = $request->get('replace', '');
        $context = $request->get('context', '');

        switch ($context) {
            case 'all':
                $records = $this->search_service->searchIndividuals([$tree], [$search]);
                $count   = $this->replaceRecords($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s individual has been updated.', '%s individuals have been updated.', $count, I18N::number($count)));

                $records = $this->search_service->searchFamilies([$tree], [$search]);
                $count   = $this->replaceRecords($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s family has been updated.', '%s families have been updated.', $count, I18N::number($count)));

                $records = $this->search_service->searchRepositories([$tree], [$search]);
                $count   = $this->replaceRecords($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s repository has been updated.', '%s repositories have been updated.', $count, I18N::number($count)));

                $records = $this->search_service->searchSources([$tree], [$search]);
                $count   = $this->replaceRecords($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s source has been updated.', '%s sources have been updated.', $count, I18N::number($count)));

                $records = $this->search_service->searchNotes([$tree], [$search]);
                $count   = $this->replaceRecords($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s note has been updated.', '%s notes have been updated.', $count, I18N::number($count)));
                break;

            case 'name':
                $adv_name_tags = preg_split("/[\s,;: ]+/", $tree->getPreference('ADVANCED_NAME_FACTS'));
                $name_tags     = array_unique(array_merge([
                    'NAME',
                    'NPFX',
                    'GIVN',
                    'SPFX',
                    'SURN',
                    'NSFX',
                    '_MARNM',
                    '_AKA',
                ], $adv_name_tags));

                $records = $this->search_service->searchIndividuals([$tree], [$search]);
                $count   = $this->replaceIndividualNames($records, $search, $replace, $name_tags);
                FlashMessages::addMessage(I18N::plural('%s individual has been updated.', '%s individuals have been updated.', $count, I18N::number($count)));
                break;

            case 'place':
                $records = $this->search_service->searchIndividuals([$tree], [$search]);
                $count   = $this->replacePlaces($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s individual has been updated.', '%s individuals have been updated.', $count, I18N::number($count)));

                $records = $this->search_service->searchFamilies([$tree], [$search]);
                $count   = $this->replacePlaces($records, $search, $replace);
                FlashMessages::addMessage(I18N::plural('%s family has been updated.', '%s families have been updated.', $count, I18N::number($count)));
                break;
        }

        $url = route('search-replace', [
            'search'  => $search,
            'replace' => $replace,
            'context' => $context,
            'ged'     => $tree->name(),
        ]);

        return redirect($url);
    }
758483
public function acceptAllChanges(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $url = $request->get('url', '');

        $changes = DB::table('change')
            ->where('gedcom_id', '=', $tree->id())
            ->where('status', '=', 'pending')
            ->orderBy('change_id')
            ->get();

        foreach ($changes as $change) {
            if (empty($change->new_gedcom)) {
                // delete
                FunctionsImport::updateRecord($change->old_gedcom, $tree, true);
            } else {
                // add/update
                FunctionsImport::updateRecord($change->new_gedcom, $tree, false);
            }

            DB::table('change')
                ->where('change_id', '=', $change->change_id)
                ->update(['status' => 'accepted']);

            Log::addEditLog('Accepted change ' . $change->change_id . ' for ' . $change->xref . ' / ' . $tree->name(), $tree);
        }

        return redirect(route('show-pending', [
            'ged' => $tree->name(),
            'url' => $url,
        ]));
    }
477864
public function update(UserRequest $request, User $user)
    {
        $user->update($request->all());

        return $this->makeRedirect(true, 'admin.users.index', __('update'));
    }
883295
public function tab(ServerRequestInterface $request, Tree $tree, UserInterface $user): ResponseInterface
    {
        $xref        = $request->get('xref', '');
        $record      = Individual::getInstance($xref, $tree);
        $module_name = $request->get('module');
        $module      = $this->module_service->findByName($module_name);

        Auth::checkIndividualAccess($record);
        Auth::checkComponentAccess($module, 'tab', $tree, $user);

        $layout = view('layouts/ajax', [
            'content' => $module->getTabContent($record),
        ]);

        return response($layout);
    }
610844
public function save(Request $request, UserInterface $user)
    {
        $eid = $request->get('eid');
        $language = $request->get('language');
        $tid = $request->get('tid');
        $teaserId = $request->get('teaser_id');
        $isPublish = $request->get('isPublish');
        $values = $request->get('values');
        $publishComment = $request->get('publishComment');

        if ($values) {
            $values = json_decode($values, true);
        }

        $element = $this->elementService->findElement($eid);
        $elementtype = $this->elementService->findElementtype($element);
        $elementtypeStructure = $elementtype->getStructure();

        $oldElementVersion = $this->elementService->findLatestElementVersion($element);
        $oldElementStructure = $this->elementService->findElementStructure($oldElementVersion, 'de');
        $oldVersion = $oldElementVersion->getVersion();
        $isMaster = $element->getMasterLanguage() === $language;

        $tree = $this->treeManager->getByNodeId($tid);
        $node = $tree->get($tid);

        $teaser = null;
        if ($teaserId) {
            $teaser = $this->teaserManager->find($teaserId);
        }

        $comment = null;
        if ($request->get('comment')) {
            $comment = $request->get('comment');
        }

        if ($language === $element->getMasterLanguage()) {
            $elementStructure = new ElementStructure();
            if ($oldElementStructure->getDataId()) {
                $elementStructure
                    ->setDataId($oldElementStructure->getDataId())
                    ->setDsId($oldElementStructure->getDsId())
                    ->setType('root')
                    ->setName($oldElementStructure->getName());
            } else {
                $elementStructure
                    ->setDataId(UuidUtil::generate())
                    ->setDsId($elementtypeStructure->getRootDsId())
                    ->setType('root')
                    ->setName($elementtypeStructure->getRootNode()->getName());
            }
            $map = $this->applyStructure($elementStructure, $elementtypeStructure, $values, $language, $oldElementStructure);
            $this->applyOldValues($elementStructure, $oldElementStructure, $elementtypeStructure, $language);
            $this->applyValues($elementStructure, $elementtypeStructure, $values, $language, $map, null);
        } else {
            $elementStructure = clone $oldElementStructure;
            $this->applyValues($elementStructure, $elementtypeStructure, $values, $language, null, $element->getMasterLanguage());
        }

        $elementStructure->setId(null);

        $rii = new \RecursiveIteratorIterator($elementStructure->getIterator(), \RecursiveIteratorIterator::SELF_FIRST);
        foreach ($rii as $structure) {
            /* @var $structure ElementStructure */
            $structure->setId(null);
        }

        $elementVersion = $this->elementService->createElementVersion($element, $elementStructure, $language, $user->getId(), $comment);

        if ($teaser) {
            $this->saveTeaserData($teaser, $language, $request);
        } else {
            $this->saveNodeData($node, $language, $request);
        }

        // TODO: available languages
        $this->saveMeta($elementVersion, $language, $isMaster, ['de'], $request);

        $event = new SaveElementEvent($element, $language, $oldVersion);
        $this->eventDispatcher->dispatch(ElementEvents::SAVE_ELEMENT, $event);

        $publishSlaves = [];
        if ($isPublish) {
            $publishSlaves = $this->checkPublishSlaves($elementVersion, $node, $teaser, $language);
            if ($teaser) {
                $this->publishTeaser($elementVersion, $teaser, $language, $user->getId(), $publishComment, $publishSlaves);
            } else {
                $this->publishTreeNode($elementVersion, $node, $language, $user->getId(), $publishComment, $publishSlaves);
            }
        }

        $status = '';
        if ($teaser) {
            if ($this->teaserManager->isPublished($teaser, $language)) {
                $status = $this->teaserManager->isAsync($teaser, $language) ? 'async' : 'online';
            }
        } else {
            if ($tree->isPublished($node, $language)) {
                $status = $tree->isAsync($node, $language) ? 'async' : 'online';
            }
        }

        return [$elementVersion, $node, $teaser, $publishSlaves, $status];
    }
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());
    }
279588
public function postDeleteMessageAction(ServerRequestInterface $request, Tree $tree): ResponseInterface
    {
        $message_ids = (array) $request->get('message_id', []);

        DB::table('message')
            ->where('user_id', '=', Auth::id())
            ->whereIn('message_id', $message_ids)
            ->delete();

        if ($request->get('ctype') === 'user') {
            $url = route('user-page', ['ged' => $tree->name()]);
        } else {
            $url = route('tree-page', ['ged' => $tree->name()]);
        }

        return redirect($url);
    }