/ingo/lib/Storage/Filters/Sql.php

https://github.com/finger2000/horde · PHP · 319 lines · 196 code · 25 blank · 98 comment · 9 complexity · e1711252e6d253ba2730341b84338a48 MD5 · raw file

  1. <?php
  2. /**
  3. * Ingo_Storage_Filters_Sql is the object used to hold user-defined filtering
  4. * rule information.
  5. *
  6. * See the enclosed file LICENSE for license information (ASL). If you
  7. * did not receive this file, see http://www.horde.org/licenses/asl.php.
  8. *
  9. * @author Jan Schneider <jan@horde.org>
  10. * @package Ingo
  11. */
  12. class Ingo_Storage_Filters_Sql extends Ingo_Storage_Filters {
  13. /**
  14. * Handle for the current database connection.
  15. *
  16. * @var Horde_Db_Adapter
  17. */
  18. protected $_db;
  19. /**
  20. * Driver specific parameters.
  21. *
  22. * @var array
  23. */
  24. protected $_params;
  25. /**
  26. * Constructor.
  27. *
  28. * @param Horde_Db_Adapter $db Handle for the database connection.
  29. * @param array $params Driver specific parameters.
  30. */
  31. public function __construct(Horde_Db_Adapter $db, $params)
  32. {
  33. $this->_db = $db;
  34. $this->_params = $params;
  35. }
  36. /**
  37. * Loads all rules from the DB backend.
  38. *
  39. * @param boolean $readonly Whether to disable any write operations.
  40. */
  41. public function init($readonly = false)
  42. {
  43. $query = sprintf('SELECT * FROM %s WHERE rule_owner = ? ORDER BY rule_order',
  44. $this->_params['table_rules']);
  45. $values = array(Ingo::getUser());
  46. try {
  47. $result = $this->_db->selectAll($query, $values);
  48. } catch (Horde_Db_Exception $e) {
  49. throw new Ingo_Exception($e);
  50. }
  51. $data = array();
  52. foreach ($result as $row) {
  53. $data[$row['rule_order']] = array(
  54. 'id' => (int)$row['rule_id'],
  55. 'name' => Horde_String::convertCharset($row['rule_name'], $this->_params['charset'], 'UTF-8'),
  56. 'action' => (int)$row['rule_action'],
  57. 'action-value' => Horde_String::convertCharset($row['rule_value'], $this->_params['charset'], 'UTF-8'),
  58. 'flags' => (int)$row['rule_flags'],
  59. 'conditions' => empty($row['rule_conditions']) ? null : Horde_String::convertCharset(unserialize($row['rule_conditions']), $this->_params['charset'], 'UTF-8'),
  60. 'combine' => (int)$row['rule_combine'],
  61. 'stop' => (bool)$row['rule_stop'],
  62. 'disable' => !(bool)$row['rule_active']);
  63. }
  64. $this->setFilterlist($data);
  65. if (empty($data) && !$readonly) {
  66. $data = @unserialize($GLOBALS['prefs']->getDefault('rules'));
  67. if ($data) {
  68. foreach ($data as $val) {
  69. $this->addRule($val, false);
  70. }
  71. } else {
  72. $this->addRule(
  73. array('name' => 'Whitelist',
  74. 'action' => Ingo_Storage::ACTION_WHITELIST),
  75. false);
  76. $this->addRule(
  77. array('name' => 'Vacation',
  78. 'action' => Ingo_Storage::ACTION_VACATION,
  79. 'disable' => true),
  80. false);
  81. $this->addRule(
  82. array('name' => 'Blacklist',
  83. 'action' => Ingo_Storage::ACTION_BLACKLIST),
  84. false);
  85. $this->addRule(
  86. array('name' => 'Spam Filter',
  87. 'action' => Ingo_Storage::ACTION_SPAM,
  88. 'disable' => true),
  89. false);
  90. $this->addRule(
  91. array('name' => 'Forward',
  92. 'action' => Ingo_Storage::ACTION_FORWARD),
  93. false);
  94. }
  95. }
  96. }
  97. /**
  98. * Converts a rule hash from Ingo's internal format to the database
  99. * format.
  100. *
  101. * @param array $rule Rule hash in Ingo's format.
  102. *
  103. * @return array Rule hash in DB's format.
  104. */
  105. protected function _ruleToBackend(array $rule)
  106. {
  107. return array(Horde_String::convertCharset($rule['name'], 'UTF-8', $this->_params['charset']),
  108. (int)$rule['action'],
  109. isset($rule['action-value']) ? Horde_String::convertCharset($rule['action-value'], 'UTF-8', $this->_params['charset']) : null,
  110. isset($rule['flags']) ? (int)$rule['flags'] : null,
  111. isset($rule['conditions']) ? serialize(Horde_String::convertCharset($rule['conditions'], 'UTF-8', $this->_params['charset'])) : null,
  112. isset($rule['combine']) ? (int)$rule['combine'] : null,
  113. isset($rule['stop']) ? (int)$rule['stop'] : null,
  114. isset($rule['disable']) ? (int)(!$rule['disable']) : 1);
  115. }
  116. /**
  117. * Adds a rule hash to the filters list.
  118. *
  119. * @param array $rule A rule hash.
  120. * @param boolean $default If true merge the rule hash with default rule
  121. * values.
  122. */
  123. public function addRule(array $rule, $default = true)
  124. {
  125. if ($default) {
  126. $rule = array_merge($this->getDefaultRule(), $rule);
  127. }
  128. $query = sprintf('INSERT INTO %s (rule_owner, rule_name, rule_action, rule_value, rule_flags, rule_conditions, rule_combine, rule_stop, rule_active, rule_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
  129. $this->_params['table_rules']);
  130. $order = key(array_reverse($this->_filters, true)) + 1;
  131. $values = array_merge(array(Ingo::getUser()),
  132. $this->_ruleToBackend($rule),
  133. array($order));
  134. try {
  135. $result = $this->_db->insert($query, $values);
  136. } catch (Horde_Db_Exception $e) {
  137. throw new Ingo_Exception($e);
  138. }
  139. $rule['id'] = $result;
  140. $this->_filters[$order] = $rule;
  141. }
  142. /**
  143. * Updates an existing rule with a rule hash.
  144. *
  145. * @param array $rule A rule hash
  146. * @param integer $id A rule number
  147. */
  148. public function updateRule($rule, $id)
  149. {
  150. $query = sprintf('UPDATE %s SET rule_name = ?, rule_action = ?, rule_value = ?, rule_flags = ?, rule_conditions = ?, rule_combine = ?, rule_stop = ?, rule_active = ?, rule_order = ? WHERE rule_id = ? AND rule_owner = ?',
  151. $this->_params['table_rules']);
  152. $values = array_merge($this->_ruleToBackend($rule),
  153. array($id, $rule['id'], Ingo::getUser()));
  154. try {
  155. $this->_db->update($query, $values);
  156. }catch (Horde_Db_Exception $e) {
  157. throw new Ingo_Exception($e);
  158. }
  159. $this->_filters[$id] = $rule;
  160. }
  161. /**
  162. * Deletes a rule from the filters list.
  163. *
  164. * @param integer $id Number of the rule to delete.
  165. *
  166. * @return boolean True if the rule has been found and deleted.
  167. */
  168. public function deleteRule($id)
  169. {
  170. if (!isset($this->_filters[$id])) {
  171. return false;
  172. }
  173. $query = sprintf('DELETE FROM %s WHERE rule_id = ? AND rule_owner = ?',
  174. $this->_params['table_rules']);
  175. $values = array($this->_filters[$id]['id'], Ingo::getUser());
  176. try {
  177. $result = $this->_db->delete($query, $values);
  178. } catch (Horde_Db_Exception $e) {
  179. throw new Ingo_Exception($e);
  180. }
  181. unset($this->_filters[$id]);
  182. $query = sprintf('UPDATE %s SET rule_order = rule_order - 1 WHERE rule_owner = ? AND rule_order > ?',
  183. $this->_params['table_rules']);
  184. $values = array(Ingo::getUser(), $id);
  185. try {
  186. $this->_db->update($query, $values);
  187. } catch (Horde_Db_Exception $e) {
  188. throw new Ingo_Exception($e);
  189. }
  190. return true;
  191. }
  192. /**
  193. * Creates a copy of an existing rule.
  194. *
  195. * The created copy is added to the filters list right after the original
  196. * rule.
  197. *
  198. * @param integer $id Number of the rule to copy.
  199. *
  200. * @return boolean True if the rule has been found and copied.
  201. */
  202. public function copyRule($id)
  203. {
  204. if (isset($this->_filters[$id])) {
  205. $newrule = $this->_filters[$id];
  206. $newrule['name'] = sprintf(_("Copy of %s"), $this->_filters[$id]['name']);
  207. $this->addRule($newrule, false);
  208. $this->ruleUp(count($this->_filters) - 1, count($this->_filters) - $id - 2);
  209. return true;
  210. }
  211. return false;
  212. }
  213. /**
  214. * Moves a rule up in the filters list.
  215. *
  216. * @param integer $id Number of the rule to move.
  217. * @param integer $steps Number of positions to move the rule up.
  218. */
  219. public function ruleUp($id, $steps = 1)
  220. {
  221. return $this->_ruleMove($id, -$steps);
  222. }
  223. /**
  224. * Moves a rule down in the filters list.
  225. *
  226. * @param integer $id Number of the rule to move.
  227. * @param integer $steps Number of positions to move the rule down.
  228. */
  229. public function ruleDown($id, $steps = 1)
  230. {
  231. return $this->_ruleMove($id, $steps);
  232. }
  233. /**
  234. * Moves a rule in the filters list.
  235. *
  236. * @param integer $id Number of the rule to move.
  237. * @param integer $steps Number of positions and direction to move the
  238. * rule.
  239. */
  240. protected function _ruleMove($id, $steps)
  241. {
  242. $query = sprintf('UPDATE %s SET rule_order = rule_order %s 1 WHERE rule_owner = ? AND rule_order %s ? AND rule_order %s ?',
  243. $this->_params['table_rules'],
  244. $steps > 0 ? '-' : '+',
  245. $steps > 0 ? '>' : '>=',
  246. $steps > 0 ? '<=' : '<');
  247. $values = array(Ingo::getUser());
  248. if ($steps < 0) {
  249. $values[] = (int)($id + $steps);
  250. $values[] = (int)$id;
  251. } else {
  252. $values[] = (int)$id;
  253. $values[] = (int)($id + $steps);
  254. }
  255. try {
  256. $this->_db->update($query, $values);
  257. } catch (Horde_Db_Exception $e) {
  258. throw new Ingo_Exception($e);
  259. }
  260. $query = sprintf('UPDATE %s SET rule_order = ? WHERE rule_owner = ? AND rule_id = ?',
  261. $this->_params['table_rules']);
  262. $values = array((int)($id + $steps),
  263. Ingo::getUser(),
  264. $this->_filters[$id]['id']);
  265. try {
  266. $this->_db->update($query, $values);
  267. } catch (Horde_Db_Exception $e) {
  268. throw new Ingo_Exception($e);
  269. }
  270. $this->init();
  271. }
  272. /**
  273. * Disables a rule.
  274. *
  275. * @param integer $id Number of the rule to disable.
  276. */
  277. public function ruleDisable($id)
  278. {
  279. $rule = $this->_filters[$id];
  280. $rule['disable'] = true;
  281. $this->updateRule($rule, $id);
  282. }
  283. /**
  284. * Enables a rule.
  285. *
  286. * @param integer $id Number of the rule to enable.
  287. */
  288. public function ruleEnable($id)
  289. {
  290. $rule = $this->_filters[$id];
  291. $rule['disable'] = false;
  292. $this->updateRule($rule, $id);
  293. }
  294. }