1: <?php
2:
3: /**
4: * Document class Geo
5: *
6: * PHP Version 5.6
7: *
8: * @category Class
9: * @package Geolib
10: * @author Peter Pitchford <peter@geotonics.com>
11: * @license GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html
12: * @link http://geotonics.com/#geolib
13: */
14:
15: /**
16: * Geo - Class for static utility functions
17: *
18: * @category Utility
19: * @package Geolib
20: * @author Peter Pitchford <peter@geotonics.com>
21: * @license GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html
22: * @version Release: .1
23: * @link http://geotonics.com/#geolib
24: * @since Class available since Release .1
25: */
26: class Geo
27: {
28:
29:
30: /**
31: * Checks email address for valid syntax.
32: *
33: * @param string $email Email address
34: *
35: * @return bool
36: */
37: public static function isValidEmail($email)
38: {
39: $regex = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/';
40: return preg_match($regex, $email);
41: }
42:
43: /**
44: * Case-insensitive str_replace()
45: *
46: * @param string $find Text to replace
47: * @param string $replace Replacement
48: * @param string $string Text to search
49: *
50: * @return string Updated text
51: */
52: public static function strReplace($find, $replace, $string)
53: {
54:
55: $parts = explode(strtolower($find), strtolower($string));
56: $pos = 0;
57: foreach ($parts as $key => $part) {
58: $parts[$key] = substr($string, $pos, strlen($part));
59: $pos += strlen($part) + strlen($find);
60: }
61: return (join($replace, $parts));
62: }
63:
64: /**
65: * Prepares text and converts it into html.
66: *
67: * @param string $txt Text to convert
68: * @param bool $addHtmlEntities Add html entities
69: *
70: * @return html
71: */
72: public static function textToHtml($txt, $addHtmlEntities = null)
73: {
74:
75: // Transforms txt in html
76: //Kills double spaces and spaces inside tags.
77: while (!(strpos($txt, ' ') === false)) {
78: $txt = str_replace(' ', ' ', $txt);
79: }
80:
81: $txt = str_replace(' >', '>', $txt);
82: $txt = str_replace('< ', '<', $txt);
83: if ($addHtmlEntities) {
84: //Transforms accents in html entities.
85: $txt = htmlentities($txt);
86:
87: //We need some HTML entities back!
88: $txt = str_replace('"', '"', $txt);
89: $txt = str_replace('<', '<', $txt);
90: $txt = str_replace('>', '>', $txt);
91: $txt = str_replace('&', '&', $txt);
92: }
93: /*
94: //Ajdusts links - anything starting with HTTP opens in a new window
95: $txt = geoStrReplace("<a href=\"http://", "<a target=\"_blank\" href=\"http://", $txt);
96: $txt = geoStrReplace("<a href=http://", "<a target=\"_blank\" href=http://", $txt);
97: */
98:
99: //Basic formatting
100: $eol = (strpos($txt, "\r") === false) ? "\n" : "\r\n";
101: $txt = trim($txt);
102: $html = '<p>' . str_replace("$eol$eol", "</p><p>", $txt) . '</p>';
103: $html = str_replace("$eol", "<br />", $html);
104: $html = str_replace("</p>", "</p>", $html);
105:
106: $html = str_replace("<p></p>", "<p> </p>", $html);
107:
108: //Wipes <br> after block tags (for when the user includes some html in the text).
109: $wipebr = array(
110: "table",
111: "tr",
112: "td",
113: "blockquote",
114: "ul",
115: "ol",
116: "li"
117: );
118: for ($x = 0; $x < count($wipebr); $x++) {
119: $tag = $wipebr[$x];
120: $html = static::strReplace("<$tag><br />", "<$tag>", $html);
121: $html = static::strReplace("</$tag><br />", "</$tag>", $html);
122: }
123:
124: return $html;
125: }
126:
127: /**
128: * Writes content to file.
129: *
130: * @param string $filename Name of file to write to
131: * @param string $content Content to write to file
132: * @param string $mode Mode for PHP fwrite
133: *
134: * @return string Message with status of write
135: */
136: public static function writeToFile($filename, $content, $mode = 'w')
137: {
138: $content = static::arr($content);
139: $content = implode("\t", $content) . "\n";
140: if (is_writable($filename)) {
141: if ($handle = fopen($filename, $mode)) {
142: if (fwrite($handle, $content) === false) {
143: $feedback = "Cannot write to file (" . $filename . ")";
144: } else {
145: $feedback = "Success, wrote content to file (" . $filename . ")";
146: }
147: fclose($handle);
148: } else {
149: $feedback = "Cannot open file (" . $filename . ")";
150: }
151:
152: } else {
153: if (file_exists($filename)) {
154: $feedback = "The file " . $filename . " is not writable";
155: } else {
156: // try to create file
157: $handle = fopen($filename, "w");
158: fclose($handle);
159: if (file_exists($filename)) {
160: $feedback=static::writeToFile($filename, $content, $mode);
161:
162: } else {
163: $feedback = $filename . " does not exist anc could not be created";
164: }
165: }
166: }
167: return $feedback;
168: }
169:
170:
171: /**
172: * Naturally sorts a Two dimensional array
173: *
174: * @param array $arrayInput Array to be sorted passed by reference
175: *
176: * @return void
177: */
178: public static function natSort2d(&$arrayInput)
179: {
180: $arrayTemp = $arrayOut = array();
181:
182: foreach ($arrayInput as $key => $value) {
183: reset($value);
184: $arrayTemp[$key] = current($value);
185: }
186:
187: natsort($arrayTemp);
188:
189: foreach ($arrayTemp as $key => $value) {
190: $arrayOut[] = $arrayInput[$key];
191: }
192:
193: $arrayInput = $arrayOut;
194: }
195:
196: /**
197: * Parses string to find the first words or first paragraph
198: *
199: * @param string $string String to parse for first words
200: * @param int $numWords Number of words to return. If true, return first paragraph
201: * @param bool $returnString Return first words, otherwise return an array of parts.
202: *
203: * @return mixed Either first words (plus ellipsis if text has been abbreviated), or array of parts
204: * Default is array of parts
205: * If parts, array[0] is the first $numWords words, array[1] is the rest of the text.
206: */
207: public static function firstWords($string, $numWords, $returnString = null)
208: {
209: $string = strip_tags($string);
210: $parts = explode("\n", $string, 2);
211: //GeoDebug::db($parts, 'origparts');
212: // divide on first paragraph
213: if ($numWords === true) {
214: return $parts;
215: } else {
216: // divide on first $num words into an array
217: $words = explode(' ', $parts[0]);
218: $size = sizeof($words);
219:
220: if ($size < $numWords+1) {
221: if ($returnString) {
222: return $parts[0];
223: }
224: return $parts;
225: }
226:
227: $parts2[] = implode(" ", array_slice($words, 0, $numWords));
228:
229: if (isset($parts[1])) {
230: $parts2[] = $parts[1];
231: }
232:
233: $parts2[] = implode(" ", array_slice($words, $numWords));
234:
235: if ($returnString) {
236: return $parts2[0]."...";
237: }
238:
239: return $parts2;
240: }
241: }
242:
243:
244:
245: /**
246: * Sets default value if value is not already set
247: *
248: * @param mixed $var Variable to be set if not already set.
249: * @param mixed $default Value to be given to variable if it is not already set.
250: *
251: * @return mixed value
252: */
253: public static function val(&$var, $default = null)
254: {
255: if (!isset($var) && $default !== null) {
256: $var = $default;
257: }
258: return $var;
259: }
260:
261: /**
262: * Creates tabs for source code or html
263: *
264: * @param int $tabs Number of tabs to create
265: * @param bool $text Content of tabs. Default is 3 text spaces.
266: * If true, content is 3 html spaces
267: *
268: * @return text|html
269: */
270: public static function geoTabs($tabs = 1, $text = " ")
271: {
272: if ($text === true) {
273: $text = " ";
274: }
275: $tab = '';
276: for ($i = 0; $i < $tabs; $i++) {
277: $tab .= $text;
278: }
279: return $tab;
280: }
281:
282:
283: /**
284: * Explodes string on given separator, returns given index of the resulting array.
285: *
286: * @param string $val Value to explode
287: * @param string $index Index of array value to return. Default is 1
288: * @param string $sep Separator to explode on
289: *
290: * @return string $arr[$index] index of array
291: */
292: public static function exp($val, $index = 1, $sep = "_")
293: {
294: $arr = explode($sep, $val);
295: if (isset($arr[$index])) {
296: return $arr[$index];
297: }
298: }
299:
300: /**
301: * Sets session variables. Optionally add name of session array
302: *
303: * @param string $name Name of session variable
304: * @param string $value Value of session variable
305: * @param string $subArrayName Name of session sub array.
306: * @param string $userSessionName Name of user session
307: * @param string $arrayName Name of session array. Default is "geolib"
308: *
309: * @return void
310: */
311: public static function setSession(
312: $name,
313: $value = null,
314: $subArrayName = null,
315: $userSessionName = null,
316: $arrayName = GEO_INSTANCE
317: ) {
318: if ($arrayName) {
319: if ($subArrayName) {
320: if ($name) {
321: if ($value) {
322: $_SESSION[$arrayName][$subArrayName][$name]=$value;
323: } else {
324: unset($_SESSION[$arrayName][$subArrayName][$name]);
325: }
326: } else {
327: if ($value) {
328: if ($userSessionName) {
329: $_SESSION[$arrayName][$subArrayName][$userSessionName][]=$value;
330: } else {
331: $_SESSION[$arrayName][$subArrayName][]=$value;
332: }
333: } else {
334: unset($_SESSION[$arrayName][$subArrayName]);
335: }
336: }
337: } else {
338: if ($name) {
339: if ($value) {
340: $_SESSION[$arrayName][$name]=$value;
341: } else {
342: unset($_SESSION[$arrayName][$name]);
343: }
344: } else {
345: if ($value) {
346: $_SESSION[$arrayName][]=$value;
347: } else {
348: unset($_SESSION[$arrayName]);
349: }
350: }
351: }
352: } elseif ($name) {
353: if ($value) {
354: $_SESSION[$name]=$value;
355: } else {
356: unset($_SESSION[$name]);
357: }
358: }
359: }
360:
361: /**
362: * Gets session variables.
363: *
364: * @param string $name Name of session variable
365: * @param string $subArrayName Name of session sub array.
366: * @param string $arrayName Name of session array. Default is "geolib"
367: *
368: * @return void
369: */
370: public static function session($name, $subArrayName = null, $arrayName = GEO_INSTANCE)
371: {
372:
373: if ($arrayName) {
374: if ($subArrayName) {
375: if (isset($_SESSION[$arrayName][$subArrayName][$name])) {
376: return $_SESSION[$arrayName][$subArrayName][$name];
377: }
378: } elseif (isset($_SESSION[$arrayName][$name])) {
379: return $_SESSION[$arrayName][$name];
380: }
381: } elseif ($name) {
382: if (isset($_SESSION[$name])) {
383: return $_SESSION[$name];
384: }
385: }
386: }
387:
388: /**
389: * Sends email with default parameters.
390: *
391: * @param string $text Email content
392: * @param string $subject Email subject
393: * @param string $address Email to address
394: * @param string $from Email from address
395: *
396: * @return bool success or failure form php mail()
397: */
398: public static function email($text = "debug", $subject = "debug", $address = null, $from = null)
399: {
400: if (!$address) {
401: $address = GEO_DEFAULT_EMAIL;
402: }
403:
404: if (!$from) {
405: $from = GEO_DEFAULT_FROM;
406: }
407:
408: if (is_array($text) || is_object($text)) {
409: $text = print_r($text, true);
410: }
411:
412: $headers = 'From: ' . $from . PHP_EOL;
413: $headers .= 'Content-type: text/plain; charset=utf-8' . PHP_EOL;
414: $retpath1 = '-f' . $from;
415: return mail($address, $subject, $text, $headers, $retpath1);
416: }
417:
418: /**
419: * Split array into equal pieces
420: *
421: * @param array $arr Array to be split
422: * @param int $numparts Number of pieces
423: *
424: * @return array|null Array of pieces or null if no $arr
425: */
426: public static function arraySplit($arr, $numparts)
427: {
428: if (!$arr) {
429: return null;
430: }
431: if ($numparts == 1) {
432: return array($arr);
433: }
434: $toparts = count($arr);
435: $count = 0;
436: if ($toparts > ($numparts - 1)) {
437: $portions = ceil($toparts / $numparts);
438:
439: for ($a = 1; $a < $numparts + 1; $a++) {
440: for ($yz = 0; $yz <= $portions - 1; $yz++) {
441: if (isset($arr[$count]) && $arr[$count]) {
442: $ret[$a - 1][] = $arr[$count];
443: }
444: $count++;
445: }
446: }
447: } else {
448: // Already more pieces than requested, split arrays into existing
449: // number of pieces
450: return static::arraySplit($arr, $toparts);
451: }
452: return $ret;
453: }
454:
455: /**
456: * Formats html. Leaves pre and text area tags alone
457: * Eliminates all line breaks and multiple spaces in the html, then adds new tabs and line breaks
458: * This function is memory intensive! Only use it for debugging.
459: *
460: * @param string $html Html to be formatted
461: *
462: * @return $html Formatted html
463: */
464: public static function tidy($html)
465: {
466: if (GeoDebug::isOn()) {
467: // don't tidy these tags
468: $nonTidys = array(
469: 'pre',
470: 'textarea'
471: );
472:
473: $newTidyMatches = array();
474: foreach ($nonTidys as $nonTidy) {
475: $pattern = "/<" . $nonTidy . ".*?>.*?<\/" . $nonTidy . ">/is";
476: preg_match_all($pattern, $html, $nonTidyMatches);
477:
478: if ($nonTidyMatches[0]) {
479: $newTidyMatches[$nonTidy] = $nonTidyMatches[0];
480: foreach ($newTidyMatches[$nonTidy] as $key => $match) {
481: $html = preg_replace($pattern, "GEO_" . $nonTidy . "_MATCH_" . $key, $html, 1);
482: }
483: }
484: }
485: }
486:
487: $oneliners = array('td','dl','h1','h2','h3','h4','option','li');
488: $lt = '';
489: $page = '';
490: $html = preg_replace("/(\040)+/", ' ', $html);
491: $html = preg_replace("/\s+/", ' ', $html);
492: $html = str_replace(array("\n","\r"), " ", $html);
493: $html = str_replace("> <", "><", $html);
494: $ntabs = 0;
495: $matches[4] = $html;
496:
497: // shorter strings must be after strings that include it
498: $tags="noscript|script|form|table|param|p|h1|h2|h3|h4|tr|td|html|head|title|".
499: "body|div|dd|ol|ul|link|li|blockquote|option|select|meta|object|center";
500:
501: while (preg_match("{(.*?)(</?(".$tags.").*?>)(.*)}i", $matches[4], $matches)) {
502: //geoVar($matches, 'matches');
503:
504: if ($matches[2][1] == "/") {
505: $start = false;
506: } elseif ($matches[3] == 'meta' || $matches[3] == 'link' || $matches[3] == 'param') {
507: $start = null;
508: } else {
509: $start = true;
510: }
511:
512: if ($start === false) {
513: $ntabs--;
514: } else {
515: $tt = $matches[3];
516: }
517:
518: if ($matches[1] || $matches[1] === "0") {
519: if (!in_array($lt, $oneliners)) {
520: $page .= "\n";
521:
522: if ($start == false) {
523: $page .= geoTabs($ntabs + 1);
524: } else {
525: $page .= geoTabs($ntabs);
526: }
527: }
528: $page .= $matches[1];
529: }
530:
531: if (!(in_array($lt, $oneliners) && $lstart == true && in_array($lt, $oneliners) && $start == false)) {
532: $page .= "\n";
533: $page .= geoTabs($ntabs);
534: }
535:
536: $page .= $matches[2];
537: $leftover = $matches[4];
538:
539: if ($start == true) {
540: $ntabs++;
541: }
542:
543: if (in_array($matches[2], $oneliners)) {
544: $page .= "\n" . geoTabs($ntabs);
545: }
546: $lt = $tt;
547: $lstart = $start;
548: }
549:
550: if ($page) {
551: if (GeoDebug::isOn()) {
552: if ($newTidyMatches) {
553: foreach ($newTidyMatches as $nonTidy => $matches) {
554: foreach ($matches as $key => $match) {
555: $page = preg_replace("/GEO_" . $nonTidy . "_MATCH_" . $key . "/", $match, $page, 1);
556: }
557: }
558: }
559: }
560: $page .= "\n" . geoTabs($ntabs) . $leftover;
561: $page = trim($page);
562: return $page;
563: } else {
564: return $html;
565: }
566: }
567:
568: /**
569: * Creates array from value if value is not already an array
570: *
571: * @param mixed $value Any value
572: * @param bool $returnEmptyArray If not value, instead of returning value in an array
573: * return an emtpy array;
574: *
575: * @return array
576: */
577: public static function arr($value, $returnEmptyArray = null)
578: {
579: if (is_array($value)) {
580: return $value;
581: }
582:
583: if (isset($value) || !$returnEmptyArray) {
584: return array($value);
585: }
586: return array();
587: }
588:
589: /**
590: * Returns value from array, or array if array is not an array or key is null
591: *
592: * @param array $array Source of value
593: * @param string|int $key Array key which indicates value
594: *
595: * @return mixed
596: */
597: public static function ifArr($array, $key = null)
598: {
599: if (is_array($array) && isset($key)) {
600: if (isset($array[$key])) {
601: return $array[$key];
602: }
603: return null;
604:
605: }
606:
607: return $array;
608: }
609:
610: /**
611: * Turns cents into dollars
612: *
613: * @param int|float $number Dollars or cents (default assumes dollars)
614: * @param int|bool $divisor Devide $number by this int or if $divisor
615: * is true or null, just format dollars
616: * @param bool $addDollarSign Optionally add dollar sign to result
617: *
618: * @return float
619: */
620: public static function dollars($number, $divisor = 100, $addDollarSign = null)
621: {
622: if ($divisor === true) {
623: $divisor = null;
624: }
625: if ($divisor) {
626: $number /= $divisor;
627: }
628:
629: return geoIf($addDollarSign, "$") . money_format('%n', $number);
630: }
631:
632: /**
633: * Direct browser to a different page before any page output
634: *
635: * @param string $uri target uri. If null, the requested uri without any parameters is used.
636: * If true the requested uri with any parameters is used.
637: *
638: * @return void, ends current script and redirects page
639: * @errors Will cause PHP runtime error if called after any character
640: * has been echoed
641: */
642: public static function redirect($uri = null)
643: {
644: if ($uri===true) {
645: $uri = $_SERVER['REQUEST_URI'];
646: } elseif (!strlen($uri)) {
647: $url = parse_url($_SERVER["REQUEST_URI"]);
648: $uri = $url["path"];
649: //$uri = $_SERVER['REQUEST_URI'];
650: }
651: // Redirect browser to $uri page
652: header("Location: " . $uri);
653:
654: //this is executed only if header fails and throws warning
655: echo "Redirect to $uri ($uri) failed";
656: exit;
657: }
658:
659: /**
660: * Used with jquery to make tabs
661: *
662: * @param array $contentArr Contains title and content arrays
663: * @param array $tabsClass Optional class for tabs
664: *
665: * @return mixed html and jquery to create tabs
666: *
667: * $contentArr[0] is an array of tab titles
668: * $contentArr[1] is an array of tab content
669: * If content is multi-dementional, each array is treated the same as
670: * $contentArr to create a nested set of tabs.
671: */
672: public static function makeTabs($contentArr, $tabsClass = null)
673: {
674: //GeoDebug::db($contentArr[0], 'contentArr[0]');
675: $content = $js = '';
676: $titleArr=array();
677: foreach ($contentArr[0] as $titleNum => $title) {
678: $tabNumber = ($titleNum + 1);
679: $tabId = "tabs-" . $tabNumber;
680:
681: $titleArr[] = geoLink("#" . $tabId, $title);
682:
683: if (is_array($contentArr[1][$titleNum])) {
684: $js .= "$('#tabs" . $tabNumber . "').tabs();";
685: $contentArr[1][$titleNum] = static::makeTabs(
686: $contentArr[1][$titleNum],
687: $tabNumber
688: );
689: }
690:
691: $content .= div(
692: div($contentArr[1][$titleNum], null, 'tabs' . $tabNumber),
693: null,
694: $tabId
695: );
696: }
697:
698: $js = "$('#tabs').tabs();" . $js;
699: return div(
700: geoList($titleArr).$content,
701: $tabsClass,
702: 'tabs'
703: ).geoScript(true, $js);
704: }
705:
706: /**
707: * Creates a css table from a multidimensional array
708: *
709: * @param array $rows A mulitidemensional array. Each row is an array of content
710: * If the row index is non numeric:
711: * -The row index will be used as the row id
712: * -If the row index has one or more underlines "_"
713: * -The first segment will be used as the row class
714: * -Otherwise, if the row index has no underlines
715: * -The row index will also be used as the row class
716: *
717: * @param array|string $classes Wrapper Class or classes (in addition to the default wrapper class(es))
718: * @param array|string $rowClasses If $rowClasses is an array each value is a class for a corresponding row.
719: This will only work is if $rows and $rowClassess have matching indexes.
720: * If $rowClasses is a string it becomes the class for all rows
721: * @param array|string $rowIds If $rowIds is an array, each value is an id for a corresponding content row
722: * If $rowIds is a string, the id for a corresponding content row is the row
723: * key plus "_" plus the string.
724: * @param array|string $columnClasses If an array each value is a class for a corresponding content column.
725: * If a string it becomes the class for all rows
726: * @param string $tableClass Default class or classes for wrapper. Default is "cssTable"
727: *
728: * @return string|html
729: */
730: public static function cssTable(
731: $rows,
732: $classes = null,
733: $rowClasses = null,
734: $rowIds = null,
735: $columnClasses = null,
736: $tableClass = "cssTable"
737: ) {
738:
739: if (isset($rows) && $rows) {
740: $classes = static::arr($classes, true);
741:
742: if ($tableClass) {
743: $classes[] = $tableClass;
744: }
745:
746: foreach ($rows as $key => $row) {
747:
748: if (!is_numeric($key)){
749: $rowIds[$key]=$key;
750: $rowClasses[$key]=static::exp($key,0);
751: }
752:
753: $allRows[$key]=div($row, $columnClasses);
754: }
755:
756: return div(div($allRows, $rowClasses, $rowIds), geoIf($classes, implode(' ', $classes)));
757:
758: }
759:
760: }
761:
762: /**
763: * Case insensitive version of PHP's in_array
764: *
765: * @param string $search Variable to test for
766: * @param array $array Target of case insensitive search
767: *
768: * @return bool
769: */
770: public static function inArrayi($search, &$array)
771: {
772: $search = strtolower($search);
773: foreach ($array as $item) {
774: if (strtolower($item) == $search) {
775: return true;
776: }
777: }
778: return false;
779: }
780:
781: /**
782: * Allows inline test for value.
783: * Same as geoIf, except it can test undefined variables but not constants.
784: *
785: * @param mixed $var Variable to be tested for value
786: * @param mixed $result1 Value to be returned if test is passed
787: * @param mixed $result2 Value to be returns if test fails
788: *
789: * @return mixed Result of test
790: */
791: public static function ifVal(&$var, &$result1 = true, &$result2 = null)
792: {
793: if ($var) {
794: return $result1;
795: }
796: return $result2;
797: }
798:
799: /**
800: * Recurve method to get file names from a directory.
801: *
802: * @param string $dirstr Directory to get filenames from
803: * @param bool $includeSubDirs Flag to indicate names of files from subdirectories will be included.
804: * @param bool $geoLinks Flag to indicate that the filenames will be linked to the files.
805: * @param array $skips Names of files to skip over
806: *
807: * @return array File names
808: */
809: public static function fileNames(
810: $dirstr = null,
811: $includeSubDirs = false,
812: $geoLinks = true,
813: $skips = array('error_log', 'Thumbs.db', 'Desktop.ini', '.htaccess', '.htpasswd')
814: ) {
815:
816: if ($dirstr) {
817: $dirstr .= "/";
818: } else {
819: $dirstr = "./";
820: }
821:
822: if (is_dir($dirstr)) {
823: $fh = opendir($dirstr);
824: }
825:
826:
827: if ($fh) {
828: $skips = static::arr($skips);
829: $files = $directories = array();
830:
831: while (false !== ($filename = readdir($fh))) {
832: $prefiles[] = $filename;
833: }
834:
835: natsort($prefiles);
836: $prefiles = array_values($prefiles);
837:
838: foreach ($prefiles as $filename) {
839: $dirFile = $dirstr . $filename;
840: if ($filename != '.' && $filename != '..' && !in_array($filename, $skips)) {
841: if ($includeSubDirs && is_dir($dirFile)) {
842: $directories[$filename]
843: = static::fileNames($dirstr . $filename, $includeSubDirs, $geoLinks, $skips);
844: } elseif ($geoLinks) {
845: $files[] = geoLink($dirstr . $filename, $filename);
846: } else {
847: $files[] = $filename;
848: }
849: }
850: }
851: closedir($fh);
852:
853: if ($directories) {
854: $files['directories'] = $directories;
855: }
856:
857: return $files;
858: }
859: }
860:
861:
862: /**
863: * Creates validated text input fields, or simply displays values
864: *
865: * @param string $name Input name
866: * @param array $values Reference to array of values (usually from database)
867: * @param array $missing Reference to array of validation messages
868: * @param string $prefix Prefix to add to name
869: * @param string $printableClass Display data as strings instead of text input fields, and use this as class
870: *
871: * @return HTML text input with validation
872: */
873: public static function validText($name, &$values, &$missing, $prefix = null, $printableClass = null, $class = null)
874: {
875: if (isset($values[$name])) {
876: $value=$values[$name];
877: } else {
878: $value='';
879: }
880:
881: if ($printableClass) {
882: return span($value, $printableClass);
883: }
884:
885: if ($prefix) {
886: $prefixName=$prefix."_".$name;
887: } else {
888: $prefixName=$name;
889: }
890:
891:
892: $input=geoInput('text', $prefixName, $value, null, $prefixName, $class);
893: if (isset($missing[$prefixName])) {
894: $input.=div($missing[$prefixName], 'errorText');
895: }
896: return $input;
897: }
898: }
899: