source: trunk/install/includes/database.php@ 252

Last change on this file since 252 was 2, checked in by root, 15 years ago

importo il progetto

File size: 35.1 KB
Line 
1<?php
2
3/************************************************************************/
4/* Eleonline */
5/* ============================================ */
6/* Installer was based on Joomla Installer */
7/************************************************************************/
8
9
10// no direct access
11defined( '_VALID_MOS' ) or die( 'Restricted access' );
12
13/**
14* Database connector class
15* @subpackage Database
16* @package PHP-Nuke
17*/
18class database {
19 /** @var string Internal variable to hold the query sql */
20 var $_sql = '';
21 /** @var int Internal variable to hold the database error number */
22 var $_errorNum = 0;
23 /** @var string Internal variable to hold the database error message */
24 var $_errorMsg = '';
25 /** @var string Internal variable to hold the prefix used on all database tables */
26 var $_table_prefix = '';
27 /** @var Internal variable to hold the connector resource */
28 var $_resource = '';
29 /** @var Internal variable to hold the last query cursor */
30 var $_cursor = null;
31 /** @var boolean Debug option */
32 var $_debug = 0;
33 /** @var int The limit for the query */
34 var $_limit = 0;
35 /** @var int The for offset for the limit */
36 var $_offset = 0;
37 /** @var int A counter for the number of queries performed by the object instance */
38 var $_ticker = 0;
39 /** @var array A log of queries */
40 var $_log = null;
41 /** @var string The null/zero date string */
42 var $_nullDate = '0000-00-00 00:00:00';
43 /** @var string Quote for named objects */
44 var $_nameQuote = '`';
45
46 /**
47 * Database object constructor
48 * @param string Database host
49 * @param string Database user name
50 * @param string Database user password
51 * @param string Database name
52 * @param string Common prefix for all tables
53 * @param boolean If true and there is an error, go offline
54 */
55 function database( $host='localhost', $user, $pass, $db='', $table_prefix='', $goOffline=true ) {
56 // perform a number of fatality checks, then die gracefully
57 if (!function_exists( 'mysql_connect' )) {
58 $mosSystemError = 1;
59 if ($goOffline) {
60 $basePath = dirname( __FILE__ );
61 include $basePath . '/../configuration.php';
62 include $basePath . '/../offline.php';
63 exit();
64 }
65 }
66 if (phpversion() < '4.2.0') {
67 if (!($this->_resource = @mysql_connect( $host, $user, $pass ))) {
68 $mosSystemError = 2;
69 if ($goOffline) {
70 $basePath = dirname( __FILE__ );
71 include $basePath . '/../configuration.php';
72 include $basePath . '/../offline.php';
73 exit();
74 }
75 }
76 } else {
77 if (!($this->_resource = @mysql_connect( $host, $user, $pass, true ))) {
78 $mosSystemError = 2;
79 if ($goOffline) {
80 $basePath = dirname( __FILE__ );
81 include $basePath . '/../configuration.php';
82 include $basePath . '/../offline.php';
83 exit();
84 }
85 }
86 }
87 if ($db != '' && !mysql_select_db( $db, $this->_resource )) {
88 $mosSystemError = 3;
89 if ($goOffline) {
90 $basePath = dirname( __FILE__ );
91 include $basePath . '/../configuration.php';
92 include $basePath . '/../offline.php';
93 exit();
94 }
95 }
96 $this->_table_prefix = $table_prefix;
97 //@mysql_query("SET NAMES 'utf8'", $this->_resource);
98 $this->_ticker = 0;
99 $this->_log = array();
100 }
101 /**
102 * @param int
103 */
104 function debug( $level ) {
105 $this->_debug = intval( $level );
106 }
107 /**
108 * @return int The error number for the most recent query
109 */
110 function getErrorNum() {
111 return $this->_errorNum;
112 }
113 /**
114 * @return string The error message for the most recent query
115 */
116 function getErrorMsg() {
117 return str_replace( array( "\n", "'" ), array( '\n', "\'" ), $this->_errorMsg );
118 }
119 /**
120 * Get a database escaped string
121 * @return string
122 */
123 function getEscaped( $text ) {
124 return mysql_escape_string( $text );
125 }
126 /**
127 * Get a quoted database escaped string
128 * @return string
129 */
130 function Quote( $text ) {
131 return '\'' . $this->getEscaped( $text ) . '\'';
132 }
133 /**
134 * Quote an identifier name (field, table, etc)
135 * @param string The name
136 * @return string The quoted name
137 */
138 function NameQuote( $s ) {
139 $q = $this->_nameQuote;
140 if (strlen( $q ) == 1) {
141 return $q . $s . $q;
142 } else {
143 return $q{0} . $s . $q{1};
144 }
145 }
146 /**
147 * @return string The database prefix
148 */
149 function getPrefix() {
150 return $this->_table_prefix;
151 }
152 /**
153 * @return string Quoted null/zero date string
154 */
155 function getNullDate() {
156 return $this->_nullDate;
157 }
158 /**
159 * Sets the SQL query string for later execution.
160 *
161 * This function replaces a string identifier <var>$prefix</var> with the
162 * string held is the <var>_table_prefix</var> class variable.
163 *
164 * @param string The SQL query
165 * @param string The offset to start selection
166 * @param string The number of results to return
167 * @param string The common table prefix
168 */
169 function setQuery( $sql, $offset = 0, $limit = 0, $prefix='#__' ) {
170 $this->_sql = $this->replacePrefix( $sql, $prefix );
171 $this->_limit = intval( $limit );
172 $this->_offset = intval( $offset );
173 }
174
175 /**
176 * This function replaces a string identifier <var>$prefix</var> with the
177 * string held is the <var>_table_prefix</var> class variable.
178 *
179 * @param string The SQL query
180 * @param string The common table prefix
181 * @author thede, David McKinnis
182 */
183 function replacePrefix( $sql, $prefix='#__' ) {
184 $sql = trim( $sql );
185
186 $escaped = false;
187 $quoteChar = '';
188
189 $n = strlen( $sql );
190
191 $startPos = 0;
192 $literal = '';
193 while ($startPos < $n) {
194 $ip = strpos($sql, $prefix, $startPos);
195 if ($ip === false) {
196 break;
197 }
198
199 $j = strpos( $sql, "'", $startPos );
200 $k = strpos( $sql, '"', $startPos );
201 if (($k !== FALSE) && (($k < $j) || ($j === FALSE))) {
202 $quoteChar = '"';
203 $j = $k;
204 } else {
205 $quoteChar = "'";
206 }
207
208 if ($j === false) {
209 $j = $n;
210 }
211
212 $literal .= str_replace( $prefix, $this->_table_prefix, substr( $sql, $startPos, $j - $startPos ) );
213 $startPos = $j;
214
215 $j = $startPos + 1;
216
217 if ($j >= $n) {
218 break;
219 }
220
221 // quote comes first, find end of quote
222 while (TRUE) {
223 $k = strpos( $sql, $quoteChar, $j );
224 $escaped = false;
225 if ($k === false) {
226 break;
227 }
228 $l = $k - 1;
229 while ($l >= 0 && $sql{$l} == '\\') {
230 $l--;
231 $escaped = !$escaped;
232 }
233 if ($escaped) {
234 $j = $k+1;
235 continue;
236 }
237 break;
238 }
239 if ($k === FALSE) {
240 // error in the query - no end quote; ignore it
241 break;
242 }
243 $literal .= substr( $sql, $startPos, $k - $startPos + 1 );
244 $startPos = $k+1;
245 }
246 if ($startPos < $n) {
247 $literal .= substr( $sql, $startPos, $n - $startPos );
248 }
249 return $literal;
250 }
251 /**
252 * @return string The current value of the internal SQL vairable
253 */
254 function getQuery() {
255 return "<pre>" . htmlspecialchars( $this->_sql ) . "</pre>";
256 }
257 /**
258 * Execute the query
259 * @return mixed A database resource if successful, FALSE if not.
260 */
261 function query() {
262 global $mosConfig_debug;
263 if ($this->_limit > 0 && $this->_offset == 0) {
264 $this->_sql .= "\nLIMIT $this->_limit";
265 } else if ($this->_limit > 0 || $this->_offset > 0) {
266 $this->_sql .= "\nLIMIT $this->_offset, $this->_limit";
267 }
268 if ($this->_debug) {
269 $this->_ticker++;
270 $this->_log[] = $this->_sql;
271 }
272 $this->_errorNum = 0;
273 $this->_errorMsg = '';
274 $this->_cursor = mysql_query( $this->_sql, $this->_resource );
275 if (!$this->_cursor) {
276 $this->_errorNum = mysql_errno( $this->_resource );
277 $this->_errorMsg = mysql_error( $this->_resource )." SQL=$this->_sql";
278 if ($this->_debug) {
279 trigger_error( mysql_error( $this->_resource ), E_USER_NOTICE );
280 //echo "<pre>" . $this->_sql . "</pre>\n";
281 if (function_exists( 'debug_backtrace' )) {
282 foreach( debug_backtrace() as $back) {
283 if (@$back['file']) {
284 echo '<br />'.$back['file'].':'.$back['line'];
285 }
286 }
287 }
288 }
289 return false;
290 }
291 return $this->_cursor;
292 }
293
294 /**
295 * @return int The number of affected rows in the previous operation
296 */
297 function getAffectedRows() {
298 return mysql_affected_rows( $this->_resource );
299 }
300
301 function query_batch( $abort_on_error=true, $p_transaction_safe = false) {
302 $this->_errorNum = 0;
303 $this->_errorMsg = '';
304 if ($p_transaction_safe) {
305 $si = mysql_get_server_info( $this->_resource );
306 preg_match_all( "/(\d+)\.(\d+)\.(\d+)/i", $si, $m );
307 if ($m[1] >= 4) {
308 $this->_sql = 'START TRANSACTION;' . $this->_sql . '; COMMIT;';
309 } else if ($m[2] >= 23 && $m[3] >= 19) {
310 $this->_sql = 'BEGIN WORK;' . $this->_sql . '; COMMIT;';
311 } else if ($m[2] >= 23 && $m[3] >= 17) {
312 $this->_sql = 'BEGIN;' . $this->_sql . '; COMMIT;';
313 }
314 }
315 $query_split = preg_split ("/[;]+/", $this->_sql);
316 $error = 0;
317 foreach ($query_split as $command_line) {
318 $command_line = trim( $command_line );
319 if ($command_line != '') {
320 $this->_cursor = mysql_query( $command_line, $this->_resource );
321 if (!$this->_cursor) {
322 $error = 1;
323 $this->_errorNum .= mysql_errno( $this->_resource ) . ' ';
324 $this->_errorMsg .= mysql_error( $this->_resource )." SQL=$command_line <br />";
325 if ($abort_on_error) {
326 return $this->_cursor;
327 }
328 }
329 }
330 }
331 return $error ? false : true;
332 }
333
334 /**
335 * Diagnostic function
336 */
337 function explain() {
338 $temp = $this->_sql;
339 $this->_sql = "EXPLAIN $this->_sql";
340 $this->query();
341
342 if (!($cur = $this->query())) {
343 return null;
344 }
345 $first = true;
346
347 $buf = "<table cellspacing=\"1\" cellpadding=\"2\" border=\"0\" bgcolor=\"#000000\" align=\"center\">";
348 $buf .= $this->getQuery();
349 while ($row = mysql_fetch_assoc( $cur )) {
350 if ($first) {
351 $buf .= "<tr>";
352 foreach ($row as $k=>$v) {
353 $buf .= "<th bgcolor=\"#ffffff\">$k</th>";
354 }
355 $buf .= "</tr>";
356 $first = false;
357 }
358 $buf .= "<tr>";
359 foreach ($row as $k=>$v) {
360 $buf .= "<td bgcolor=\"#ffffff\">$v</td>";
361 }
362 $buf .= "</tr>";
363 }
364 $buf .= "</table><br />&nbsp;";
365 mysql_free_result( $cur );
366
367 $this->_sql = $temp;
368
369 return "<div style=\"background-color:#FFFFCC\" align=\"left\">$buf</div>";
370 }
371 /**
372 * @return int The number of rows returned from the most recent query.
373 */
374 function getNumRows( $cur=null ) {
375 return mysql_num_rows( $cur ? $cur : $this->_cursor );
376 }
377
378 /**
379 * This method loads the first field of the first row returned by the query.
380 *
381 * @return The value returned in the query or null if the query failed.
382 */
383 function loadResult() {
384 if (!($cur = $this->query())) {
385 return null;
386 }
387 $ret = null;
388 if ($row = mysql_fetch_row( $cur )) {
389 $ret = $row[0];
390 }
391 mysql_free_result( $cur );
392 return $ret;
393 }
394 /**
395 * Load an array of single field results into an array
396 */
397 function loadResultArray($numinarray = 0) {
398 if (!($cur = $this->query())) {
399 return null;
400 }
401 $array = array();
402 while ($row = mysql_fetch_row( $cur )) {
403 $array[] = $row[$numinarray];
404 }
405 mysql_free_result( $cur );
406 return $array;
407 }
408 /**
409 * Load a assoc list of database rows
410 * @param string The field name of a primary key
411 * @return array If <var>key</var> is empty as sequential list of returned records.
412 */
413 function loadAssocList( $key='' ) {
414 if (!($cur = $this->query())) {
415 return null;
416 }
417 $array = array();
418 while ($row = mysql_fetch_assoc( $cur )) {
419 if ($key) {
420 $array[$row[$key]] = $row;
421 } else {
422 $array[] = $row;
423 }
424 }
425 mysql_free_result( $cur );
426 return $array;
427 }
428 /**
429 * This global function loads the first row of a query into an object
430 *
431 * If an object is passed to this function, the returned row is bound to the existing elements of <var>object</var>.
432 * If <var>object</var> has a value of null, then all of the returned query fields returned in the object.
433 * @param string The SQL query
434 * @param object The address of variable
435 */
436 function loadObject( &$object ) {
437 if ($object != null) {
438 if (!($cur = $this->query())) {
439 return false;
440 }
441 if ($array = mysql_fetch_assoc( $cur )) {
442 mysql_free_result( $cur );
443 mosBindArrayToObject( $array, $object, null, null, false );
444 return true;
445 } else {
446 return false;
447 }
448 } else {
449 if ($cur = $this->query()) {
450 if ($object = mysql_fetch_object( $cur )) {
451 mysql_free_result( $cur );
452 return true;
453 } else {
454 $object = null;
455 return false;
456 }
457 } else {
458 return false;
459 }
460 }
461 }
462 /**
463 * Load a list of database objects
464 * @param string The field name of a primary key
465 * @return array If <var>key</var> is empty as sequential list of returned records.
466 * If <var>key</var> is not empty then the returned array is indexed by the value
467 * the database key. Returns <var>null</var> if the query fails.
468 */
469 function loadObjectList( $key='' ) {
470 if (!($cur = $this->query())) {
471 return null;
472 }
473 $array = array();
474 while ($row = mysql_fetch_object( $cur )) {
475 if ($key) {
476 $array[$row->$key] = $row;
477 } else {
478 $array[] = $row;
479 }
480 }
481 mysql_free_result( $cur );
482 return $array;
483 }
484 /**
485 * @return The first row of the query.
486 */
487 function loadRow() {
488 if (!($cur = $this->query())) {
489 return null;
490 }
491 $ret = null;
492 if ($row = mysql_fetch_row( $cur )) {
493 $ret = $row;
494 }
495 mysql_free_result( $cur );
496 return $ret;
497 }
498 /**
499 * Load a list of database rows (numeric column indexing)
500 * @param string The field name of a primary key
501 * @return array If <var>key</var> is empty as sequential list of returned records.
502 * If <var>key</var> is not empty then the returned array is indexed by the value
503 * the database key. Returns <var>null</var> if the query fails.
504 */
505 function loadRowList( $key=null ) {
506 if (!($cur = $this->query())) {
507 return null;
508 }
509 $array = array();
510 while ($row = mysql_fetch_row( $cur )) {
511 if ( !is_null( $key ) ) {
512 $array[$row[$key]] = $row;
513 } else {
514 $array[] = $row;
515 }
516 }
517 mysql_free_result( $cur );
518 return $array;
519 }
520 /**
521 * Document::db_insertObject()
522 *
523 * { Description }
524 *
525 * @param [type] $keyName
526 * @param [type] $verbose
527 */
528 function insertObject( $table, &$object, $keyName = NULL, $verbose=false ) {
529 $fmtsql = "INSERT INTO $table ( %s ) VALUES ( %s ) ";
530 $fields = array();
531 foreach (get_object_vars( $object ) as $k => $v) {
532 if (is_array($v) or is_object($v) or $v === NULL) {
533 continue;
534 }
535 if ($k[0] == '_') { // internal field
536 continue;
537 }
538 $fields[] = $this->NameQuote( $k );
539 $values[] = $this->Quote( $v );
540 }
541 $this->setQuery( sprintf( $fmtsql, implode( ",", $fields ) , implode( ",", $values ) ) );
542 ($verbose) && print "$sql<br />\n";
543 if (!$this->query()) {
544 return false;
545 }
546 $id = mysql_insert_id( $this->_resource );
547 ($verbose) && print "id=[$id]<br />\n";
548 if ($keyName && $id) {
549 $object->$keyName = $id;
550 }
551 return true;
552 }
553
554 /**
555 * Document::db_updateObject()
556 *
557 * { Description }
558 *
559 * @param [type] $updateNulls
560 */
561 function updateObject( $table, &$object, $keyName, $updateNulls=true ) {
562 $fmtsql = "UPDATE $table SET %s WHERE %s";
563 $tmp = array();
564 foreach (get_object_vars( $object ) as $k => $v) {
565 if( is_array($v) or is_object($v) or $k[0] == '_' ) { // internal or NA field
566 continue;
567 }
568 if( $k == $keyName ) { // PK not to be updated
569 $where = $keyName . '=' . $this->Quote( $v );
570 continue;
571 }
572 if ($v === NULL && !$updateNulls) {
573 continue;
574 }
575 if( $v == '' ) {
576 $val = "''";
577 } else {
578 $val = $this->Quote( $v );
579 }
580 $tmp[] = $this->NameQuote( $k ) . '=' . $val;
581 }
582 $this->setQuery( sprintf( $fmtsql, implode( ",", $tmp ) , $where ) );
583 return $this->query();
584 }
585
586 /**
587 * @param boolean If TRUE, displays the last SQL statement sent to the database
588 * @return string A standised error message
589 */
590 function stderr( $showSQL = false ) {
591 return "DB function failed with error number $this->_errorNum"
592 ."<br /><font color=\"red\">$this->_errorMsg</font>"
593 .($showSQL ? "<br />SQL = <pre>$this->_sql</pre>" : '');
594 }
595
596 function insertid() {
597 return mysql_insert_id( $this->_resource );
598 }
599
600 function getVersion() {
601 return mysql_get_server_info( $this->_resource );
602 }
603
604 /**
605 * @return array A list of all the tables in the database
606 */
607 function getTableList() {
608 $this->setQuery( 'SHOW TABLES' );
609 return $this->loadResultArray();
610 }
611 /**
612 * @param array A list of table names
613 * @return array A list the create SQL for the tables
614 */
615 function getTableCreate( $tables ) {
616 $result = array();
617
618 foreach ($tables as $tblval) {
619 $this->setQuery( 'SHOW CREATE table ' . $this->getEscaped( $tblval ) );
620 $rows = $this->loadRowList();
621 foreach ($rows as $row) {
622 $result[$tblval] = $row[1];
623 }
624 }
625
626 return $result;
627 }
628 /**
629 * @param array A list of table names
630 * @return array An array of fields by table
631 */
632 function getTableFields( $tables ) {
633 $result = array();
634
635 foreach ($tables as $tblval) {
636 $this->setQuery( 'SHOW FIELDS FROM ' . $tblval );
637 $fields = $this->loadObjectList();
638 foreach ($fields as $field) {
639 $result[$tblval][$field->Field] = preg_replace("/[(0-9)]/",'', $field->Type );
640 }
641 }
642
643 return $result;
644 }
645
646 /**
647 * Fudge method for ADOdb compatibility
648 */
649 function GenID( $foo1=null, $foo2=null ) {
650 return '0';
651 }
652}
653
654/**
655* mosDBTable Abstract Class.
656* @abstract
657* @package PHP-Nuke
658* @subpackage Database
659*
660* Parent classes to all database derived objects. Customisation will generally
661* not involve tampering with this object.
662* @package PHP-Nuke
663* @author Andrew Eddie <eddieajau@users.sourceforge.net
664*/
665class mosDBTable {
666 /** @var string Name of the table in the db schema relating to child class */
667 var $_tbl = '';
668 /** @var string Name of the primary key field in the table */
669 var $_tbl_key = '';
670 /** @var string Error message */
671 var $_error = '';
672 /** @var mosDatabase Database connector */
673 var $_db = null;
674
675 /**
676 * Object constructor to set table and key field
677 *
678 * Can be overloaded/supplemented by the child class
679 * @param string $table name of the table in the db schema relating to child class
680 * @param string $key name of the primary key field in the table
681 */
682 function mosDBTable( $table, $key, &$db ) {
683 $this->_tbl = $table;
684 $this->_tbl_key = $key;
685 $this->_db =& $db;
686 }
687
688 /**
689 * Returns an array of public properties
690 * @return array
691 */
692 function getPublicProperties() {
693 static $cache = null;
694 if (is_null( $cache )) {
695 $cache = array();
696 foreach (get_class_vars( get_class( $this ) ) as $key=>$val) {
697 if (substr( $key, 0, 1 ) != '_') {
698 $cache[] = $key;
699 }
700 }
701 }
702 return $cache;
703 }
704 /**
705 * Filters public properties
706 * @access protected
707 * @param array List of fields to ignore
708 */
709 function filter( $ignoreList=null ) {
710 $ignore = is_array( $ignoreList );
711
712 $iFilter = new InputFilter();
713 foreach ($this->getPublicProperties() as $k) {
714 if ($ignore && in_array( $k, $ignoreList ) ) {
715 continue;
716 }
717 $this->$k = $iFilter->process( $this->$k );
718 }
719 }
720 /**
721 * @return string Returns the error message
722 */
723 function getError() {
724 return $this->_error;
725 }
726 /**
727 * Gets the value of the class variable
728 * @param string The name of the class variable
729 * @return mixed The value of the class var (or null if no var of that name exists)
730 */
731 function get( $_property ) {
732 if(isset( $this->$_property )) {
733 return $this->$_property;
734 } else {
735 return null;
736 }
737 }
738
739 /**
740 * Set the value of the class variable
741 * @param string The name of the class variable
742 * @param mixed The value to assign to the variable
743 */
744 function set( $_property, $_value ) {
745 $this->$_property = $_value;
746 }
747
748 /**
749 * Resets public properties
750 * @param mixed The value to set all properties to, default is null
751 */
752 function reset( $value=null ) {
753 $keys = $this->getPublicProperties();
754 foreach ($keys as $k) {
755 $this->$k = $value;
756 }
757 }
758 /**
759 * binds a named array/hash to this object
760 *
761 * can be overloaded/supplemented by the child class
762 * @param array $hash named array
763 * @return null|string null is operation was satisfactory, otherwise returns an error
764 */
765 function bind( $array, $ignore='' ) {
766 if (!is_array( $array )) {
767 $this->_error = strtolower(get_class( $this ))."::bind failed.";
768 return false;
769 } else {
770 return mosBindArrayToObject( $array, $this, $ignore );
771 }
772 }
773
774 /**
775 * binds an array/hash to this object
776 * @param int $oid optional argument, if not specifed then the value of current key is used
777 * @return any result from the database operation
778 */
779 function load( $oid=null ) {
780 $k = $this->_tbl_key;
781
782 if ($oid !== null) {
783 $this->$k = $oid;
784 }
785
786 $oid = $this->$k;
787
788 if ($oid === null) {
789 return false;
790 }
791
792 $class_vars = get_class_vars(get_class($this));
793 foreach ($class_vars as $name => $value) {
794 if (($name != $k) and ($name != "_db") and ($name != "_tbl") and ($name != "_tbl_key")) {
795 $this->$name = $value;
796 }
797 }
798
799 $this->reset();
800
801 $query = "SELECT *"
802 . "\n FROM $this->_tbl"
803 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $oid )
804 ;
805 $this->_db->setQuery( $query );
806
807 return $this->_db->loadObject( $this );
808 }
809
810 /**
811 * generic check method
812 *
813 * can be overloaded/supplemented by the child class
814 * @return boolean True if the object is ok
815 */
816 function check() {
817 return true;
818 }
819
820 /**
821 * Inserts a new row if id is zero or updates an existing row in the database table
822 *
823 * Can be overloaded/supplemented by the child class
824 * @param boolean If false, null object variables are not updated
825 * @return null|string null if successful otherwise returns and error message
826 */
827 function store( $updateNulls=false ) {
828 $k = $this->_tbl_key;
829
830 if ($this->$k != 0) {
831 $ret = $this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );
832 } else {
833 $ret = $this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
834 }
835 if( !$ret ) {
836 $this->_error = strtolower(get_class( $this ))."::store failed <br />" . $this->_db->getErrorMsg();
837 return false;
838 } else {
839 return true;
840 }
841 }
842 /**
843 */
844 function move( $dirn, $where='' ) {
845 $k = $this->_tbl_key;
846
847 $sql = "SELECT $this->_tbl_key, ordering FROM $this->_tbl";
848
849 if ($dirn < 0) {
850 $sql .= "\n WHERE ordering < " . (int) $this->ordering;
851 $sql .= ($where ? "\n AND $where" : '');
852 $sql .= "\n ORDER BY ordering DESC";
853 $sql .= "\n LIMIT 1";
854 } else if ($dirn > 0) {
855 $sql .= "\n WHERE ordering > " . (int) $this->ordering;
856 $sql .= ($where ? "\n AND $where" : '');
857 $sql .= "\n ORDER BY ordering";
858 $sql .= "\n LIMIT 1";
859 } else {
860 $sql .= "\nWHERE ordering = " . (int) $this->ordering;
861 $sql .= ($where ? "\n AND $where" : '');
862 $sql .= "\n ORDER BY ordering";
863 $sql .= "\n LIMIT 1";
864 }
865
866 $this->_db->setQuery( $sql );
867//echo 'A: ' . $this->_db->getQuery();
868
869
870 $row = null;
871 if ($this->_db->loadObject( $row )) {
872 $query = "UPDATE $this->_tbl"
873 . "\n SET ordering = " . (int) $row->ordering
874 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
875 ;
876 $this->_db->setQuery( $query );
877
878 if (!$this->_db->query()) {
879 $err = $this->_db->getErrorMsg();
880 die( $err );
881 }
882//echo 'B: ' . $this->_db->getQuery();
883
884 $query = "UPDATE $this->_tbl"
885 . "\n SET ordering = " . (int) $this->ordering
886 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $row->$k )
887 ;
888 $this->_db->setQuery( $query );
889//echo 'C: ' . $this->_db->getQuery();
890
891 if (!$this->_db->query()) {
892 $err = $this->_db->getErrorMsg();
893 die( $err );
894 }
895
896 $this->ordering = $row->ordering;
897 } else {
898 $query = "UPDATE $this->_tbl"
899 . "\n SET ordering = " . (int) $this->ordering
900 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
901 ;
902 $this->_db->setQuery( $query );
903//echo 'D: ' . $this->_db->getQuery();
904
905
906 if (!$this->_db->query()) {
907 $err = $this->_db->getErrorMsg();
908 die( $err );
909 }
910 }
911 }
912 /**
913 * Compacts the ordering sequence of the selected records
914 * @param string Additional where query to limit ordering to a particular subset of records
915 */
916 function updateOrder( $where='' ) {
917 $k = $this->_tbl_key;
918
919 if (!array_key_exists( 'ordering', get_class_vars( strtolower(get_class( $this )) ) )) {
920 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support ordering.";
921 return false;
922 }
923
924 if ($this->_tbl == "#__content_frontpage") {
925 $order2 = ", content_id DESC";
926 } else {
927 $order2 = '';
928 }
929
930 $query = "SELECT $this->_tbl_key, ordering"
931 . "\n FROM $this->_tbl"
932 . ( $where ? "\n WHERE $where" : '' )
933 . "\n ORDER BY ordering$order2 "
934 ;
935 $this->_db->setQuery( $query );
936 if (!($orders = $this->_db->loadObjectList())) {
937 $this->_error = $this->_db->getErrorMsg();
938 return false;
939 }
940 // first pass, compact the ordering numbers
941 for ($i=0, $n=count( $orders ); $i < $n; $i++) {
942 if ($orders[$i]->ordering >= 0) {
943 $orders[$i]->ordering = $i+1;
944 }
945 }
946
947 $shift = 0;
948 $n=count( $orders );
949 for ($i=0; $i < $n; $i++) {
950 //echo "i=$i id=".$orders[$i]->$k." order=".$orders[$i]->ordering;
951 if ($orders[$i]->$k == $this->$k) {
952 // place 'this' record in the desired location
953 $orders[$i]->ordering = min( $this->ordering, $n );
954 $shift = 1;
955 } else if ($orders[$i]->ordering >= $this->ordering && $this->ordering > 0) {
956 $orders[$i]->ordering++;
957 }
958 }
959 //echo '<pre>';print_r($orders);echo '</pre>';
960 // compact once more until I can find a better algorithm
961 for ($i=0, $n=count( $orders ); $i < $n; $i++) {
962 if ($orders[$i]->ordering >= 0) {
963 $orders[$i]->ordering = $i+1;
964 $query = "UPDATE $this->_tbl"
965 . "\n SET ordering = " . (int) $orders[$i]->ordering
966 . "\n WHERE $k = " . $this->_db->Quote( $orders[$i]->$k )
967 ;
968 $this->_db->setQuery( $query);
969 $this->_db->query();
970 //echo '<br />'.$this->_db->getQuery();
971 }
972 }
973
974 // if we didn't reorder the current record, make it last
975 if ($shift == 0) {
976 $order = $n+1;
977 $query = "UPDATE $this->_tbl"
978 . "\n SET ordering = " . (int) $order
979 . "\n WHERE $k = " . $this->_db->Quote( $this->$k )
980 ;
981 $this->_db->setQuery( $query );
982 $this->_db->query();
983 //echo '<br />'.$this->_db->getQuery();
984 }
985 return true;
986 }
987 /**
988 * Generic check for whether dependancies exist for this object in the db schema
989 *
990 * can be overloaded/supplemented by the child class
991 * @param string $msg Error message returned
992 * @param int Optional key index
993 * @param array Optional array to compiles standard joins: format [label=>'Label',name=>'table name',idfield=>'field',joinfield=>'field']
994 * @return true|false
995 */
996 function canDelete( $oid=null, $joins=null ) {
997 $k = $this->_tbl_key;
998 if ($oid) {
999 $this->$k = intval( $oid );
1000 }
1001 if (is_array( $joins )) {
1002 $select = $k;
1003 $join = '';
1004 foreach( $joins as $table ) {
1005 $tblName = $this->getEscaped( $table['name'] );
1006 $idField = $this->getEscaped( $table['idfield'] );
1007 $jnField = $this->getEscaped( $table['joinfield'] );
1008 $select .= ",\n COUNT(DISTINCT `$tblName`.`$idField`) AS `count_".substr($tblName, 3)."_$idField`";
1009 $join .= "\n LEFT JOIN `$tblName` ON `$tblName`.`$jnField` = `$this->_tbl`.`$k`";
1010 }
1011
1012 $query = "SELECT $select"
1013 . "\n FROM `$this->_tbl`"
1014 . $join
1015 . "\n WHERE `$this->_tbl`.`$k` = ". (int) $this->$k
1016 . "\n GROUP BY `$this->_tbl`.`$k`"
1017 ;
1018 $this->_db->setQuery( $query );
1019
1020 $obj = null;
1021 if (!$this->_db->loadObject($obj)) {
1022 $this->_error = $this->_db->getErrorMsg();
1023 return false;
1024 }
1025 $msg = array();
1026 foreach( $joins as $table ) {
1027 $tblName = $this->getEscaped( $table['name'] );
1028 $idField = $this->getEscaped( $table['idfield'] );
1029 $k = 'count_'.substr($tblName, 3).'_'.$idField;
1030 if ($obj->$k) {
1031 $msg[] = $table['label'];
1032 }
1033 }
1034
1035 if (count( $msg )) {
1036 $this->_error = "noDeleteRecord" . ": " . implode( ', ', $msg );
1037 return false;
1038 } else {
1039 return true;
1040 }
1041 }
1042
1043 return true;
1044 }
1045
1046 /**
1047 * Default delete method
1048 *
1049 * can be overloaded/supplemented by the child class
1050 * @return true if successful otherwise returns and error message
1051 */
1052 function delete( $oid=null ) {
1053 //if (!$this->canDelete( $msg )) {
1054 // return $msg;
1055 //}
1056
1057 $k = $this->_tbl_key;
1058 if ($oid) {
1059 $this->$k = intval( $oid );
1060 }
1061
1062 $query = "DELETE FROM $this->_tbl"
1063 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
1064 ;
1065 $this->_db->setQuery( $query );
1066
1067 if ($this->_db->query()) {
1068 return true;
1069 } else {
1070 $this->_error = $this->_db->getErrorMsg();
1071 return false;
1072 }
1073 }
1074
1075 /**
1076 * Checks out an object
1077 * @param int User id
1078 * @param int Object id
1079 */
1080 function checkout( $user_id, $oid=null ) {
1081 if (!array_key_exists( 'checked_out', get_class_vars( strtolower(get_class( $this )) ) )) {
1082 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support checkouts.";
1083 return false;
1084 }
1085 $k = $this->_tbl_key;
1086 if ($oid !== null) {
1087 $this->$k = $oid;
1088 }
1089
1090 $time = date( 'Y-m-d H:i:s' );
1091 if (intval( $user_id )) {
1092 $user_id = intval( $user_id );
1093 // new way of storing editor, by id
1094 $query = "UPDATE $this->_tbl"
1095 . "\n SET checked_out = $user_id, checked_out_time = " . $this->_db->Quote( $time )
1096 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
1097 ;
1098 $this->_db->setQuery( $query );
1099
1100 $this->checked_out = $user_id;
1101 $this->checked_out_time = $time;
1102 } else {
1103 $user_id = $this->_db->Quote( $user_id );
1104 // old way of storing editor, by name
1105 $query = "UPDATE $this->_tbl"
1106 . "\n SET checked_out = 1, checked_out_time = " . $this->_db->Quote( $time ) . ", editor = $user_id"
1107 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
1108 ;
1109 $this->_db->setQuery( $query );
1110
1111 $this->checked_out = 1;
1112 $this->checked_out_time = $time;
1113 $this->checked_out_editor = $user_id;
1114 }
1115
1116 return $this->_db->query();
1117 }
1118
1119 /**
1120 * Checks in an object
1121 * @param int Object id
1122 */
1123 function checkin( $oid=null ) {
1124 if (!array_key_exists( 'checked_out', get_class_vars( strtolower(get_class( $this )) ) )) {
1125 $this->_error = "WARNING: ".strtolower(get_class( $this ))." does not support checkin.";
1126 return false;
1127 }
1128 $k = $this->_tbl_key;
1129 $nullDate = $this->_db->getNullDate();
1130
1131 if ($oid !== null) {
1132 $this->$k = intval( $oid );
1133 }
1134 if ($this->$k == NULL) {
1135 return false;
1136 }
1137
1138 $query = "UPDATE $this->_tbl"
1139 . "\n SET checked_out = 0, checked_out_time = " . $this->_db->Quote( $nullDate )
1140 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->$k )
1141 ;
1142 $this->_db->setQuery( $query );
1143
1144 $this->checked_out = 0;
1145 $this->checked_out_time = '';
1146
1147 return $this->_db->query();
1148 }
1149
1150 /**
1151 * Increments the hit counter for an object
1152 * @param int Object id
1153 */
1154 function hit( $oid=null ) {
1155 global $mosConfig_enable_log_items;
1156
1157 $k = $this->_tbl_key;
1158 if ($oid !== null) {
1159 $this->$k = intval( $oid );
1160 }
1161
1162 $query = "UPDATE $this->_tbl"
1163 . "\n SET hits = ( hits + 1 )"
1164 . "\n WHERE $this->_tbl_key = " . $this->_db->Quote( $this->id )
1165 ;
1166 $this->_db->setQuery( $query );
1167 $this->_db->query();
1168
1169 if (@$mosConfig_enable_log_items) {
1170 $now = date( 'Y-m-d' );
1171 $query = "SELECT hits"
1172 . "\n FROM #__core_log_items"
1173 . "\n WHERE time_stamp = " . $this->_db->Quote( $now )
1174 . "\n AND item_table = " . $this->_db->Quote( $this->_tbl )
1175 . "\n AND item_id = " . $this->_db->Quote( $this->$k )
1176 ;
1177 $this->_db->setQuery( $query );
1178 $hits = intval( $this->_db->loadResult() );
1179 if ($hits) {
1180 $query = "UPDATE #__core_log_items"
1181 . "\n SET hits = ( hits + 1 )"
1182 . "\n WHERE time_stamp = " . $this->_db->Quote( $now )
1183 . "\n AND item_table = " . $this->_db->Quote( $this->_tbl )
1184 . "\n AND item_id = " . $this->_db->Quote( $this->$k )
1185 ;
1186 $this->_db->setQuery( $query );
1187 $this->_db->query();
1188 } else {
1189 $query = "INSERT INTO #__core_log_items"
1190 . "\n VALUES ( " . $this->_db->Quote( $now ) . ", " . $this->_db->Quote( $this->_tbl ) . ", " . $this->_db->Quote( $this->$k ) . ", 1 )"
1191 ;
1192 $this->_db->setQuery( $query );
1193 $this->_db->query();
1194 }
1195 }
1196 }
1197
1198 /**
1199 * Tests if item is checked out
1200 * @param int A user id
1201 * @return boolean
1202 */
1203 function isCheckedOut( $user_id=0 ) {
1204 if ($user_id) {
1205 return ($this->checked_out && $this->checked_out != $user_id);
1206 } else {
1207 return $this->checked_out;
1208 }
1209 }
1210
1211 /**
1212 * Generic save function
1213 * @param array Source array for binding to class vars
1214 * @param string Filter for the order updating
1215 * @returns TRUE if completely successful, FALSE if partially or not succesful
1216 * NOTE: Filter will be deprecated in verion 1.1
1217 */
1218 function save( $source, $order_filter='' ) {
1219 if (!$this->bind( $source )) {
1220 return false;
1221 }
1222 if (!$this->check()) {
1223 return false;
1224 }
1225 if (!$this->store()) {
1226 return false;
1227 }
1228 if (!$this->checkin()) {
1229 return false;
1230 }
1231
1232 if ($order_filter) {
1233 $filter_value = $this->$order_filter;
1234 $this->updateOrder( $order_filter ? "`$order_filter` = " . $this->_db->Quote( $filter_value ) : '' );
1235 }
1236 $this->_error = '';
1237 return true;
1238 }
1239
1240 /**
1241 * @deprecated As of 1.0.3, replaced by publish
1242 */
1243 function publish_array( $cid=null, $publish=1, $user_id=0 ) {
1244 $this->publish( $cid, $publish, $user_id );
1245 }
1246
1247 /**
1248 * Generic Publish/Unpublish function
1249 * @param array An array of id numbers
1250 * @param integer 0 if unpublishing, 1 if publishing
1251 * @param integer The id of the user performnig the operation
1252 * @since 1.0.4
1253 */
1254 function publish( $cid=null, $publish=1, $user_id=0 ) {
1255 mosArrayToInts( $cid, array() );
1256 $user_id = (int) $user_id;
1257 $publish = (int) $publish;
1258 $k = $this->_tbl_key;
1259
1260 if (count( $cid ) < 1) {
1261 $this->_error = "Nessun elemento selezionato.";
1262 return false;
1263 }
1264
1265 $cids = $this->_tbl_key . '=' . implode( ' OR ' . $this->_tbl_key . '=', $cid );
1266
1267 $query = "UPDATE $this->_tbl"
1268 . "\n SET published = " . (int) $publish
1269 . "\n WHERE ($cids)"
1270 . "\n AND (checked_out = 0 OR checked_out = " . (int) $user_id . ")"
1271 ;
1272 $this->_db->setQuery( $query );
1273 if (!$this->_db->query()) {
1274 $this->_error = $this->_db->getErrorMsg();
1275 return false;
1276 }
1277
1278 if (count( $cid ) == 1) {
1279 $this->checkin( $cid[0] );
1280 }
1281 $this->_error = '';
1282 return true;
1283 }
1284
1285 /**
1286 * Export item list to xml
1287 * @param boolean Map foreign keys to text values
1288 */
1289 function toXML( $mapKeysToText=false ) {
1290 $xml = '<record table="' . $this->_tbl . '"';
1291
1292 if ($mapKeysToText) {
1293 $xml .= ' mapkeystotext="true"';
1294 }
1295 $xml .= '>';
1296 foreach (get_object_vars( $this ) as $k => $v) {
1297 if (is_array($v) or is_object($v) or $v === NULL) {
1298 continue;
1299 }
1300 if ($k[0] == '_') { // internal field
1301 continue;
1302 }
1303 $xml .= '<' . $k . '><![CDATA[' . $v . ']]></' . $k . '>';
1304 }
1305 $xml .= '</record>';
1306
1307 return $xml;
1308 }
1309}
1310?>
Note: See TracBrowser for help on using the repository browser.