joomla-platform / libraries / joomla / database / database / mysqlexporter.php

<?php
/**
 * @package     Joomla.Platform
 * @subpackage  Database
 *
 * @copyright   Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE
 */

defined('JPATH_PLATFORM') or die;

/**
 * MySQL export driver.
 *
 * @package     Joomla.Platform
 * @subpackage  Database
 * @since       11.1
 */
class JDatabaseExporterMySQL
{
    /**
     * @var    array  An array of cached data.
     * @since  11.1
     */
    protected $cache = array();

    /**
     * @var    JDatabaseMySQL  The database connector to use for exporting structure and/or data.
     * @since  11.1
     */
    protected $db = null;

    /**
     * @var    array  An array input sources (table names).
     * @since  11.1
     */
    protected $from = array();

    /**
     * @var    string  The type of output format (xml).
     * @since  11.1
     */
    protected $asFormat = 'xml';

    /**
     * @var    JObject  An array of options for the exporter.
     * @since  11.1
     */
    protected $options = null;

    /**
     * Constructor.
     *
     * Sets up the default options for the exporter.
     *
     * @return  JDatabaseExporterMySQL
     * @since   11.1
     */
    public function __construct()
    {
        $this->options = new JObject;

        $this->cache = array(
            'columns'   => array(),
            'keys'      => array(),
        );

        // Set up the class defaults:

        // Export with only structure
        $this->withStructure();

        // Export as xml.
        $this->asXml();

        // Default destination is a string using $output = (string) $exporter;
    }

    /**
     * Magic function to exports the data to a string.
     *
     * @return  string
     * @since   11.1
     * @throws  Exception if an error is encountered.
     */
    public function __toString()
    {
        // Check everything is ok to run first.
        $this->check();

        $buffer = '';

        // Get the format.
        switch ($this->asFormat)
        {
            case 'xml':
            default:
                $buffer = $this->buildXml();
                break;
        }

        return $buffer;
    }

    /**
     * Set the output option for the exporter to XML format.
     *
     * @return  JDatabaseExporterMySQL  Method supports chaining.
     * @since   11.1
     */
    public function asXml()
    {
        $this->asFormat = 'xml';

        return $this;
    }

    /**
     * Builds the XML data for the tables to export.
     *
     * @return  string  An XML string
     * @throws  Exception if an error occurs.
     * @since   11.1
     */
    protected function buildXml()
    {
        $buffer = array();

        $buffer[] = '<?xml version="1.0"?>';
        $buffer[] = '<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
        $buffer[] = ' <database name="">';

        $buffer = array_merge($buffer, $this->buildXmlStructure());

        $buffer[] = ' </database>';
        $buffer[] = '</mysqldump>';

        return implode("\n", $buffer);
    }

    /**
     * Builds the XML structure to export.
     *
     * @return  array  An array of XML lines (strings).
     * @throws  Exception if an error occurs.
     * @since   11.1
     */
    protected function buildXmlStructure()
    {
        $buffer = array();

        foreach ($this->from as $table)
        {
            // Replace the magic prefix if found.
            $table = $this->getGenericTableName($table);

            // Get the details columns information.
            $fields = $this->getColumns($table);
            $keys   = $this->getKeys($table);

            $buffer[] = '  <table_structure name="'.$table .'">';

            foreach ($fields as $field) {
                $buffer[] = '   <field Field="'.$field->Field.'"'.
                    ' Type="'.$field->Type.'"'.
                    ' Null="'.$field->Null.'"'.
                    ' Key="'.$field->Key.'"'.
                    (isset($field->Default) ? ' Default="'.$field->Default.'"' : '').
                    ' Extra="'.$field->Extra.'"'.
                    ' />';
            }

            foreach ($keys as $key) {
                $buffer[] = '   <key Table="'.$table.'"'.
                    ' Non_unique="'.$key->Non_unique.'"'.
                    ' Key_name="'.$key->Key_name.'"'.
                    ' Seq_in_index="'.$key->Seq_in_index.'"'.
                    ' Column_name="'.$key->Column_name.'"'.
                    ' Collation="'.$key->Collation.'"'.
                    ' Null="'.$key->Null.'"'.
                    ' Index_type="'.$key->Index_type.'"'.
                    ' Comment="'.htmlspecialchars($key->Comment).'"'.
                    ' />';

            }

            $buffer[] = '  </table_structure>';
        }

        return $buffer;
    }

    /**
     * Checks if all data and options are in order prior to exporting.
     *
     * @return  JDatabaseExporterMySQL  Method supports chaining.
     * @since   11.1
     * @throws  Exception if an error is encountered.
     */
    public function check()
    {
        // Check if the db connector has been set.
        if (!($this->db instanceof JDatabaseMySQL)) {
            throw new Exception('JPLATFORM_ERROR_DATABASE_CONNECTOR_WRONG_TYPE');
        }

        // Check if the tables have been specified.
        if (empty($this->from)) {
            throw new Exception('JPLATFORM_ERROR_NO_TABLES_SPECIFIED');
        }

        return $this;
    }

    /**
     * Get the details list of columns for a table.
     *
     * @param   string  $table  The name of the table.
     *
     * @return  array   An arry of the column specification for the table.
     * @since   11.1
     * @throws  Exception
     * @todo    Move into database connector class.
     */
    protected function getColumns($table)
    {
        if (empty($this->cache['columns'][$table])) {
            // Get the details columns information.
            $this->db->setQuery(
                'SHOW FULL COLUMNS FROM '.$this->db->nameQuote($table)
            );
            $this->cache['columns'][$table] = $this->db->loadObjectList('Field');

            // Check for a db error.
            if ($this->db->getErrorNum()) {
                throw new Exception($this->db->getErrorMsg());
            }
        }

        return $this->cache['columns'][$table];
    }

    /**
     * Get the generic name of the table, converting the database prefix to the wildcard string.
     *
     * @param   string  $table  The name of the table.
     *
     * @return  string  The name of the table with the database prefix replaced with #__.
     * @since   11.1
     */
    protected function getGenericTableName($table)
    {
        // TODO Incorporate into parent class and use $this.
        $prefix = $this->db->getPrefix();

        // Replace the magic prefix if found.
        $table = preg_replace("|^$prefix|", '#__', $table);

        return $table;
    }

    /**
     * Get the details list of keys for a table.
     *
     * @param   string  $table  The name of the table.
     *
     * @return  array  An arry of the column specification for the table.
     * @since   11.1
     * @throws  Exception
     * @todo    Move into database connector class.
     */
    protected function getKeys($table)
    {
        if (empty($this->cache['keys'][$table])) {
            // Get the details columns information.
            $this->db->setQuery(
                'SHOW KEYS FROM '.$this->db->nameQuote($table)
            );
            $this->cache['keys'][$table] = $this->db->loadObjectList();

            // Check for a db error.
            if ($this->db->getErrorNum()) {
                throw new Exception($db->getErrorMsg());
            }
        }

        return $this->cache['keys'][$table];
    }

    /**
     * Specifies a list of table names to export.
     *
     * @param   mixed  $from  The name of a single table, or an array of the table names to export.
     *
     * @return  JDatabaseExporterMySQL  Method supports chaining.
     * @since   11.1
     * @throws  Exception if input is not a string or array.
     */
    public function from($from)
    {
        if (is_string($from)) {
            $this->from = array($from);
        }
        else if (is_array($from)) {
            $this->from = $from;
        }
        else {
            throw new Exception('JPLATFORM_ERROR_INPUT_REQUIRES_STRING_OR_ARRAY');
        }

        return $this;
    }

    /**
     * Sets the database connector to use for exporting structure and/or data from MySQL.
     *
     * @param   JDatabaseMySQL  $db  The database connector.
     *
     * @return  JDatabaseExporterMySQL  Method supports chaining.
     * @since   11.1
     */
    public function setDbo(JDatabaseMySQL $db)
    {
        $this->db = $db;

        return $this;
    }

    /**
     * Sets an internal option to export the structure of the input table(s).
     *
     * @param   boolean  $setting  True to export the structure, false to not.
     *
     * @return  JDatabaseExporterMySQL  Method supports chaining.
     * @since   11.1
     */
    public function withStructure($setting = true)
    {
        $this->options->set('with-structure', (boolean) $setting);

        return $this;
    }
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.