CWIS Developer Documentation

- Home
- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

StdLib.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: StdLib.php
4 #
5 # Part of the ScoutLib application support library
6 # Copyright 2016 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu
8 #
9
14 class StdLib
15 {
16
17 # ---- PUBLIC INTERFACE --------------------------------------------------
18
23 public static function GetMyCaller()
24 {
25 $Trace = version_compare(PHP_VERSION, "5.4.0", ">=")
26 ? debug_backtrace(FALSE, 2) : debug_backtrace(FALSE);
27 $Caller = basename($Trace[1]["file"]).":".$Trace[1]["line"];
28 return $Caller;
29 }
30
47 public static function CheckMyCaller($DesiredCaller, $ExceptionMsg = NULL)
48 {
49 # retrieve caller info
50 $Trace = version_compare(PHP_VERSION, "5.4.0", ">=")
51 ? debug_backtrace(FALSE, 3) : debug_backtrace(FALSE);
52 $FullFile = $Trace[1]["file"];
53 $File = basename($FullFile);
54 $Line = $Trace[1]["line"];
55 $Class = isset($Trace[2]["class"]) ? $Trace[2]["class"] : "";
56 $Function = isset($Trace[2]["function"]) ? $Trace[2]["function"] : "";
57
58 # if caller does not match desired caller
59 if (($DesiredCaller != $Class)
60 && ($DesiredCaller != $Class."::".$Function)
61 && ($DesiredCaller != $Class.$Function)
62 && ($DesiredCaller != $File)
63 && ($DesiredCaller != $File.":".$Line))
64 {
65 # if exception message supplied
66 if ($ExceptionMsg !== NULL)
67 {
68 # make any needed substitutions in exception message
69 $Msg = str_replace(
70 array(
71 "%FILE%",
72 "%LINE%",
73 "%FULLFILE%",
74 "%CLASS%",
75 "%FUNCTION%",
76 "%METHOD%"),
77 array(
78 $File,
79 $Line,
80 $FullFile,
81 $Class,
82 $Function,
83 $Class."::".$Function),
84 $ExceptionMsg);
85
86 # throw exception
87 throw new Exception($Msg);
88 }
89 else
90 {
91 # report to our caller that their caller was not the desired one
92 return FALSE;
93 }
94 }
95
96 # report to our caller that their caller was not the desired one
97 return TRUE;
98 }
99
105 public static function Pluralize($Word)
106 {
107 # return word unchanged if singular and plural are the same
108 if (in_array(strtolower($Word), self::$UncountableWords))
109 {
110 return $Word;
111 }
112
113 # check for irregular singular forms
114 foreach (self::$IrregularWords as $Pattern => $Result)
115 {
116 $Pattern = '/'.$Pattern.'$/i';
117 if (preg_match($Pattern, $Word))
118 {
119 return preg_replace($Pattern, $Result, $Word);
120 }
121 }
122
123 # check for matches using regular expressions
124 foreach (self::$PluralizePatterns as $Pattern => $Result)
125 {
126 if (preg_match($Pattern, $Word))
127 {
128 return preg_replace($Pattern, $Result, $Word);
129 }
130 }
131
132 # return word unchanged if we could not process it
133 return $Word;
134 }
135
141 public static function Singularize($Word)
142 {
143 # return word unchanged if singular and plural are the same
144 if (in_array(strtolower($Word), self::$UncountableWords))
145 {
146 return $Word;
147 }
148
149 # check for irregular plural forms
150 foreach (self::$IrregularWords as $Result => $Pattern)
151 {
152 $Pattern = '/'.$Pattern.'$/i';
153 if (preg_match($Pattern, $Word))
154 {
155 return preg_replace($Pattern, $Result, $Word);
156 }
157 }
158
159 # check for matches using regular expressions
160 foreach (self::$SingularizePatterns as $Pattern => $Result)
161 {
162 if (preg_match($Pattern, $Word))
163 {
164 return preg_replace($Pattern, $Result, $Word);
165 }
166 }
167
168 # return word unchanged if we could not process it
169 return $Word;
170 }
171
179 public static function SortCompare($A, $B)
180 {
181 if ($A == $B)
182 {
183 return 0;
184 }
185 else
186 {
187 return ($A < $B) ? -1 : 1;
188 }
189 }
190
191
204 public static function GetLatLngForZipCode($Zip)
205 {
206 static $ZipCache = array();
207
208 # if we don't have a cached value for this zip, look one up
209 if (!isset($ZipCache[$Zip]))
210 {
211 # try to open our zip code database
212 $FHandle = fopen(dirname(__FILE__)."/StdLib--ZipCodeCoords.txt", "r");
213
214 # if we couldn't open the file, we can't look up a value
215 if ($FHandle === FALSE)
216 {
217 throw new Exception("Unable to open zip code coordinates file");
218 }
219
220 # iterate over our database until we find the desired zip
221 # or run out of database
222 while (($Line = fgetcsv($FHandle, 0, "\t")) !== FALSE)
223 {
224 if ($Line[0] == $Zip)
225 {
226 $ZipCache[$Zip] = array(
227 "Lat" => $Line[1], "Lng" => $Line[2]);
228 break;
229 }
230 }
231
232 # if we've scanned the entire file and have no coords for
233 # this zip, cache a failure
234 if (!isset($ZipCache[$Zip]))
235 {
236 $ZipCache[$Zip] = FALSE;
237 }
238 }
239
240 # hand back cached value
241 return $ZipCache[$Zip];
242 }
243
251 public static function ZipCodeDistance($ZipA, $ZipB)
252 {
253
254 $FirstPoint = self::GetLatLngForZipCode($ZipA);
255 $SecondPoint = self::GetLatLngForZipCode($ZipB);
256
257 # if we scanned the whole file and lack data for either of our
258 # points, return NULL
259 if ($FirstPoint === FALSE || $SecondPoint === FALSE)
260 {
261 return FALSE;
262 }
263
264 return self::ComputeGreatCircleDistance(
265 $FirstPoint["Lat"], $FirstPoint["Lng"],
266 $SecondPoint["Lat"], $SecondPoint["Lng"]);
267 }
268
278 public static function ComputeGreatCircleDistance($LatSrc, $LonSrc,
279 $LatDst, $LonDst)
280 {
281 # See http://en.wikipedia.org/wiki/Great-circle_distance
282
283 # Convert it all to Radians
284 $Ps = deg2rad($LatSrc);
285 $Ls = deg2rad($LonSrc);
286 $Pf = deg2rad($LatDst);
287 $Lf = deg2rad($LonDst);
288
289 # Compute the central angle
290 return 3958.756 * atan2(
291 sqrt( pow(cos($Pf)*sin($Lf-$Ls), 2) +
292 pow(cos($Ps)*sin($Pf) -
293 sin($Ps)*cos($Pf)*cos($Lf-$Ls), 2)),
294 sin($Ps)*sin($Pf)+cos($Ps)*cos($Pf)*cos($Lf-$Ls));
295
296 }
297
307 public static function ComputeBearing($LatSrc, $LonSrc,
308 $LatDst, $LonDst)
309 {
310 # See http://mathforum.org/library/drmath/view/55417.html
311
312 # Convert angles to radians
313 $Ps = deg2rad($LatSrc);
314 $Ls = deg2rad($LonSrc);
315 $Pf = deg2rad($LatDst);
316 $Lf = deg2rad($LonDst);
317
318 return rad2deg(atan2(sin($Lf-$Ls)*cos($Pf),
319 cos($Ps)*sin($Pf)-sin($Ps)*cos($Pf)*cos($Lf-$Ls)));
320 }
321
323 const SQL_DATE_FORMAT = "Y-m-d H:i:s";
324
325
326 # ---- PRIVATE INTERFACE -------------------------------------------------
327
328 private static $PluralizePatterns = array(
329 '/(quiz)$/i' => "$1zes",
330 '/^(ox)$/i' => "$1en",
331 '/([m|l])ouse$/i' => "$1ice",
332 '/(matr|vert|ind)ix|ex$/i' => "$1ices",
333 '/(x|ch|ss|sh)$/i' => "$1es",
334 '/([^aeiouy]|qu)y$/i' => "$1ies",
335 '/(hive)$/i' => "$1s",
336 '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
337 '/(shea|lea|loa|thie)f$/i' => "$1ves",
338 '/sis$/i' => "ses",
339 '/([ti])um$/i' => "$1a",
340 '/(tomat|potat|ech|her|vet)o$/i'=> "$1oes",
341 '/(bu)s$/i' => "$1ses",
342 '/(alias)$/i' => "$1es",
343 '/(octop)us$/i' => "$1i",
344 '/(ax|test)is$/i' => "$1es",
345 '/(us)$/i' => "$1es",
346 '/s$/i' => "s",
347 '/$/' => "s"
348 );
349 private static $SingularizePatterns = array(
350 '/(quiz)zes$/i' => "$1",
351 '/(matr)ices$/i' => "$1ix",
352 '/(vert|ind)ices$/i' => "$1ex",
353 '/^(ox)en$/i' => "$1",
354 '/(alias)es$/i' => "$1",
355 '/(octop|vir)i$/i' => "$1us",
356 '/(cris|ax|test)es$/i' => "$1is",
357 '/(shoe)s$/i' => "$1",
358 '/(o)es$/i' => "$1",
359 '/(bus)es$/i' => "$1",
360 '/([m|l])ice$/i' => "$1ouse",
361 '/(x|ch|ss|sh)es$/i' => "$1",
362 '/(m)ovies$/i' => "$1ovie",
363 '/(s)eries$/i' => "$1eries",
364 '/([^aeiouy]|qu)ies$/i' => "$1y",
365 '/([lr])ves$/i' => "$1f",
366 '/(tive)s$/i' => "$1",
367 '/(hive)s$/i' => "$1",
368 '/(li|wi|kni)ves$/i' => "$1fe",
369 '/(shea|loa|lea|thie)ves$/i'=> "$1f",
370 '/(^analy)ses$/i' => "$1sis",
371 '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
372 '/([ti])a$/i' => "$1um",
373 '/(n)ews$/i' => "$1ews",
374 '/(h|bl)ouses$/i' => "$1ouse",
375 '/(corpse)s$/i' => "$1",
376 '/(us)es$/i' => "$1",
377 '/s$/i' => ""
378 );
379 private static $IrregularWords = array(
380 'move' => 'moves',
381 'foot' => 'feet',
382 'goose' => 'geese',
383 'sex' => 'sexes',
384 'child' => 'children',
385 'man' => 'men',
386 'tooth' => 'teeth',
387 'person' => 'people'
388 );
389 private static $UncountableWords = array(
390 'sheep',
391 'fish',
392 'deer',
393 'series',
394 'species',
395 'money',
396 'rice',
397 'information',
398 'equipment'
399 );
400 }
StdLib\CheckMyCaller
static CheckMyCaller($DesiredCaller, $ExceptionMsg=NULL)
Check the caller of the current function.
Definition: StdLib.php:47
StdLib\SortCompare
static SortCompare($A, $B)
Perform compare and return value appropriate for sort function callbacks.
Definition: StdLib.php:179
StdLib\ZipCodeDistance
static ZipCodeDistance($ZipA, $ZipB)
Compute the distance between two US ZIP codes.
Definition: StdLib.php:251
StdLib\GetMyCaller
static GetMyCaller()
Get string with file and line number for call to current function.
Definition: StdLib.php:23
StdLib\Pluralize
static Pluralize($Word)
Pluralize an English word.
Definition: StdLib.php:105
StdLib\GetLatLngForZipCode
static GetLatLngForZipCode($Zip)
Look up the GPS coordinates for a US ZIP code.
Definition: StdLib.php:204
StdLib
Standard utility library.
Definition: StdLib.php:14
PHP
PHP
Definition: RSSClient--Test.php:12
StdLib\ComputeGreatCircleDistance
static ComputeGreatCircleDistance($LatSrc, $LonSrc, $LatDst, $LonDst)
Computes the distance in kilometers between two points, assuming a spherical earth.
Definition: StdLib.php:278
StdLib\ComputeBearing
static ComputeBearing($LatSrc, $LonSrc, $LatDst, $LonDst)
Computes the initial angle on a course connecting two points, assuming a spherical earth...
Definition: StdLib.php:307
StdLib\SQL_DATE_FORMAT
const SQL_DATE_FORMAT
Format to feed to date() to get SQL-compatible date/time string.
Definition: StdLib.php:323
StdLib\Singularize
static Singularize($Word)
Singularize an English word.
Definition: StdLib.php:141