Get a list of initial surname letters.

@param bool   $marnm if set, include married names
@param bool   $fams  if set, only consider individuals with FAMS records
@param string $locale
@param string $collation

@return int[]
327563
public function surnameAlpha(bool $marnm, bool $fams, string $locale, string $collation): array
    {
        $n_surn = $this->fieldWithCollation('n_surn', $collation);
        $alphas = [];

        $query = DB::table('name')->where('n_file', '=', $this->tree->id());

        $this->whereFamily($fams, $query);
        $this->whereMarriedName($marnm, $query);

        // Fetch all the letters in our alphabet, whether or not there
        // are any names beginning with that letter. It looks better to
        // show the full alphabet, rather than omitting rare letters such as X.
        foreach ($this->localization_service->alphabet() as $letter) {
            $query2 = clone $query;

            $this->whereInitial($query2, 'n_surn', $letter, $locale, $collation);

            $alphas[$letter] = $query2->count();
        }

        // Now fetch initial letters that are not in our alphabet,
        // including "@" (for "@N.N.") and "" for no surname.
        $query2 = clone $query;
        foreach ($this->localization_service->alphabet() as $n => $letter) {
            $query2->where($n_surn, 'NOT LIKE', $letter . '%');
        }

        $rows = $query2
            ->select([DB::raw('SUBSTR(n_surn, 1, 1) AS initial'), DB::raw('COUNT(*) AS count')])
            ->groupBy('initial')
            ->orderBy(DB::raw("CASE initial WHEN '' THEN 1 ELSE 0 END"))
            ->orderBy(DB::raw("CASE initial WHEN '@' THEN 1 ELSE 0 END"))
            ->orderBy('initial')
            ->pluck('count', 'initial');

        foreach ($rows as $alpha => $count) {
            $alphas[$alpha] = (int) $count;
        }

        $count_no_surname = $query->where('n_surn', '=', '')->count();

        if ($count_no_surname !== 0) {
            // Special code to indicate "no surname"
            $alphas[','] = $count_no_surname;
        }

        return $alphas;
    }
1042424
protected function getForeignKeysMigrations($new = [], $old = [])
    {
        if (empty($new['tables'])) {
            return [];
        }
        $output = [];
        foreach ($new['tables'] as $tableId => $newTable) {
            if ($newTable['table']['table_name'] === $this->options['default_migration_table']) {
                continue;
            }
            $oldTable = $old['tables'][$tableId];

            if (!empty($oldTable['foreign_keys'])) {
                foreach ($oldTable['foreign_keys'] as $fkName => $fkData) {
                    if (!isset($newTable['foreign_keys'][$fkName])) {
                        $output[] = $this->getForeignKeyRemove($tableId, $fkName);
                    }
                }
            }
            if (!empty($newTable['foreign_keys'])) {
                foreach ($newTable['foreign_keys'] as $fkName => $fkData) {
                    if (!isset($oldTable['foreign_keys'][$fkName])) {
                        $output[] = $this->getForeignKeyCreate($tableId, $fkName);
                    }
                }
            }
        }

        return $output;
    }
801993
public function getColumnForeignKeys($column)
    {
        $matches = [];
        foreach ($this->foreignKeys as $fk) {
            if (in_array($column, $fk->getLocalColumns())) {
                $matches[] = $fk;
            }
        }

        return $matches;
    }
692798
function languageNameListFromLocaleList( $localeList )
    {
        $languageList = array();
        foreach( $localeList as $locale )
            $languageList[] = $this->languageNameFromLocale( $locale );

        return $languageList;
    }
45799
protected function getNameForLocale($locale, &$names)
    {
        if (isset($names[$locale][1])) {
            $name = $names[$locale][1];
            unset($names[$locale][1]);
        } elseif (isset($names[$locale][4])) {
            $name = $names[$locale][4];
            unset($names[$locale][4]);
        } else {
            $name = array_shift($names[$locale]);
        }

        return $name;
    }
134699
private function topSurnames(int $number_of_surnames, int $threshold): array
    {
        // Use the count of base surnames.
        $top_surnames = DB::table('name')
            ->where('n_file', '=', $this->tree->id())
            ->where('n_type', '<>', '_MARNM')
            ->whereNotIn('n_surn', ['', '@N.N.'])
            ->select('n_surn')
            ->groupBy('n_surn')
            ->orderByRaw('count(n_surn) desc')
            ->take($number_of_surnames)
            ->get()
            ->pluck('n_surn')
            ->all();

        $surnames = [];
        foreach ($top_surnames as $top_surname) {
            $variants = DB::table('name')
                ->where('n_file', '=', $this->tree->id())
                ->where(DB::raw('n_surn /* COLLATE ' . I18N::collation() . ' */'), '=', $top_surname)
                ->select('n_surn', DB::raw('COUNT(*) AS count'))
                ->groupBy('n_surn')
                ->get()
                ->pluck('count', 'n_surn')
                ->all();

            if (array_sum($variants) > $threshold) {
                $surnames[$top_surname] = $variants;
            }
        }

        return $surnames;
    }
989521
public function getColumns($bWithoutForeignKey = true, $bAliased = true, $bPrefixed = false)
    {
        $aColumns = $this->columns;

        if ($bWithoutForeignKey) {
            $aColumns = $this->removeForeignKeyColumns($aColumns);
        }

        if ($bAliased) {
            $aColumns = $this->aliaseColumns($aColumns, $this->getAlias());
        }

        if ($bPrefixed) {
            $aColumns = $this->prefixeColumns($aColumns, $this->getAlias());
        }

        return $aColumns;
    }
1227597
public function searchFamilyNames(array $trees, array $search, int $offset = 0, int $limit = PHP_INT_MAX): Collection
    {
        $query = DB::table('families')
            ->leftJoin('name AS husb_name', static function (JoinClause $join): void {
                $join
                    ->on('husb_name.n_file', '=', 'families.f_file')
                    ->on('husb_name.n_id', '=', 'families.f_husb')
                    ->where('husb_name.n_type', '<>', '_MARNM');
            })
            ->leftJoin('name AS wife_name', static function (JoinClause $join): void {
                $join
                    ->on('wife_name.n_file', '=', 'families.f_file')
                    ->on('wife_name.n_id', '=', 'families.f_wife')
                    ->where('wife_name.n_type', '<>', '_MARNM');
            });

        $prefix = DB::connection()->getTablePrefix();
        $field  = DB::raw('COALESCE(' . $prefix . "husb_name.n_full, '') || COALESCE(" . $prefix . "wife_name.n_full, '')");

        $this->whereTrees($query, 'f_file', $trees);
        $this->whereSearch($query, $field, $search);

        $query
            ->orderBy('husb_name.n_sort')
            ->orderBy('wife_name.n_sort')
            ->select(['families.*', 'husb_name.n_sort', 'wife_name.n_sort'])
            ->distinct();

        return $this->paginateQuery($query, Family::rowMapper(), GedcomRecord::accessFilter(), $offset, $limit);
    }
1253315
public function getchangedI18N($locale=null) {
		if(!$locale)
			return array_keys($this->translationschanged);
		elseif(isset($this->translationschanged[$locale]))
			return array_keys($this->translationschanged[$locale]);
		else
			return [];
	}
204642
public function getList($country, $currency, $locale, $query)
    {
        $url = implode('/', [$this->url, 'autosuggest', 'v1.0', $country, $currency, $locale]);
        $data = $this->request($url, compact('query'));
        return $data->Places ?? [];
    }
592560
public static List<Locale> getCandidateLocales(Locale locale) {

        String language = LanguageMatch.getAlias(locale);
        String country = FormatUtils.getRegion(locale);
        String variant = locale.getVariant();

        if (language.equals("zh") && locale.getScript().equals("Hant")) {
            country = "TW";
        }

        List<Locale> list = new LinkedList<>();

        if (!variant.isEmpty()) {
            list.add(new Locale(language, country, variant));
        }

        if (!country.isEmpty()) {
            list.add(new Locale(language, country, ""));
        }

        if (!language.isEmpty()) {
            list.add(new Locale(language, "", ""));
            if (language.equals("nn")) {
                list.add(new Locale("nb", "", ""));
            }
        }

        list.add(Locale.ROOT);
        return list;

    }
1182743
static function fetchTranslatedNames( &$countries )
    {
        $locale = eZLocale::instance();
        $translatedCountryNames = $locale->translatedCountryNames();
        foreach ( array_keys( $countries ) as $countryKey )
        {
            $translatedName = isset( $translatedCountryNames[$countryKey] ) ? $translatedCountryNames[$countryKey] : false;
            if ( $translatedName )
                $countries[$countryKey]['Name'] = $translatedName;
        }
        usort( $countries, array( 'eZCountryType', 'compareCountryNames' ) );
    }
1207865
public function getMessages($locale = null)
    {
        return $locale === null ? $this->messages : $this->messages[$locale];
    }
438089
public function list($filter = [], $num = 30, $offset = 0, $cols = null) {
		$query = $this->newSelect();
		if (is_array($cols)) {
			$query->addColumns(...$cols);
		}
		foreach ($filter as $k => $v) {
			$query->andWhere(field($k)->eq($v));
		}
		$query->offset($offset)->limit($num);
		return $this->execute($query);
	}
1360113
private function getInitialLettersList() { 
        $list = array();
        /** @var \Fisharebest\Webtrees\Tree $tree */
        $tree = $this->data->get('tree');
		$script_base_url = WT_SCRIPT_NAME . '?mod=' . \MyArtJaub\Webtrees\Constants::MODULE_MAJ_PATROLIN_NAME . '&mod_action=Lineage';
		
        foreach (QueryName::surnameAlpha($tree, false, false) as $letter => $count) {
            switch ($letter) {
                case '@':
                    $html = I18N::translateContext('Unknown surname', '…');
                    break;
                case ',':
                    $html = I18N::translate('None');
                    break;
                default:
                    $html = Filter::escapeHtml($letter);
                    break;
            }
            if ($count) {
                if ($letter == $this->data->get('alpha')) {
                    $list[] = '<a href="' . $script_base_url . '&alpha=' . rawurlencode($letter) . '&amp;ged=' . $tree->getNameUrl() . '" class="warning" title="' . I18N::number($count) . '">' . $html . '</a>';
                } else {
                    $list[] = '<a href="' . $script_base_url . '&alpha=' . rawurlencode($letter) . '&amp;ged=' . $tree->getNameUrl() . '" title="' . I18N::number($count) . '">' . $html . '</a>';
                }
            } else {
                $list[] = $html;
            }
        }
    
        // Search spiders don't get the "show all" option as the other links give them everything.
        if (!Auth::isSearchEngine()) {
            if ($this->data->get('show_all') === 'yes') {
                $list[] = '<span class="warning">' . I18N::translate('All') . '</span>';
            } else {
                $list[] = '<a href="' . $script_base_url . '&show_all=yes' . '&amp;ged=' . $tree->getNameUrl() . '">' . I18N::translate('All') . '</a>';
            }
        }
    
        return $list;
    }
825048
public function getAllNames(): array
    {
        if ($this->getAllNames === null) {
            // Check the script used by each name, so we can match cyrillic with cyrillic, greek with greek, etc.
            $husb_names = [];
            if ($this->husb) {
                $husb_names = array_filter($this->husb->getAllNames(), static function (array $x): bool {
                    return $x['type'] !== '_MARNM';
                });
            }
            // If the individual only has married names, create a dummy birth name.
            if (empty($husb_names)) {
                $husb_names[] = [
                    'type' => 'BIRT',
                    'sort' => '@N.N.',
                    'full' => I18N::translateContext('Unknown given name', '…') . ' ' . I18N::translateContext('Unknown surname', '…'),
                ];
            }
            foreach ($husb_names as $n => $husb_name) {
                $husb_names[$n]['script'] = I18N::textScript($husb_name['full']);
            }

            $wife_names = [];
            if ($this->wife) {
                $wife_names = array_filter($this->wife->getAllNames(), static function (array $x): bool {
                    return $x['type'] !== '_MARNM';
                });
            }
            // If the individual only has married names, create a dummy birth name.
            if (empty($wife_names)) {
                $wife_names[] = [
                    'type' => 'BIRT',
                    'sort' => '@N.N.',
                    'full' => I18N::translateContext('Unknown given name', '…') . ' ' . I18N::translateContext('Unknown surname', '…'),
                ];
            }
            foreach ($wife_names as $n => $wife_name) {
                $wife_names[$n]['script'] = I18N::textScript($wife_name['full']);
            }

            // Add the matched names first
            foreach ($husb_names as $husb_name) {
                foreach ($wife_names as $wife_name) {
                    if ($husb_name['script'] === $wife_name['script']) {
                        $this->getAllNames[] = [
                            'type' => $husb_name['type'],
                            'sort' => $husb_name['sort'] . ' + ' . $wife_name['sort'],
                            'full' => $husb_name['full'] . ' + ' . $wife_name['full'],
                            // No need for a fullNN entry - we do not currently store FAM names in the database
                        ];
                    }
                }
            }

            // Add the unmatched names second (there may be no matched names)
            foreach ($husb_names as $husb_name) {
                foreach ($wife_names as $wife_name) {
                    if ($husb_name['script'] !== $wife_name['script']) {
                        $this->getAllNames[] = [
                            'type' => $husb_name['type'],
                            'sort' => $husb_name['sort'] . ' + ' . $wife_name['sort'],
                            'full' => $husb_name['full'] . ' + ' . $wife_name['full'],
                            // No need for a fullNN entry - we do not currently store FAM names in the database
                        ];
                    }
                }
            }
        }

        return $this->getAllNames;
    }
120511
public function getGlossaryTerms(LocaleEntity $locale, TranslatableEntity $translatable)
    {
        $result = [];
        $connection = $this->app->make(EntityManager::class)->getConnection();
        $rs = $connection->executeQuery(
            '
                select
                    CommunityTranslationGlossaryEntries.id,
                    CommunityTranslationGlossaryEntries.term,
                    CommunityTranslationGlossaryEntries.type,
                    CommunityTranslationGlossaryEntries.comments as commentsE,
                    CommunityTranslationGlossaryEntriesLocalized.translation,
                    CommunityTranslationGlossaryEntriesLocalized.comments as commentsEL,
                    match(CommunityTranslationGlossaryEntries.term) against (:search in natural language mode) as relevance
                from
                    CommunityTranslationGlossaryEntries
                    left join CommunityTranslationGlossaryEntriesLocalized on CommunityTranslationGlossaryEntries.id = CommunityTranslationGlossaryEntriesLocalized.entry and :locale = CommunityTranslationGlossaryEntriesLocalized.locale
                having
                    relevance > 0
                order by
                    relevance desc,
                    CommunityTranslationGlossaryEntries.term asc
                limit
                    0, ' . ((int) self::MAX_GLOSSARY_ENTRIES) . '
            ',
            [
                'search' => $translatable->getText(),
                'locale' => $locale->getID(),
            ]
        );
        while ($row = $rs->fetch()) {
            $result[] = [
                'id' => (int) $row['id'],
                'term' => $row['term'],
                'type' => $row['type'],
                'termComments' => $row['commentsE'],
                'translation' => ($row['translation'] === null) ? '' : $row['translation'],
                'translationComments' => ($row['commentsEL'] === null) ? '' : $row['commentsEL'],
            ];
        }
        $rs->closeCursor();

        return $result;
    }