1
+ <?php if (!defined ('APPLICATION ' )) exit ();
2
+
3
+ if (!function_exists ('formatString ' )) {
4
+ /**
5
+ * Formats a string by inserting data from its arguments, similar to sprintf, but with a richer syntax.
6
+ *
7
+ * @param string $string The string to format with fields from its args enclosed in curly braces.
8
+ * The format of fields is in the form {Field,Format,Arg1,Arg2}. The following formats are the following:
9
+ * - date: Formats the value as a date. Valid arguments are short, medium, long.
10
+ * - number: Formats the value as a number. Valid arguments are currency, integer, percent.
11
+ * - time: Formats the value as a time. This format has no additional arguments.
12
+ * - url: Calls url() function around the value to show a valid url with the site.
13
+ * You can pass a domain to include the domain.
14
+ * - urlencode, rawurlencode: Calls urlencode/rawurlencode respectively.
15
+ * - html: Calls htmlspecialchars.
16
+ * @param array $args The array of arguments.
17
+ * If you want to nest arrays then the keys to the nested values can be separated by dots.
18
+ * @return string The formatted string.
19
+ * <code>
20
+ * echo formatString("Hello {Name}, It's {Now,time}.", array('Name' => 'Frank', 'Now' => '1999-12-31 23:59'));
21
+ * // This would output the following string:
22
+ * // Hello Frank, It's 12:59PM.
23
+ * </code>
24
+ */
25
+ function formatString ($ string , $ args = []) {
26
+ _formatStringCallback ($ args , true );
27
+ $ result = preg_replace_callback ('/{([^\s][^}]+[^\s]?)}/ ' , '_formatStringCallback ' , $ string );
28
+
29
+ return $ result ;
30
+ }
31
+ }
32
+
33
+ if (!function_exists ('_formatStringCallback ' )) {
34
+ /**
35
+ * The callback helper for {@link formatString()}.
36
+ *
37
+ * @param array $match Either the array of arguments or the regular expression match.
38
+ * @param bool $setArgs Whether this is a call to initialize the arguments or a matching callback.
39
+ * @return mixed Returns the matching string or nothing when setting the arguments.
40
+ * @access private
41
+ */
42
+ function _formatStringCallback ($ match , $ setArgs = false ) {
43
+ static $ args = [], $ contextUserID = null ;
44
+ if ($ setArgs ) {
45
+ $ args = $ match ;
46
+
47
+ if (isset ($ args ['_ContextUserID ' ])) {
48
+ $ contextUserID = $ args ['_ContextUserID ' ];
49
+ } else {
50
+ $ contextUserID = Gdn::session () && Gdn::session ()->isValid () ? Gdn::session ()->UserID : null ;
51
+ }
52
+
53
+ return '' ;
54
+ }
55
+
56
+ $ match = $ match [1 ];
57
+ if ($ match == '{ ' ) {
58
+ return $ match ;
59
+ }
60
+
61
+ // Parse out the field and format.
62
+ $ parts = explode (', ' , $ match );
63
+ $ field = trim ($ parts [0 ]);
64
+ $ format = trim (($ parts [1 ] ?? '' ));
65
+ $ subFormat = isset ($ parts [2 ]) ? strtolower (trim ($ parts [2 ])) : '' ;
66
+ $ formatArgs = $ parts [3 ] ?? '' ;
67
+
68
+ if (in_array ($ format , ['currency ' , 'integer ' , 'percent ' ])) {
69
+ $ formatArgs = $ subFormat ;
70
+ $ subFormat = $ format ;
71
+ $ format = 'number ' ;
72
+ } elseif (is_numeric ($ subFormat )) {
73
+ $ formatArgs = $ subFormat ;
74
+ $ subFormat = '' ;
75
+ }
76
+
77
+ $ value = valr ($ field , $ args , null );
78
+ if ($ value === null && !in_array ($ format , ['url ' , 'exurl ' , 'number ' , 'plural ' ])) {
79
+ $ result = '' ;
80
+ } else {
81
+ switch (strtolower ($ format )) {
82
+ case 'date ' :
83
+ switch ($ subFormat ) {
84
+ case 'short ' :
85
+ $ result = Gdn_Format::date ($ value , '%d/%m/%Y ' );
86
+ break ;
87
+ case 'medium ' :
88
+ $ result = Gdn_Format::date ($ value , '%e %b %Y ' );
89
+ break ;
90
+ case 'long ' :
91
+ $ result = Gdn_Format::date ($ value , '%e %B %Y ' );
92
+ break ;
93
+ default :
94
+ $ result = Gdn_Format::date ($ value );
95
+ break ;
96
+ }
97
+ break ;
98
+ case 'html ' :
99
+ case 'htmlspecialchars ' :
100
+ $ result = htmlspecialchars ($ value );
101
+ break ;
102
+ case 'number ' :
103
+ if (!is_numeric ($ value )) {
104
+ $ result = $ value ;
105
+ } else {
106
+ switch ($ subFormat ) {
107
+ case 'currency ' :
108
+ $ result = '$ ' .number_format ($ value , is_numeric ($ formatArgs ) ? $ formatArgs : 2 );
109
+ break ;
110
+ case 'integer ' :
111
+ $ result = (string )round ($ value );
112
+ if (is_numeric ($ formatArgs ) && strlen ($ result ) < $ formatArgs ) {
113
+ $ result = str_repeat ('0 ' , $ formatArgs - strlen ($ result )).$ result ;
114
+ }
115
+ break ;
116
+ case 'percent ' :
117
+ $ result = round ($ value * 100 , is_numeric ($ formatArgs ) ? $ formatArgs : 0 );
118
+ break ;
119
+ default :
120
+ $ result = number_format ($ value , is_numeric ($ formatArgs ) ? $ formatArgs : 0 );
121
+ break ;
122
+ }
123
+ }
124
+ break ;
125
+ case 'plural ' :
126
+ if (is_array ($ value )) {
127
+ $ value = count ($ value );
128
+ } elseif (stringEndsWith ($ field , 'UserID ' , true )) {
129
+ $ value = 1 ;
130
+ }
131
+
132
+ if (!is_numeric ($ value )) {
133
+ $ result = $ value ;
134
+ } else {
135
+ if (!$ subFormat ) {
136
+ $ subFormat = rtrim ("%s $ field " , 's ' );
137
+ }
138
+ if (!$ formatArgs ) {
139
+ $ formatArgs = $ subFormat .'s ' ;
140
+ }
141
+
142
+ $ result = plural ($ value , $ subFormat , $ formatArgs );
143
+ }
144
+ break ;
145
+ case 'rawurlencode ' :
146
+ $ result = rawurlencode ($ value );
147
+ break ;
148
+ case 'text ' :
149
+ $ result = Gdn_Format::text ($ value , false );
150
+ break ;
151
+ case 'time ' :
152
+ $ result = Gdn_Format::date ($ value , '%l:%M%p ' );
153
+ break ;
154
+ case 'url ' :
155
+ if (strpos ($ field , '/ ' ) !== false ) {
156
+ $ value = $ field ;
157
+ }
158
+ $ result = url ($ value , $ subFormat == 'domain ' );
159
+ break ;
160
+ case 'exurl ' :
161
+ if (strpos ($ field , '/ ' ) !== false ) {
162
+ $ value = $ field ;
163
+ }
164
+ $ result = externalUrl ($ value );
165
+ break ;
166
+ case 'urlencode ' :
167
+ $ result = urlencode ($ value );
168
+ break ;
169
+ case 'gender ' :
170
+ // Format in the form of FieldName,gender,male,female,unknown[,plural]
171
+ if (is_array ($ value ) && count ($ value ) == 1 ) {
172
+ $ value = array_shift ($ value );
173
+ }
174
+
175
+ $ gender = 'u ' ;
176
+
177
+ if (!is_array ($ value )) {
178
+ $ user = Gdn::userModel ()->getID ($ value );
179
+ if ($ user ) {
180
+ $ gender = $ user ->Gender ;
181
+ }
182
+ } else {
183
+ $ gender = 'p ' ;
184
+ }
185
+
186
+ switch ($ gender ) {
187
+ case 'm ' :
188
+ $ result = $ subFormat ;
189
+ break ;
190
+ case 'f ' :
191
+ $ result = $ formatArgs ;
192
+ break ;
193
+ case 'p ' :
194
+ $ result = ($ parts [5 ] ?? ($ parts [4 ] ?? false ));
195
+ break ;
196
+ case 'u ' :
197
+ default :
198
+ $ result = ($ parts [4 ] ?? false );
199
+ }
200
+
201
+ break ;
202
+ case 'user ' :
203
+ case 'you ' :
204
+ case 'his ' :
205
+ case 'her ' :
206
+ case 'your ' :
207
+ // $Result = print_r($Value, true);
208
+ $ argsBak = $ args ;
209
+ if (is_array ($ value ) && count ($ value ) == 1 ) {
210
+ $ value = array_shift ($ value );
211
+ }
212
+
213
+ if (is_array ($ value )) {
214
+ if (isset ($ value ['UserID ' ])) {
215
+ $ user = $ value ;
216
+ $ user ['Name ' ] = formatUsername ($ user , $ format , $ contextUserID );
217
+
218
+ $ result = userAnchor ($ user );
219
+ } else {
220
+ $ max = c ('Garden.FormatUsername.Max ' , 5 );
221
+ // See if there is another count.
222
+ $ extraCount = valr ($ field .'_Count ' , $ args , 0 );
223
+
224
+ $ count = count ($ value );
225
+ $ result = '' ;
226
+ for ($ i = 0 ; $ i < $ count ; $ i ++) {
227
+ if ($ i >= $ max && $ count > $ max + 1 ) {
228
+ $ others = $ count - $ i + $ extraCount ;
229
+ $ result .= ' ' .t ('sep and ' , 'and ' ).' '
230
+ .plural ($ others , '%s other ' , '%s others ' );
231
+ break ;
232
+ }
233
+
234
+ $ iD = $ value [$ i ];
235
+ if (is_array ($ iD )) {
236
+ continue ;
237
+ }
238
+
239
+ if ($ i == $ count - 1 ) {
240
+ $ result .= ' ' .t ('sep and ' , 'and ' ).' ' ;
241
+ } elseif ($ i > 0 ) {
242
+ $ result .= ', ' ;
243
+ }
244
+
245
+ $ special = [-1 => t ('everyone ' ), -2 => t ('moderators ' ), -3 => t ('administrators ' )];
246
+ if (isset ($ special [$ iD ])) {
247
+ $ result .= $ special [$ iD ];
248
+ } else {
249
+ $ user = Gdn::userModel ()->getID ($ iD );
250
+ if ($ user ) {
251
+ $ user ->Name = formatUsername ($ user , $ format , $ contextUserID );
252
+ $ result .= userAnchor ($ user );
253
+ }
254
+ }
255
+ }
256
+ }
257
+ } else {
258
+ $ user = Gdn::userModel ()->getID ($ value );
259
+ if ($ user ) {
260
+ // Store this name separately because of special 'You' case.
261
+ $ name = formatUsername ($ user , $ format , $ contextUserID );
262
+ // Manually build instead of using userAnchor() because of special 'You' case.
263
+ $ result = anchor (htmlspecialchars ($ name ), userUrl ($ user ));
264
+ } else {
265
+ $ result = '' ;
266
+ }
267
+ }
268
+
269
+ $ args = $ argsBak ;
270
+ break ;
271
+ default :
272
+ $ result = $ value ;
273
+ break ;
274
+ }
275
+ }
276
+ return $ result ;
277
+ }
278
+ }
0 commit comments