|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00034 defined('MOODLE_INTERNAL') || die(); 00035 00047 abstract class moodle_list { 00048 public $attributes; 00049 public $listitemclassname = 'list_item'; 00050 00052 public $items = array(); 00053 00055 public $type; 00056 00058 public $parentitem = null; 00059 public $table; 00060 public $fieldnamesparent = 'parent'; 00061 00063 public $records = array(); 00064 00065 public $editable; 00066 00068 public $childparent; 00069 00070 //------------------------------------------------------ 00071 //vars used for pagination. 00072 public $page = 0; // 0 means no pagination 00073 public $firstitem = 1; 00074 public $lastitem = 999999; 00075 public $pagecount; 00076 public $paged = false; 00077 public $offset = 0; 00078 //------------------------------------------------------ 00079 public $pageurl; 00080 public $pageparamname; 00081 00093 public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20) { 00094 global $PAGE; 00095 00096 $this->editable = $editable; 00097 $this->attributes = $attributes; 00098 $this->type = $type; 00099 $this->page = $page; 00100 $this->pageparamname = $pageparamname; 00101 $this->itemsperpage = $itemsperpage; 00102 if ($pageurl === null) { 00103 $this->pageurl = new moodle_url($PAGE->url); 00104 $this->pageurl->params(array($this->pageparamname => $this->page)); 00105 } else { 00106 $this->pageurl = $pageurl; 00107 } 00108 } 00109 00115 public function to_html($indent=0, $extraargs=array()) { 00116 if (count($this->items)) { 00117 $tabs = str_repeat("\t", $indent); 00118 $first = true; 00119 $itemiter = 1; 00120 $lastitem = ''; 00121 $html = ''; 00122 00123 foreach ($this->items as $item) { 00124 $last = (count($this->items) == $itemiter); 00125 if ($this->editable) { 00126 $item->set_icon_html($first, $last, $lastitem); 00127 } 00128 if ($itemhtml = $item->to_html($indent+1, $extraargs)) { 00129 $html .= "$tabs\t<li".((!empty($item->attributes))?(' '.$item->attributes):'').">"; 00130 $html .= $itemhtml; 00131 $html .= "</li>\n"; 00132 } 00133 $first = false; 00134 $lastitem = $item; 00135 $itemiter++; 00136 } 00137 } else { 00138 $html = ''; 00139 } 00140 if ($html) { //if there are list items to display then wrap them in ul / ol tag. 00141 $tabs = str_repeat("\t", $indent); 00142 $html = $tabs.'<'.$this->type.((!empty($this->attributes))?(' '.$this->attributes):'').">\n".$html; 00143 $html .= $tabs."</".$this->type.">\n"; 00144 } else { 00145 $html =''; 00146 } 00147 return $html; 00148 } 00149 00157 public function find_item($id, $suppresserror = false) { 00158 if (isset($this->items)) { 00159 foreach ($this->items as $key => $child) { 00160 if ($child->id == $id) { 00161 return $this->items[$key]; 00162 } 00163 } 00164 foreach (array_keys($this->items) as $key) { 00165 $thischild = $this->items[$key]; 00166 $ref = $thischild->children->find_item($id, true);//error always reported at top level 00167 if ($ref !== null) { 00168 return $ref; 00169 } 00170 } 00171 } 00172 00173 if (!$suppresserror) { 00174 print_error('listnoitem'); 00175 } 00176 return null; 00177 } 00178 00179 public function add_item($item) { 00180 $this->items[] = $item; 00181 } 00182 00183 public function set_parent($parent) { 00184 $this->parentitem = $parent; 00185 } 00186 00198 public function list_from_records($paged = false, $offset = 0) { 00199 $this->paged = $paged; 00200 $this->offset = $offset; 00201 $this->get_records(); 00202 $records = $this->records; 00203 $page = $this->page; 00204 if (!empty($page)) { 00205 $this->firstitem = ($page - 1) * $this->itemsperpage; 00206 $this->lastitem = $this->firstitem + $this->itemsperpage - 1; 00207 } 00208 $itemiter = $offset; 00209 //make a simple array which is easier to search 00210 $this->childparent = array(); 00211 foreach ($records as $record) { 00212 $this->childparent[$record->id] = $record->parent; 00213 } 00214 00215 //create top level list items and they're responsible for creating their children 00216 foreach ($records as $record) { 00217 if (array_key_exists($record->parent, $this->childparent)) { 00218 // This record is a child of another record, so it will be dealt 00219 // with by a call to list_item::create_children, not here. 00220 continue; 00221 } 00222 00223 $inpage = $itemiter >= $this->firstitem && $itemiter <= $this->lastitem; 00224 00225 // Make list item for top level for all items 00226 // we need the info about the top level items for reordering peers. 00227 if ($this->parentitem !== null) { 00228 $newattributes = $this->parentitem->attributes; 00229 } else { 00230 $newattributes = ''; 00231 } 00232 00233 $this->items[$itemiter] = new $this->listitemclassname($record, $this, $newattributes, $inpage); 00234 00235 if ($inpage) { 00236 $this->items[$itemiter]->create_children($records, $this->childparent, $record->id); 00237 } else { 00238 // Don't recurse down the tree for items that are not on this page 00239 $this->paged = true; 00240 } 00241 00242 $itemiter++; 00243 } 00244 return array($this->paged, $itemiter); 00245 } 00246 00250 public abstract function get_records(); 00251 00255 public function display_page_numbers() { 00256 $html = ''; 00257 $topcount = count($this->items); 00258 $this->pagecount = (integer) ceil(($topcount + $this->offset)/ QUESTION_PAGE_LENGTH ); 00259 if (!empty($this->page) && ($this->paged)) { 00260 $html = "<div class=\"paging\">".get_string('page').":\n"; 00261 foreach (range(1,$this->pagecount) as $currentpage) { 00262 if ($this->page == $currentpage) { 00263 $html .= " $currentpage \n"; 00264 } 00265 else { 00266 $html .= "<a href=\"".$this->pageurl->out(true, array($this->pageparamname => $currentpage))."\">"; 00267 $html .= " $currentpage </a>\n"; 00268 } 00269 } 00270 $html .= "</div>"; 00271 } 00272 return $html; 00273 } 00274 00281 public function get_items_peers($itemid) { 00282 $itemref = $this->find_item($itemid); 00283 $peerids = $itemref->parentlist->get_child_ids(); 00284 return $peerids; 00285 } 00286 00292 public function get_child_ids() { 00293 $childids = array(); 00294 foreach ($this->items as $child) { 00295 $childids[] = $child->id; 00296 } 00297 return $childids; 00298 } 00299 00306 public function move_item_up_down($direction, $id) { 00307 $peers = $this->get_items_peers($id); 00308 $itemkey = array_search($id, $peers); 00309 switch ($direction) { 00310 case 'down' : 00311 if (isset($peers[$itemkey+1])) { 00312 $olditem = $peers[$itemkey+1]; 00313 $peers[$itemkey+1] = $id; 00314 $peers[$itemkey] = $olditem; 00315 } else { 00316 print_error('listcantmoveup'); 00317 } 00318 break; 00319 00320 case 'up' : 00321 if (isset($peers[$itemkey-1])) { 00322 $olditem = $peers[$itemkey-1]; 00323 $peers[$itemkey-1] = $id; 00324 $peers[$itemkey] = $olditem; 00325 } else { 00326 print_error('listcantmovedown'); 00327 } 00328 break; 00329 } 00330 $this->reorder_peers($peers); 00331 } 00332 00333 public function reorder_peers($peers) { 00334 global $DB; 00335 foreach ($peers as $key => $peer) { 00336 $DB->set_field($this->table, "sortorder", $key, array("id"=>$peer)); 00337 } 00338 } 00339 00344 public function move_item_left($id) { 00345 global $DB; 00346 00347 $item = $this->find_item($id); 00348 if (!isset($item->parentlist->parentitem->parentlist)) { 00349 print_error('listcantmoveleft'); 00350 } else { 00351 $newpeers = $this->get_items_peers($item->parentlist->parentitem->id); 00352 if (isset($item->parentlist->parentitem->parentlist->parentitem)) { 00353 $newparent = $item->parentlist->parentitem->parentlist->parentitem->id; 00354 } else { 00355 $newparent = 0; // top level item 00356 } 00357 $DB->set_field($this->table, "parent", $newparent, array("id"=>$item->id)); 00358 $oldparentkey = array_search($item->parentlist->parentitem->id, $newpeers); 00359 $neworder = array_merge(array_slice($newpeers, 0, $oldparentkey+1), array($item->id), array_slice($newpeers, $oldparentkey+1)); 00360 $this->reorder_peers($neworder); 00361 } 00362 return $item->parentlist->parentitem; 00363 } 00364 00370 public function move_item_right($id) { 00371 global $DB; 00372 00373 $peers = $this->get_items_peers($id); 00374 $itemkey = array_search($id, $peers); 00375 if (!isset($peers[$itemkey-1])) { 00376 print_error('listcantmoveright'); 00377 } else { 00378 $DB->set_field($this->table, "parent", $peers[$itemkey-1], array("id"=>$peers[$itemkey])); 00379 $newparent = $this->find_item($peers[$itemkey-1]); 00380 if (isset($newparent->children)) { 00381 $newpeers = $newparent->children->get_child_ids(); 00382 } 00383 if ($newpeers) { 00384 $newpeers[] = $peers[$itemkey]; 00385 $this->reorder_peers($newpeers); 00386 } 00387 } 00388 } 00389 00399 public function process_actions($left, $right, $moveup, $movedown) { 00400 //should this action be processed by this list object? 00401 if (!(array_key_exists($left, $this->records) || array_key_exists($right, $this->records) || array_key_exists($moveup, $this->records) || array_key_exists($movedown, $this->records))) { 00402 return false; 00403 } 00404 if (!empty($left)) { 00405 $oldparentitem = $this->move_item_left($left); 00406 if ($this->item_is_last_on_page($oldparentitem->id)) { 00407 // Item has jumped onto the next page, change page when we redirect. 00408 $this->page ++; 00409 $this->pageurl->params(array($this->pageparamname => $this->page)); 00410 } 00411 } else if (!empty($right)) { 00412 $this->move_item_right($right); 00413 if ($this->item_is_first_on_page($right)) { 00414 // Item has jumped onto the previous page, change page when we redirect. 00415 $this->page --; 00416 $this->pageurl->params(array($this->pageparamname => $this->page)); 00417 } 00418 } else if (!empty($moveup)) { 00419 $this->move_item_up_down('up', $moveup); 00420 if ($this->item_is_first_on_page($moveup)) { 00421 // Item has jumped onto the previous page, change page when we redirect. 00422 $this->page --; 00423 $this->pageurl->params(array($this->pageparamname => $this->page)); 00424 } 00425 } else if (!empty($movedown)) { 00426 $this->move_item_up_down('down', $movedown); 00427 if ($this->item_is_last_on_page($movedown)) { 00428 // Item has jumped onto the next page, change page when we redirect. 00429 $this->page ++; 00430 $this->pageurl->params(array($this->pageparamname => $this->page)); 00431 } 00432 } else { 00433 return false; 00434 } 00435 00436 redirect($this->pageurl); 00437 } 00438 00444 public function item_is_first_on_page($itemid) { 00445 return $this->page && isset($this->items[$this->firstitem]) && 00446 $itemid == $this->items[$this->firstitem]->id; 00447 } 00448 00454 public function item_is_last_on_page($itemid) { 00455 return $this->page && isset($this->items[$this->lastitem]) && 00456 $itemid == $this->items[$this->lastitem]->id; 00457 } 00458 } 00459 00465 abstract class list_item { 00467 public $id; 00468 00470 public $name; 00471 00473 public $item; 00474 public $fieldnamesname = 'name'; 00475 public $attributes; 00476 public $display; 00477 public $icons = array(); 00478 00480 public $parentlist; 00481 00483 public $children; 00484 00494 public function __construct($item, $parent, $attributes = '', $display = true) { 00495 $this->item = $item; 00496 if (is_object($this->item)) { 00497 $this->id = $this->item->id; 00498 $this->name = $this->item->{$this->fieldnamesname}; 00499 } 00500 $this->set_parent($parent); 00501 $this->attributes = $attributes; 00502 $parentlistclass = get_class($parent); 00503 $this->children = new $parentlistclass($parent->type, $parent->attributes, $parent->editable, $parent->pageurl, 0); 00504 $this->children->set_parent($this); 00505 $this->display = $display; 00506 } 00507 00512 public function item_html($extraargs = array()) { 00513 if (is_string($this->item)) { 00514 $html = $this->item; 00515 } elseif (is_object($this->item)) { 00516 //for debug purposes only. You should create a sub class to 00517 //properly handle the record 00518 $html = join(', ', (array)$this->item); 00519 } 00520 return $html; 00521 } 00522 00531 public function to_html($indent = 0, $extraargs = array()) { 00532 if (!$this->display) { 00533 return ''; 00534 } 00535 $tabs = str_repeat("\t", $indent); 00536 00537 if (isset($this->children)) { 00538 $childrenhtml = $this->children->to_html($indent+1, $extraargs); 00539 } else { 00540 $childrenhtml = ''; 00541 } 00542 return $this->item_html($extraargs).' '.(join($this->icons, '')).(($childrenhtml !='')?("\n".$childrenhtml):''); 00543 } 00544 00545 public function set_icon_html($first, $last, $lastitem) { 00546 global $CFG; 00547 $strmoveup = get_string('moveup'); 00548 $strmovedown = get_string('movedown'); 00549 $strmoveleft = get_string('maketoplevelitem', 'question'); 00550 00551 if (isset($this->parentlist->parentitem)) { 00552 $parentitem = $this->parentlist->parentitem; 00553 if (isset($parentitem->parentlist->parentitem)) { 00554 $action = get_string('makechildof', 'question', $parentitem->parentlist->parentitem->name); 00555 } else { 00556 $action = $strmoveleft; 00557 } 00558 $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'left'=>$this->id))); 00559 $this->icons['left'] = $this->image_icon($action, $url, 'left'); 00560 } else { 00561 $this->icons['left'] = $this->image_spacer(); 00562 } 00563 00564 if (!$first) { 00565 $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'moveup'=>$this->id))); 00566 $this->icons['up'] = $this->image_icon($strmoveup, $url, 'up'); 00567 } else { 00568 $this->icons['up'] = $this->image_spacer(); 00569 } 00570 00571 if (!$last) { 00572 $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'movedown'=>$this->id))); 00573 $this->icons['down'] = $this->image_icon($strmovedown, $url, 'down'); 00574 } else { 00575 $this->icons['down'] = $this->image_spacer(); 00576 } 00577 00578 if (!empty($lastitem)) { 00579 $makechildof = get_string('makechildof', 'question', $lastitem->name); 00580 $url = new moodle_url($this->parentlist->pageurl, (array('sesskey'=>sesskey(), 'right'=>$this->id))); 00581 $this->icons['right'] = $this->image_icon($makechildof, $url, 'right'); 00582 } else { 00583 $this->icons['right'] = $this->image_spacer(); 00584 } 00585 } 00586 00587 public function image_icon($action, $url, $icon) { 00588 global $OUTPUT; 00589 return '<a title="' . s($action) .'" href="'.$url.'"> 00590 <img src="' . $OUTPUT->pix_url('t/'.$icon) . '" class="iconsmall" alt="' . s($action). '" /></a> '; 00591 } 00592 00593 public function image_spacer() { 00594 global $OUTPUT; 00595 return '<img src="' . $OUTPUT->pix_url('spacer') . '" class="iconsmall" alt="" />'; 00596 } 00597 00605 public function create_children(&$records, &$children, $thisrecordid) { 00606 //keys where value is $thisrecordid 00607 $thischildren = array_keys($children, $thisrecordid); 00608 foreach ($thischildren as $child) { 00609 $thisclass = get_class($this); 00610 $newlistitem = new $thisclass($records[$child], $this->children, $this->attributes); 00611 $this->children->add_item($newlistitem); 00612 $newlistitem->create_children($records, $children, $records[$child]->id); 00613 } 00614 } 00615 00616 public function set_parent($parent) { 00617 $this->parentlist = $parent; 00618 } 00619 }