1: <?php
2: /**
3: * An abstract utility class to handle string manipulation. All methods
4: * are statically available.
5: */
6: abstract class QString {
7: /**
8: * This faux constructor method throws a caller exception.
9: * The String object should never be instantiated, and this constructor
10: * override simply guarantees it.
11: *
12: * @throws QCallerException
13: */
14: public final function __construct() {
15: throw new QCallerException('String should never be instantiated. All methods and variables are publically statically accessible.');
16: }
17:
18: /**
19: * Returns the first character of a given string, or null if the given
20: * string is null.
21: *
22: * @param string $strString
23: *
24: * @return string the first character, or null
25: */
26: public final static function FirstCharacter($strString) {
27: if (defined('__QAPPLICATION_ENCODING_TYPE__')) {
28: if (mb_strlen($strString, __QAPPLICATION_ENCODING_TYPE__) > 0)
29: return mb_substr($strString, 0 , 1, __QAPPLICATION_ENCODING_TYPE__);
30: else
31: return null;
32: } else {
33: if (strlen($strString)) {
34: return $strString[0];
35: } else {
36: return null;
37: }
38: }
39: }
40:
41: /**
42: * Returns the last character of a given string, or null if the given
43: * string is null.
44: *
45: * @param string $strString
46: *
47: * @return string the last character, or null
48: */
49: public final static function LastCharacter($strString) {
50: if (defined('__QAPPLICATION_ENCODING_TYPE__')) {
51: $intLength = mb_strlen($strString, __QAPPLICATION_ENCODING_TYPE__);
52: if ($intLength > 0)
53: return mb_substr($strString, $intLength - 1, 1, __QAPPLICATION_ENCODING_TYPE__);
54: else
55: return null;
56: } else {
57: $intLength = strlen($strString);
58: if ($intLength > 0)
59: return $strString[$intLength -1];
60: else
61: return null;
62: }
63: }
64:
65: /**
66: * Checks whether a given string starts with another (sub)string
67: *
68: * @param string $strHaystack
69: * @param string $strNeedle
70: *
71: * @return bool
72: */
73: public final static function StartsWith($strHaystack, $strNeedle) {
74: // If the length of needle is greater than the length of haystack, then return false
75: if(strlen($strNeedle) > strlen($strHaystack)){
76: // To supress the error in strpos function below
77: return false;
78: }
79:
80: // search backwards starting from haystack length characters from the end
81: return $strNeedle === "" || strrpos($strHaystack, $strNeedle, -strlen($strHaystack)) !== false;
82: }
83:
84: /**
85: * Checks whether a given string ends with another (sub)string
86: *
87: * @param string $strHaystack
88: * @param string $strNeedle
89: *
90: * @return bool
91: */
92: public final static function EndsWith($strHaystack, $strNeedle) {
93: // If the length of needle is greater than the length of haystack, then return false
94: if(strlen($strNeedle) > strlen($strHaystack)){
95: // To supress the error in strpos function below
96: return false;
97: }
98:
99: // search forward starting from end minus needle length characters
100: return $strNeedle === "" || strpos($strHaystack, $strNeedle, strlen($strHaystack) - strlen($strNeedle)) !== false;
101: }
102:
103: /**
104: * Truncates the string to a given length, adding elipses (if needed).
105: *
106: * @param string $strText string to truncate
107: * @param integer $intMaxLength the maximum possible length of the string to return (including length of the elipse)
108: *
109: * @return string the full string or the truncated string with eplise
110: */
111: public final static function Truncate($strText, $intMaxLength) {
112: if (mb_strlen($strText, __QAPPLICATION_ENCODING_TYPE__) > $intMaxLength)
113: return mb_substr($strText, 0, $intMaxLength - 3, __QAPPLICATION_ENCODING_TYPE__) . "...";
114: else
115: return $strText;
116: }
117:
118: /**
119: * Escapes the string so that it can be safely used in as an Xml Node (basically, adding CDATA if needed)
120: *
121: * @param string $strString string to escape
122: *
123: * @return string the XML Node-safe String
124: */
125: public final static function XmlEscape($strString) {
126: if ((mb_strpos($strString, '<', 0, __QAPPLICATION_ENCODING_TYPE__) !== false) ||
127: (mb_strpos($strString, '&', 0, __QAPPLICATION_ENCODING_TYPE__) !== false)) {
128: $strString = str_replace(']]>', ']]]]><![CDATA[>', $strString);
129: $strString = sprintf('<![CDATA[%s]]>', $strString);
130: }
131:
132: return $strString;
133: }
134:
135: /**
136: * Finds longest substring which is common among two strings
137: *
138: * @param string $str1
139: * @param string $str2
140: *
141: * @return string
142: */
143: // Implementation from http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring
144: public final static function LongestCommonSubsequence($str1, $str2) {
145: if (defined('__QAPPLICATION_ENCODING_TYPE__')) {
146: $str1Len = mb_strlen($str1, __QAPPLICATION_ENCODING_TYPE__);
147: $str2Len = mb_strlen($str2, __QAPPLICATION_ENCODING_TYPE__);
148: } else {
149: $str1Len = strlen($str1);
150: $str2Len = strlen($str2);
151: }
152:
153: if($str1Len == 0 || $str2Len == 0)
154: return '';
155:
156: $CSL = array(); //Common Sequence Length array
157: $intLargestSize = 0;
158: $ret = array();
159:
160: //initialize the CSL array to assume there are no similarities
161: for($i=0; $i<$str1Len; $i++){
162: $CSL[$i] = array();
163: for($j=0; $j<$str2Len; $j++){
164: $CSL[$i][$j] = 0;
165: }
166: }
167:
168: for($i=0; $i<$str1Len; $i++){
169: for($j=0; $j<$str2Len; $j++){
170: //check every combination of characters
171: if( $str1[$i] == $str2[$j] ){
172: //these are the same in both strings
173: if($i == 0 || $j == 0)
174: //it's the first character, so it's clearly only 1 character long
175: $CSL[$i][$j] = 1;
176: else
177: //it's one character longer than the string from the previous character
178: $CSL[$i][$j] = $CSL[$i-1][$j-1] + 1;
179:
180: if( $CSL[$i][$j] > $intLargestSize ){
181: //remember this as the largest
182: $intLargestSize = $CSL[$i][$j];
183: //wipe any previous results
184: $ret = array();
185: //and then fall through to remember this new value
186: }
187: if( $CSL[$i][$j] == $intLargestSize )
188: //remember the largest string(s)
189: $ret[] = substr($str1, $i-$intLargestSize+1, $intLargestSize);
190: }
191: //else, $CSL should be set to 0, which it was already initialized to
192: }
193: }
194: //return the first match
195: if(count($ret) > 0)
196: return $ret[0];
197: else
198: return ''; //no matches
199: }
200: }