/reportbuilder/classes/local/entities/base.php

https://github.com/markn86/moodle · PHP · 311 lines · 106 code · 40 blank · 165 comment · 7 complexity · 9a141b6d4f160f4fcd8f42712888641e MD5 · raw file

  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. declare(strict_types=1);
  17. namespace core_reportbuilder\local\entities;
  18. use coding_exception;
  19. use lang_string;
  20. use core_reportbuilder\local\report\column;
  21. use core_reportbuilder\local\report\filter;
  22. /**
  23. * Base class for all report entities
  24. *
  25. * @package core_reportbuilder
  26. * @copyright 2019 Marina Glancy <marina@moodle.com>
  27. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  28. */
  29. abstract class base {
  30. /** @var string $entityname Internal reference to name of entity */
  31. private $entityname = '';
  32. /** @var lang_string $entitytitle Used as a title for the entity in reports */
  33. private $entitytitle = null;
  34. /** @var array $tablealiases Database tables that this entity uses and their default aliases */
  35. private $tablealiases = [];
  36. /** @var string[] $joins List of SQL joins for the entity */
  37. private $joins = [];
  38. /** @var column[] $columns List of columns for the entity */
  39. private $columns = [];
  40. /** @var filter[] $filters List of filters for the entity */
  41. private $filters = [];
  42. /** @var filter[] $conditions List of conditions for the entity */
  43. private $conditions = [];
  44. /**
  45. * Database tables that this entity uses and their default aliases
  46. *
  47. * Must be overridden by the entity to list all database tables that it expects to be present in the main
  48. * SQL or in JOINs added to this entity
  49. *
  50. * @return string[] Array of $tablename => $alias
  51. */
  52. abstract protected function get_default_table_aliases(): array;
  53. /**
  54. * The default title for this entity
  55. *
  56. * @return lang_string
  57. */
  58. abstract protected function get_default_entity_title(): lang_string;
  59. /**
  60. * Initialise the entity, called automatically when it is added to a report
  61. *
  62. * This is where entity defines all its columns and filters by calling:
  63. * - {@see add_column}
  64. * - {@see add_filter}
  65. * - etc
  66. *
  67. * @return self
  68. */
  69. abstract public function initialise(): self;
  70. /**
  71. * The default machine-readable name for this entity that will be used in the internal names of the columns/filters
  72. *
  73. * @return string
  74. */
  75. protected function get_default_entity_name(): string {
  76. $namespace = explode('\\', get_called_class());
  77. return end($namespace);
  78. }
  79. /**
  80. * Set entity name
  81. *
  82. * @param string $entityname
  83. * @return self
  84. * @throws coding_exception
  85. */
  86. final public function set_entity_name(string $entityname): self {
  87. if ($entityname === '' || $entityname !== clean_param($entityname, PARAM_ALPHANUMEXT)) {
  88. throw new coding_exception('Entity name must be comprised of alphanumeric character, underscore or dash');
  89. }
  90. $this->entityname = $entityname;
  91. return $this;
  92. }
  93. /**
  94. * Return entity name
  95. *
  96. * @return string
  97. */
  98. final public function get_entity_name(): string {
  99. return $this->entityname ?: $this->get_default_entity_name();
  100. }
  101. /**
  102. * Set entity title
  103. *
  104. * @param lang_string $title
  105. * @return self
  106. */
  107. final public function set_entity_title(lang_string $title): self {
  108. $this->entitytitle = $title;
  109. return $this;
  110. }
  111. /**
  112. * Get entity title
  113. *
  114. * @return lang_string
  115. */
  116. final public function get_entity_title(): lang_string {
  117. return $this->entitytitle ?? $this->get_default_entity_title();
  118. }
  119. /**
  120. * Override the default alias for given database table used in entity queries
  121. *
  122. * @param string $tablename
  123. * @param string $alias
  124. * @return self
  125. * @throws coding_exception
  126. */
  127. final public function set_table_alias(string $tablename, string $alias): self {
  128. if (!array_key_exists($tablename, $this->get_default_table_aliases())) {
  129. throw new coding_exception('Invalid table name', $tablename);
  130. }
  131. $this->tablealiases[$tablename] = $alias;
  132. return $this;
  133. }
  134. /**
  135. * Returns an alias used in the queries for a given table
  136. *
  137. * @param string $tablename
  138. * @return string
  139. * @throws coding_exception
  140. */
  141. final public function get_table_alias(string $tablename): string {
  142. $defaulttablealiases = $this->get_default_table_aliases();
  143. if (!array_key_exists($tablename, $defaulttablealiases)) {
  144. throw new coding_exception('Invalid table name', $tablename);
  145. }
  146. return $this->tablealiases[$tablename] ?? $defaulttablealiases[$tablename];
  147. }
  148. /**
  149. * Add join clause required for this entity to join to existing tables/entities
  150. *
  151. * @param string $join
  152. * @return self
  153. */
  154. final public function add_join(string $join): self {
  155. $this->joins[trim($join)] = trim($join);
  156. return $this;
  157. }
  158. /**
  159. * Add multiple join clauses required for this entity {@see add_join}
  160. *
  161. * @param string[] $joins
  162. * @return self
  163. */
  164. final public function add_joins(array $joins): self {
  165. foreach ($joins as $join) {
  166. $this->add_join($join);
  167. }
  168. return $this;
  169. }
  170. /**
  171. * Return entity joins
  172. *
  173. * @return string[]
  174. */
  175. final protected function get_joins(): array {
  176. return array_values($this->joins);
  177. }
  178. /**
  179. * Add a column to the entity
  180. *
  181. * @param column $column
  182. * @return self
  183. */
  184. final protected function add_column(column $column): self {
  185. $this->columns[$column->get_name()] = $column;
  186. return $this;
  187. }
  188. /**
  189. * Returns entity columns
  190. *
  191. * @return column[]
  192. */
  193. final public function get_columns(): array {
  194. return $this->columns;
  195. }
  196. /**
  197. * Returns an entity column
  198. *
  199. * @param string $name
  200. * @return column
  201. * @throws coding_exception For invalid column name
  202. */
  203. final public function get_column(string $name): column {
  204. if (!array_key_exists($name, $this->columns)) {
  205. throw new coding_exception('Invalid column name', $name);
  206. }
  207. return $this->columns[$name];
  208. }
  209. /**
  210. * Add a filter to the entity
  211. *
  212. * @param filter $filter
  213. * @return self
  214. */
  215. final protected function add_filter(filter $filter): self {
  216. $this->filters[$filter->get_name()] = $filter;
  217. return $this;
  218. }
  219. /**
  220. * Returns entity filters
  221. *
  222. * @return filter[]
  223. */
  224. final public function get_filters(): array {
  225. return $this->filters;
  226. }
  227. /**
  228. * Returns an entity filter
  229. *
  230. * @param string $name
  231. * @return filter
  232. * @throws coding_exception For invalid filter name
  233. */
  234. final public function get_filter(string $name): filter {
  235. if (!array_key_exists($name, $this->filters)) {
  236. throw new coding_exception('Invalid filter name', $name);
  237. }
  238. return $this->filters[$name];
  239. }
  240. /**
  241. * Add a condition to the entity
  242. *
  243. * @param filter $condition
  244. * @return $this
  245. */
  246. final protected function add_condition(filter $condition): self {
  247. $this->conditions[$condition->get_name()] = $condition;
  248. return $this;
  249. }
  250. /**
  251. * Returns entity conditions
  252. *
  253. * @return filter[]
  254. */
  255. final public function get_conditions(): array {
  256. return $this->conditions;
  257. }
  258. /**
  259. * Returns an entity condition
  260. *
  261. * @param string $name
  262. * @return filter
  263. * @throws coding_exception For invalid condition name
  264. */
  265. final public function get_condition(string $name): filter {
  266. if (!array_key_exists($name, $this->conditions)) {
  267. throw new coding_exception('Invalid condition name', $name);
  268. }
  269. return $this->conditions[$name];
  270. }
  271. }