3 ///////////////////////////////////////////////////////////////////////////
5 // NOTICE OF COPYRIGHT //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
8 // http://moodle.com //
10 // Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
11 // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
13 // This program is free software; you can redistribute it and/or modify //
14 // it under the terms of the GNU General Public License as published by //
15 // the Free Software Foundation; either version 2 of the License, or //
16 // (at your option) any later version. //
18 // This program is distributed in the hope that it will be useful, //
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
21 // GNU General Public License for more details: //
23 // http://www.gnu.org/copyleft/gpl.html //
25 ///////////////////////////////////////////////////////////////////////////
27 /// This class represent one XMLDB Statement
28 /// (a group of SQL arbitrary sentences)
29 /// (only INSERT is allowed for now)
31 class XMLDBStatement
extends XMLDBObject
{
33 var $table; // Table we are handling
34 var $type; // XMLDB_STATEMENT_TYPE
35 var $sentences; // Collection of sentences in the statement
38 * Creates one new XMLDBStatement
40 function XMLDBStatement($name) {
41 parent
::XMLDBObject($name);
43 $this->type
= XMLDB_STATEMENT_INCORRECT
;
44 $this->sentences
= array();
48 * Get the statement table
55 * Get the statement type
62 * Get the statement sentences
64 function &getSentences() {
65 return $this->sentences
;
69 * Set the statement table
71 function setTable($table) {
72 $this->table
= $table;
76 * Set the statement type
78 function setType($type) {
83 * Add one statement sentence
85 function addSentence($sentence) {
86 $this->sentences
[] = $sentence;
90 * Load data from XML to the index
92 function arr2XMLDBStatement($xmlarr) {
97 /// traverse_xmlize($xmlarr); //Debug
98 /// print_object ($GLOBALS['traverse_array']); //Debug
99 /// $GLOBALS['traverse_array']=""; //Debug
101 /// Process key attributes (table, type, comment, previous, next)
102 if (isset($xmlarr['@']['TABLE'])) {
103 $this->table
= strtolower(trim($xmlarr['@']['TABLE']));
105 $this->errormsg
= 'Missing TABLE attribute';
106 $this->debug($this->errormsg
);
110 if (isset($xmlarr['@']['TYPE'])) {
111 /// Check for valid type
112 $type = $this->getXMLDBStatementType(trim($xmlarr['@']['TYPE']));
116 $this->errormsg
= 'Invalid TYPE attribute';
117 $this->debug($this->errormsg
);
121 $this->errormsg
= 'Missing TYPE attribute';
122 $this->debug($this->errormsg
);
126 /// Look for sentences
127 $sentencesarr = array();
129 if (isset($xmlarr['#']['SENTENCES'])) {
130 $sentences = $xmlarr['#']['SENTENCES'][0]['#']['SENTENCE'];
132 foreach ($sentences as $sentence) {
133 if (isset($sentence['@']['TEXT'])) {
134 $sentencesarr[] = trim($sentence['@']['TEXT']);
136 $this->errormsg
= 'Missing TEXT attribute in sentence';
137 $this->debug($this->errormsg
);
144 /// Finally, set the array of sentences
145 $this->sentences
= $sentencesarr;
147 /// Now, perform some validations over sentences
148 /// XMLDB_STATEMENT_INSERT checks
149 if ($this->type
== XMLDB_STATEMENT_INSERT
) {
150 /// Separate fields and values into two arrays
151 if ($this->sentences
) {
152 foreach ($this->sentences
as $sentence) {
153 $fields = $this->getFieldsFromInsertSentence($sentence);
154 $values = $this->getValuesFromInsertSentence($sentence);
155 /// Check that we aren't inserting the id field
156 if (in_array('id', $fields)) {
157 $this->errormsg
= 'Cannot insert the "id" field. It is an autonumeric column';
158 $this->debug($this->errormsg
);
161 if ($result && count($fields) == 0) {
162 $this->errormsg
= 'Missing fields in sentence "' . $sentence . '"';
163 $this->debug($this->errormsg
);
166 if ($result && count($values) == 0) {
167 $this->errormsg
= 'Missing values in sentence "' . $sentence . '"';
168 $this->debug($this->errormsg
);
171 if ($result && count($fields) != count($values)) {
172 $this->errormsg
= 'Incorrect number of fields (' .implode(', ', $fields) . ') or values (' . implode(', ', $values) . ')';
173 $this->debug($this->errormsg
);
179 /// Sentences different from INSERT are not valid for now
180 $this->errormsg
= 'Only INSERT statements are supported';
181 $this->debug($this->errormsg
);
185 if (isset($xmlarr['@']['COMMENT'])) {
186 $this->comment
= trim($xmlarr['@']['COMMENT']);
189 if (isset($xmlarr['@']['PREVIOUS'])) {
190 $this->previous
= trim($xmlarr['@']['PREVIOUS']);
193 if (isset($xmlarr['@']['NEXT'])) {
194 $this->next
= trim($xmlarr['@']['NEXT']);
197 /// Set some attributes
199 $this->loaded
= true;
201 $this->calculateHash();
206 * This function returns the correct XMLDB_STATEMENT_XXX value for the
207 * string passed as argument
209 function getXMLDBStatementType($type) {
211 $result = XMLDB_STATEMENT_INCORRECT
;
213 switch (strtolower($type)) {
215 $result = XMLDB_STATEMENT_INSERT
;
218 $result = XMLDB_STATEMENT_UPDATE
;
221 $result = XMLDB_STATEMENT_DELETE
;
224 $result = XMLDB_STATEMENT_CUSTOM
;
227 /// Return the normalized XMLDB_STATEMENT
232 * This function returns the correct name value for the
233 * XMLDB_STATEMENT_XXX passed as argument
235 function getXMLDBStatementName($type) {
239 switch (strtolower($type)) {
240 case XMLDB_STATEMENT_INSERT
:
243 case XMLDB_STATEMENT_UPDATE
:
246 case XMLDB_STATEMENT_DELETE
:
249 case XMLDB_STATEMENT_CUSTOM
:
253 /// Return the normalized name
258 * This function calculate and set the hash of one XMLDBStatement
260 function calculateHash($recursive = false) {
261 if (!$this->loaded
) {
264 $key = $this->table
. $this->type
. implode (', ', $this->sentences
);
265 $this->hash
= md5($key);
270 * This function will output the XML text for one statement
272 function xmlOutput() {
274 $o.= ' <STATEMENT NAME="' . $this->name
. '" TYPE="' . XMLDBStatement
::getXMLDBStatementName($this->type
) . '" TABLE="' . $this->table
. '"';
275 if ($this->comment
) {
276 $o.= ' COMMENT="' . htmlspecialchars($this->comment
) . '"';
278 if ($this->previous
) {
279 $o.= ' PREVIOUS="' . $this->previous
. '"';
282 $o.= ' NEXT="' . $this->next
. '"';
284 if ($this->sentences
) {
286 $o.= ' <SENTENCES>' . "\n";
287 foreach ($this->sentences
as $sentence) {
288 $o.= ' <SENTENCE TEXT="' . htmlspecialchars($sentence) . '" />' . "\n";
290 $o.= ' </SENTENCES>' . "\n";
291 $o.= ' </STATEMENT>' . "\n";
300 * This function will set all the attributes of the XMLDBIndex object
301 * based on information passed in one ADOindex
303 function setFromADOIndex($adoindex) {
305 /// Set the unique field
306 $this->unique
= false;
308 $this->fields
= $adoindex['columns'];
310 $this->loaded
= true;
311 $this->changed
= true;
315 * Shows info in a readable format
317 function readableInfo() {
326 $o .= ' (' . implode(', ', $this->fields
) . ')';
332 * This function will return an array of fields from one INSERT sentence
334 function getFieldsFromInsertSentence($sentence) {
338 /// Get first part from the sentence (before VALUES)
339 preg_match('/^\((.*)\)\s+VALUES/is', $sentence, $matches);
340 if (isset($matches[1])) {
342 /// Convert the comma separated string to an array
343 $arr = $this->comma2array($part);
353 * This function will return an array of values from one INSERT sentence
355 function getValuesFromInsertSentence($sentence) {
359 /// Get second part from the sentence (after VALUES)
360 preg_match('/VALUES\s*\((.*)\)$/is', $sentence, $matches);
361 if (isset($matches[1])) {
363 /// Convert the comma separated string to an array
364 $arr = $this->comma2array($part);
374 * This function will return the code needed to execute a collection
375 * of sentences present inside one statement for the specified BD
377 * For now it only supports INSERT statements
379 function getExecuteStatementSQL ($dbtype, $prefix, $statement_end=true) {
383 /// Based on statement type
384 switch ($this->type
) {
385 case XMLDB_STATEMENT_INSERT
:
386 $results = $this->getExecuteInsertSQL($dbtype, $prefix, $statement_end);
388 case XMLDB_STATEMENT_UPDATE
:
390 case XMLDB_STATEMENT_DELETE
:
392 case XMLDB_STATEMENT_CUSTOM
:
400 * This function will return the code needed to execute a collection
401 * of insert sentences present inside the statement for the specified BD
402 * and prefix. Just one simple wrapper over generators.
404 function getExecuteInsertSQL ($dbtype, $prefix, $statement_end=true) {
408 $classname = 'XMLDB' . $dbtype;
409 $generator = new $classname();
410 $generator->setPrefix($prefix);
412 $results = $generator->getExecuteInsertSQL($this);
414 if ($statement_end) {
415 $results = $generator->getEndedStatements($results);