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