databases
[ class tree: databases ] [ index: databases ] [ all elements ]

Source for file MySQLDatabase.class.php

Documentation is available at MySQLDatabase.class.php

  1. <?php
  2. /*
  3. if( !extension_loaded( 'mysql' ) )
  4.   dl( 'mysql.so' );
  5. */
  6. /**
  7.  * For including this file you have to define the constant "CLASSPATH".
  8.  * Because every include in the framework depends on the CLASSPATH definition.
  9.  * The CLASSPATH means the relative path to the folder that contains the
  10.  * framework GilliGan.
  11.  *
  12.  * @package    databases
  13.  * @subpackage mysql
  14.  */
  15. if( !defined( "CLASSPATH" ) )
  16. {
  17.   echo "<h3>You have to define the constant CLASSPATH!</h3>\r\n";
  18.   echo "Example: define( 'CLASSPATH', '../path/to/classes/' );\r\n";
  19.   exit();
  20. }
  21.  
  22. if( defined( "LANG" ) )
  23.   /**
  24.    * Including language specific messages.
  25.    */
  26.   include( CLASSPATH."core/lang_spec_values/".LANG.".inc.php" );
  27. else
  28. {
  29.   echo "<h3>You have to define the constant LANG!</h3>\r\n";
  30.   echo "Example for german: define( 'LANG', 'de' );\r\n";
  31.   exit();
  32. }
  33.  
  34. /**
  35.  * Loading global settings for GilliGan.
  36.  */
  37. require_once( CLASSPATH."settings.inc.php" );
  38. /**
  39.  *
  40.  */
  41. include_once( CLASSPATH."core/PlainTextFormatter.class.php" );
  42. /**
  43.  * Loading the parent class.
  44.  */
  45. require_once( CLASSPATH."databases/Database.class.php" );
  46. /**
  47.  *
  48.  */
  49. include_once( CLASSPATH."databases/mysql/MySQLDatabaseTable.class.php" );
  50. /**
  51.  *
  52.  */
  53. include_once( CLASSPATH."filesystem/Files.class.php" );
  54. /**
  55.  *
  56.  */
  57. include_once( CLASSPATH."filesystem/FilesystemToolkit.class.php" );
  58.  
  59. /**
  60.  *
  61.  */
  62. $GLOBALS["GilliGan_MySQL_QueryLog"] = "";
  63. /**
  64.  * @package    databases
  65.  * @subpackage mysql
  66.  *
  67.  * @version    0.2.02
  68.  * @author     Daniel Plücken <daniel@debakel.net>
  69.  * @license    http://www.gnu.org/copyleft/lesser.html
  70.  *              GNU Lesser General Public License
  71.  * @copyright  Copyright (C) 2004 Daniel Plücken <daniel@debakel.net>
  72.  *
  73.  *  This library is free software; you can redistribute it and/or
  74.  *  modify it under the terms of the GNU Lesser General Public
  75.  *  License as published by the Free Software Foundation; either
  76.  *  version 2.1 of the License.
  77.  *
  78.  *  This library is distributed in the hope that it will be useful,
  79.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  80.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  81.  *  GNU Lesser General Public License for more details.
  82.  *
  83.  *  You should have received a copy of the GNU Lesser General
  84.  *  Public License along with this library; if not, write to the
  85.  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  86.  *  Boston, MA 02111-1307 USA
  87.  */
  88. class MySQLDatabase extends Database
  89. {
  90.   /**
  91.     * Constructor
  92.     *
  93.     * @access  public
  94.     * @version 1.21
  95.     * @since   0.1.0
  96.     *
  97.     * @param   string  $name 
  98.     * @param   object  $parent 
  99.     *
  100.     * @return  MySQLDatabase 
  101.     */
  102.   function MySQLDatabase( $name, $parent = "" )
  103.   {
  104.     if( !empty( $name ) )
  105.     {
  106.       $this->name = $name;
  107.       if(
  108.           !function_exists( "is_a" )
  109.        && get_class( $parent ) == "mysqldatabasehost"
  110.        || function_exists( "is_a" )
  111.        && is_a( $parent, "MySQLDatabaseHost" )
  112.         )
  113.         $parent->addDB( $this );
  114.     }
  115.     else
  116.     if(
  117.         defined( "DEBUG" )
  118.      || SCRIPTDEBUGGING
  119.       )
  120.     {
  121.        echo "<pre>\r\n";
  122.        echo "<h3>You have to give a name to this database!</h3>";
  123.        echo "<b>Use following Syntax:<b>\r\n\r\n";
  124.        echo "  \x24db = new MySQLDatabase( \x24name, $parent = \"\" );\r\n\r\n";
  125.        echo "<b>BACKTRACE DEBUG:</b>\r\n";
  126.        $debugArr = debug_backtrace();
  127.  
  128.        if ( DEBUG_COMPLETE_BACKTRACES )
  129.            print_r( $debugArr );
  130.        else
  131.            print_r( $debugArr[count($debugArr)-1] );
  132.  
  133.        echo "</pre>\r\n";
  134.     }
  135.   }
  136.  
  137.  
  138.  
  139.   /**
  140.    * Sets the references to objects of database-tables to the attribute
  141.    * $this->dbt.
  142.    *
  143.    * @access  public
  144.    * @version 1.11
  145.    * @since   0.1.0
  146.    *
  147.    * @param   string  $regExp  Makes sure that only database-tables were stored,
  148.    *                            which names matching the given regular expression.
  149.    * @param   boolean $resFld  Cause whether the tables's fields should be
  150.    *                            research too.
  151.    *
  152.    * @return  void 
  153.    */
  154.   function researchTables( $regExp = "", $resFld = false )
  155.   {
  156.      if( $this->probeConnection() )
  157.      {
  158.         $dbt_list = mysql_list_tables( $this->name, $this->getResourceID() );
  159.  
  160.         unset( $this->db );
  161.         $i = 0;
  162.         $t = 0;
  163.         $cnt = mysql_num_rows( $dbt_list );
  164.         while( $i < $cnt )
  165.         {
  166.            $tmp_name = mysql_db_name( $dbt_list, $i );
  167.  
  168.            if( empty( $regExp ) )
  169.            {
  170.               $this->dbt[$i] = new MySQLDatabaseTable( $tmp_name );
  171.               $this->dbt[$i]->setParent( $this );
  172.               if( $resFld )
  173.                 $this->dbt[$i]->researchFields();
  174.            }
  175.            else
  176.            if( preg_match( $regExp, $tmp_name ) )
  177.            {
  178.               $this->dbt[$t] = new MySQLDatabaseTable( $tmp_name );
  179.               $this->dbt[$t]->setParent( $this );
  180.               if( $resFld )
  181.                 $this->dbt[$t]->researchFields();
  182.  
  183.               $t++;
  184.            }
  185.  
  186.            $i++;
  187.         }
  188.      }
  189.   }
  190.  
  191.  
  192.  
  193.   /**
  194.    * Dumps this Database.
  195.    *
  196.    * @access  public
  197.    * @version 1.1
  198.    * @since   0.1.1
  199.    *
  200.    * @param   string  $target 
  201.    * @param   string  $regExp  Makes sure that only database-tables were stored,
  202.    *                            which names matching the given regular expression.
  203.    *
  204.    * @return  boolean 
  205.    */
  206.   function dump( $target = "./__dumps", $regExp = "" )
  207.   {
  208.      $this->researchTables( $regExp = "", $regExp2 = "" );
  209.  
  210.      if( !is_dir( $target ) )
  211.          mkdir( $target, 0777 );
  212.  
  213.      $old = @umask( 0 );
  214.      @chmod( $target, 0777 );
  215.      @umask( $old );
  216.  
  217.      if( !is_dir( $target."/".$this->name ) )
  218.          mkdir( $target."/".$this->name, 0777 );
  219.  
  220.      $old = @umask( 0 );
  221.      @chmod( $target."/".$this->name, 0777 );
  222.      @umask( $old );
  223.  
  224.      echo "<b>Database</b> ".$this->name."<br />\r\n";
  225.  
  226.      for( $i = 0; $i < count( $this->dbt ); $i++ )
  227.      {
  228.          $f = new Files(
  229.          $target."/".$this->name."/"
  230.                          .$this->dbt[$i]->name.".sql"
  231.                        );
  232.  
  233.          $f->setContent( $this->dbt[$i]->getDump() );
  234.          echo $this->dbt[$i]->getLastQuery()."<br />\r\n";
  235.          $f->save();
  236.  
  237.          $old = @umask( 0 );
  238.          @chmod(
  239.          $target."/".$this->name."/"
  240.                 .$this->dbt[$i]->name.".sql",
  241.          0777
  242.          );
  243.          @umask( $old );
  244.      }
  245.   }
  246.  
  247.  
  248.  
  249.   /**
  250.    * Imports Dumps from given source to this database.
  251.    *
  252.    * @access  public
  253.    * @version 1.1
  254.    * @since   0.1.1
  255.    *
  256.    * @param   string  $source 
  257.    * @param   string  $regExp  Makes sure that only files will be imported,
  258.    *                            which names matching the given regular expression.
  259.    *
  260.    * @return  boolean 
  261.    */
  262.   function importDump( $source = "./__dumps", $regExp = "" )
  263.   {
  264.       $tmp_arr = FilesystemToolkit::loadFolderContent( $source, $regExp, "^ &$" );
  265.       $source  = FilesystemToolkit::getCleanPath( $source );
  266.  
  267.       if( strtoupper( MYSQL_IMPORT_KIND ) == "MYSQL" )
  268.       for( $i = 0; $i < count( $tmp_arr ); $i++ )
  269.       {
  270.           $tmp_data_order = "-e \"source ".$source."/".$tmp_arr[$i]["name"]."\" "
  271.                           .$this->name;
  272.  
  273.           $tmp_exec = FilesystemToolkit::getCleanPath( PATH2MYSQL )
  274.           ."/mysql ".$tmp_data_order;
  275.  
  276.           echo $tmp_exec."<br />";
  277.           exec( $tmp_exec );
  278.       }
  279.       else
  280.       for( $i = 0; $i < count( $tmp_arr ); $i++ )
  281.       {
  282.           $tmp_f = new Files( $source."/".$tmp_arr[$i]["name"] );
  283.  
  284.           $str_tmp = &$tmp_f->getContent();
  285.  
  286.           $this->import( $str_tmp );
  287.           unset( $tmp_f );
  288.       }
  289.  
  290.   }
  291.  
  292.  
  293.  
  294.   /**
  295.    * Researches a whole folder to import dumped data from it.
  296.    *
  297.    * @access  public
  298.    * @version 1.5
  299.    * @since   0.1.7
  300.    *
  301.    * @param   string  $source The source resource of the MySQL-Dump.
  302.    *
  303.    * @return  boolean 
  304.    */
  305.   function importSingleDump( $source = "http://www.test.de/getMySQLTable.php" )
  306.   {
  307.     if ( $f = fopen( $source, 'r' ) )
  308.     {
  309.         $str_rest = "";
  310.         while ( !feof( $f ) )
  311.         {
  312.             $data = $str_rest.fgets( $f );
  313.  
  314.             $pos = 0;
  315.             $query = "";
  316.             while (
  317.                     (
  318.                       $pos_new = Strings::pregpos(
  319.                          $data,
  320.                          "!;\s+(?:INSERT|REPLACE|UPDATE|DROP|CREATE) !is",
  321.                          $pos
  322.                                                  )
  323.                     ) !== false
  324.                   )
  325.             {
  326.                $length = $pos_new - $pos;
  327.                $tok = trim( substr( $data ,$pos, $length ) );
  328.  
  329.                $query .= $tok;
  330.                if (
  331.                     !empty( $query )
  332.                     // Check whether the last tok ends with a html entity or
  333.                     // unicode.
  334.                  && preg_match( "!&(?:[a-z0-9]{2,9}|#\d{1,5})$!i", $query )
  335.                   )
  336.                   $query .= ";\r\n";
  337.                else
  338.                if ( !preg_match( "!&(?:[a-z0-9]{2,9}|#\d{1,5})$!i", $query ) )
  339.                {
  340.                   $this->query( $query );
  341.                   $query = "";
  342.                }
  343.  
  344.                $pos = $pos_new + 3;
  345.             }
  346.             $str_rest = substr( $data ,$pos );
  347.  
  348.             ob_flush();
  349.             flush();
  350.         }
  351.  
  352.         fclose( $f );
  353.     }
  354.  
  355.     $str_rest = trim( $str_rest );
  356.     if ( !empty( $str_rest ) )
  357.        $this->query( $str_rest );
  358.   }
  359.  
  360.  
  361.  
  362.   // *   - %databasetable% -> The name of the database in which an error occurs.
  363.   /**
  364.    * This function parses pseudo variables in a text on SQL-errors.
  365.    *
  366.    *   - %database%      -> The name of this database.
  367.    *   - %query%         -> The query which was tried to execute.
  368.    *
  369.    * @static
  370.    * @access  public
  371.    * @version 1.0
  372.    * @since   0.1.5
  373.    *
  374.    * @param   string $database 
  375.    * @param   string $query 
  376.    * @param   string $text 
  377.    *
  378.    * @return  string 
  379.    */
  380.   function __parse_vars( $database, $query, $text )
  381.   {
  382.     $out = preg_replace( "!\%database\%!i", $database, $text );
  383.     $out = preg_replace( "!\%query\%!i", $query, $out );
  384.     // $out = preg_replace( "!\%databasetable\%!i", $databasetable, $out );
  385.  
  386.     return $out;
  387.   }
  388.  
  389.  
  390.   /**
  391.    * Will query this database.
  392.    *
  393.    * @access  public
  394.    * @version 1.6
  395.    * @since   0.1.0
  396.    *
  397.    * @param   string  $sqlOrder 
  398.    * @param   boolean $no_logs 
  399.    *
  400.    * @return  boolean 
  401.    */
  402.   function query( $sqlOrder, $no_logs = false )
  403.   {
  404.      static $int_query_cnt = 1;
  405.  
  406.      if ( MYSQLDEBUGGING )
  407.      {   $query_microtime_begin = time() + microtime(); }
  408.  
  409.      if ( $this->probeConnection() )
  410.      {
  411.         $result = mysql_db_query(
  412.                                     $this->name, $sqlOrder,
  413.                                     $this->getResourceID()
  414.                                 );
  415.      }
  416.  
  417.      if ( MYSQLDEBUGGING )
  418.      {
  419.         $query_microtime = time() + microtime() - $query_microtime_begin;
  420.         $GLOBALS["GilliGan_MySQL_QueryLog"] .= "\r\n<!--\r\nQuery "
  421.                    .$int_query_cnt.":\r\n"
  422.                    ."------\r\n"
  423.                    .PlainTextFormatter::formatSQL(
  424.                        str_replace(
  425.                            "-->",
  426.                            "--[ADDED TO AVOID CLOSING OF EMBRACING COMMENT]>",
  427.                            $sqlOrder
  428.                                   )
  429.                                                  )
  430.                    ."\r\n------------------------------------------\r\n"
  431.                    ."Execution Time: "
  432.                    .$query_microtime
  433.                    ." Seconds"
  434.                    ."\r\n------------------------------------------\r\n"
  435.  
  436.                    ."-->";
  437.         $GLOBALS["GilliGan_MySQL_QueryExecutionTime"] += $query_microtime;
  438.         $int_query_cnt++;
  439.      }
  440.  
  441.  
  442.      $this->last_query = $sqlOrder;
  443.      $err   = mysql_error( $this->getResourceID() );
  444.      $errno = mysql_errno( $this->getResourceID() );
  445.  
  446.  
  447.  
  448.      if ( !$result )
  449.      {
  450.          if (
  451.                !empty( $this->parent->error_callback )
  452.             && function_exists( $this->parent->error_callback )
  453.             && in_array(
  454.                          $errno,
  455.                          array(
  456.                                 // no connection
  457.                                 2013,
  458.                                 // Access denied for user
  459.                                 1045,
  460.                                 // no such database
  461.                                 1049
  462.                               )
  463.                        )
  464.             )
  465.          {
  466.              $tmp_name = $this->parent->error_callback;
  467.              $tmp_name( $errno, $err );
  468.          }
  469.          else
  470.          if (
  471.               !empty( $this->error_callback )
  472.            && function_exists( $this->error_callback )
  473.             )
  474.          {
  475.              $tmp_name = $this->error_callback;
  476.              $tmp_name( $errno, $err );
  477.          }
  478.          else
  479.          {
  480.              if (
  481.                   !$no_logs
  482.                && GENERATEMYSQLSYSTEMERRORLOGS
  483.                 )
  484.              {
  485.                $res = $this->query(
  486.                              "SELECT * "
  487.                               ."FROM __admin_mysql_errorlogs "
  488.                              ."WHERE script_name = '".$_SERVER["SCRIPT_NAME"]."' "
  489.                                ."AND mysql_errno = '".$errno."' "
  490.                                ."AND active = '1'",
  491.                              true
  492.                                   );
  493.  
  494.                $cnt = mysql_num_rows( $res );
  495.  
  496.                if( $cnt > 0 )
  497.                  $this->query(
  498.                  "UPDATE __admin_mysql_errorlogs "
  499.                    ."SET mysql_error = '".str_replace( "'","\'", $err )."', "
  500.                        ."mysql_errno = '".$errno."', "
  501.                        ."mysql_query = '".str_replace( "'","\'", $sqlOrder )."', "
  502.                        ."time_last = NOW() "
  503.                  ."WHERE script_name = '".$_SERVER["SCRIPT_NAME"]."'", true
  504.                              );
  505.                else
  506.                {
  507.                  $this->query(
  508.                  "INSERT INTO __admin_mysql_errorlogs "
  509.                         ."SET mysql_error = '".str_replace( "'","\'", $err )."', "
  510.                             ."mysql_errno = '".$errno."', "
  511.                             ."mysql_query = '".str_replace( "'","\'", $sqlOrder )."', "
  512.                             ."time_first = NOW(), "
  513.                             ."script_name = '".$_SERVER["SCRIPT_NAME"]."'", true
  514.                              );
  515.  
  516.                  mail(
  517.                             ADMINEMAIL,
  518.                             $GLOBALS["email_subject"]["sqlerror"],
  519.                             MySQLDatabase::__parse_vars(
  520.                                           $this->name,
  521.                                           $sqlOrder,
  522.                                           $GLOBALS["email_body"]["sqlerror"]
  523.                                                        ),
  524.                             "From: \"info@".str_replace(
  525.                                                          "www.", "",
  526.                                                          $_SERVER["HTTP_HOST"]
  527.                                                        )."\" "
  528.                                  ."< info@".str_replace(
  529.                                                          "www.", "",
  530.                                                          $_SERVER["HTTP_HOST"]
  531.                                                        )." >\r\n"
  532.                            ."Reply-To: \"noreply\" <>\r\n"
  533.                      );
  534.                }
  535.  
  536.                /*
  537.                $res_arr = mysql_fetch_assoc( $res )
  538.                if( empty( $res_arr["active"] ) )
  539.                  mail(  );
  540.                */
  541.              }
  542.  
  543.              if (
  544.                   defined( "DEBUG" )
  545.                || MYSQLDEBUGGING
  546.                 )
  547.              {
  548.                if ( function_exists( "debug_backtrace" ) )
  549.                {
  550.                   echo "<pre>\r\n";
  551.                   echo "<b>An error occurs!</b>\r\n";
  552.                   echo "<b>BACKTRACE DEBUG:</b>\r\n";
  553.                   $debugArr = debug_backtrace();
  554.  
  555.                   if ( DEBUG_COMPLETE_BACKTRACES )
  556.                       print_r( $debugArr );
  557.                   else
  558.                       print_r( $debugArr[count($debugArr)-1] );
  559.  
  560.                   echo "</pre>\r\n";
  561.                   echo "<br />\r\n";
  562.                }
  563.  
  564.                echo "<b>ISO-Occurrance-Date:</b> "
  565.                    .date( "Y-m-d H:i:s" )."<br /><br />\r\n";
  566.  
  567.                echo "<b>MySQL says:</b><br />\r\n";
  568.                echo $err."<br /><br />\r\n";
  569.                echo "<b>Your query is:</b><br />\r\n";
  570.                die( "<pre>".PlainTextFormatter::formatSQL( $sqlOrder )."</pre>" );
  571.              }
  572.          }
  573.      }
  574.  
  575.      return $result;
  576.   }
  577.  
  578.  
  579.  
  580.   /**
  581.    * Imports a given SQL-string into this Database.
  582.    *
  583.    * @access  public
  584.    * @version 1.0
  585.    * @since   0.1.43
  586.    *
  587.    * @param   string  $str_dump The dump to import.
  588.    *
  589.    * @return  boolean 
  590.    */
  591.   function import( $str_dump )
  592.   {
  593.       $tmp_look_ahead = "(?="
  594.                            ."("
  595.                              ."INSERT\s+INTO"
  596.                             ."|REPLACE\s+INTO"
  597.                             ."|UPDATE"
  598.                             ."|CREATE\s+TABLE"
  599.                             ."|DROP\s+TABLE"
  600.                            .")"
  601.                        .")";
  602.       $tmp_reg_exp = "(\s*+|--[^\r\n]*+)*{$tmp_look_ahead}";
  603.  
  604.       $str_dump  = preg_replace( "!^{$tmp_reg_exp}!is", "", $str_dump );
  605.       $order_arr = preg_split( "!;{$tmp_reg_exp}!is", $str_dump );
  606.  
  607.       foreach ( $order_arr as $str_query )
  608.           $this->query( $str_query );
  609.   }
  610.  
  611.  
  612.  
  613.   /**
  614.    * Probes whether there is a connection to the databasehost, if not it will
  615.    * attempt to connect to the host.
  616.    *
  617.    * @access  public
  618.    * @version 1.21
  619.    * @since   0.1.1
  620.    *
  621.    * @return  boolean 
  622.    */
  623.   function probeConnection()
  624.   {
  625.      if(
  626.          function_exists( "debug_backtrace" )
  627.       && (
  628.            !function_exists( "is_a" )
  629.         && get_class( $this->parent ) != "mysqldatabasehost"
  630.         || function_exists( "is_a" )
  631.         && !is_a( $this->parent, "MySQLDatabaseHost" )
  632.          )
  633.       && (
  634.            defined( "DEBUG" )
  635.         || MYSQLDEBUGGING
  636.          )
  637.        )
  638.      {
  639.        $debugArr = debug_backtrace();
  640.        echo "There is no valid parent-object for the database named "
  641.            ."\"".$this->name."\".<br />\r\n"
  642.            ."Please add this database-object to a databasehost-object before "
  643.            ."you make a call such as on <b>line&nbsp;"
  644.            .$debugArr[count($debugArr)-1]["line"]."</b> in <b>file&nbsp;\""
  645.            .$debugArr[count($debugArr)-1]["file"]."\"</b>."
  646.            ."<br /><br />\r\n";
  647.        echo "<b>BACKTRACE DEBUG:</b><br />\r\n";
  648.        echo "<pre>\r\n";
  649.  
  650.        if ( DEBUG_COMPLETE_BACKTRACES )
  651.            print_r( $debugArr );
  652.        else
  653.            print_r( $debugArr[count($debugArr)-1] );
  654.  
  655.        echo "</pre>\r\n";
  656.        exit();
  657.      }
  658.      else
  659.      if( !$this->parent->is_connected )
  660.        $this->parent->connect();
  661.  
  662.      if( $this->parent->is_connected )
  663.        return true;
  664.      else
  665.        return false;
  666.   }
  667. } // END of class MySQLDatabase
  668. ?>

Documentation generated on Thu, 05 Jun 2008 19:14:00 +0200 by phpDocumentor 1.4.1