CWIS Developer Documentation
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 
26  public static function GetCallerInfo($Element = NULL)
27  {
28  $Trace = version_compare(PHP_VERSION, "5.4.0", ">=")
29  ? debug_backtrace(FALSE, 2) : debug_backtrace(FALSE);
30  $FullFileName = $Trace[1]["file"];
31  $Info = [
32  "FileName" => basename($FullFileName),
33  "RelativeFileName" => str_replace(getcwd()."/", "", $FullFileName),
34  "FullFileName" => $FullFileName,
35  "LineNumber" => $Trace[1]["line"],
36  ];
37  return ($Element === NULL) ? $Info : $Info[$Element];
38  }
39 
44  public static function GetMyCaller()
45  {
46  $Trace = version_compare(PHP_VERSION, "5.4.0", ">=")
47  ? debug_backtrace(FALSE, 2) : debug_backtrace(FALSE);
48  $FileName = $Trace[1]["file"];
49  $Caller = basename($FileName).":".$Trace[1]["line"];
50  return $Caller;
51  }
52 
69  public static function CheckMyCaller($DesiredCaller, $ExceptionMsg = NULL)
70  {
71  # retrieve caller info
72  $Trace = version_compare(PHP_VERSION, "5.4.0", ">=")
73  ? debug_backtrace(FALSE, 3) : debug_backtrace(FALSE);
74  $FullFile = $Trace[1]["file"];
75  $File = basename($FullFile);
76  $Line = $Trace[1]["line"];
77  $Class = isset($Trace[2]["class"]) ? $Trace[2]["class"] : "";
78  $Function = isset($Trace[2]["function"]) ? $Trace[2]["function"] : "";
79 
80  # if caller does not match desired caller
81  if (($DesiredCaller != $Class)
82  && ($DesiredCaller != $Class."::".$Function)
83  && ($DesiredCaller != $Class.$Function)
84  && ($DesiredCaller != $File)
85  && ($DesiredCaller != $File.":".$Line))
86  {
87  # if exception message supplied
88  if ($ExceptionMsg !== NULL)
89  {
90  # make any needed substitutions in exception message
91  $Msg = str_replace(
92  array(
93  "%FILE%",
94  "%LINE%",
95  "%FULLFILE%",
96  "%CLASS%",
97  "%FUNCTION%",
98  "%METHOD%"),
99  array(
100  $File,
101  $Line,
102  $FullFile,
103  $Class,
104  $Function,
105  $Class."::".$Function),
106  $ExceptionMsg);
107 
108  # throw exception
109  throw new Exception($Msg);
110  }
111  else
112  {
113  # report to our caller that their caller was not the desired one
114  return FALSE;
115  }
116  }
117 
118  # report to our caller that their caller was not the desired one
119  return TRUE;
120  }
121 
128  public static function GetBacktraceAsString($IncludeArgs = TRUE)
129  {
130  # get backtrace text
131  ob_start();
132  $TraceOpts = $IncludeArgs ? 0 : DEBUG_BACKTRACE_IGNORE_ARGS;
133  debug_print_backtrace($TraceOpts);
134  $TraceString = ob_get_contents();
135  ob_end_clean();
136 
137  # remove this function from backtrace entries
138  $TraceString = preg_replace(
139  "/^#0\s+".__METHOD__."[^\n]*\n/", "", $TraceString, 1);
140 
141  # renumber backtrace entries
142  $TraceString = preg_replace_callback("/^#(\d+)/m", function($Matches)
143  {
144  return "#".($Matches[1] - 1);
145  },
146  $TraceString);
147 
148  # strip leading path off files names
149  $HomeDir = dirname($_SERVER["SCRIPT_FILENAME"]);
150  $TraceString = preg_replace("%".preg_quote($HomeDir, "%")."/%",
151  "", $TraceString);
152 
153  # return backtrace string to caller
154  return $TraceString;
155  }
156 
162  public static function Pluralize($Word)
163  {
164  # return word unchanged if singular and plural are the same
165  if (in_array(strtolower($Word), self::$UncountableWords))
166  {
167  return $Word;
168  }
169 
170  # check for irregular singular forms
171  foreach (self::$IrregularWords as $Pattern => $Result)
172  {
173  $Pattern = '/'.$Pattern.'$/i';
174  if (preg_match($Pattern, $Word))
175  {
176  return preg_replace($Pattern, $Result, $Word);
177  }
178  }
179 
180  # check for matches using regular expressions
181  foreach (self::$PluralizePatterns as $Pattern => $Result)
182  {
183  if (preg_match($Pattern, $Word))
184  {
185  return preg_replace($Pattern, $Result, $Word);
186  }
187  }
188 
189  # return word unchanged if we could not process it
190  return $Word;
191  }
192 
198  public static function Singularize($Word)
199  {
200  # return word unchanged if singular and plural are the same
201  if (in_array(strtolower($Word), self::$UncountableWords))
202  {
203  return $Word;
204  }
205 
206  # check for irregular plural forms
207  foreach (self::$IrregularWords as $Result => $Pattern)
208  {
209  $Pattern = '/'.$Pattern.'$/i';
210  if (preg_match($Pattern, $Word))
211  {
212  return preg_replace($Pattern, $Result, $Word);
213  }
214  }
215 
216  # check for matches using regular expressions
217  foreach (self::$SingularizePatterns as $Pattern => $Result)
218  {
219  if (preg_match($Pattern, $Word))
220  {
221  return preg_replace($Pattern, $Result, $Word);
222  }
223  }
224 
225  # return word unchanged if we could not process it
226  return $Word;
227  }
228 
237  public static function NeatlyTruncateString($String, $MaxLength, $BreakAnywhere=FALSE)
238  {
239  $TagStrippedString = strip_tags(html_entity_decode($String));
240 
241  # if the string contained no HTML tags, we can just treat it as text
242  if ($String == $TagStrippedString)
243  {
244  $Length = self::strlen($String);
245 
246  # if string was short enough, we need not do anything
247  if ($Length <= $MaxLength)
248  {
249  return $String;
250  }
251 
252  # if BreakAnywhere is set, just chop at the max length
253  if ($BreakAnywhere)
254  {
255  $BreakPos = $MaxLength;
256  }
257  # otherwise look for an acceptable breakpoint
258  else
259  {
260  $BreakPos = self::strrpos($String, " ", -($Length - $MaxLength));
261 
262  # if we couldn't find a breakpoint, just chop at max length
263  if ($BreakPos === FALSE)
264  {
265  $BreakPos = $MaxLength;
266  }
267  }
268 
269  $Result = self::substr($String, 0, $BreakPos);
270 
271  # tack on the ellipsis
272  $Result .= "...";
273  }
274  # otherwise, we're in an HTML string and we have to account for
275  # how many characters are actually displayed when the string will be
276  # rendered
277  else
278  {
279  # if there aren't enough non-whitespace displayed characters to
280  # exceed the max length, bail because we don't need to do
281  # anything
282  if (self::strlen(trim($TagStrippedString)) <= $MaxLength)
283  {
284  return $String;
285  }
286 
287  # okay, the hard way -- we have to do some limited parsing
288  # of html and attempt to count the number of printing characters
289  # as we're doing that. to accomplish this, we'll build a
290  # little state machine and iterate over the characters one at a
291  # time
292 
293  # split the string into characters (annoyingly, split()/mb_split()
294  # cannot do this, so we have to use preg_split() in unicode mode)
295  $Tokens = preg_split('%%u', $String, -1, PREG_SPLIT_NO_EMPTY);
296 
297  # define our states
298  $S_Text = 0;
299  $S_MaybeTag = 1;
300  $S_MaybeEntity = 2;
301  $S_Tag = 3;
302  $S_Quote = 4;
303 
304  # max length of an HTML Entity
305  $MaxEntityLength = 8;
306 
307  # track how much we have displayed
308  $DisplayedLength = 0;
309 
310  $Buffer = ""; # for characters we're not sure about
311  $BufLen = 0; # count of buffered characters
312  $Result = ""; # for characters we've included
313  $QuoteChar =""; # quote character in use
314 
315  # start in the 'text state'
316  $State = $S_Text;
317 
318  # iterate over all our tokens
319  foreach ($Tokens as $Token)
320  {
321  switch ($State)
322  {
323  # text state handles words that will be displayed
324  case $S_Text:
325  switch($Token)
326  {
327  # look for characters that can end a word
328  case "<":
329  case "&":
330  case " ":
331  # if we've buffered up a word
332  if ($BufLen > 0)
333  {
334  # and if displaying that word exceeds
335  # our length, then we're done
336  if ($DisplayedLength + $BufLen > $MaxLength)
337  {
338  break 3;
339  }
340 
341  # otherwise, add the buffered word to our display
342  $Result .= $Buffer;
343  $DisplayedLength += $BufLen;
344  }
345 
346  # buffer this character
347  $Buffer = $Token;
348  $BufLen = 1;
349 
350  # if it could have been the start of a tag or an entity,
351  # change state appropriately
352  if ($Token != " ")
353  {
354  $State = ($Token == "<") ? $S_MaybeTag :
355  $S_MaybeEntity;
356  }
357  break;
358 
359  # for characters that can't break a word, just buffer them
360  default:
361  $Buffer .= $Token;
362  $BufLen++;
363  break;
364  }
365  break;
366 
367  # MaybeTag state checks if a < began a tag or not
368  case $S_MaybeTag:
369  # tags start with alpha characters (like <b>)
370  # or a slash (like </b>)
371  if (ctype_alpha($Token) || $Token == "/")
372  {
373  # if this was a tag, output it, output it,
374  # clear our buffer, and move to the Tag state
375  $Result .= $Buffer.$Token;
376  $Buffer = "";
377  $BufLen = 0;
378  $State = $S_Tag;
379  }
380  else
381  {
382  # otherwise, check if displaying this character would
383  # exceed our length. bail if so
384  if ($DisplayedLength + 1 > $MaxLength)
385  {
386  break 2;
387  }
388  # if not, output the characters, clear our buffer,
389  # move to the Text state
390  $Result .= $Buffer.$Token;
391  $DisplayedLength++;
392  $Buffer = "";
393  $BufLen = 0;
394  $State = $S_Text;
395  }
396  break;
397 
398  # Tag state processes the contents of a tag
399  case $S_Tag:
400  # always output tag contents
401  $Result .= $Token;
402 
403  # check if this is the beginning of a quoted string,
404  # changing state appropriately if so
405  if ($Token == "\"" || $Token == "'")
406  {
407  $QuoteChar = $Token;
408  $State = $S_Quote;
409  }
410  # if this is the end of the tag, go back to Text state
411  elseif ($Token == ">")
412  {
413  $State = $S_Text;
414  }
415  break;
416 
417  # Quote state processes quoted attributes
418  case $S_Quote:
419  # always output quote contents
420  $Result .= $Token;
421 
422  # if we've found the matching quote character,
423  # return to the Tag state
424  if ($Token == $QuoteChar)
425  {
426  $State = $S_Tag;
427  }
428  break;
429 
430  # MaybeEntity decides if we're enjoying an HTML entity
431  # or just an ampersand
432  case $S_MaybeEntity:
433  # buffer this token
434  $Buffer.= $Token;
435  $BufLen++;
436 
437  # if it was a space, then we're not in an entity
438  # as they cannot contain spaces
439  if ($Token == " ")
440  {
441  # check if we should be fone
442  if ($DisplayedLength + $BufLen > $MaxLength)
443  {
444  break 2;
445  }
446  # if not, output the buffer, clear it, and return to Text
447  $Result .= $Buffer;
448  $DisplayedLength += $BufLen;
449  $Buffer = "";
450  $BufLen = 0;
451  $State = $S_Text;
452  }
453  # if we have &xxxx; then count that as a single character entity,
454  # output it, clear the buffer, and return to Text
455  elseif ($Token == ";")
456  {
457  $Result .= $Buffer;
458  $DisplayedLength++;
459  $Buffer = "";
460  $BufLen = 0;
461  $State = $S_Text;
462  }
463  # if this has been too many characters without a ;
464  # for it to be an entity, return to text
465  elseif ($BufLen > 8)
466  {
467  $State = $S_Text;
468  }
469 
470  break;
471  }
472  }
473 
474  # tack on the ellipsis
475  $Result .= "...";
476 
477  # if our string contained HTML tags that we may need to close
478  if (preg_match_all("%<(/?[a-z]+)[^>]*>%", $Result, $Matches))
479  {
480  # pull out matches for the names of tags
481  $Matches = $Matches[1];
482 
483  # build up an array of open tags
484  $Tags = array();
485  while ( ($Tag = array_shift($Matches)) !== NULL )
486  {
487  # if this was not a close tag, prepend it to our array
488  if (self::substr($Tag, 0, 1) != "/")
489  {
490  array_unshift($Tags, $Tag);
491  }
492  # if this tag is not self-closing, append it to our list of open tags
493  elseif (self::substr($Tag, -1) != "/")
494  {
495  # if this was a close tag, look to see if this tag was open
496  $Tgt = array_search(self::substr($Tag, 1), $Tags);
497  if ($Tgt !== FALSE)
498  {
499  # if so, remove this tag from our list
500  unset($Tags[$Tgt]);
501  }
502  }
503  }
504 
505  # iterate over open tags, closing them as we go
506  while ( ($Tag = array_shift($Tags)) !== NULL)
507  {
508  $Result .= "</".$Tag.">";
509  }
510  }
511  }
512 
513  return $Result;
514  }
515 
520  public static function substr()
521  {
522  return self::CallMbStringFuncIfAvailable(__FUNCTION__, func_get_args(), 3);
523  }
524 
529  public static function strpos()
530  {
531  return self::CallMbStringFuncIfAvailable(__FUNCTION__, func_get_args(), 3);
532  }
533 
538  public static function strrpos()
539  {
540  return self::CallMbStringFuncIfAvailable(__FUNCTION__, func_get_args(), 3);
541  }
542 
547  public static function strlen()
548  {
549  return self::CallMbStringFuncIfAvailable(__FUNCTION__, func_get_args(), 1);
550  }
551 
559  public static function SortCompare($A, $B)
560  {
561  if ($A == $B)
562  {
563  return 0;
564  }
565  else
566  {
567  return ($A < $B) ? -1 : 1;
568  }
569  }
570 
583  public static function GetLatLngForZipCode($Zip)
584  {
585  static $ZipCache = array();
586 
587  # if we don't have a cached value for this zip, look one up
588  if (!isset($ZipCache[$Zip]))
589  {
590  # try to open our zip code database
591  $FHandle = fopen(dirname(__FILE__)."/StdLib--ZipCodeCoords.txt", "r");
592 
593  # if we couldn't open the file, we can't look up a value
594  if ($FHandle === FALSE)
595  {
596  throw new Exception("Unable to open zip code coordinates file");
597  }
598 
599  # iterate over our database until we find the desired zip
600  # or run out of database
601  while (($Line = fgetcsv($FHandle, 0, "\t")) !== FALSE)
602  {
603  if ($Line[0] == $Zip)
604  {
605  $ZipCache[$Zip] = array(
606  "Lat" => $Line[1], "Lng" => $Line[2]);
607  break;
608  }
609  }
610 
611  # if we've scanned the entire file and have no coords for
612  # this zip, cache a failure
613  if (!isset($ZipCache[$Zip]))
614  {
615  $ZipCache[$Zip] = FALSE;
616  }
617  }
618 
619  # hand back cached value
620  return $ZipCache[$Zip];
621  }
622 
630  public static function ZipCodeDistance($ZipA, $ZipB)
631  {
632 
633  $FirstPoint = self::GetLatLngForZipCode($ZipA);
634  $SecondPoint = self::GetLatLngForZipCode($ZipB);
635 
636  # if we scanned the whole file and lack data for either of our
637  # points, return NULL
638  if ($FirstPoint === FALSE || $SecondPoint === FALSE)
639  {
640  return FALSE;
641  }
642 
643  return self::ComputeGreatCircleDistance(
644  $FirstPoint["Lat"], $FirstPoint["Lng"],
645  $SecondPoint["Lat"], $SecondPoint["Lng"]);
646  }
647 
657  public static function ComputeGreatCircleDistance($LatSrc, $LonSrc,
658  $LatDst, $LonDst)
659  {
660  # See http://en.wikipedia.org/wiki/Great-circle_distance
661 
662  # Convert it all to Radians
663  $Ps = deg2rad($LatSrc);
664  $Ls = deg2rad($LonSrc);
665  $Pf = deg2rad($LatDst);
666  $Lf = deg2rad($LonDst);
667 
668  # Compute the central angle
669  return 3958.756 * atan2(
670  sqrt( pow(cos($Pf)*sin($Lf-$Ls), 2) +
671  pow(cos($Ps)*sin($Pf) -
672  sin($Ps)*cos($Pf)*cos($Lf-$Ls), 2)),
673  sin($Ps)*sin($Pf)+cos($Ps)*cos($Pf)*cos($Lf-$Ls));
674 
675  }
676 
686  public static function ComputeBearing($LatSrc, $LonSrc,
687  $LatDst, $LonDst)
688  {
689  # See http://mathforum.org/library/drmath/view/55417.html
690 
691  # Convert angles to radians
692  $Ps = deg2rad($LatSrc);
693  $Ls = deg2rad($LonSrc);
694  $Pf = deg2rad($LatDst);
695  $Lf = deg2rad($LonDst);
696 
697  return rad2deg(atan2(sin($Lf-$Ls)*cos($Pf),
698  cos($Ps)*sin($Pf)-sin($Ps)*cos($Pf)*cos($Lf-$Ls)));
699  }
700 
708  public static function ArrayPermutations($Items, $Perms = array())
709  {
710  if (empty($Items))
711  {
712  $Result = array($Perms);
713  }
714  else
715  {
716  $Result = array();
717  for ($Index = count($Items) - 1; $Index >= 0; --$Index)
718  {
719  $NewItems = $Items;
720  $NewPerms = $Perms;
721  list($Segment) = array_splice($NewItems, $Index, 1);
722  array_unshift($NewPerms, $Segment);
723  $Result = array_merge($Result,
724  self::ArrayPermutations($NewItems, $NewPerms));
725  }
726  }
727  return $Result;
728  }
729 
736  public static function GetUsStatesList()
737  {
738  return array(
739  "AL" => "Alabama",
740  "AK" => "Alaska",
741  "AZ" => "Arizona",
742  "AR" => "Arkansas",
743  "CA" => "California",
744  "CO" => "Colorado",
745  "CT" => "Connecticut",
746  "DE" => "Delaware",
747  "DC" => "District of Columbia",
748  "FL" => "Florida",
749  "GA" => "Georgia",
750  "HI" => "Hawaii",
751  "ID" => "Idaho",
752  "IL" => "Illinois",
753  "IN" => "Indiana",
754  "IA" => "Iowa",
755  "KS" => "Kansas",
756  "KY" => "Kentucky",
757  "LA" => "Louisiana",
758  "ME" => "Maine",
759  "MD" => "Maryland",
760  "MA" => "Massachusetts",
761  "MI" => "Michigan",
762  "MN" => "Minnesota",
763  "MS" => "Mississippi",
764  "MO" => "Missouri",
765  "MT" => "Montana",
766  "NE" => "Nebraska",
767  "NV" => "Nevada",
768  "NH" => "New Hampshire",
769  "NJ" => "New Jersey",
770  "NM" => "New Mexico",
771  "NY" => "New York",
772  "NC" => "North Carolina",
773  "ND" => "North Dakota",
774  "OH" => "Ohio",
775  "OK" => "Oklahoma",
776  "OR" => "Oregon",
777  "PA" => "Pennsylvania",
778  "RI" => "Rhode Island",
779  "SC" => "South Carolina",
780  "SD" => "South Dakota",
781  "TN" => "Tennessee",
782  "TX" => "Texas",
783  "UT" => "Utah",
784  "VT" => "Vermont",
785  "VA" => "Virginia",
786  "WA" => "Washington",
787  "WV" => "West Virginia",
788  "WI" => "Wisconsin",
789  "WY" => "Wyoming",
790  );
791  }
792 
794  const SQL_DATE_FORMAT = "Y-m-d H:i:s";
795 
796 
797  # ---- PRIVATE INTERFACE -------------------------------------------------
798 
799  private static $PluralizePatterns = array(
800  '/(quiz)$/i' => "$1zes",
801  '/^(ox)$/i' => "$1en",
802  '/([m|l])ouse$/i' => "$1ice",
803  '/(matr|vert|ind)ix|ex$/i' => "$1ices",
804  '/(x|ch|ss|sh)$/i' => "$1es",
805  '/([^aeiouy]|qu)y$/i' => "$1ies",
806  '/(hive)$/i' => "$1s",
807  '/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
808  '/(shea|lea|loa|thie)f$/i' => "$1ves",
809  '/sis$/i' => "ses",
810  '/([ti])um$/i' => "$1a",
811  '/(tomat|potat|ech|her|vet)o$/i'=> "$1oes",
812  '/(bu)s$/i' => "$1ses",
813  '/(alias)$/i' => "$1es",
814  '/(octop)us$/i' => "$1i",
815  '/(ax|test)is$/i' => "$1es",
816  '/(us)$/i' => "$1es",
817  '/s$/i' => "s",
818  '/$/' => "s"
819  );
820  private static $SingularizePatterns = array(
821  '/(quiz)zes$/i' => "$1",
822  '/(matr)ices$/i' => "$1ix",
823  '/(vert|ind)ices$/i' => "$1ex",
824  '/^(ox)en$/i' => "$1",
825  '/(alias)es$/i' => "$1",
826  '/(octop|vir)i$/i' => "$1us",
827  '/(cris|ax|test)es$/i' => "$1is",
828  '/(shoe)s$/i' => "$1",
829  '/(o)es$/i' => "$1",
830  '/(bus)es$/i' => "$1",
831  '/([m|l])ice$/i' => "$1ouse",
832  '/(x|ch|ss|sh)es$/i' => "$1",
833  '/(m)ovies$/i' => "$1ovie",
834  '/(s)eries$/i' => "$1eries",
835  '/([^aeiouy]|qu)ies$/i' => "$1y",
836  '/([lr])ves$/i' => "$1f",
837  '/(tive)s$/i' => "$1",
838  '/(hive)s$/i' => "$1",
839  '/(li|wi|kni)ves$/i' => "$1fe",
840  '/(shea|loa|lea|thie)ves$/i'=> "$1f",
841  '/(^analy)ses$/i' => "$1sis",
842  '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
843  '/([ti])a$/i' => "$1um",
844  '/(n)ews$/i' => "$1ews",
845  '/(h|bl)ouses$/i' => "$1ouse",
846  '/(corpse)s$/i' => "$1",
847  '/(us)es$/i' => "$1",
848  '/s$/i' => ""
849  );
850  private static $IrregularWords = array(
851  'move' => 'moves',
852  'foot' => 'feet',
853  'goose' => 'geese',
854  'sex' => 'sexes',
855  'child' => 'children',
856  'man' => 'men',
857  'tooth' => 'teeth',
858  'person' => 'people'
859  );
860  private static $UncountableWords = array(
861  'sheep',
862  'fish',
863  'deer',
864  'series',
865  'species',
866  'money',
867  'rice',
868  'information',
869  'equipment'
870  );
871 
879  private static function CallMbStringFuncIfAvailable($Func, $Args, $NumPlainArgs)
880  {
881  if (function_exists("mb_".$Func))
882  {
883  $FuncToCall = "mb_".$Func;
884  }
885  else
886  {
887  if (count($Args) > $NumPlainArgs)
888  {
889  throw new Exception(
890  "Function mb_".$Func."() required but not available.");
891  }
892  $FuncToCall = $Func;
893  }
894  return call_user_func_array($FuncToCall, $Args);
895  }
896 }
static strrpos()
Multibyte-aware (if supported in PHP) version of strrpos().
Definition: StdLib.php:538
static CheckMyCaller($DesiredCaller, $ExceptionMsg=NULL)
Check the caller of the current function.
Definition: StdLib.php:69
static SortCompare($A, $B)
Perform compare and return value appropriate for sort function callbacks.
Definition: StdLib.php:559
static ZipCodeDistance($ZipA, $ZipB)
Compute the distance between two US ZIP codes.
Definition: StdLib.php:630
static strpos()
Multibyte-aware (if supported in PHP) version of strpos().
Definition: StdLib.php:529
static GetMyCaller()
Get string with file and line number for call to current function.
Definition: StdLib.php:44
static Pluralize($Word)
Pluralize an English word.
Definition: StdLib.php:162
static GetLatLngForZipCode($Zip)
Look up the GPS coordinates for a US ZIP code.
Definition: StdLib.php:583
Standard utility library.
Definition: StdLib.php:14
static ArrayPermutations($Items, $Perms=array())
Return all possible permutations of a given array.
Definition: StdLib.php:708
static substr()
Multibyte-aware (if supported in PHP) version of substr().
Definition: StdLib.php:520
static GetBacktraceAsString($IncludeArgs=TRUE)
Get backtrace as a string.
Definition: StdLib.php:128
static ComputeGreatCircleDistance($LatSrc, $LonSrc, $LatDst, $LonDst)
Computes the distance in kilometers between two points, assuming a spherical earth.
Definition: StdLib.php:657
static ComputeBearing($LatSrc, $LonSrc, $LatDst, $LonDst)
Computes the initial angle on a course connecting two points, assuming a spherical earth...
Definition: StdLib.php:686
const SQL_DATE_FORMAT
Format to feed to date() to get SQL-compatible date/time string.
Definition: StdLib.php:794
static NeatlyTruncateString($String, $MaxLength, $BreakAnywhere=FALSE)
Attempt to truncate a string as neatly as possible with respect to word breaks, punctuation, and HTML tags.
Definition: StdLib.php:237
static strlen()
Multibyte-aware (if supported in PHP) version of strlen().
Definition: StdLib.php:547
static Singularize($Word)
Singularize an English word.
Definition: StdLib.php:198
static GetUsStatesList()
Get an array of US state names with their two-letter abbreviations as the index.
Definition: StdLib.php:736
static GetCallerInfo($Element=NULL)
Get info about call to current function.
Definition: StdLib.php:26