PluginProbe ʕ •ᴥ•ʔ
AlphaListing / 4.3.6
AlphaListing v4.3.6
trunk 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0
alphalisting / src / Alphabet.php
alphalisting / src Last commit date
Shortcode 9 months ago Alphabet.php 9 months ago Extension.php 9 months ago Grouping.php 9 months ago GutenBlock.php 9 months ago Indices.php 9 months ago Numbers.php 9 months ago Query.php 9 months ago Shortcode.php 9 months ago Singleton.php 9 months ago Strings.php 9 months ago
Alphabet.php
251 lines
1 <?php
2 /**
3 * Alphabet class
4 *
5 * @package alphalisting
6 */
7
8 declare(strict_types=1);
9
10 namespace eslin87\AlphaListing;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * AlphaListing Alphabet handler class
18 *
19 * @since 4.0.0
20 */
21 class Alphabet {
22 /**
23 * The index label to use for posts which are not matched by any known letter,
24 * from the $alphabet, such as numerics
25 *
26 * @since 4.0.0
27 * @var string
28 */
29 public $unknown_letter;
30
31 /**
32 * All available characters of the alphabet in order. For example, with the
33 * default 26-letter European alphabet indexed `0` through to `25`, where `0`
34 * is `A` and `25` is `Z`. The values in this array are used as the keys for
35 * the `$keyed_alphabet` associative-array.
36 *
37 * @since 4.0.0
38 * @var array<int,string>
39 * @see $keyed_alphabet
40 */
41 public $alphabet_keys;
42
43 /**
44 * All available letters in groups of similarity. For example, by default `A`,
45 * `Á`, `À`, `Ä`, `Â`, `a`, `á`, `à`, `ä`, and `â` are all in a single group
46 * whose key is `A`. This is because each of those examples are derived from
47 * the latin letter named `alpha`. The keys used in this associative-array are
48 * stored as values in the `$alphabet_keys` array.
49 *
50 * @since 4.0.0
51 * @var array<string,string>
52 * @see $alphabet_keys
53 */
54 public $keyed_alphabet;
55
56 /**
57 * Any unknown letter is sorted to be before the rest of the alphabet
58 *
59 * @since 4.1.0
60 * @var bool
61 */
62 public $unknown_letter_is_first = false;
63
64 /**
65 * Build a translated alphabet
66 *
67 * @since 4.0.0
68 */
69 public function __construct() {
70 /* translators: List the aphabet of your language in the order that your language prefers. list as groups of identical meanings but different characters together, e.g. in English we group A with a because they are both the same letter but different character-code. Each character group should be followed by a comma separating it from the next group. Any amount of characters per group are acceptible, and there is no requirement for all the groups to contain the same amount of characters as all the others. Be careful with the character you place first in each group as that will be used as the identifier for the group which gets displayed on the page, e.g. in English a group definition of "Aa" will indicate that we display all the posts in the group, i.e. whose titles begin with either "A" or "a", listed under a heading of "A" (the first character in the definition). */
71 $alphabet = __( 'AÁÀÄÂaáàäâ,Bb,CÇcç,Dd,EÉÈËÊeéèëê,Ff,Gg,Hh,IÍÌÏÎiíìïî,Jj,Kk,Ll,Mm,Nn,OÓÒÖÔoóòöô,Pp,Qq,Rr,Ssß,Tt,UÚÙÜÛuúùüû,Vv,Ww,Xx,Yy,Zz', 'alphalisting' );
72 /* translators: This should be a single character to denote "all entries that didn't fit under one of the alphabet character groups defined". This is used in English to categorise posts whose title begins with a numeric (0 through to 9), or some other character that is not a standard English alphabet letter. */
73 $others = __( '#', 'alphalisting' );
74
75 /**
76 * Filters the alphabet. The string should contain groups of similar or
77 * identical characters separated by commas. The first character in each
78 * group is the one used for the group title.
79 *
80 * @since 1.7.1
81 * @param string $alphabet The $alphabet
82 */
83 $alphabet = apply_filters( 'alphalisting_alphabet', $alphabet );
84 /**
85 * Filters the alphabet. The string should contain groups of similar or
86 * identical characters separated by commas. The first character in each
87 * group is the one used for the group title.
88 *
89 * @since 1.7.1
90 * @param string $alphabet The $alphabet.
91 */
92 $alphabet = apply_filters( 'alphalisting-alphabet', $alphabet ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
93
94 /**
95 * Specifies the character used for all non-alphabetic titles, such as
96 * numeric titles in the default setup for English. Defaults to '#' unless
97 * overridden by a language pack.
98 *
99 * @since 1.7.1
100 * @param string $non_alpha_char The character for non-alphabetic post titles.
101 */
102 $others = apply_filters( 'alphalisting_non_alpha_char', $others );
103 /**
104 * Specifies the character used for all non-alphabetic titles, such as numeric
105 * titles in the default setup for English. Defaults to '#' unless overridden
106 * by a language pack.
107 *
108 * @since 1.7.1
109 * @param string $non_alpha_char The character for non-alphabetic post titles.
110 */
111 $others = apply_filters( 'alphalisting-non-alpha-char', $others ); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
112
113 $alphabet_groups = explode( ',', $alphabet );
114 if ( defined( 'ALPHALISTING_LOG' ) && ALPHALISTING_LOG > 1 ) {
115 do_action( 'alphalisting_log', 'AlphaListing: Alphabet Groups', $alphabet_groups );
116 }
117 $letters = array_reduce(
118 $alphabet_groups,
119 /**
120 * Closure to extract the alphabet groups
121 *
122 * @param array<string,string> $carry
123 * @param string $group_as_string
124 * @return array<string,string>
125 */
126 function( array $carry, string $group_as_string ): array {
127 $group_as_array = Strings::mb_string_to_array( $group_as_string );
128 $group_index_character = $group_as_array[0];
129 $group_as_array = array_reduce(
130 $group_as_array,
131 /**
132 * Closure to extract the letters from each alphabet group
133 *
134 * @param array<string,string> $group_carry
135 * @param string $character
136 * @return array<string,string>
137 */
138 function( array $group_carry, string $character ) use ( $group_index_character ) {
139 $character = "__$character";
140 $group_carry[ $character ] = $group_index_character;
141 return $group_carry;
142 },
143 array()
144 );
145 return array_merge( $carry, $group_as_array );
146 },
147 array()
148 );
149
150 if ( defined( 'ALPHALISTING_LOG' ) && ALPHALISTING_LOG > 2 ) {
151 do_action( 'alphalisting_log', 'AlphaListing: Alphabet', $letters );
152 }
153
154 $this->unknown_letter = $others;
155 $this->unknown_letter_is_first = ! ! apply_filters( 'alphalisting_unknown_letter_is_first', false );
156 $this->alphabet_keys = array_values( array_unique( $letters ) );
157 $this->keyed_alphabet = $letters;
158 }
159
160 /**
161 * Get a letter for a key
162 *
163 * @since 4.0.0
164 * @param string $key The key to look up.
165 * @return string The letter.
166 */
167 public function get_letter_for_key( string $key ): string {
168 if ( $key === $this->unknown_letter || ! in_array( "__$key", array_keys( $this->keyed_alphabet ), true ) ) {
169 return $this->unknown_letter;
170 }
171 return $this->keyed_alphabet[ "__$key" ];
172 }
173
174 /**
175 * Get a key for a letter offset
176 *
177 * @since 4.0.0
178 * @param int $offset The offset from the start of the alphabet (0-based).
179 * @return string The alphabet group key.
180 */
181 public function get_key_for_offset( int $offset ): string {
182 if ( $this->unknown_letter_is_first ) {
183 if ( 0 === $offset ) {
184 return $this->unknown_letter;
185 }
186 --$offset;
187 }
188
189 if ( count( $this->alphabet_keys ) <= $offset ) {
190 return $this->unknown_letter;
191 }
192
193 return $this->alphabet_keys[ $offset ];
194 }
195
196 /**
197 * Get the character indicating an unknown alphabet letter
198 *
199 * @since 4.0.0
200 * @return string The character.
201 */
202 public function get_unknown_letter(): string {
203 return $this->unknown_letter;
204 }
205
206 /**
207 * Get the alphabet characters.
208 *
209 * @since 4.0.0
210 * @param bool $include_unknown Whether to include the 'unknown' character in the array.
211 * @return array<int,string> The characters.
212 */
213 public function chars( bool $include_unknown = false ): array {
214 $letters = $this->alphabet_keys;
215 if ( ! $include_unknown ) {
216 return $letters;
217 }
218
219 if ( $this->unknown_letter_is_first ) {
220 array_unshift( $letters, $this->unknown_letter );
221 } else {
222 $letters[] = $this->unknown_letter;
223 }
224 return $letters;
225 }
226
227 /**
228 * Count the alphabet
229 *
230 * @since 4.0.0
231 * @param bool $include_unknown Wether to include the 'unknown' character when counting the alphabet.
232 * @return int The number of letters in the alphabet.
233 */
234 public function count( bool $include_unknown = false ): int {
235 return count( $this->chars( $include_unknown ) );
236 }
237
238 /**
239 * Perform an action for every alphabet letter.
240 *
241 * @since 4.0.0
242 * @param callable $callback The function to run on every loop iteration.
243 * @param bool $include_unknown Whether to include the 'unknown' character in the loop.
244 * @return void
245 */
246 public function loop( callable $callback, bool $include_unknown = false ) {
247 $alphabet = $this->chars( $include_unknown );
248 array_walk( $alphabet, $callback, $this->count( $include_unknown ) );
249 }
250 }
251