/backup/util/settings/setting_dependency.class.php

https://github.com/viggof/moodle · PHP · 455 lines · 201 code · 12 blank · 242 comment · 40 complexity · 3c5276184162631693b50fb40acbc88f 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. /**
  17. * @package moodlecore
  18. * @copyright 2010 Sam Hemelryk
  19. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  20. */
  21. /**
  22. * Generic abstract dependency class
  23. *
  24. * @copyright 2010 Sam Hemelryk
  25. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26. */
  27. abstract class setting_dependency {
  28. /**
  29. * Used to define the type of a dependency.
  30. *
  31. * Note with these that checked and true, and not checked and false are equal.
  32. * This is because the terminology differs but the resulting action is the same.
  33. * Reduces code!
  34. */
  35. const DISABLED_VALUE = 0;
  36. const DISABLED_NOT_VALUE = 1;
  37. const DISABLED_TRUE = 2;
  38. const DISABLED_FALSE = 3;
  39. const DISABLED_CHECKED = 4;
  40. const DISABLED_NOT_CHECKED = 5;
  41. const DISABLED_EMPTY = 6;
  42. const DISABLED_NOT_EMPTY = 7;
  43. /**
  44. * The parent setting (primary)
  45. * @var base_setting
  46. */
  47. protected $setting;
  48. /**
  49. * The dependent setting (secondary)
  50. * @var base_setting
  51. */
  52. protected $dependentsetting;
  53. /**
  54. * The default setting
  55. * @var mixed
  56. */
  57. protected $defaultvalue;
  58. /**
  59. * The last value the dependent setting had
  60. * @var mixed
  61. */
  62. protected $lastvalue;
  63. /**
  64. * Creates the dependency object
  65. * @param base_setting $setting The parent setting or the primary setting if you prefer
  66. * @param base_setting $dependentsetting The dependent setting
  67. * @param mixed $defaultvalue The default value to assign if the dependency is unmet
  68. */
  69. public function __construct(base_setting $setting, base_setting $dependentsetting, $defaultvalue = false) {
  70. $this->setting = $setting;
  71. $this->dependentsetting = $dependentsetting;
  72. $this->defaultvalue = $defaultvalue;
  73. $this->lastvalue = $dependentsetting->get_value();
  74. }
  75. /**
  76. * Destroy all circular references. It helps PHP 5.2 a lot!
  77. */
  78. public function destroy() {
  79. // No need to destroy anything recursively here, direct reset
  80. $this->setting = null;
  81. $this->dependentsetting = null;
  82. }
  83. /**
  84. * Processes a change is setting called by the primary setting
  85. * @param int $changetype
  86. * @param mixed $oldvalue
  87. * @return bool
  88. */
  89. final public function process_change($changetype, $oldvalue) {
  90. // Check the type of change requested
  91. switch ($changetype) {
  92. // Process a status change
  93. case base_setting::CHANGED_STATUS: return $this->process_status_change($oldvalue);
  94. // Process a visibility change
  95. case base_setting::CHANGED_VISIBILITY: return $this->process_visibility_change($oldvalue);
  96. // Process a value change
  97. case base_setting::CHANGED_VALUE: return $this->process_value_change($oldvalue);
  98. }
  99. // Throw an exception if we get this far
  100. throw new backup_ui_exception('unknownchangetype');
  101. }
  102. /**
  103. * Processes a visibility change
  104. * @param bool $oldvisibility
  105. * @return bool
  106. */
  107. protected function process_visibility_change($oldvisibility) {
  108. // Store the current dependent settings visibility for comparison
  109. $prevalue = $this->dependentsetting->get_visibility();
  110. // Set it regardless of whether we need to
  111. $this->dependentsetting->set_visibility($this->setting->get_visibility());
  112. // Return true if it changed
  113. return ($prevalue != $this->dependentsetting->get_visibility());
  114. }
  115. /**
  116. * All dependencies must define how they would like to deal with a status change
  117. * @param int $oldstatus
  118. */
  119. abstract protected function process_status_change($oldstatus);
  120. /**
  121. * All dependencies must define how they would like to process a value change
  122. */
  123. abstract protected function process_value_change($oldvalue);
  124. /**
  125. * Gets the primary setting
  126. * @return backup_setting
  127. */
  128. public function get_setting() {
  129. return $this->setting;
  130. }
  131. /**
  132. * Gets the dependent setting
  133. * @return backup_setting
  134. */
  135. public function get_dependent_setting() {
  136. return $this->dependentsetting;
  137. }
  138. /**
  139. * This function enforces the dependency
  140. */
  141. abstract public function enforce();
  142. /**
  143. * Returns an array of properties suitable to be used to define a moodleforms
  144. * disabled command
  145. * @return array
  146. */
  147. abstract public function get_moodleform_properties();
  148. /**
  149. * Returns true if the dependent setting is locked.
  150. * @return bool
  151. */
  152. abstract public function is_locked();
  153. }
  154. /**
  155. * A dependency that disables the secondary setting if the primary setting is
  156. * equal to the provided value
  157. *
  158. * @copyright 2010 Sam Hemelryk
  159. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  160. */
  161. class setting_dependency_disabledif_equals extends setting_dependency {
  162. /**
  163. * The value to compare to
  164. * @var mixed
  165. */
  166. protected $value;
  167. /**
  168. * Creates the dependency
  169. *
  170. * @param base_setting $setting
  171. * @param base_setting $dependentsetting
  172. * @param mixed $value
  173. * @param mixed $defaultvalue
  174. */
  175. public function __construct(base_setting $setting, base_setting $dependentsetting, $value, $defaultvalue = false) {
  176. parent::__construct($setting, $dependentsetting, $defaultvalue);
  177. $this->value = ($value)?(string)$value:0;
  178. }
  179. /**
  180. * Returns true if the dependent setting is locked.
  181. * @return bool
  182. */
  183. public function is_locked() {
  184. // If the setting is locked or the dependent setting should be locked then return true
  185. if ($this->setting->get_status() !== base_setting::NOT_LOCKED || $this->setting->get_value() == $this->value) {
  186. return true;
  187. }
  188. // Else return based upon the dependent settings status
  189. return ($this->dependentsetting->get_status() !== base_setting::NOT_LOCKED);
  190. }
  191. /**
  192. * Processes a value change in the primary setting
  193. * @param mixed $oldvalue
  194. * @return bool
  195. */
  196. protected function process_value_change($oldvalue) {
  197. $prevalue = $this->dependentsetting->get_value();
  198. // If the setting is the desired value enact the dependency
  199. if ($this->setting->get_value() == $this->value) {
  200. // The dependent setting needs to be locked by hierachy and set to the
  201. // default value.
  202. $this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
  203. $this->dependentsetting->set_value($this->defaultvalue);
  204. } else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
  205. // We can unlock the dependent setting
  206. $this->dependentsetting->set_status(base_setting::NOT_LOCKED);
  207. }
  208. // Return true if the value has changed for the dependent setting
  209. return ($prevalue != $this->dependentsetting->get_value());
  210. }
  211. /**
  212. * Processes a status change in the primary setting
  213. * @param mixed $oldstatus
  214. * @return bool
  215. */
  216. protected function process_status_change($oldstatus) {
  217. // Store the dependent status
  218. $prevalue = $this->dependentsetting->get_status();
  219. // Store the current status
  220. $currentstatus = $this->setting->get_status();
  221. if ($currentstatus == base_setting::NOT_LOCKED) {
  222. if ($prevalue == base_setting::LOCKED_BY_HIERARCHY && $this->setting->get_value() != $this->value) {
  223. // Dependency has changes, is not fine, unlock the dependent setting
  224. $this->dependentsetting->set_status(base_setting::NOT_LOCKED);
  225. }
  226. } else {
  227. // Make sure the dependent setting is also locked, in this case by hierarchy
  228. $this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
  229. }
  230. // Return true if the dependent setting has changed.
  231. return ($prevalue != $this->dependentsetting->get_status());
  232. }
  233. /**
  234. * Enforces the dependency if required.
  235. * @return bool True if there were changes
  236. */
  237. public function enforce() {
  238. // This will be set to true if ANYTHING changes
  239. $changes = false;
  240. // First process any value changes
  241. if ($this->process_value_change($this->setting->get_value())) {
  242. $changes = true;
  243. }
  244. // Second process any status changes
  245. if ($this->process_status_change($this->setting->get_status())) {
  246. $changes = true;
  247. }
  248. // Finally process visibility changes
  249. if ($this->process_visibility_change($this->setting->get_visibility())) {
  250. $changes = true;
  251. }
  252. return $changes;
  253. }
  254. /**
  255. * Returns an array of properties suitable to be used to define a moodleforms
  256. * disabled command
  257. * @return array
  258. */
  259. public function get_moodleform_properties() {
  260. return array(
  261. 'setting'=>$this->dependentsetting->get_ui_name(),
  262. 'dependenton'=>$this->setting->get_ui_name(),
  263. 'condition'=>'eq',
  264. 'value'=>$this->value
  265. );
  266. }
  267. }
  268. /**
  269. * A dependency that disables the secondary element if the primary element is
  270. * true or checked
  271. *
  272. * @copyright 2010 Sam Hemelryk
  273. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  274. */
  275. class setting_dependency_disabledif_checked extends setting_dependency_disabledif_equals {
  276. public function __construct(base_setting $setting, base_setting $dependentsetting, $defaultvalue = false) {
  277. parent::__construct($setting, $dependentsetting, true, $defaultvalue);
  278. $this->value = true;
  279. }
  280. /**
  281. * Returns an array of properties suitable to be used to define a moodleforms
  282. * disabled command
  283. * @return array
  284. */
  285. public function get_moodleform_properties() {
  286. return array(
  287. 'setting'=>$this->dependentsetting->get_ui_name(),
  288. 'dependenton'=>$this->setting->get_ui_name(),
  289. 'condition'=>'checked'
  290. );
  291. }
  292. }
  293. /**
  294. * A dependency that disables the secondary element if the primary element is
  295. * false or not checked
  296. *
  297. * @copyright 2010 Sam Hemelryk
  298. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  299. */
  300. class setting_dependency_disabledif_not_checked extends setting_dependency_disabledif_equals {
  301. public function __construct(base_setting $setting, base_setting $dependentsetting, $defaultvalue = false) {
  302. parent::__construct($setting, $dependentsetting, false, $defaultvalue);
  303. $this->value = false;
  304. }
  305. /**
  306. * Returns an array of properties suitable to be used to define a moodleforms
  307. * disabled command
  308. * @return array
  309. */
  310. public function get_moodleform_properties() {
  311. return array(
  312. 'setting'=>$this->dependentsetting->get_ui_name(),
  313. 'dependenton'=>$this->setting->get_ui_name(),
  314. 'condition'=>'notchecked'
  315. );
  316. }
  317. }
  318. /**
  319. * A dependency that disables the secondary setting if the value of the primary setting
  320. * is not empty.
  321. *
  322. * @copyright 2010 Sam Hemelryk
  323. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  324. */
  325. class setting_dependency_disabledif_not_empty extends setting_dependency_disabledif_equals {
  326. public function __construct(base_setting $setting, base_setting $dependentsetting, $defaultvalue = false) {
  327. parent::__construct($setting, $dependentsetting, false, $defaultvalue);
  328. $this->value = false;
  329. }
  330. /**
  331. * Returns an array of properties suitable to be used to define a moodleforms
  332. * disabled command
  333. * @return array
  334. */
  335. public function get_moodleform_properties() {
  336. return array(
  337. 'setting'=>$this->dependentsetting->get_ui_name(),
  338. 'dependenton'=>$this->setting->get_ui_name(),
  339. 'condition'=>'notequal',
  340. 'value'=>''
  341. );
  342. }
  343. /**
  344. * Processes a value change in the primary setting
  345. * @param mixed $oldvalue
  346. * @return bool
  347. */
  348. protected function process_value_change($oldvalue) {
  349. $prevalue = $this->dependentsetting->get_value();
  350. // If the setting is the desired value enact the dependency
  351. $value = $this->setting->get_value();
  352. if (!empty($value)) {
  353. // The dependent setting needs to be locked by hierachy and set to the
  354. // default value.
  355. $this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
  356. if ($this->defaultvalue === false) {
  357. $this->dependentsetting->set_value($value);
  358. } else {
  359. $this->dependentsetting->set_value($this->defaultvalue);
  360. }
  361. } else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
  362. // We can unlock the dependent setting
  363. $this->dependentsetting->set_status(base_setting::NOT_LOCKED);
  364. }
  365. // Return true if the value has changed for the dependent setting
  366. return ($prevalue != $this->dependentsetting->get_value());
  367. }
  368. /**
  369. * Returns true if the dependent setting is locked.
  370. * @return bool
  371. */
  372. public function is_locked() {
  373. // If the setting is locked or the dependent setting should be locked then return true
  374. if ($this->setting->get_status() !== base_setting::NOT_LOCKED || !empty($value)) {
  375. return true;
  376. }
  377. // Else return based upon the dependent settings status
  378. return ($this->dependentsetting->get_status() !== base_setting::NOT_LOCKED);
  379. }
  380. }
  381. /**
  382. * A dependency that disables the secondary setting if the value of the primary setting
  383. * is empty.
  384. *
  385. * @copyright 2010 Sam Hemelryk
  386. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  387. */
  388. class setting_dependency_disabledif_empty extends setting_dependency_disabledif_equals {
  389. public function __construct(base_setting $setting, base_setting $dependentsetting, $defaultvalue = false) {
  390. parent::__construct($setting, $dependentsetting, false, $defaultvalue);
  391. $this->value = false;
  392. }
  393. /**
  394. * Returns an array of properties suitable to be used to define a moodleforms
  395. * disabled command
  396. * @return array
  397. */
  398. public function get_moodleform_properties() {
  399. return array(
  400. 'setting'=>$this->dependentsetting->get_ui_name(),
  401. 'dependenton'=>$this->setting->get_ui_name(),
  402. 'condition'=>'notequal',
  403. 'value'=>''
  404. );
  405. }
  406. /**
  407. * Processes a value change in the primary setting
  408. * @param mixed $oldvalue
  409. * @return bool
  410. */
  411. protected function process_value_change($oldvalue) {
  412. $prevalue = $this->dependentsetting->get_value();
  413. // If the setting is the desired value enact the dependency
  414. $value = $this->setting->get_value();
  415. if (empty($value)) {
  416. // The dependent setting needs to be locked by hierachy and set to the
  417. // default value.
  418. $this->dependentsetting->set_status(base_setting::LOCKED_BY_HIERARCHY);
  419. if ($this->defaultvalue === false) {
  420. $this->dependentsetting->set_value($value);
  421. } else {
  422. $this->dependentsetting->set_value($this->defaultvalue);
  423. }
  424. } else if ($this->dependentsetting->get_status() == base_setting::LOCKED_BY_HIERARCHY) {
  425. // We can unlock the dependent setting
  426. $this->dependentsetting->set_status(base_setting::NOT_LOCKED);
  427. }
  428. // Return true if the value has changed for the dependent setting
  429. return ($prevalue != $this->dependentsetting->get_value());
  430. }
  431. /**
  432. * Returns true if the dependent setting is locked.
  433. * @return bool
  434. */
  435. public function is_locked() {
  436. // If the setting is locked or the dependent setting should be locked then return true
  437. if ($this->setting->get_status() !== base_setting::NOT_LOCKED || empty($value)) {
  438. return true;
  439. }
  440. // Else return based upon the dependent settings status
  441. return ($this->dependentsetting->get_status() !== base_setting::NOT_LOCKED);
  442. }
  443. }