1 <?php
  2 /**
  3  * @package     Joomla.Platform
  4  * @subpackage  Database
  5  *
  6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
  7  * @license     GNU General Public License version 2 or later; see LICENSE
  8  */
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 /**
 13  * Joomla Platform Database Importer Class
 14  *
 15  * @since  12.1
 16  */
 17 abstract class JDatabaseImporter
 18 {
 19     /**
 20      * @var    array  An array of cached data.
 21      * @since  13.1
 22      */
 23     protected $cache = array();
 24 
 25     /**
 26      * The database connector to use for exporting structure and/or data.
 27      *
 28      * @var    JDatabaseDriver
 29      * @since  13.1
 30      */
 31     protected $db = null;
 32 
 33     /**
 34      * The input source.
 35      *
 36      * @var    mixed
 37      * @since  13.1
 38      */
 39     protected $from = array();
 40 
 41     /**
 42      * The type of input format (XML).
 43      *
 44      * @var    string
 45      * @since  13.1
 46      */
 47     protected $asFormat = 'xml';
 48 
 49     /**
 50      * An array of options for the exporter.
 51      *
 52      * @var    object
 53      * @since  13.1
 54      */
 55     protected $options = null;
 56 
 57     /**
 58      * Constructor.
 59      *
 60      * Sets up the default options for the exporter.
 61      *
 62      * @since   13.1
 63      */
 64     public function __construct()
 65     {
 66         $this->options = new stdClass;
 67 
 68         $this->cache = array('columns' => array(), 'keys' => array());
 69 
 70         // Set up the class defaults:
 71 
 72         // Import with only structure
 73         $this->withStructure();
 74 
 75         // Export as XML.
 76         $this->asXml();
 77 
 78         // Default destination is a string using $output = (string) $exporter;
 79     }
 80 
 81     /**
 82      * Set the output option for the exporter to XML format.
 83      *
 84      * @return  JDatabaseImporter  Method supports chaining.
 85      *
 86      * @since   13.1
 87      */
 88     public function asXml()
 89     {
 90         $this->asFormat = 'xml';
 91 
 92         return $this;
 93     }
 94 
 95     /**
 96      * Checks if all data and options are in order prior to exporting.
 97      *
 98      * @return  JDatabaseImporter  Method supports chaining.
 99      *
100      * @since   13.1
101      * @throws  Exception if an error is encountered.
102      */
103     abstract public function check();
104 
105     /**
106      * Specifies the data source to import.
107      *
108      * @param   mixed  $from  The data source to import.
109      *
110      * @return  JDatabaseImporter  Method supports chaining.
111      *
112      * @since   13.1
113      */
114     public function from($from)
115     {
116         $this->from = $from;
117 
118         return $this;
119     }
120 
121     /**
122      * Get the SQL syntax to drop a column.
123      *
124      * @param   string  $table  The table name.
125      * @param   string  $name   The name of the field to drop.
126      *
127      * @return  string
128      *
129      * @since   13.1
130      */
131     protected function getDropColumnSql($table, $name)
132     {
133         return 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP COLUMN ' . $this->db->quoteName($name);
134     }
135 
136     /**
137      * Get the real name of the table, converting the prefix wildcard string if present.
138      *
139      * @param   string  $table  The name of the table.
140      *
141      * @return  string  The real name of the table.
142      *
143      * @since   13.1
144      */
145     protected function getRealTableName($table)
146     {
147         $prefix = $this->db->getPrefix();
148 
149         // Replace the magic prefix if found.
150         $table = preg_replace('|^#__|', $prefix, $table);
151 
152         return $table;
153     }
154 
155     /**
156      * Merges the incoming structure definition with the existing structure.
157      *
158      * @return  void
159      *
160      * @note    Currently only supports XML format.
161      * @since   13.1
162      * @throws  RuntimeException on error.
163      */
164     public function mergeStructure()
165     {
166         $prefix = $this->db->getPrefix();
167         $tables = $this->db->getTableList();
168 
169         if ($this->from instanceof SimpleXMLElement)
170         {
171             $xml = $this->from;
172         }
173         else
174         {
175             $xml = new SimpleXMLElement($this->from);
176         }
177 
178         // Get all the table definitions.
179         $xmlTables = $xml->xpath('database/table_structure');
180 
181         foreach ($xmlTables as $table)
182         {
183             // Convert the magic prefix into the real table name.
184             $tableName = (string) $table['name'];
185             $tableName = preg_replace('|^#__|', $prefix, $tableName);
186 
187             if (in_array($tableName, $tables))
188             {
189                 // The table already exists. Now check if there is any difference.
190                 if ($queries = $this->getAlterTableSql($xml->database->table_structure))
191                 {
192                     // Run the queries to upgrade the data structure.
193                     foreach ($queries as $query)
194                     {
195                         $this->db->setQuery((string) $query);
196                         $this->db->execute();
197                     }
198                 }
199             }
200             else
201             {
202                 // This is a new table.
203                 $sql = $this->xmlToCreate($table);
204 
205                 $this->db->setQuery((string) $sql);
206                 $this->db->execute();
207             }
208         }
209     }
210 
211     /**
212      * Sets the database connector to use for exporting structure and/or data.
213      *
214      * @param   JDatabaseDriver  $db  The database connector.
215      *
216      * @return  JDatabaseImporter  Method supports chaining.
217      *
218      * @since   13.1
219      */
220     public function setDbo(JDatabaseDriver $db)
221     {
222         $this->db = $db;
223 
224         return $this;
225     }
226 
227     /**
228      * Sets an internal option to merge the structure based on the input data.
229      *
230      * @param   boolean  $setting  True to export the structure, false to not.
231      *
232      * @return  JDatabaseImporter  Method supports chaining.
233      *
234      * @since   13.1
235      */
236     public function withStructure($setting = true)
237     {
238         $this->options->withStructure = (boolean) $setting;
239 
240         return $this;
241     }
242 }
243