1: <?php
2: // $Id: object.php,v 1.1 2007/05/15 02:34:37 minahito Exp $
3: // ------------------------------------------------------------------------ //
4: // XOOPS - PHP Content Management System //
5: // Copyright (c) 2000 XOOPS.org //
6: // <http://www.xoops.org/> //
7: // ------------------------------------------------------------------------ //
8: // This program is free software; you can redistribute it and/or modify //
9: // it under the terms of the GNU General Public License as published by //
10: // the Free Software Foundation; either version 2 of the License, or //
11: // (at your option) any later version. //
12: // //
13: // You may not change or alter any portion of this comment or credits //
14: // of supporting developers from this source code or any supporting //
15: // source code which is considered copyrighted (c) material of the //
16: // original comment or credit authors. //
17: // //
18: // This program is distributed in the hope that it will be useful, //
19: // but WITHOUT ANY WARRANTY; without even the implied warranty of //
20: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
21: // GNU General Public License for more details. //
22: // //
23: // You should have received a copy of the GNU General Public License //
24: // along with this program; if not, write to the Free Software //
25: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
26: // ------------------------------------------------------------------------ //
27: // Author: Kazumi Ono (AKA onokazu) //
28: // URL: http://www.myweb.ne.jp/, http://www.xoops.org/, http://xoopscube.jp/ //
29: // Project: The XOOPS Project //
30: // ------------------------------------------------------------------------- //
31:
32: /**
33: * @package kernel
34: * @copyright copyright © 2000 XOOPS.org
35: */
36:
37: /**#@+
38: * Xoops object datatype
39: *
40: **/
41: define('XOBJ_DTYPE_STRING', 1);
42: define('XOBJ_DTYPE_TXTBOX', 1);
43: define('XOBJ_DTYPE_TEXT', 2);
44: define('XOBJ_DTYPE_TXTAREA', 2);
45: define('XOBJ_DTYPE_INT', 3);
46: define('XOBJ_DTYPE_URL', 4);
47: define('XOBJ_DTYPE_EMAIL', 5);
48: define('XOBJ_DTYPE_ARRAY', 6);
49: define('XOBJ_DTYPE_OTHER', 7);
50: define('XOBJ_DTYPE_SOURCE', 8);
51: define('XOBJ_DTYPE_STIME', 9);
52: define('XOBJ_DTYPE_MTIME', 10);
53: define('XOBJ_DTYPE_LTIME', 11);
54: define('XOBJ_DTYPE_FLOAT', 12);
55: define('XOBJ_DTYPE_BOOL', 13);
56: /**#@-*/
57:
58: /**
59: * Interface for all objects in the Xoops kernel.
60: */
61: class AbstractXoopsObject
62: {
63: function setNew()
64: {
65: }
66:
67: function unsetNew()
68: {
69: }
70:
71: /**
72: * @return bool
73: */
74: function isNew()
75: {
76: }
77:
78: function initVar($key, $data_type, $default, $required, $size)
79: {
80: }
81:
82: /**
83: * You should use this method to initilize object's properties.
84: * This method may not trigger setDirty().
85: * @param $values array
86: */
87: function assignVars($values)
88: {
89: }
90:
91: /**
92: * You should use this method to change object's properties.
93: * This method may trigger setDirty().
94: */
95: function set($key, $value)
96: {
97: }
98:
99: function get($key)
100: {
101: }
102:
103: /**
104: * Return html string for template.
105: * You can call get() method to get pure value.
106: */
107: function getShow($key)
108: {
109: }
110: }
111:
112:
113: /**
114: * Base class for all objects in the Xoops kernel (and beyond)
115: *
116: * @author Kazumi Ono (AKA onokazu)
117: * @copyright copyright © 2000 XOOPS.org
118: * @package kernel
119: **/
120: class XoopsObject extends AbstractXoopsObject
121: {
122:
123: /**
124: * holds all variables(properties) of an object
125: *
126: * @var array
127: * @access protected
128: **/
129: var $vars = array();
130:
131: /**
132: * variables cleaned for store in DB
133: *
134: * @var array
135: * @access protected
136: */
137: var $cleanVars = array();
138:
139: /**
140: * is it a newly created object?
141: *
142: * @var bool
143: * @access private
144: */
145: var $_isNew = false;
146:
147: /**
148: * has any of the values been modified?
149: *
150: * @var bool
151: * @access private
152: */
153: var $_isDirty = false;
154:
155: /**
156: * errors
157: *
158: * @var array
159: * @access private
160: */
161: var $_errors = array();
162:
163: /**
164: * additional filters registered dynamically by a child class object
165: *
166: * @access private
167: */
168: var $_filters = array();
169:
170: /**
171: * constructor
172: *
173: * normally, this is called from child classes only
174: * @access public
175: */
176: function XoopsObject()
177: {
178: }
179:
180: /**#@+
181: * used for new/clone objects
182: *
183: * @access public
184: */
185: function setNew()
186: {
187: $this->_isNew = true;
188: }
189: function unsetNew()
190: {
191: $this->_isNew = false;
192: }
193: function isNew()
194: {
195: return $this->_isNew;
196: }
197: /**#@-*/
198:
199: /**#@+
200: * mark modified objects as dirty
201: *
202: * used for modified objects only
203: * @access public
204: */
205: function setDirty()
206: {
207: $this->_isDirty = true;
208: }
209: function unsetDirty()
210: {
211: $this->_isDirty = false;
212: }
213: function isDirty()
214: {
215: return $this->_isDirty;
216: }
217: /**#@-*/
218:
219: /**
220: * initialize variables for the object
221: *
222: * @access public
223: * @param string $key
224: * @param int $data_type set to one of XOBJ_DTYPE_XXX constants (set to XOBJ_DTYPE_OTHER if no data type ckecking nor text sanitizing is required)
225: * @param mixed
226: * @param bool $required require html form input?
227: * @param int $maxlength for XOBJ_DTYPE_TXTBOX type only
228: * @param string $option does this data have any select options?
229: */
230: function initVar($key, $data_type, $value = null, $required = false, $maxlength = null, $options = '')
231: {
232: $this->vars[$key] = array('value' => $value, 'required' => $required, 'data_type' => $data_type, 'maxlength' => $maxlength, 'changed' => false, 'options' => $options);
233: }
234:
235: /**
236: * assign a value to a variable
237: *
238: * @access public
239: * @param string $key name of the variable to assign
240: * @param mixed $value value to assign
241: */
242: function assignVar($key, $value)
243: {
244: $vars = &$this->vars;
245: if (isset($value) && isset($vars[$key])) $vars[$key]['value'] =& $value; }
246:
247: /**
248: * assign values to multiple variables in a batch
249: *
250: * @access private
251: * @param array $var_array associative array of values to assign
252: */
253: function assignVars($var_arr)
254: {
255: $vars = &$this->vars;
256: foreach ($var_arr as $key => $value) {
257: if (isset($value) && isset($vars[$key])) $vars[$key]['value'] = $value;
258: }
259: }
260:
261: /**
262: * assign a value to a variable
263: *
264: * @access public
265: * @param string $key name of the variable to assign
266: * @param mixed $value value to assign
267: * @param bool $not_gpc
268: */
269: function setVar($key, $value, $not_gpc = false)
270: {
271: if (!empty($key) && isset($value) && isset($this->vars[$key])) {
272: $var =& $this->vars[$key];
273: $var['value'] =& $value;
274: $var['not_gpc'] = $not_gpc;
275: $var['changed'] = true;
276: $this->setDirty();
277: }
278: }
279:
280: /**
281: * assign values to multiple variables in a batch
282: *
283: * @access private
284: * @param array $var_arr associative array of values to assign
285: * @param bool $not_gpc
286: */
287: function setVars($var_arr, $not_gpc = false)
288: {
289: foreach ($var_arr as $key => $value) {
290: $this->setVar($key, $value, $not_gpc);
291: }
292: }
293:
294: /**
295: * Assign values to multiple variables in a batch
296: *
297: * Meant for a CGI contenxt:
298: * - prefixed CGI args are considered save
299: * - avoids polluting of namespace with CGI args
300: *
301: * @access private
302: * @param array $var_arr associative array of values to assign
303: * @param string $pref prefix (only keys starting with the prefix will be set)
304: */
305: function setFormVars($var_arr=null, $pref='xo_', $not_gpc=false) {
306: $len = strlen($pref);
307: foreach ($var_arr as $key => $value) {
308: if ($pref == substr($key,0,$len)) {
309: $this->setVar(substr($key,$len), $value, $not_gpc);
310: }
311: }
312: }
313:
314:
315: /**
316: * returns all variables for the object
317: *
318: * @access public
319: * @return array associative array of key->value pairs
320: */
321: function &getVars()
322: {
323: return $this->vars;
324: }
325:
326: /**
327: * returns a specific variable for the object in a proper format
328: *
329: * @access public
330: * @param string $key key of the object's variable to be returned
331: * @param string $format format to use for the output
332: * @return mixed formatted value of the variable
333: */
334: function &getVar($key, $format = 's')
335: {
336: $var =& $this->vars[$key];
337: $ret = $var['value'];
338: switch ($var['data_type']) {
339:
340: case XOBJ_DTYPE_TXTBOX:
341: switch (strtolower($format)) {
342: case 's':
343: case 'show':
344: case 'e':
345: case 'edit':
346: $ts =& MyTextSanitizer::getInstance();
347: return $ts->htmlSpecialChars($ret);
348: case 'p':
349: case 'preview':
350: case 'f':
351: case 'formpreview':
352: $ts =& MyTextSanitizer::getInstance();
353: return $ts->htmlSpecialChars($ts->stripSlashesGPC($ret));
354: default:
355: return $ret;
356: }
357: case XOBJ_DTYPE_TXTAREA:
358: switch (strtolower($format)) {
359: case 's':
360: case 'show':
361: $ts =& MyTextSanitizer::getInstance();
362: $vars =&$this->vars;
363: $html = !empty($vars['dohtml']['value']) ? 1 : 0;
364: $xcode = (!isset($vars['doxcode']['value']) || $vars['doxcode']['value'] == 1) ? 1 : 0;
365: $smiley = (!isset($vars['dosmiley']['value']) || $vars['dosmiley']['value'] == 1) ? 1 : 0;
366: $image = (!isset($vars['doimage']['value']) || $vars['doimage']['value'] == 1) ? 1 : 0;
367: $br = (!isset($vars['dobr']['value']) || $vars['dobr']['value'] == 1) ? 1 : 0;
368: return $ts->displayTarea($ret, $html, $smiley, $xcode, $image, $br);
369: case 'e':
370: case 'edit':
371: $ret = htmlspecialchars($ret, ENT_QUOTES);
372: return $ret;
373: case 'p':
374: case 'preview':
375: $ts =& MyTextSanitizer::getInstance();
376: $vars =&$this->vars;
377: $html = !empty($vars['dohtml']['value']) ? 1 : 0;
378: $xcode = (!isset($vars['doxcode']['value']) || $vars['doxcode']['value'] == 1) ? 1 : 0;
379: $smiley = (!isset($vars['dosmiley']['value']) || $vars['dosmiley']['value'] == 1) ? 1 : 0;
380: $image = (!isset($vars['doimage']['value']) || $vars['doimage']['value'] == 1) ? 1 : 0;
381: $br = (!isset($vars['dobr']['value']) || $vars['dobr']['value'] == 1) ? 1 : 0;
382: return $ts->previewTarea($ret, $html, $smiley, $xcode, $image, $br);
383: case 'f':
384: case 'formpreview':
385: $ts =& MyTextSanitizer::getInstance();
386: return htmlspecialchars($ts->stripSlashesGPC($ret), ENT_QUOTES);
387: default:
388: return $ret;
389: }
390: case XOBJ_DTYPE_ARRAY:
391: return unserialize($ret);
392: case XOBJ_DTYPE_SOURCE:
393: switch (strtolower($format)) {
394: case 'e':
395: case 'edit':
396: return htmlspecialchars($ret, ENT_QUOTES);
397: case 'p':
398: case 'preview':
399: $ts =& MyTextSanitizer::getInstance();
400: return $ts->stripSlashesGPC($ret);
401: case 'f':
402: case 'formpreview':
403: $ts =& MyTextSanitizer::getInstance();
404: $ret = htmlspecialchars($ts->stripSlashesGPC($ret), ENT_QUOTES);
405: return $ret;
406: default:
407: return $ret;
408: }
409: default:
410: if ($var['options'] != '' && $ret != '') {
411: switch (strtolower($format)) {
412: case 's':
413: case 'show':
414: $selected = explode('|', $ret);
415: $options = explode('|', $var['options']);
416: $i = 1;
417: $ret = array();
418: foreach ($options as $op) {
419: if (in_array($i, $selected)) {
420: $ret[] = $op;
421: }
422: $i++;
423: }
424: return implode(', ', $ret);
425: case 'e':
426: case 'edit':
427: return explode('|', $ret);
428: default:
429: return $ret;
430: }
431:
432: }
433: break;
434: }
435: return $ret;
436: }
437:
438: function getShow($key)
439: {
440: return $this->getVar($key, 's');
441: }
442:
443: /**
444: * Sets $value to $key property. This method calls setVar(), but make
445: * not_gpc true for the compatibility with XoopsSimpleObject.
446: * @param string $key
447: * @param mixed $value
448: */
449: function set($key, $value)
450: {
451: $this->setVar($key, $value, true);
452: }
453:
454: function get($key)
455: {
456: return $this->vars[$key]['value'];
457: }
458:
459: /**
460: * Return value as raw.
461: * @deprecated
462: */
463: function getProperty($key)
464: {
465: return $this->vars[$key]['value'];
466: }
467:
468: /**
469: * @deprecated
470: */
471: function getProperties()
472: {
473: $ret=array();
474: foreach(array_keys($this->vars) as $key) {
475: $ret[$key]=$this->vars[$key]['value'];
476: }
477: return $ret;
478: }
479:
480: /**
481: * clean values of all variables of the object for storage.
482: * also add slashes whereever needed
483: *
484: * @return bool true if successful
485: * @access public
486: */
487: function cleanVars()
488: {
489: $ts =& MyTextSanitizer::getInstance();
490: foreach ($this->vars as $k => $v) {
491: $cleanv = $v['value'];
492: if (!$v['changed']) {
493: } else {
494: $cleanv = is_string($cleanv) ? trim($cleanv) : $cleanv;
495: switch ($v['data_type']) {
496: case XOBJ_DTYPE_TXTBOX:
497: if ($v['required'] && $cleanv != '0' && $cleanv == '') {
498: $this->setErrors("$k is required.");
499: continue;
500: }
501: if (isset($v['maxlength']) && strlen($cleanv) > (int)$v['maxlength']) {
502: $this->setErrors("$k must be shorter than ".(int)$v['maxlength']." characters.");
503: continue;
504: }
505: if (!$v['not_gpc']) {
506: $cleanv = $ts->stripSlashesGPC($ts->censorString($cleanv));
507: } else {
508: $cleanv = $ts->censorString($cleanv);
509: }
510: break;
511: case XOBJ_DTYPE_TXTAREA:
512: if ($v['required'] && $cleanv != '0' && $cleanv == '') {
513: $this->setErrors("$k is required.");
514: continue;
515: }
516: if (!$v['not_gpc']) {
517: $cleanv = $ts->stripSlashesGPC($ts->censorString($cleanv));
518: } else {
519: $cleanv = $ts->censorString($cleanv);
520: }
521: break;
522: case XOBJ_DTYPE_SOURCE:
523: if (!$v['not_gpc']) {
524: $cleanv = $ts->stripSlashesGPC($cleanv);
525: } else {
526: $cleanv = $cleanv;
527: }
528: break;
529:
530: case XOBJ_DTYPE_INT:
531: $cleanv = (int)$cleanv;
532: break;
533:
534: case XOBJ_DTYPE_FLOAT:
535: $cleanv = (float)$cleanv;
536: break;
537:
538: case XOBJ_DTYPE_BOOL:
539: $cleanv = $cleanv ? 1 : 0;
540: break;
541:
542: case XOBJ_DTYPE_EMAIL:
543: if ($v['required'] && $cleanv == '') {
544: $this->setErrors("$k is required.");
545: continue;
546: }
547: if ($cleanv != '' && !preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+([\.][a-z0-9-]+)+$/i",$cleanv)) {
548: $this->setErrors("Invalid Email");
549: continue;
550: }
551: if (!$v['not_gpc']) {
552: $cleanv = $ts->stripSlashesGPC($cleanv);
553: }
554: break;
555: case XOBJ_DTYPE_URL:
556: if ($v['required'] && $cleanv == '') {
557: $this->setErrors("$k is required.");
558: continue;
559: }
560: if ($cleanv != '' && !preg_match("/^http[s]*:\/\//i", $cleanv)) {
561: $cleanv = 'http://' . $cleanv;
562: }
563: if (!$v['not_gpc']) {
564: $cleanv =& $ts->stripSlashesGPC($cleanv);
565: }
566: break;
567: case XOBJ_DTYPE_ARRAY:
568: $cleanv = serialize($cleanv);
569: break;
570: case XOBJ_DTYPE_STIME:
571: case XOBJ_DTYPE_MTIME:
572: case XOBJ_DTYPE_LTIME:
573: $cleanv = !is_string($cleanv) ? (int)$cleanv : strtotime($cleanv);
574: break;
575: default:
576: break;
577: }
578: }
579: $this->cleanVars[$k] =& $cleanv;
580: unset($cleanv);
581: }
582: if (count($this->_errors) > 0) {
583: return false;
584: }
585: $this->unsetDirty();
586: return true;
587: }
588:
589: /**
590: * dynamically register additional filter for the object
591: *
592: * @param string $filtername name of the filter
593: * @access public
594: */
595: function registerFilter($filtername)
596: {
597: $this->_filters[] = $filtername;
598: }
599:
600: /**
601: * load all additional filters that have been registered to the object
602: *
603: * @access private
604: */
605: function _loadFilters()
606: {
607: //include_once XOOPS_ROOT_PATH.'/class/filters/filter.php';
608: //foreach ($this->_filters as $f) {
609: // include_once XOOPS_ROOT_PATH.'/class/filters/'.strtolower($f).'php';
610: //}
611: }
612:
613: /**
614: * create a clone(copy) of the current object
615: *
616: * @access public
617: * @return object clone
618: */
619: function &xoopsClone()
620: {
621: $class = get_class($this);
622: $clone =new $class();
623: foreach ($this->vars as $k => $v) {
624: $clone->assignVar($k, $v['value']);
625: }
626: // need this to notify the handler class that this is a newly created object
627: $clone->setNew();
628: return $clone;
629: }
630:
631: /**
632: * add an error
633: *
634: * @param string $value error to add
635: * @access public
636: */
637: function setErrors($err_str)
638: {
639: $this->_errors[] = trim($err_str);
640: }
641:
642: /**
643: * return the errors for this object as an array
644: *
645: * @return array an array of errors
646: * @access public
647: */
648: function getErrors()
649: {
650: return $this->_errors;
651: }
652:
653: /**
654: * return the errors for this object as html
655: *
656: * @return string html listing the errors
657: * @access public
658: */
659: function getHtmlErrors()
660: {
661: $ret = '<h4>Errors</h4>';
662: if (!empty($this->_errors)) {
663: foreach ($this->_errors as $error) {
664: $ret .= $error.'<br />';
665: }
666: } else {
667: $ret .= 'None<br />';
668: }
669: return $ret;
670: }
671: }
672:
673: /**
674: * XOOPS object handler class.
675: * This class is an abstract class of handler classes that are responsible for providing
676: * data access mechanisms to the data source of its corresponsing data objects
677: * @package kernel
678: * @abstract
679: *
680: * @author Kazumi Ono <onokazu@xoops.org>
681: * @copyright copyright © 2000 The XOOPS Project
682: */
683: class XoopsObjectHandler
684: {
685:
686: /**
687: * holds referenced to {@link XoopsDatabase} class object
688: *
689: * @var object
690: * @see XoopsDatabase
691: * @access protected
692: */
693: var $db;
694:
695: //
696: /**
697: * called from child classes only
698: *
699: * @param object $db reference to the {@link XoopsDatabase} object
700: * @access protected
701: */
702: function XoopsObjectHandler(&$db)
703: {
704: $this->db =& $db;
705: }
706:
707: /**
708: * creates a new object
709: *
710: * @abstract
711: */
712: function &create()
713: {
714: }
715:
716: /**
717: * gets a value object
718: *
719: * @param int $int_id
720: * @abstract
721: */
722: function &get($int_id)
723: {
724: }
725:
726: /**
727: * insert/update object
728: *
729: * @param object $object
730: * @abstract
731: */
732: function insert(&$object)
733: {
734: }
735:
736: /**
737: * delete obejct from database
738: *
739: * @param object $object
740: * @abstract
741: */
742: function delete(&$object)
743: {
744: }
745:
746: }
747: ?>
748: