Erebot  latest
A modular IRC bot for PHP 5.3+
Utils.php
1 <?php
2 /*
3  This file is part of Erebot, a modular IRC bot written in PHP.
4 
5  Copyright © 2010 François Poirotte
6 
7  Erebot is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Erebot is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Erebot. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 namespace Erebot;
22 
27 class Utils
28 {
30  const VSTATIC_CONST = 0x01;
31 
33  const VSTATIC_VAR = 0x02;
34 
60  public static function getCallerObject()
61  {
62  $bt = debug_backtrace();
63  $caller = isset($bt[2]['object']) ? $bt[2]['object'] : null;
64  return $caller;
65  }
66 
80  public static function isUTF8($text)
81  {
82  // From http://w3.org/International/questions/qa-forms-utf-8.html
83  // Pointed out by bitseeker on http://php.net/utf8_encode
84  return (bool) preg_match(
85  '%^(?:
86  [\x09\x0A\x0D\x20-\x7E] # ASCII
87  | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
88  | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
89  | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
90  | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
91  | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
92  | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
93  | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
94  )*$%SDxs',
95  $text
96  );
97  }
98 
124  public static function toUTF8($text, $from = 'iso-8859-1')
125  {
126  $alreadyEncoded = self::isUTF8($text);
127 
128  // Special value so that double-encoded text can be decoded.
129  if ($from == '__double') {
130  if ($alreadyEncoded) {
131  // If no decoding function is available, we'll just
132  // return the double-encoded text as-is.
133  // This is better than throwing an exception anyway.
134  $res = $text;
135 
136  if (function_exists('utf8_decode')) {
137  $res = utf8_decode($text);
138  } elseif (function_exists('iconv')) {
139  $res = iconv('utf-8', 'iso-8859-1//TRANSLIT', $text);
140  } elseif (function_exists('recode')) {
141  $res = recode('utf-8..iso-8859-1', $text);
142  } elseif (function_exists('mb_convert_encoding')) {
143  $res = mb_convert_encoding($text, 'iso-8859-1', 'utf-8');
144  } elseif (function_exists('html_entity_decode')) {
145  $res = html_entity_decode(
146  htmlentities($text, ENT_QUOTES, 'utf-8'),
147  ENT_QUOTES,
148  'iso-8850-1'
149  );
150  }
151 
152  // So, was it really double-encoded?
153  return (self::isUTF8($res) ? $res : $text);
154  }
155 
156  // Someone tried to foul us, but we'll foul them instead.
157  // Here we blindly assume the text is in ISO-8859-1.
158  $from = 'iso-8859-1';
159  }
160 
161  if ($alreadyEncoded) {
162  return $text;
163  }
164 
165  if (!strcasecmp($from, 'iso-8859-1') &&
166  function_exists('utf8_encode')) {
167  return utf8_encode($text);
168  }
169 
170  if (function_exists('iconv')) {
171  return iconv($from, 'UTF-8//TRANSLIT', $text);
172  }
173 
174  if (function_exists('recode')) {
175  return recode($from.'..utf-8', $text);
176  }
177 
178  if (function_exists('mb_convert_encoding')) {
179  return mb_convert_encoding($text, 'UTF-8', $from);
180  }
181 
182  if (function_exists('html_entity_decode')) {
183  return html_entity_decode(
184  htmlentities($text, ENT_QUOTES, $from),
185  ENT_QUOTES,
186  'UTF-8'
187  );
188  }
189 
190  throw new \Erebot\NotImplementedException('No way to convert to UTF-8');
191  }
192 
218  public static function getVStatic(
219  $class,
220  $name,
221  $source = self::VSTATIC_CONST
222  ) {
223  if (is_object($class)) {
224  $class = get_class($class);
225  }
226  $refl = new \ReflectionClass($class);
227 
228  if (($source & self::VSTATIC_CONST) == self::VSTATIC_CONST) {
229  try {
230  return $refl->getConstant($name);
231  } catch (ReflectionException $e) {
232  }
233  }
234 
235  if (($source & self::VSTATIC_VAR) == self::VSTATIC_VAR) {
236  try {
237  $reflProp = $refl->getProperty($name);
238  return $reflProp->getValue();
239  } catch (ReflectionException $e) {
240  }
241  }
242 
243  throw new \Erebot\NotFoundException('No such thing');
244  }
245 
257  public static function stringifiable($item)
258  {
259  if (is_string($item)) {
260  return true;
261  }
262  if (is_object($item) && method_exists($item, '__toString')) {
263  return true;
264  }
265  return false;
266  }
267 
280  public static function humanSize($size, $max = null, $system = 'si', $retstring = '%01.2f %s')
281  {
282  // Pick units
283  $systems = array();
284  $systems['si']['suffix'] = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
285  $systems['si']['size'] = 1000;
286  $systems['bi']['suffix'] = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB');
287  $systems['bi']['size'] = 1024;
288  $sys = isset($systems[$system]) ? $systems[$system] : $systems['si'];
289 
290  // Max unit to display
291  $depth = count($sys['suffix']) - 1;
292  if ($max && false !== $d = array_search($max, $sys['suffix'])) {
293  $depth = $d;
294  }
295 
296  // Loop
297  $i = 0;
298  while ($size >= $sys['size'] && $i < $depth) {
299  $size /= $sys['size'];
300  $i++;
301  }
302 
303  return sprintf($retstring, $size, $sys['suffix'][$i]);
304  }
305 
319  public static function parseHumanSize($humanSize)
320  {
321  $size = (float) str_replace(",", ".", $humanSize);
322  $suffix = (string) substr(
323  $humanSize,
324  strspn($humanSize, "1234567890.,+-")
325  );
326  $suffix = trim($suffix);
327  $exponents = array_flip(array('', 'K', 'M', 'G', 'T', 'P'));
328  $base = 1000;
329 
330  switch (strlen($suffix)) {
331  case 0:
332  return null;
333 
334  case 1:
335  $exp = 0;
336  break;
337 
338  case 3:
339  // 3 chars? We MUST be using SI units then.
340  if ($suffix[1] != 'i') {
341  return null;
342  }
343  $suffix = $suffix[0].$suffix[1];
344  $base = 1024;
345  // We don't break on purpose.
346 
347  case 2:
348  if (!isset($exponents[$suffix[0]])) {
349  return null;
350  }
351  $exp = $exponents[$suffix[0]];
352  }
353  return (int) ($size * pow($base, $exp));
354  }
355 }
Definition: CLI.php:21
Utility methods for Erebot.
Definition: Utils.php:27
static getVStatic($class, $name, $source=self::VSTATIC_CONST)
Definition: Utils.php:218
static stringifiable($item)
Definition: Utils.php:257
static parseHumanSize($humanSize)
Definition: Utils.php:319
static getCallerObject()
Definition: Utils.php:60
static humanSize($size, $max=null, $system= 'si', $retstring= '%01.2f%s')
Definition: Utils.php:280
static toUTF8($text, $from= 'iso-8859-1')
Definition: Utils.php:124
static isUTF8($text)
Definition: Utils.php:80