layout_profile.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. <?php
  2. // This file is part of the Sloodle project (www.sloodle.org)
  3. /**
  4. * This file defines structures for managing Sloodle layout profiles.
  5. *
  6. * @package sloodle
  7. * @copyright Copyright (c) 2007-2010 various contributors
  8. * @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
  9. *
  10. * @contributor Peter R. Bloomfield
  11. * @contributor Edmund Edgar
  12. */
  13. class SloodleLayout
  14. {
  15. var $name;
  16. var $id;
  17. var $course; // NB This is an ID of the course, not an object representing the course
  18. var $entries = array();
  19. var $originalentries = array();
  20. function SloodleLayout($r = null) {
  21. if ($r != null) {
  22. return $this->load_from_row($r);
  23. }
  24. return null;
  25. }
  26. // return a name for the layout, numbering based on the prefix
  27. function UniqueName($prefix) {
  28. for ($i=1; $i<100000; $i++) {
  29. $candidate = $prefix.$i;
  30. if (!$rec = sloodle_get_record('sloodle_layout','name',$candidate)) {
  31. return $candidate;
  32. }
  33. }
  34. return false;
  35. }
  36. function load_from_row($r) {
  37. if (!$r) return null;
  38. $this->name = $r->name;
  39. $this->id = $r->id;
  40. $this->course = $r->course;
  41. $this->controllerid = $r->controllerid;
  42. $this->originalentries = $this->get_entries($store = false);
  43. return true;
  44. }
  45. function load($id) {
  46. $rec = sloodle_get_record('sloodle_layout','id',$id);
  47. if (!$rec) return null;
  48. $loaded = $this->load_from_row($rec);
  49. return true;
  50. }
  51. function populate_entries_from_active_objects() {
  52. $entries = $this->entries;
  53. $ok = true;
  54. for ($i=0; $i<count($entries); $i++) {
  55. $entry = $entries[$i];
  56. if ( (isset($entry->objectuuid)) && ($entry->objectuuid != null) && ($entry->objectuuid != '') ) {
  57. $entry->populate_from_active_object();
  58. }
  59. }
  60. return $ok;
  61. }
  62. function has_active_objects_rezzed_by_rezzer( $rezzeruuid ) {
  63. global $CFG;
  64. $layoutid = intval($this->id);
  65. $select = "select count(*) as cnt from {$CFG->prefix}sloodle_active_object a inner join {$CFG->prefix}sloodle_layout_entry le on a.layoutentryid=le.id where a.rezzeruuid=? and le.layout=?";
  66. $recs = sloodle_get_records_sql_params( $select, array($rezzeruuid, $layoutid ));
  67. if (!$recs) {
  68. return false;
  69. }
  70. $rec = array_pop($recs);
  71. $cnt = $rec->cnt;
  72. return ( $cnt > 0 );
  73. }
  74. function rezzed_active_objects( $rezzeruuid = null ) {
  75. global $CFG;
  76. $layoutid = intval($this->id);
  77. $select = "select a.* from {$CFG->prefix}sloodle_active_object a inner join {$CFG->prefix}sloodle_layout_entry le on a.layoutentryid=le.id where le.layout=?";
  78. $args = array($layoutid);
  79. if ($rezzeruuid) {
  80. $rezzeruuid = addslashes($rezzeruuid);
  81. $select .= " and rezzeruuid=?";
  82. $args[] = $rezzeruuid;
  83. }
  84. $recs = sloodle_get_records_sql_params( $select, $args );
  85. if (!$recs) {
  86. return false;
  87. }
  88. $aos = array();
  89. foreach($recs as $rec) {
  90. $ao = new SloodleActiveObject();
  91. $ao->loadFromRecord($rec);
  92. $aos[] = $ao;
  93. }
  94. return $aos;
  95. }
  96. // return a has of rezzed objects with the layout entry id as the key
  97. function rezzed_active_objects_by_layout_entry_id( $rezzeruuid = null ) {
  98. $aos = $this->rezzed_active_objects( $rezzeruuid );
  99. $aohash = array();
  100. if (is_array($aos) && count($aos) > 0) {
  101. foreach($aos as $ao) {
  102. $leid = $ao->layoutentryid;
  103. if (!isset($aohash[ $leid ])) {
  104. $aohash[ $leid ] = array();
  105. }
  106. $aohash[ $leid ][] = $ao;
  107. }
  108. }
  109. return $aohash;
  110. }
  111. function get_sloodle_course() {
  112. $course = new SloodleCourse();
  113. if ($course->load($this->course)) {
  114. return $course;
  115. }
  116. return null;
  117. }
  118. function get_course() {
  119. return sloodle_get_record('course','id',$this->course);
  120. }
  121. // return a set of SloodleLayoutEntry objects for the layout.
  122. // store parameter indicates whether they should be stored as instance variables.
  123. // set $store=false if you're planning to update the object entries and you're only reading them in so the object will know what is already there and what to insert and delete.
  124. function get_entries($store = true) {
  125. $rows = sloodle_get_records('sloodle_layout_entry','layout',$this->id);
  126. $entries = array();
  127. if ($rows && ( count($rows) > 0) ) {
  128. foreach($rows as $row) {
  129. $entries[] = new SloodleLayoutEntry($row);
  130. }
  131. }
  132. if ($store) {
  133. $this->entries = $entries;
  134. }
  135. //print "<h4>layout.get_entries returning ".count($entries)."entries</h4>";
  136. return $entries;
  137. }
  138. function add_entry($entry) {
  139. $entries = $this->entries;
  140. $entries[] = $entry;
  141. $this->entries = $entries;
  142. }
  143. function insert() {
  144. $this->id = sloodle_insert_record('sloodle_layout', $this);
  145. $this->save_entries();
  146. return $this->id;
  147. }
  148. function update() {
  149. if (!sloodle_update_record('sloodle_layout', $this)) {
  150. return false;
  151. }
  152. return $this->save_entries();
  153. }
  154. function delete() {
  155. $this->delete_entries();
  156. if (!sloodle_delete_records('sloodle_layout', 'id', $this->id)) {
  157. return false;
  158. }
  159. return true;
  160. }
  161. function delete_entries() {
  162. $this->entries = array();
  163. $this->save_entries();
  164. }
  165. function save_clone( $name ) {
  166. $clone = new SloodleLayout();
  167. $clone->name = $name;
  168. $clone->course = $this->course;
  169. $clone->controllerid = $this->controllerid;
  170. if (!$cloneid = sloodle_insert_record('sloodle_layout', $clone)) {
  171. return false;
  172. }
  173. $clone->id = $cloneid;
  174. $clone->entries = array();
  175. foreach($this->originalentries as $entry) {
  176. $cloneentry = ( version_compare(phpversion(), '5.0') ) ? clone($entry) : $entry;
  177. $cloneentry->id = null;
  178. $clone->entries[] = $cloneentry;
  179. }
  180. $clone->save_entries();
  181. return $cloneid;
  182. }
  183. function save_entries() {
  184. $neededids = array();
  185. foreach($this->entries as $entry) {
  186. $entry->layout = $this->id;
  187. if (!$entry->id) {
  188. $entry->id = $entry->insert();
  189. } else {
  190. $entry->update();
  191. }
  192. $neededids[] = $entry->id;
  193. }
  194. if (count($this->originalentries) > 0) {
  195. foreach($this->originalentries as $entry) {
  196. $entryid = $entry->id;
  197. if (!in_array($entryid,$neededids)) {
  198. $entry->delete();
  199. }
  200. }
  201. }
  202. return true;
  203. }
  204. }
  205. /**
  206. * Stores data for a single entry in a layout profile.
  207. * Used with {@link SloodleCourse}
  208. * @package sloodle
  209. */
  210. class SloodleLayoutEntry
  211. {
  212. // DATA //
  213. /**
  214. * The name of the object this entry represents.
  215. * @var string
  216. * @access public
  217. */
  218. var $name = '';
  219. /**
  220. * The position of the object, as a 3d vector, in string format "<x,y,z>"
  221. * @var string
  222. * @access public
  223. */
  224. var $position = '<0.0,0.0,0.0>';
  225. /**
  226. * The rotation of the object, as a 3d vector of Euler angles, in string format "<x,y,z>"
  227. * @var string
  228. * @access public
  229. */
  230. var $rotation = '<0.0,0.0,0.0>';
  231. var $id;
  232. var $layout;
  233. var $configs;
  234. var $originalconfigs;
  235. function SloodleLayoutEntry($r = null) {
  236. if ($r != null) {
  237. return $this->load_from_row($r);
  238. }
  239. return true;
  240. }
  241. // returns an objectconfig object for the tool, based on the name of the entry
  242. // returns null if it can't find one.
  243. function get_object_config() {
  244. if ( !$name = $this->name ) {
  245. return null;
  246. }
  247. return SloodleObjectConfig::ForObjectName( $name );
  248. }
  249. function load_from_row($r) {
  250. if (!$r) return null;
  251. $this->name = $r->name;
  252. $this->position = $r->position;
  253. $this->rotation = $r->rotation;
  254. $this->id = $r->id;
  255. $this->layout = $r->layout;
  256. if (isset($r->objectuuid)) {
  257. $this->objectuuid = $r->objectuuid; // not saved - just used to populate defaults
  258. }
  259. $this->configs = $this->get_layout_entry_configs();
  260. $this->originalconfigs = $this->configs; // save the original configs so we know what to delete, what to update and what to add
  261. return true;
  262. }
  263. function load($id) {
  264. $rec = sloodle_get_record('sloodle_layout_entry', 'id', $id);
  265. if (!$rec) return null;
  266. return $this->load_from_row($rec);
  267. }
  268. function populate_from_active_object() {
  269. if (!$objectuuid = $this->objectuuid) {
  270. return false;
  271. }
  272. $object = sloodle_get_record('sloodle_active_object','uuid',$this->objectuuid);
  273. $object_id = $object->id;
  274. if (!$object_id) return false;
  275. $configs = sloodle_get_records('sloodle_object_config','object',$object_id);
  276. foreach($configs as $config) {
  277. $this->set_config($config->name,$config->value);
  278. }
  279. return true;
  280. }
  281. function get_layout() {
  282. if ($this->layout != null) {
  283. $layout = new SloodleLayout();
  284. if ( $layout->load($this->layout) ) {
  285. return $layout;
  286. }
  287. }
  288. return null;
  289. }
  290. /**
  291. * Return an array of layout_entry_config objects
  292. * @param integer $layout_entry_id The ID of the layout entry
  293. * @return array Array if successful (empty if there are no entries) , or null otherwise
  294. */
  295. function get_layout_entry_configs() {
  296. $recs = sloodle_get_records('sloodle_layout_entry_config', 'layout_entry', $this->id);
  297. if (!$recs) return null;
  298. // Construct the array of SloodleLayoutEntry objects
  299. $entryconfigs = array();
  300. foreach ($recs as $r) {
  301. $entryconfigs[] = new SloodleLayoutEntryConfig($r);
  302. }
  303. return $entryconfigs;
  304. }
  305. function get_layout_entry_configs_as_hidden_fields($prefix, $suffix) {
  306. $str = '';
  307. foreach($this->get_layout_entry_configs_as_name_value_hash() as $n=>$v) {
  308. $fieldname = $prefix.$n.$suffix;
  309. $str .= '<input type="hidden" name="'.$fieldname.'" value="'.$v.'" />';
  310. }
  311. return $str;
  312. }
  313. function get_layout_entry_configs_as_name_value_hash() {
  314. $objs = $this->get_layout_entry_configs();
  315. $configs = array();
  316. if (count($objs) > 0) {
  317. foreach($objs as $obj) {
  318. $configs[$obj->name] = $obj->value;
  319. }
  320. }
  321. return $configs;
  322. }
  323. /**
  324. * Sets the position as separate X,Y,Z components
  325. * @param float $x The X component to set
  326. * @param float $y The Y component to set
  327. * @param float $z The Z component to set
  328. * @return void
  329. */
  330. function set_position_xyz($x, $y, $z)
  331. {
  332. $this->position = "<$x,$y,$z>";
  333. }
  334. /**
  335. * Sets the rotation as separate X,Y,Z components
  336. * @param float $x The X component to set
  337. * @param float $y The Y component to set
  338. * @param float $z The Z component to set
  339. * @return void
  340. */
  341. function set_rotation_xyz($x, $y, $z)
  342. {
  343. $this->rotation = "<$x,$y,$z>";
  344. }
  345. function get_config($name) {
  346. $configs = $this->get_layout_entry_configs_as_name_value_hash();
  347. if (!isset($configs[$name])) {
  348. return null;
  349. }
  350. return $configs[$name];
  351. }
  352. function set_config($name, $value) { // add config with given name/value, overwriting if necessary
  353. $configs = $this->configs;
  354. $done = false;
  355. if ( is_array($configs) ) {
  356. for( $i=0; $i<count($configs); $i++) {
  357. $config = $configs[$i];
  358. if ($config->name == $name) {
  359. $config->value = $value;
  360. $configs[$i] = $config;
  361. $done = true;
  362. }
  363. }
  364. } else {
  365. $configs = array();
  366. }
  367. if (!$done) {
  368. $config = new SloodleLayoutEntryConfig();
  369. $config->layout_entry = $this->id;
  370. $config->name = $name;
  371. $config->value = $value;
  372. $configs[] = $config;
  373. }
  374. $this->configs = $configs;
  375. }
  376. function insert() {
  377. $this->id = sloodle_insert_record('sloodle_layout_entry', $this);
  378. if (!$this->id) {
  379. return false;
  380. }
  381. if ( $this->save_configs() ) {
  382. return $this->id;
  383. }
  384. }
  385. function update() {
  386. if (!sloodle_update_record('sloodle_layout_entry', $this)) {
  387. return false;
  388. }
  389. return $this->save_configs();
  390. }
  391. function delete() {
  392. if (!$this->id) return false;
  393. if (!$this->delete_configs()) {
  394. return false;
  395. }
  396. $result = sloodle_delete_records('sloodle_layout_entry', 'id', $this->id);
  397. return $result;
  398. }
  399. function delete_configs() {
  400. return sloodle_delete_records('sloodle_layout_entry_config', 'layout_entry', $this->id);
  401. }
  402. function save_configs() {
  403. if (count($this->configs) == 0) {
  404. return true;
  405. }
  406. foreach($this->configs as $config) {
  407. $config->layout_entry = $this->id;
  408. if (!$config->id) {
  409. $entry_id = $config->insert();
  410. } else {
  411. $config->update();
  412. }
  413. }
  414. return true;
  415. }
  416. function active_objects() {
  417. $recs = sloodle_get_records('sloodle_active_object','layoutentryid',intval($this->id));
  418. $aos = array();
  419. if (is_array($recs) && (count($recs) > 0)) {
  420. foreach($recs as $rec) {
  421. $ao = new SloodleActiveObject();
  422. $ao->loadFromRecord($rec);
  423. $aos[] = $ao;
  424. }
  425. }
  426. return $aos;
  427. }
  428. // returns an instance of SloodleLayoutEntry with the default config for an object with the specified name
  429. // is_dummy means we have a non-sloodle object with no particular fields.
  430. function ForConfig( $name, $is_dummy = false ) {
  431. if ($is_dummy) {
  432. if ( !$obj = SloodleObjectConfig::ForNonSloodleObjectWithName( $name ) ) {
  433. return null;
  434. }
  435. } else {
  436. if ( !$obj = SloodleObjectConfig::ForObjectName( $name ) ) {
  437. return null;
  438. }
  439. }
  440. $le = new SloodleLayoutEntry();
  441. $le->name = $name;
  442. foreach( $obj->field_sets as $grp ) {
  443. foreach($grp as $n => $op) {
  444. $le->set_config($n, $op->default);
  445. }
  446. }
  447. return $le;
  448. }
  449. function objectDefinition() {
  450. return SloodleObjectConfig::ForObjectName( $this->name );
  451. }
  452. function get_course_module_instance() {
  453. if (!$defn = $this->objectDefinition() ) {
  454. return null;
  455. }
  456. if (!$modtype = $defn->module) {
  457. return null;
  458. }
  459. if (!$sloodlemoduleid = intval($this->get_config('sloodlemoduleid'))){
  460. return null;
  461. }
  462. if (!$cm = sloodle_get_record('course_modules', 'id', $sloodlemoduleid)) {
  463. return null;
  464. }
  465. if (!$inst = sloodle_get_record($modtype, 'id', $cm->instance)) {
  466. return null;
  467. }
  468. return $inst;
  469. }
  470. function get_course_module_title() {
  471. if (!$inst = $this->get_course_module_instance()) {
  472. return null;
  473. }
  474. return $inst->name;
  475. }
  476. }
  477. class SloodleLayoutEntryConfig
  478. {
  479. var $id;
  480. var $layout_entry;
  481. var $name;
  482. var $value;
  483. function SloodleLayoutEntryConfig($row = null) {
  484. if ($row != null) {
  485. return $this->load_from_row($row);
  486. }
  487. return null;
  488. }
  489. function load_from_row($row) {
  490. if (!$row) return null;
  491. $this->id = $row->id;
  492. $this->layout_entry = $row->layout_entry;
  493. $this->name = $row->name;
  494. $this->value = $row->value;
  495. }
  496. function load($id) {
  497. $rec = sloodle_get_record('sloodle_layout_entry_config', 'id', $id);
  498. if (!$rec) return null;
  499. return $this->load_from_row($rec);
  500. }
  501. function insert() {
  502. return $this->id = sloodle_insert_record('sloodle_layout_entry_config', $this);
  503. }
  504. function update() {
  505. return sloodle_update_record('sloodle_layout_entry_config', $this);
  506. }
  507. }
  508. ?>