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 * Defines a category in my profile page navigation. 19 * 20 * @package core_user 21 * @copyright 2015 onwards Ankit Agarwal 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_user\output\myprofile; 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Defines a category in my profile page navigation. 30 * 31 * @since Moodle 2.9 32 * @package core_user 33 * @copyright 2015 onwards Ankit Agarwal 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class category implements \renderable { 37 38 /** 39 * @var string Name of the category after which this category should appear. 40 */ 41 private $after; 42 43 /** 44 * @var string Name of the category. 45 */ 46 private $name; 47 48 /** 49 * @var string Title of the category. 50 */ 51 private $title; 52 53 /** 54 * @var node[] Array of nodes associated with this category. 55 */ 56 private $nodes = array(); 57 58 /** 59 * @var string HTML class attribute for this category. Classes should be separated by a space, e.g. 'class1 class2' 60 */ 61 private $classes; 62 63 /** 64 * @var array list of properties publicly accessible via __get. 65 */ 66 private $properties = array('after', 'name', 'title', 'nodes', 'classes'); 67 68 /** 69 * Constructor for category class. 70 * 71 * @param string $name Category name. 72 * @param string $title category title. 73 * @param null|string $after Name of category after which this category should appear. 74 * @param null|string $classes a list of css classes. 75 */ 76 public function __construct($name, $title, $after = null, $classes = null) { 77 $this->after = $after; 78 $this->name = $name; 79 $this->title = $title; 80 $this->classes = $classes; 81 } 82 83 /** 84 * Add a node to this category. 85 * 86 * @param node $node node object. 87 * @see \core_user\output\myprofile\tree::add_node() 88 * 89 * @throws \coding_exception 90 */ 91 public function add_node(node $node) { 92 $name = $node->name; 93 if (isset($this->nodes[$name])) { 94 throw new \coding_exception("Node with name $name already exists"); 95 } 96 if ($node->parentcat !== $this->name) { 97 throw new \coding_exception("Node parent must match with the category it is added to"); 98 } 99 $this->nodes[$node->name] = $node; 100 } 101 102 /** 103 * Sort nodes of the category in the order in which they should be displayed. 104 * 105 * @see \core_user\output\myprofile\tree::sort_categories() 106 * @throws \coding_exception 107 */ 108 public function sort_nodes() { 109 $tempnodes = array(); 110 $this->validate_after_order(); 111 112 // First content noes. 113 foreach ($this->nodes as $node) { 114 $after = $node->after; 115 $content = $node->content; 116 if (($after == null && !empty($content)) || $node->name === 'editprofile') { 117 // Can go anywhere in the cat. Also show content nodes first. 118 $tempnodes = array_merge($tempnodes, array($node->name => $node), $this->find_nodes_after($node)); 119 } 120 } 121 122 // Now nodes with no content. 123 foreach ($this->nodes as $node) { 124 $after = $node->after; 125 $content = $node->content; 126 if ($after == null && empty($content)) { 127 // Can go anywhere in the cat. Also show content nodes first. 128 $tempnodes = array_merge($tempnodes, array($node->name => $node), $this->find_nodes_after($node)); 129 } 130 } 131 132 if (count($tempnodes) !== count($this->nodes)) { 133 // Orphan nodes found. 134 throw new \coding_exception('Some of the nodes specified contains invalid \'after\' property'); 135 } 136 $this->nodes = $tempnodes; 137 } 138 139 /** 140 * Verifies that node with content can come after node with content only . Also verifies the same thing for nodes without 141 * content. 142 * @throws \coding_exception 143 */ 144 protected function validate_after_order() { 145 $nodearray = $this->nodes; 146 foreach ($this->nodes as $node) { 147 $after = $node->after; 148 if (!empty($after)) { 149 if (empty($nodearray[$after])) { 150 throw new \coding_exception('node {$node->name} specified contains invalid \'after\' property'); 151 } else { 152 // Valid node found. 153 $afternode = $nodearray[$after]; 154 $beforecontent = $node->content; 155 $aftercontent = $afternode->content; 156 157 if ((empty($beforecontent) && !empty($aftercontent)) || (!empty($beforecontent) && empty($aftercontent))) { 158 // Only node with content are allowed after content nodes. Same goes for no content nodes. 159 throw new \coding_exception('node {$node->name} specified contains invalid \'after\' property'); 160 } 161 } 162 } 163 } 164 } 165 166 /** 167 * Given a node object find all node objects that should appear after it. 168 * 169 * @param node $node node object 170 * 171 * @return array 172 */ 173 protected function find_nodes_after($node) { 174 $return = array(); 175 $nodearray = $this->nodes; 176 foreach ($nodearray as $nodeelement) { 177 if ($nodeelement->after === $node->name) { 178 // Find all nodes that comes after this node as well. 179 $return = array_merge($return, array($nodeelement->name => $nodeelement), $this->find_nodes_after($nodeelement)); 180 } 181 } 182 return $return; 183 } 184 185 /** 186 * Magic get method. 187 * 188 * @param string $prop property to get. 189 * 190 * @return mixed 191 * @throws \coding_exception 192 */ 193 public function __get($prop) { 194 if (in_array($prop, $this->properties)) { 195 return $this->$prop; 196 } 197 throw new \coding_exception('Property "' . $prop . '" doesn\'t exist'); 198 } 199 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body