Cast.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. <?php
  2. /**
  3. * Prototype Castable Object.. for DataObject queries
  4. *
  5. * Storage for Data that may be cast into a variety of formats.
  6. *
  7. * PHP versions 4 and 5
  8. *
  9. * LICENSE: This source file is subject to version 3.01 of the PHP license
  10. * that is available through the world-wide-web at the following URI:
  11. * http://www.php.net/license/3_01.txt. If you did not receive a copy of
  12. * the PHP License and are unable to obtain it through the web, please
  13. * send a note to license@php.net so we can mail you a copy immediately.
  14. *
  15. * @category Database
  16. * @package DB_DataObject
  17. * @author Alan Knowles <alan@akbkhome.com>
  18. * @copyright 1997-2008 The PHP Group
  19. * @license http://www.php.net/license/3_01.txt PHP License 3.01
  20. * @version CVS: $Id: Cast.php 287158 2009-08-12 13:58:31Z alan_k $
  21. * @link http://pear.php.net/package/DB_DataObject
  22. */
  23. /**
  24. *
  25. * Common usages:
  26. * // blobs
  27. * $data = DB_DataObject_Cast::blob($somefile);
  28. * $data = DB_DataObject_Cast::string($somefile);
  29. * $dataObject->someblobfield = $data
  30. *
  31. * // dates?
  32. * $d1 = new DB_DataObject_Cast::date('12/12/2000');
  33. * $d2 = new DB_DataObject_Cast::date(2000,12,30);
  34. * $d3 = new DB_DataObject_Cast::date($d1->year, $d1->month+30, $d1->day+30);
  35. *
  36. * // time, datetime.. ?????????
  37. *
  38. * // raw sql????
  39. * $data = DB_DataObject_Cast::sql('cast("123123",datetime)');
  40. * $data = DB_DataObject_Cast::sql('NULL');
  41. *
  42. * // int's/string etc. are probably pretty pointless..!!!!
  43. *
  44. *
  45. * inside DB_DataObject,
  46. * if (is_a($v,'db_dataobject_class')) {
  47. * $value .= $v->toString(DB_DATAOBJECT_INT,'mysql');
  48. * }
  49. *
  50. *
  51. *
  52. *
  53. */
  54. class DB_DataObject_Cast
  55. {
  56. /**
  57. * Type of data Stored in the object..
  58. *
  59. * @var string (date|blob|.....?)
  60. * @access public
  61. */
  62. public $type;
  63. /**
  64. * Data For date representation
  65. *
  66. * @var int day/month/year
  67. * @access public
  68. */
  69. public $day;
  70. public $month;
  71. public $year;
  72. /**
  73. * Generic Data..
  74. *
  75. * @var string
  76. * @access public
  77. */
  78. public $value;
  79. /**
  80. * Data For time representation ** does not handle timezones!!
  81. *
  82. * @var int hour/minute/second
  83. * @access public
  84. */
  85. public $hour;
  86. public $minute;
  87. public $second;
  88. /**
  89. * Blob consructor
  90. *
  91. * create a Cast object from some raw data.. (binary)
  92. *
  93. *
  94. * @param string (with binary data!)
  95. *
  96. * @return object DB_DataObject_Cast
  97. * @access public
  98. */
  99. public function blob($value)
  100. {
  101. $r = new DB_DataObject_Cast;
  102. $r->type = 'blob';
  103. $r->value = $value;
  104. return $r;
  105. }
  106. /**
  107. * String consructor (actually use if for ints and everything else!!!
  108. *
  109. * create a Cast object from some string (not binary)
  110. *
  111. *
  112. * @param string (with binary data!)
  113. *
  114. * @return object DB_DataObject_Cast
  115. * @access public
  116. */
  117. public function string($value)
  118. {
  119. $r = new DB_DataObject_Cast;
  120. $r->type = 'string';
  121. $r->value = $value;
  122. return $r;
  123. }
  124. /**
  125. * SQL constructor (for raw SQL insert)
  126. *
  127. * create a Cast object from some sql
  128. *
  129. * @param string (with binary data!)
  130. *
  131. * @return object DB_DataObject_Cast
  132. * @access public
  133. */
  134. public function sql($value)
  135. {
  136. $r = new DB_DataObject_Cast;
  137. $r->type = 'sql';
  138. $r->value = $value;
  139. return $r;
  140. }
  141. /**
  142. * DateTime Constructor
  143. *
  144. * create a Cast object from a Date/Time
  145. * Maybe should accept a Date object.!
  146. * NO VALIDATION DONE, although some crappy re-calcing done!
  147. *
  148. * @param vargs... accepts
  149. * noargs (now)
  150. * yyyy-mm-dd HH:MM:SS (Iso)
  151. * array(yyyy,mm,dd,HH,MM,SS)
  152. *
  153. *
  154. * @return bool|object
  155. * @access public
  156. * @author therion 5 at hotmail
  157. */
  158. public function dateTime()
  159. {
  160. $args = func_get_args();
  161. switch (count($args)) {
  162. case 0: // no args = now!
  163. $datetime = date('Y-m-d G:i:s', mktime());
  164. // no break
  165. case 1:
  166. // continue on from 0 args.
  167. if (!isset($datetime)) {
  168. $datetime = $args[0];
  169. }
  170. $parts = explode(' ', $datetime);
  171. $bits = explode('-', $parts[0]);
  172. $bits = array_merge($bits, explode(':', $parts[1]));
  173. break;
  174. default: // 2 or more..
  175. $bits = $args;
  176. }
  177. if (count($bits) != 6) {
  178. // PEAR ERROR?
  179. return false;
  180. }
  181. $r = DB_DataObject_Cast::date($bits[0], $bits[1], $bits[2]);
  182. if (!$r) {
  183. return $r; // pass thru error (False) - doesnt happen at present!
  184. }
  185. // change the type!
  186. $r->type = 'datetime';
  187. // should we mathematically sort this out..
  188. // (or just assume that no-one's dumb enough to enter 26:90:90 as a time!
  189. $r->hour = $bits[3];
  190. $r->minute = $bits[4];
  191. $r->second = $bits[5];
  192. return $r;
  193. }
  194. /**
  195. * Date Constructor
  196. *
  197. * create a Cast object from some string (not binary)
  198. * NO VALIDATION DONE, although some crappy re-calcing done!
  199. *
  200. * @param vargs... accepts
  201. * dd/mm
  202. * dd/mm/yyyy
  203. * yyyy-mm
  204. * yyyy-mm-dd
  205. * array(yyyy,dd)
  206. * array(yyyy,dd,mm)
  207. *
  208. *
  209. *
  210. * @return object DB_DataObject_Cast
  211. * @access public
  212. */
  213. public function date()
  214. {
  215. $args = func_get_args();
  216. switch (count($args)) {
  217. case 0: // no args = today!
  218. $bits = explode('-', date('Y-m-d'));
  219. break;
  220. case 1: // one arg = a string
  221. if (strpos($args[0], '/') !== false) {
  222. $bits = array_reverse(explode('/', $args[0]));
  223. } else {
  224. $bits = explode('-', $args[0]);
  225. }
  226. break;
  227. default: // 2 or more..
  228. $bits = $args;
  229. }
  230. if (count($bits) == 1) { // if YYYY set day = 1st..
  231. $bits[] = 1;
  232. }
  233. if (count($bits) == 2) { // if YYYY-DD set day = 1st..
  234. $bits[] = 1;
  235. }
  236. // if year < 1970 we cant use system tools to check it...
  237. // so we make a few best gueses....
  238. // basically do date calculations for the year 2000!!!
  239. // fix me if anyone has more time...
  240. if (($bits[0] < 1975) || ($bits[0] > 2030)) {
  241. $oldyear = $bits[0];
  242. $bits = explode('-', date('Y-m-d', mktime(1, 1, 1, $bits[1], $bits[2], 2000)));
  243. $bits[0] = ($bits[0] - 2000) + $oldyear;
  244. } else {
  245. // now mktime
  246. $bits = explode('-', date('Y-m-d', mktime(1, 1, 1, $bits[1], $bits[2], $bits[0])));
  247. }
  248. $r = new DB_DataObject_Cast;
  249. $r->type = 'date';
  250. list($r->year, $r->month, $r->day) = $bits;
  251. return $r;
  252. }
  253. /**
  254. * time Constructor
  255. *
  256. * create a Cast object from a Date/Time
  257. * Maybe should accept a Date object.!
  258. * NO VALIDATION DONE, and no-recalcing done!
  259. *
  260. * @param vargs... accepts
  261. * noargs (now)
  262. * HH:MM:SS (Iso)
  263. * array(HH,MM,SS)
  264. *
  265. *
  266. * @return bool|object
  267. * @access public
  268. * @author therion 5 at hotmail
  269. */
  270. public function time()
  271. {
  272. $args = func_get_args();
  273. switch (count($args)) {
  274. case 0: // no args = now!
  275. $time = date('G:i:s', mktime());
  276. // no break
  277. case 1:
  278. // continue on from 0 args.
  279. if (!isset($time)) {
  280. $time = $args[0];
  281. }
  282. $bits = explode(':', $time);
  283. break;
  284. default: // 2 or more..
  285. $bits = $args;
  286. }
  287. if (count($bits) != 3) {
  288. return false;
  289. }
  290. // now take data from bits into object fields
  291. $r = new DB_DataObject_Cast;
  292. $r->type = 'time';
  293. $r->hour = $bits[0];
  294. $r->minute = $bits[1];
  295. $r->second = $bits[2];
  296. return $r;
  297. }
  298. /**
  299. * get the string to use in the SQL statement for this...
  300. *
  301. *
  302. * @param bool $to Type (DB_DATAOBJECT_*
  303. * @param object $db DB Connection Object
  304. *
  305. *
  306. * @return string
  307. * @access public
  308. */
  309. public function toString($to = false, $db)
  310. {
  311. // if $this->type is not set, we are in serious trouble!!!!
  312. // values for to:
  313. $method = 'toStringFrom' . $this->type;
  314. return $this->$method($to, $db);
  315. }
  316. /**
  317. * get the string to use in the SQL statement from a blob of binary data
  318. * ** Suppots only blob->postgres::bytea
  319. *
  320. * @param int $to Type (DB_DATAOBJECT_*
  321. * @param object $db DB Connection Object
  322. *
  323. *
  324. * @return string
  325. * @access public
  326. */
  327. public function toStringFromBlob($to, $db)
  328. {
  329. // first weed out invalid casts..
  330. // in blobs can only be cast to blobs.!
  331. // perhaps we should support TEXT fields???
  332. if (!($to & DB_DATAOBJECT_BLOB)) {
  333. return (new PEAR)->raiseError('Invalid Cast from a DB_DataObject_Cast::blob to something other than a blob!');
  334. }
  335. switch ($db->dsn["phptype"]) {
  336. case 'pgsql':
  337. return "'" . pg_escape_bytea($this->value) . "'::bytea";
  338. case 'mysql':
  339. return "'" . mysql_real_escape_string($this->value, $db->connection) . "'";
  340. case 'mysqli':
  341. // this is funny - the parameter order is reversed ;)
  342. return "'" . mysqli_real_escape_string($db->connection, $this->value) . "'";
  343. case 'sqlite':
  344. // this is funny - the parameter order is reversed ;)
  345. return "'" . sqlite_escape_string($this->value) . "'";
  346. case 'mssql':
  347. if (is_numeric($this->value)) {
  348. return $this->value;
  349. }
  350. $unpacked = unpack('H*hex', $this->value);
  351. return '0x' . $unpacked['hex'];
  352. default:
  353. return (new PEAR)->raiseError("DB_DataObject_Cast cant handle blobs for Database:{$db->dsn['phptype']} Yet");
  354. }
  355. }
  356. /**
  357. * get the string to use in the SQL statement for a blob from a string!
  358. * ** Suppots only string->postgres::bytea
  359. *
  360. *
  361. * @param int $to Type (DB_DATAOBJECT_*
  362. * @param object $db DB Connection Object
  363. *
  364. *
  365. * @return string
  366. * @access public
  367. */
  368. public function toStringFromString($to, $db)
  369. {
  370. // first weed out invalid casts..
  371. // in blobs can only be cast to blobs.!
  372. // perhaps we should support TEXT fields???
  373. //
  374. // $to == a string field which is the default type (0)
  375. // so we do not test it here. - we assume that number fields
  376. // will accept a string?? - which is stretching it a bit ...
  377. // should probaly add that test as some point.
  378. switch ($db->dsn['phptype']) {
  379. case 'pgsql':
  380. return "'" . pg_escape_string($this->value) . "'::bytea";
  381. case 'mysql':
  382. return "'" . mysql_real_escape_string($this->value, $db->connection) . "'";
  383. case 'mysqli':
  384. return "'" . mysqli_real_escape_string($db->connection, $this->value) . "'";
  385. case 'mssql':
  386. // copied from the old DB mssql code...?? not sure how safe this is.
  387. return "'" . str_replace(
  388. array("'", "\\\r\n", "\\\n"),
  389. array("''", "\\\\\r\n\r\n", "\\\\\n\n"),
  390. $this->value
  391. ) . "'";
  392. default:
  393. return (new PEAR)->raiseError("DB_DataObject_Cast cant handle blobs for Database:{$db->dsn['phptype']} Yet");
  394. }
  395. }
  396. /**
  397. * get the string to use in the SQL statement for a date
  398. *
  399. *
  400. *
  401. * @param int $to Type (DB_DATAOBJECT_*
  402. * @param object $db DB Connection Object
  403. *
  404. *
  405. * @return string
  406. * @access public
  407. */
  408. public function toStringFromDate($to, $db)
  409. {
  410. // first weed out invalid casts..
  411. // in blobs can only be cast to blobs.!
  412. // perhaps we should support TEXT fields???
  413. //
  414. if (($to !== false) && !($to & DB_DATAOBJECT_DATE)) {
  415. return (new PEAR)->raiseError('Invalid Cast from a DB_DataObject_Cast::string to something other than a date!' .
  416. ' (why not just use native features)');
  417. }
  418. return "'{$this->year}-{$this->month}-{$this->day}'";
  419. }
  420. /**
  421. * get the string to use in the SQL statement for a datetime
  422. *
  423. *
  424. *
  425. * @param int $to Type (DB_DATAOBJECT_*
  426. * @param object $db DB Connection Object
  427. *
  428. *
  429. * @return string
  430. * @access public
  431. * @author therion 5 at hotmail
  432. */
  433. public function toStringFromDateTime($to, $db)
  434. {
  435. // first weed out invalid casts..
  436. // in blobs can only be cast to blobs.!
  437. // perhaps we should support TEXT fields???
  438. if (($to !== false) &&
  439. !($to & (DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME))) {
  440. return (new PEAR)->raiseError('Invalid Cast from a ' .
  441. ' DB_DataObject_Cast::dateTime to something other than a datetime!' .
  442. ' (try using native features)');
  443. }
  444. return "'{$this->year}-{$this->month}-{$this->day} {$this->hour}:{$this->minute}:{$this->second}'";
  445. }
  446. /**
  447. * get the string to use in the SQL statement for a time
  448. *
  449. *
  450. *
  451. * @param int $to Type (DB_DATAOBJECT_*
  452. * @param object $db DB Connection Object
  453. *
  454. *
  455. * @return string
  456. * @access public
  457. * @author therion 5 at hotmail
  458. */
  459. public function toStringFromTime($to, $db)
  460. {
  461. // first weed out invalid casts..
  462. // in blobs can only be cast to blobs.!
  463. // perhaps we should support TEXT fields???
  464. if (($to !== false) && !($to & DB_DATAOBJECT_TIME)) {
  465. return (new PEAR)->raiseError('Invalid Cast from a' .
  466. ' DB_DataObject_Cast::time to something other than a time!' .
  467. ' (try using native features)');
  468. }
  469. return "'{$this->hour}:{$this->minute}:{$this->second}'";
  470. }
  471. /**
  472. * get the string to use in the SQL statement for a raw sql statement.
  473. *
  474. * @param int $to Type (DB_DATAOBJECT_*
  475. * @param object $db DB Connection Object
  476. *
  477. *
  478. * @return string
  479. * @access public
  480. */
  481. public function toStringFromSql($to, $db)
  482. {
  483. return $this->value;
  484. }
  485. }