getHelperPluginManager(); $partial = $plugins->get('partial'); $escape = $plugins->get('escapeHtml'); $assetUrl = $plugins->get('assetUrl'); $translate = $plugins->get('translate'); $escapeAttr = $plugins->get('escapeHtmlAttr'); $themeSetting = $plugins->get('themeSetting'); // $defaultPerPage = (int) $themeSetting('glossary_per_page', 10); $defaultPerPage = empty($defaultPerPage) ? null : (int) $defaultPerPage; $isHtml = !empty($isHtml); $keepOriginalOrder = !empty($keepOriginalOrder); $divclass = empty($divclass) ? '' : $divclass; // There may be multiple start letters. // TODO Js to manage multiple start letters. $query = $this->params()->fromQuery(); $currentPage = (int) ($query['page'] ?? 1) ?: 1; $perPage = (int) ($query['per_page'] ?? 0) ?: $defaultPerPage; // On the first load, the first letter is the first available one: see below. // There may be multiple first letters to consolidate small lists. $startWith = array_filter((array) ($startWith['startwith'] ?? []), 'strlen'); $hasExtensionIntl = extension_loaded('intl'); $hasExtensionIconv = extension_loaded('iconv'); if ($hasExtensionIntl) $transliterator = \Transliterator::createFromRules(':: NFD; :: [:Nonspacing Mark:] Remove; :: NFC;'); // Create the glossary alphabet, the list of current letters and current definitions and prepare first letters. $skiplinks = []; $currents = []; $currentLetters = []; foreach ($glossary as $key => $termDefinition) { if (($termDefinition['term'] ?? '') === '') { unset($glossary[$key]); continue; } $term = (string) $termDefinition['term']; $cleanTerm = trim($isHtml ? html_entity_decode(strip_tags($term)) : $term); if ($cleanTerm === '') { unset($glossary[$key]); continue; } $initial = mb_strtoupper(mb_substr($cleanTerm, 0, 1)); if ($hasExtensionIntl) { $initial = $transliterator->transliterate($initial); } elseif ($hasExtensionIconv) { $initial = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $initial); } $skipLink = preg_match('/\W|\d/u', $initial) ? '0-9' : $initial; $skiplinks[$skipLink] = true; $definition = $termDefinition['definition'] ?? ''; $glossary[$key] = [ 'term' => $cleanTerm, 'definition' => $definition, 'initial' => $initial, 'skiplink' => $skipLink, 'html' => $isHtml ? $term : $escape($term), ]; } $glossary = array_values($glossary); // Order glossary and current definition list by default. if (!$keepOriginalOrder) { if (extension_loaded('intl')) { $collator = new \Collator(null); usort($glossary, function($a, $b) use ($collator) { return $collator->compare($a['term'], $b['term']); }); } else { usort($glossary, function($a, $b) { return strcmp($a['term'], $b['term']); }); } } // Add the empty letters. // Get the default list of initials for latin. To be updated for non-latin references. // Anyway, even in latin, some characters are not transcoded, like Œ. $alphabet = ['0-9' => false] + array_fill_keys(range('A', 'Z'), false); $skiplinks = array_merge($alphabet, $skiplinks); // Don't display symbols if useless. if (empty($skiplinks['0-9'])) unset($skiplinks['0-9']); // Set first letter if not set and prepare the list of currents definitions. if (empty($startWith) && count($skiplinks)) $startWith = [key(array_filter($skiplinks))]; foreach ($glossary as $key => $termDefinition) { if (in_array($termDefinition['initial'], $startWith, true) || in_array($termDefinition['skiplink'], $startWith, true)) { $currents[] = $key; $currentLetters[] = $termDefinition['skiplink']; } } $currentLetters = array_unique($currentLetters); // TODO Use Laminas Paginator? // Prepare the paginator for the current definition list. $totalCount = count($currents); $pageCount = $perPage ? (int) ceil($totalCount / $perPage) : 1; $currentPage = $currentPage <= 1 ? 1 : $currentPage; $currentPage = $currentPage >= $pageCount ? $pageCount : $currentPage; if ($perPage && $pageCount > 1) { $offset = ($currentPage - 1) * $perPage; $previousPage = $currentPage <= 1 ? null : $currentPage - 1; $nextPage = $currentPage >= $pageCount ? null : $currentPage + 1; $currents = array_slice($currents, $offset, $perPage); } else { $offset = 0; $previousPage = null; $nextPage = null; } $this->headLink() ->appendStylesheet($assetUrl('css/block-plus.css', 'BlockPlus')); $this->headScript() ->appendFile($assetUrl('js/block-plus-glossary.js', 'BlockPlus', 'text/javascript', ['defer' => 'defer'])); ?>

$termDefinition): ?>