PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/xmldb/xmldb_object.php

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