1<?php 2namespace Fisharebest\Webtrees; 3 4/** 5 * webtrees: online genealogy 6 * Copyright (C) 2015 webtrees development team 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19/** 20 * Class AbstractModule - common functions for blocks 21 */ 22abstract class AbstractModule { 23 /** @var string A user-friendly, localized name for this module */ 24 private $title; 25 26 /** @var string The directory where the module is installed */ 27 private $directory; 28 29 /** @var string[] A cached copy of the module settings */ 30 private $settings; 31 32 /** 33 * Create a new module. 34 * 35 * @param string $directory Where is this module installed 36 */ 37 public function __construct($directory) { 38 $this->directory = $directory; 39 $this->title = $this->getTitle(); 40 } 41 42 /** 43 * @param integer $block_id 44 * @param string $setting_name 45 * @param string|null $default_value 46 * 47 * @return null|string 48 */ 49 public function getBlockSetting($block_id, $setting_name, $default_value = null) { 50 $setting_value = Database::prepare( 51 "SELECT SQL_CACHE setting_value FROM `##block_setting` WHERE block_id = :block_id AND setting_name = :setting_name" 52 )->execute(array( 53 'block_id' => $block_id, 54 'setting_name' => $setting_name, 55 ))->fetchOne(); 56 57 return $setting_value === null ? $default_value : $setting_value; 58 } 59 60 /** 61 * @param integer $block_id 62 * @param string $setting_name 63 * @param string|null $setting_value 64 * 65 * @return $this 66 */ 67 public function setBlockSetting($block_id, $setting_name, $setting_value) { 68 if ($setting_value === null) { 69 Database::prepare( 70 "DELETE FROM `##block_setting` WHERE block_id = :block_id AND setting_name = :setting_name" 71 )->execute(array( 72 'block_id' => $block_id, 73 'setting_name' => $setting_name, 74 )); 75 } else { 76 Database::prepare( 77 "REPLACE INTO `##block_setting` (block_id, setting_name, setting_value) VALUES (:block_id, :setting_name, :setting_value)" 78 )->execute(array( 79 'block_id' => $block_id, 80 'setting_name' => $setting_name, 81 'setting_value' => $setting_value, 82 )); 83 } 84 85 return $this; 86 } 87 88 /** 89 * How should this module be labelled on tabs, menus, etc.? 90 * 91 * @return string 92 */ 93 abstract public function getTitle(); 94 95 /** 96 * A sentence describing what this module does. 97 * 98 * @return string 99 */ 100 abstract public function getDescription(); 101 102 /** 103 * What is the default access level for this module? 104 * 105 * Some modules are aimed at admins or managers, and are not generally shown to users. 106 * 107 * @return integer 108 */ 109 public function defaultAccessLevel() { 110 // Returns one of: Auth::PRIV_HIDE, Auth::PRIV_PRIVATE, Auth::PRIV_USER, WT_PRIV_ADMIN 111 return Auth::PRIV_PRIVATE; 112 } 113 114 /** 115 * Provide a unique internal name for this module 116 * 117 * @return string 118 */ 119 public function getName() { 120 return basename($this->directory); 121 } 122 123 /** 124 * Load all the settings for the module into a cache. 125 * 126 * Since modules may have many settings, and will probably want to use 127 * lots of them, load them all at once and cache them. 128 * 129 * @return void 130 */ 131 private function loadAllSettings() { 132 if ($this->settings === null) { 133 $this->settings = Database::prepare( 134 "SELECT SQL_CACHE setting_name, setting_value FROM `##module_setting` WHERE module_name = ?" 135 )->execute(array($this->getName()))->fetchAssoc(); 136 } 137 } 138 139 /** 140 * Get a module setting. Return a default if the setting is not set. 141 * 142 * @param string $setting_name 143 * @param string $default 144 * 145 * @return string|null 146 */ 147 public function getSetting($setting_name, $default = null) { 148 $this->loadAllSettings(); 149 150 if (array_key_exists($setting_name, $this->settings)) { 151 return $this->settings[$setting_name]; 152 } else { 153 return $default; 154 } 155 } 156 157 /** 158 * Set a module setting. 159 * 160 * Since module settings are NOT NULL, setting a value to NULL will cause 161 * it to be deleted. 162 * 163 * @param string $setting_name 164 * @param string $setting_value 165 */ 166 public function setSetting($setting_name, $setting_value) { 167 $this->loadAllSettings(); 168 169 if ($setting_value === null) { 170 Database::prepare( 171 "DELETE FROM `##module_setting` WHERE module_name = ? AND setting_name = ?" 172 )->execute(array($this->getName(), $setting_name)); 173 unset($this->settings[$setting_name]); 174 } elseif (!array_key_exists($setting_name, $this->settings)) { 175 Database::prepare( 176 "INSERT INTO `##module_setting` (module_name, setting_name, setting_value) VALUES (?, ?, ?)" 177 )->execute(array($this->getName(), $setting_name, $setting_value)); 178 $this->settings[$setting_name] = $setting_value; 179 } elseif ($setting_value != $this->settings[$setting_name]) { 180 Database::prepare( 181 "UPDATE `##module_setting` SET setting_value = ? WHERE module_name = ? AND setting_name = ?" 182 )->execute(array($setting_value, $this->getName(), $setting_name)); 183 $this->settings[$setting_name] = $setting_value; 184 } else { 185 // Setting already exists, but with the same value - do nothing. 186 } 187 } 188 189 /** 190 * This is a general purpose hook, allowing modules to respond to routes 191 * of the form module.php?mod=FOO&mod_action=BAR 192 * 193 * @param string $mod_action 194 */ 195 public function modAction($mod_action) { 196 } 197 198 /** 199 * Get a the current access level for a module 200 * 201 * @param Tree $tree 202 * @param string $component - tab, block, menu, etc 203 * 204 * @return integer 205 */ 206 public function getAccessLevel(Tree $tree, $component) { 207 $access_level = Database::prepare( 208 "SELECT access_level FROM `##module_privacy` WHERE gedcom_id = :gedcom_id AND module_name = :module_name AND component = :component" 209 )->execute(array( 210 'gedcom_id' => $tree->getTreeId(), 211 'module_name' => $this->getName(), 212 'component' => $component, 213 ))->fetchOne(); 214 215 if ($access_level === null) { 216 return $this->defaultAccessLevel(); 217 } else { 218 return (int) $access_level; 219 } 220 } 221} 222