Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * This class represent the XMLDB base class where all the common pieces are defined
19
 *
20
 * @package    core_xmldb
21
 * @copyright  1999 onwards Martin Dougiamas     http://dougiamas.com
22
 *             2001-3001 Eloy Lafuente (stronk7) http://contiento.com
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
 
29
class xmldb_object {
30
 
31
    /** @var string name of obejct */
32
    protected $name;
33
 
34
    /** @var string comment on object */
35
    protected $comment;
36
 
37
    /** @var string */
38
    protected $previous;
39
 
40
    /** @var string */
41
    protected $next;
42
 
43
    /** @var string hash of object */
44
    protected $hash;
45
 
46
    /** @var bool is it loaded yet */
47
    protected $loaded;
48
 
49
    /** @var bool was object changed */
50
    protected $changed;
51
 
52
    /** @var string error message */
53
    protected $errormsg;
54
 
55
    /**
56
     * Creates one new xmldb_object
57
     * @param string $name
58
     */
59
    public function __construct($name) {
60
        $this->name = $name;
61
        $this->comment = null;
62
        $this->previous = null;
63
        $this->next = null;
64
        $this->hash = null;
65
        $this->loaded = false;
66
        $this->changed = false;
67
        $this->errormsg = null;
68
    }
69
 
70
    /**
71
     * This function returns true/false, if the xmldb_object has been loaded
72
     * @return bool
73
     */
74
    public function isLoaded() {
75
        return $this->loaded;
76
    }
77
 
78
    /**
79
     * This function returns true/false, if the xmldb_object has changed
80
     * @return bool
81
     */
82
    public function hasChanged() {
83
        return $this->changed;
84
    }
85
 
86
    /**
87
     * This function returns the comment of one xmldb_object
88
     * @return string
89
     */
90
    public function getComment() {
91
        return $this->comment;
92
    }
93
 
94
    /**
95
     * This function returns the hash of one xmldb_object
96
     * @return string
97
     */
98
    public function getHash() {
99
        return $this->hash;
100
    }
101
 
102
    /**
103
     * This function will return the name of the previous xmldb_object
104
     * @return string
105
     */
106
    public function getPrevious() {
107
        return $this->previous;
108
    }
109
 
110
    /**
111
     * This function will return the name of the next xmldb_object
112
     * @return string
113
     */
114
    public function getNext() {
115
        return $this->next;
116
    }
117
 
118
    /**
119
     * This function will return the name of the xmldb_object
120
     * @return string
121
     */
122
    public function getName() {
123
        return $this->name;
124
    }
125
 
126
    /**
127
     * This function will return the error detected in the object
128
     * @return string
129
     */
130
    public function getError() {
131
        return $this->errormsg;
132
    }
133
 
134
    /**
135
     * This function will set the comment of the xmldb_object
136
     * @param string $comment
137
     */
138
    public function setComment($comment) {
139
        $this->comment = $comment;
140
    }
141
 
142
    /**
143
     * This function will set the previous of the xmldb_object
144
     * @param string $previous
145
     */
146
    public function setPrevious($previous) {
147
        $this->previous = $previous;
148
    }
149
 
150
    /**
151
     * This function will set the next of the xmldb_object
152
     * @param string $next
153
     */
154
    public function setNext($next) {
155
        $this->next = $next;
156
    }
157
 
158
    /**
159
     * This function will set the hash of the xmldb_object
160
     * @param string $hash
161
     */
162
    public function setHash($hash) {
163
        $this->hash = $hash;
164
    }
165
 
166
    /**
167
     * This function will set the loaded field of the xmldb_object
168
     * @param bool $loaded
169
     */
170
    public function setLoaded($loaded = true) {
171
        $this->loaded = $loaded;
172
    }
173
 
174
    /**
175
     * This function will set the changed field of the xmldb_object
176
     * @param bool $changed
177
     */
178
    public function setChanged($changed = true) {
179
        $this->changed = $changed;
180
    }
181
    /**
182
     * This function will set the name field of the xmldb_object
183
     * @param string $name
184
     */
185
    public function setName($name) {
186
        $this->name = $name;
187
    }
188
 
189
 
190
    /**
191
     * This function will check if one key name is ok or no (true/false)
192
     * only lowercase a-z, 0-9 and _ are allowed
193
     * @return bool
194
     */
195
    public function checkName() {
196
        $result = true;
197
 
198
        if ($this->name != preg_replace('/[^a-z0-9_ -]/i', '', $this->name)) {
199
            $result = false;
200
        }
201
        return $result;
202
    }
203
 
204
    /**
205
     * This function will check that all the elements in one array
206
     * have a correct name [a-z0-9_]
207
     * @param array $arr
208
     * @return bool
209
     */
210
    public function checkNameValues($arr) {
211
        $result = true;
212
        // TODO: Perhaps, add support for reserved words
213
 
214
        // Check the name only contains valid chars
215
        if ($arr) {
216
            foreach($arr as $element) {
217
                if (!$element->checkName()) {
218
                    $result = false;
219
                }
220
            }
221
        }
222
        // Check there aren't duplicate names
223
        if ($arr) {
224
            $existing_fields = array();
225
            foreach($arr as $element) {
226
                if (in_array($element->getName(), $existing_fields)) {
227
                    debugging('Object ' . $element->getName() . ' is duplicated!', DEBUG_DEVELOPER);
228
                    $result = false;
229
                }
230
                $existing_fields[] = $element->getName();
231
            }
232
        }
233
        return $result;
234
    }
235
 
236
    /**
237
     * Reconstruct previous/next attributes.
238
     * @param array $arr
239
     * @return bool true if $arr modified
240
     */
241
    public function fixPrevNext(&$arr) {
242
        $tweaked = false;
243
 
244
        $prev = null;
245
        foreach ($arr as $key=>$el) {
246
            $prev_value = $arr[$key]->previous;
247
            $next_value = $arr[$key]->next;
248
 
249
            $arr[$key]->next     = null;
250
            $arr[$key]->previous = null;
251
            if ($prev !== null) {
252
                $arr[$prev]->next    = $arr[$key]->name;
253
                $arr[$key]->previous = $arr[$prev]->name;
254
            }
255
            $prev = $key;
256
 
257
            if ($prev_value != $arr[$key]->previous or $next_value != $arr[$key]->next) {
258
                $tweaked = true;
259
            }
260
        }
261
 
262
        return $tweaked;
263
    }
264
 
265
    /**
266
     * This function will order all the elements in one array, following
267
     * the previous/next rules
268
     * @param array $arr
269
     * @return array|bool
270
     */
271
    public function orderElements($arr) {
272
        $result = true;
273
 
274
        // Create a new array
275
        $newarr = array();
276
        if (!empty($arr)) {
277
            $currentelement = null;
278
            // Get the element without previous
279
            foreach($arr as $key => $element) {
280
                if (!$element->getPrevious()) {
281
                    $currentelement = $arr[$key];
282
                    $newarr[0] = $arr[$key];
283
                }
284
            }
285
            if (!$currentelement) {
286
                $result = false;
287
            }
288
            // Follow the next rules
289
            $counter = 1;
290
            while ($result && $currentelement->getNext()) {
291
                $i = $this->findObjectInArray($currentelement->getNext(), $arr);
292
                $currentelement = $arr[$i];
293
                $newarr[$counter] = $arr[$i];
294
                $counter++;
295
            }
296
            // Compare number of elements between original and new array
297
            if ($result && count($arr) != count($newarr)) {
298
                $result = false;
299
            } else if ($newarr) {
300
                $result = $newarr;
301
            } else {
302
                $result = false;
303
            }
304
        } else {
305
            $result = array();
306
        }
307
        return $result;
308
    }
309
 
310
    /**
311
     * Returns the position of one object in the array.
312
     * @param string $objectname
313
     * @param array $arr
314
     * @return mixed
315
     */
316
    public function findObjectInArray($objectname, $arr) {
317
        foreach ($arr as $i => $object) {
318
            if ($objectname == $object->getName()) {
319
                return $i;
320
            }
321
        }
322
        return null;
323
    }
324
 
325
    /**
326
     * This function will display a readable info about the xmldb_object
327
     * (should be implemented inside each XMLDBxxx object)
328
     * @return string
329
     */
330
    public function readableInfo() {
331
        return get_class($this);
332
    }
333
 
334
    /**
335
     * This function will perform the central debug of all the XMLDB classes
336
     * being called automatically every time one error is found. Apart from
337
     * the main actions performed in it (XMLDB agnostic) it looks for one
338
     * function called xmldb_debug() and invokes it, passing both the
339
     * message code and the whole object.
340
     * So, to perform custom debugging just add such function to your libs.
341
     *
342
     * Call to the external hook function can be disabled by request by
343
     * defining XMLDB_SKIP_DEBUG_HOOK
344
     * @param string $message
345
     */
346
    public function debug($message) {
347
 
348
        // Check for xmldb_debug($message, $xmldb_object)
349
        $funcname = 'xmldb_debug';
350
        // If exists and XMLDB_SKIP_DEBUG_HOOK is undefined
351
        if (function_exists($funcname) && !defined('XMLDB_SKIP_DEBUG_HOOK')) {
352
            $funcname($message, $this);
353
        }
354
    }
355
 
356
    /**
357
     * Returns one array of elements from one comma separated string,
358
     * supporting quoted strings containing commas and concat function calls
359
     * @param string $string
360
     * @return array
361
     */
362
    public function comma2array($string) {
363
 
364
        $foundquotes  = array();
365
        $foundconcats = array();
366
 
367
        // Extract all the concat elements from the string
368
        preg_match_all("/(CONCAT\(.*?\))/is", $string, $matches);
369
        foreach (array_unique($matches[0]) as $key=>$value) {
370
            $foundconcats['<#'.$key.'#>'] = $value;
371
        }
372
        if (!empty($foundconcats)) {
373
            $string = str_replace($foundconcats,array_keys($foundconcats),$string);
374
        }
375
 
376
        // Extract all the quoted elements from the string (skipping
377
        // backslashed quotes that are part of the content.
378
        preg_match_all("/(''|'.*?[^\\\\]')/is", $string, $matches);
379
        foreach (array_unique($matches[0]) as $key=>$value) {
380
            $foundquotes['<%'.$key.'%>'] = $value;
381
        }
382
        if (!empty($foundquotes)) {
383
            $string = str_replace($foundquotes,array_keys($foundquotes),$string);
384
        }
385
 
386
        // Explode safely the string
387
        $arr = explode (',', $string);
388
 
389
        // Put the concat and quoted elements back again, trimming every element
390
        if ($arr) {
391
            foreach ($arr as $key => $element) {
392
                // Clear some spaces
393
                $element = trim($element);
394
                // Replace the quoted elements if exists
395
                if (!empty($foundquotes)) {
396
                    $element = str_replace(array_keys($foundquotes), $foundquotes, $element);
397
                }
398
                // Replace the concat elements if exists
399
                if (!empty($foundconcats)) {
400
                    $element = str_replace(array_keys($foundconcats), $foundconcats, $element);
401
                }
402
                // Delete any backslash used for quotes. XMLDB stuff will add them before insert
403
                $arr[$key] = str_replace("\\'", "'", $element);
404
            }
405
        }
406
 
407
        return $arr;
408
    }
409
 
410
    /**
411
     * Validates the definition of objects and returns error message.
412
     *
413
     * The error message should not be localised because it is intended for developers,
414
     * end users and admins should never see these problems!
415
     *
416
     * @param xmldb_table $xmldb_table optional when object is table
417
     * @return string null if ok, error message if problem found
418
     */
419
    public function validateDefinition(xmldb_table $xmldb_table=null) {
420
        return null;
421
    }
422
}