root/kladr/include/database.php

Revision 14, 29.3 kB (checked in by teiko, 4 years ago)

Набросок kladr

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