store.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. defined('ABSPATH') || exit;
  3. @require_once NEWSLETTER_INCLUDES_DIR . '/logger.php';
  4. class NewsletterStore {
  5. static $instance = null;
  6. /**
  7. * @var NewsletterLogger
  8. */
  9. var $logger;
  10. /**
  11. *
  12. * @return NewsletterStore
  13. */
  14. static function instance() {
  15. if (self::$instance == null) {
  16. self::$instance = new NewsletterStore();
  17. }
  18. return self::$instance;
  19. }
  20. static function singleton() {
  21. return self::instance();
  22. }
  23. function __construct() {
  24. $this->logger = new NewsletterLogger('store');
  25. }
  26. function get_field($table, $id, $field_name) {
  27. global $wpdb;
  28. $field_name = (string)$field_name;
  29. if (preg_match('/^[a-zA-Z_]+$/', $field_name) == 0) {
  30. $this->logger->fatal('Invalis field name: ' . $field_name);
  31. return false;
  32. }
  33. $id = (int)$id;
  34. $r = $wpdb->get_var($wpdb->prepare("select $field_name from $table where id=%d limit 1", $id));
  35. if ($wpdb->last_error) {
  36. $this->logger->error($wpdb->last_error);
  37. return false;
  38. }
  39. return $r;
  40. }
  41. function get_single($table, $id, $format = OBJECT) {
  42. global $wpdb;
  43. $id = (int)$id;
  44. return $this->get_single_by_query($wpdb->prepare("select * from $table where id=%d limit 1", $id), $format);
  45. }
  46. function get_single_by_field($table, $field_name, $field_value, $format = OBJECT) {
  47. global $wpdb;
  48. $field_name = (string)$field_name;
  49. $field_value = (string)$field_value;
  50. if (preg_match('/^[a-zA-Z_]+$/', $field_name) == 0) {
  51. $this->logger->error('Invalis field name: ' . $field_name);
  52. return false;
  53. }
  54. return $this->get_single_by_query($wpdb->prepare("select * from $table where $field_name=%s limit 1", $field_value), $format);
  55. }
  56. function get_count($table, $where = null) {
  57. global $wpdb;
  58. $r = $wpdb->get_var("select count(*) from $table " . ($where != null ? $where : ''));
  59. if ($wpdb->last_error) {
  60. $this->logger->error($wpdb->last_error);
  61. return false;
  62. }
  63. return $r;
  64. }
  65. /**
  66. * Returns a single record executing the given query or null if no row can be found. If more rows are matching
  67. * the query, only the first one is returned. Returns "false" on error (use the strict type checking ===) and a log
  68. * is written.
  69. *
  70. * @global wpdb $wpdb
  71. * @param string $query
  72. * @param type $format
  73. * @return boolean|mixed
  74. */
  75. function get_single_by_query($query, $format = OBJECT) {
  76. global $wpdb;
  77. $r = $wpdb->get_row($query, $format);
  78. if ($wpdb->last_error) {
  79. $this->logger->error($wpdb->last_error);
  80. return false;
  81. }
  82. return $r;
  83. }
  84. function sanitize($data) {
  85. global $wpdb;
  86. //if (strpos($wpdb->charset, 'utf8mb4') === 0) return $data;
  87. if (strpos($wpdb->charset, 'utf8mb4') === 0) return $data;
  88. foreach ($data as $key => $value) {
  89. $data[$key] = preg_replace('%(?:\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})%xs', '', $value);
  90. }
  91. return $data;
  92. }
  93. /**
  94. * Save a record on given table, updating it id the "id" value is set (as key or object property) or inserting it
  95. * if "id" is not set. Accepts objects or associative arrays as data.
  96. *
  97. * Returns "false" is an error occurred or the saved data re-read from the database in given format.
  98. *
  99. * @global wpdb $wpdb
  100. * @param type $table
  101. * @param type $data
  102. */
  103. function save($table, $data, $return_format = OBJECT) {
  104. global $wpdb;
  105. if (is_object($data)) {
  106. $data = (array) $data;
  107. }
  108. // Remove transient fields
  109. foreach (array_keys($data) as $key) {
  110. if (substr($key, 0, 1) == '_') unset($data[$key]);
  111. }
  112. if (isset($data['id'])) {
  113. $id = (int)$data['id'];
  114. unset($data['id']);
  115. if (!empty($data)) {
  116. $r = $wpdb->update($table, $this->sanitize($data), array('id' => $id));
  117. if ($r === false) {
  118. $this->logger->fatal($wpdb->last_error);
  119. $this->logger->fatal($wpdb->last_query);
  120. die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
  121. }
  122. }
  123. //$this->logger->debug('save: ' . $wpdb->last_query);
  124. } else {
  125. $r = $wpdb->insert($table, $this->sanitize($data));
  126. if ($r === false) {
  127. $this->logger->fatal($wpdb->last_error);
  128. $this->logger->fatal($wpdb->last_query);
  129. die('Database error. If you were saving a newsletter try a table upgrade from the status panel.');
  130. }
  131. $id = $wpdb->insert_id;
  132. }
  133. // if ($wpdb->last_error) {
  134. // $this->logger->error('save: ' . $wpdb->last_error);
  135. // return false;
  136. // }
  137. return $this->get_single($table, $id, $return_format);
  138. }
  139. function increment($table, $id, $field) {
  140. global $wpdb;
  141. $id = (int)$id;
  142. $field = (string)$field;
  143. if (preg_match('/^[a-zA-Z_]+$/', $field) == 0) {
  144. $this->logger->error('Invalis field name: ' . $field);
  145. return false;
  146. }
  147. $result = $wpdb->query($wpdb->prepare("update $table set $field=$field+1 where id=%d", $id));
  148. if ($wpdb->last_error) {
  149. $this->logger->error($wpdb->last_error);
  150. return false;
  151. }
  152. return $result;
  153. }
  154. /**
  155. * Deletes one or more rows by id (or an array of id)
  156. *
  157. * @param int|array $id
  158. * @return int Number of rows deleted
  159. */
  160. function delete($table, $id) {
  161. global $wpdb;
  162. if (is_array($id)) {
  163. for ($i=0; $i<count($id); $i++) {
  164. $id[$i] = (int)$id[$i];
  165. }
  166. $wpdb->query("delete from " . $table . " where id in (" . implode(',', $id) . ")");
  167. } else {
  168. $wpdb->delete($table, array('id' => (int)$id));
  169. }
  170. if ($wpdb->last_error) {
  171. $this->logger->error($wpdb->last_error);
  172. return false;
  173. }
  174. return $wpdb->rows_affected;
  175. }
  176. /**
  177. *
  178. * @global wpdb $wpdb
  179. * @param type $table
  180. * @param type $order_by
  181. * @param type $format
  182. * @return type
  183. */
  184. function get_all($table, $where = null, $format = OBJECT) {
  185. global $wpdb;
  186. if ($where == null) {
  187. $result = $wpdb->get_results("select * from $table", $format);
  188. } else {
  189. $result = $wpdb->get_results("select * from $table $where", $format);
  190. }
  191. return $result;
  192. }
  193. function set_field($table, $id, $field, $value) {
  194. global $wpdb;
  195. $field = (string)$field;
  196. $id = (int)$id;
  197. $value = (string)$value;
  198. if (preg_match('/^[a-zA-Z_]+$/', $field) == 0) {
  199. $this->logger->error('Invalis field name: ' . $field_name);
  200. return false;
  201. }
  202. $result = $wpdb->query($wpdb->prepare("update $table set $field=%s where id=%d limit 1", $value, $id));
  203. if ($wpdb->last_error) {
  204. $this->logger->error($wpdb->last_error);
  205. return false;
  206. }
  207. return $result;
  208. }
  209. function query($query) {
  210. global $wpdb;
  211. $result = $wpdb->query($query);
  212. if ($wpdb->last_error) {
  213. $this->logger->error($wpdb->last_error);
  214. return false;
  215. }
  216. return $result;
  217. }
  218. }