<?php
if(!defined('ABS_PATH')) exit('ABS_PATH is not loaded. Direct access is not allowed.');

/*
 * Copyright 2014 Osclass
 * Copyright 2023 Osclass by OsclassPoint.com
 *
 * Osclass maintained & developed by OsclassPoint.com
 * You may not use this file except in compliance with the License.
 * You may download copy of Osclass at
 *
 *     https://osclass-classifieds.com/download
 *
 * Do not edit or add to this file if you wish to upgrade Osclass to newer
 * versions in the future. Software is distributed on an "AS IS" basis, without
 * warranties or conditions of any kind, either express or implied. Do not remove
 * this NOTICE section as it contains license information and copyrights.
 */


/**
 * Model database for Dump database tables
 *
 * @package Osclass
 * @subpackage Model
 * @since unknown
 */
class Dump extends DAO
{
  /**
   * It references to self object: Dump.
   * It is used as a singleton
   *
   * @access private
   * @since unknown
   * @var Dump
   */
  private static $instance;

  /**
   * @return \Dump
   */
  public static function newInstance()
  {
    if( !self::$instance instanceof self ) {
      self::$instance = new self;
    }
    return self::$instance;
  }

  /**
   * Set data
   */
  public function __construct()
  {
    parent::__construct();
  }

   /**
   * Return all tables from database
   *
   * @return array
   */
  public function showTables()
  {
    $res = $this->dao->query('SHOW TABLES;');
    if($res) {
      return $res->result();
    } else {
      return array();
    }
  }

  /**
   * Dump into path the table structure of $table
   *
   * @param string $path
   * @param string $table
   * @return bool
   */
  public function table_structure($path, $table)
  {
    if ( ! is_writable( $path ) ) {
      return false;
    }

    $_str = '/* Table structure for table `' . $table . "` */\n";

    $sql = 'show create table `' . $table . '`;';

    $result = $this->dao->query($sql);
    if($result) {
      $result =  $result->result();
    } else {
      $result =  array();
    }

    foreach($result as $_line) {
      $_str .= str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $_line['Create Table'] . ';');
      $_str .= "\n\n";
    }

    $f = fopen( $path , 'ab' );
    fwrite($f, $_str);
    fclose($f);

    return true;
  }

  /**
   * Dump all table rows into path
   *
   * @param string $path
   * @param string $table
   *
   * @return bool
   */
  public function table_data($path, $table)
  {
    if ( ! is_writable( $path ) ) {
      return false;
    }

    $this->dao->select();
    $this->dao->from($table);
    $res  = $this->dao->get();
    $result = array ();
    if ( $res ) {
      $result = $res->result();
    }

    $_str = '';
    if($res) {
      $num_rows   = $res->numRows();
      $num_fields = $res->numFields();
      $fields   = $res->resultId->fetch_fields();

      if( $num_rows > 0 ) {
        $_str .= '/* dumping data for table `' . $table . '` */';
        $_str .= "\n";

        $field_type = array();
        $i = 0;

        while ($meta = $res->resultId->fetch_field()) {
          $field_type[] = $meta->type;
        }

        $_str .= 'insert into `' . $table . '` values';
        $_str .= "\n";

        $index = 0;
        if($table==DB_TABLE_PREFIX.'t_category') {
          $this->_dump_table_category($result, $num_fields, $field_type, $fields, $index, $num_rows, $_str);
        } else {
          foreach($result as $row) {
            $_str .= '(';
            for( $i = 0; $i < $num_fields; $i++ ) {
              $v = $row[$fields[$i]->name];
              if ( null === $v ) {
                $_str .= 'null';
              } else {
                $this->_quotes($fields[$i]->type, $_str, $row[$fields[$i]->name]);
              }
              if($i < $num_fields-1) {
                $_str .= ',';
              }
            }
            $_str .= ')';

            if($index < $num_rows-1) {
              $_str .= ',';
            } else {
              $_str .= ';';
            }
            $_str .= "\n";

            $index++;
          }
        }
      }
    }

    $_str .= "\n";

    $f = fopen( $path , 'ab' );
    fwrite($f, $_str);
    fclose($f);

    return true;
  }

  /**
   * Specific dump for t_category table
   *
   * @param $result
   * @param $num_fields
   * @param $field_type
   * @param $fields
   * @param $index
   * @param $num_rows
   * @param $_str
   */
  private function _dump_table_category($result, $num_fields, $field_type, $fields, $index, $num_rows, &$_str)
  {
    $short_rows = array();
    $unshort_rows = array();
    foreach($result as $row) {
      if( $row['fk_i_parent_id'] == NULL) {
        $short_rows[] = $row;
      } else {
        $unshort_rows[$row['pk_i_id']] = $row;
      }
    }

    while(!empty($unshort_rows)) {
      foreach($unshort_rows as $k => $v) {
        foreach($short_rows as $r) {
          if($r['pk_i_id']==$v['fk_i_parent_id']) {
            unset($unshort_rows[$k]);
            $short_rows[] = $v;
          }
        }
      }
    }

    foreach($short_rows as $row) {
      $_str .= '(';
      for( $i = 0; $i < $num_fields; $i++ ) {
        $v = $row[$fields[$i]->name];
        if ( null === $v ) {
          $_str .= 'null';
        } else {
          $this->_quotes($fields[$i]->type, $_str, $v);
        }
        if($i < $num_fields-1) {
          $_str .= ',';
        }
      }
      $_str .= ')';

      if($index < $num_rows-1) {
        $_str .= ',';
      } else {
        $_str .= ';';
      }
      $_str .= "\n";

      $index++;
    }
  }


  /**
   * Add quotes if it's necessary
   *
   * data =>  http://www.php.net/manual/es/mysqli-result.fetch-field.php#106064
   *
   * @param $type
   * @param $_str
   * @param $value
   */
  private function _quotes( $type , &$_str, $value)
  {
    // * numeric *
    // BIT: 16 - TINYINT: 1 - BOOL: 1 - SMALLINT: 2 - MEDIUMINT: 9
    // INTEGER: 3 - BIGINT: 8 - SERIAL: 8 - FLOAT: 4 - DOUBLE: 5
    // DECIMAL: 246 - NUMERIC: 246 - FIXED: 246
    // * dates *
    // DATE: 10 - DATETIME: 12 - TIMESTAMP: 7 - TIME: 11 - YEAR: 13
    // * strings & binary *
    // CHAR: 254 - VARCHAR: 253 - ENUM: 254 - SET: 254 - BINARY: 254
    // VARBINARY: 253 - TINYBLOB: 252 - BLOB: 252 - MEDIUMBLOB: 252
    // TINYTEXT: 252 - TEXT: 252 - MEDIUMTEXT: 252 - LONGTEXT: 252

    $aNumeric = array(16, 1, 2, 9, 3, 8, 4, 5, 246 );
    $aDates   = array(10, 12, 7, 11, 13 );
    $aString  = array ( 254 , 253 , 252 );

    if ( in_array( $type , $aNumeric , true ) ) {
      $_str .= $value;
    } else if ( in_array( $type , $aDates , true ) ) {
      $_str .= '\'' . $this->dao->connId->real_escape_string($value) . '\'';
    } else if ( in_array( $type , $aString , true ) ) {
      $_str .= '\'' . $this->dao->connId->real_escape_string($value) . '\'';
    }
  }
}

/* file end: ./oc-includes/osclass/model/Dump.php */