From 556db98835c2e7ea96028599b8f5dd4bbfcd3511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Jurka?= Date: Thu, 12 Jan 2017 16:32:30 +0100 Subject: [PATCH 1/9] #2539 - Feature request: Pushover.net notifications --- include/autoloader.inc.php | 2 + include/classes/base.class.php | 4 + .../classes/ipushnotification.interface.php | 6 + include/classes/notification.class.php | 29 ++- .../push_notification/notifymyandroid.php | 41 ++++ .../classes/push_notification/pushover.php | 46 ++++ include/classes/pushnotification.class.php | 184 ++++++++++++++++ include/pages/account/notifications.inc.php | 24 ++- public/site_assets/bootstrap/css/mpos.css | 5 + public/site_assets/bootstrap/js/mpos.js | 11 + sql/000_base_structure.sql | 8 +- .../account/notifications/default.tpl | 202 ++++++++++++------ upgrade/definitions/1.0.1_to_1.0.2.inc.php | 35 +++ 13 files changed, 519 insertions(+), 78 deletions(-) create mode 100644 include/classes/ipushnotification.interface.php create mode 100644 include/classes/push_notification/notifymyandroid.php create mode 100644 include/classes/push_notification/pushover.php create mode 100644 include/classes/pushnotification.class.php create mode 100644 upgrade/definitions/1.0.1_to_1.0.2.inc.php diff --git a/include/autoloader.inc.php b/include/autoloader.inc.php index a46c4dde..ab0dd64a 100644 --- a/include/autoloader.inc.php +++ b/include/autoloader.inc.php @@ -78,5 +78,7 @@ require_once(CLASS_DIR . '/transaction.class.php'); require_once(CLASS_DIR . '/roundstats.class.php'); require_once(CLASS_DIR . '/news.class.php'); require_once(CLASS_DIR . '/api.class.php'); +require_once(CLASS_DIR . '/ipushnotification.interface.php'); +require_once(CLASS_DIR . '/pushnotification.class.php'); require_once(INCLUDE_DIR . '/lib/Michelf/Markdown.php'); require_once(INCLUDE_DIR . '/lib/scrypt.php'); diff --git a/include/classes/base.class.php b/include/classes/base.class.php index de77b23d..41b8d245 100644 --- a/include/classes/base.class.php +++ b/include/classes/base.class.php @@ -40,6 +40,10 @@ class Base { public function setSalty($salt) { $this->salty = $salt; } + /** + * @var Smarty + */ + var $smarty; public function setSmarty($smarty) { $this->smarty = $smarty; } diff --git a/include/classes/ipushnotification.interface.php b/include/classes/ipushnotification.interface.php new file mode 100644 index 00000000..e259c849 --- /dev/null +++ b/include/classes/ipushnotification.interface.php @@ -0,0 +1,6 @@ +mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1 AND account_id = ?"); - if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) { - if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData)) { - return true; - } else { - $this->setErrorMessage('SendMail call failed: ' . $this->getError()); - return false; - } + $stmt = $this->mysqli->prepare("SELECT type FROM $this->tableSettings WHERE type IN (?, ?) AND active = 1 AND account_id = ?"); + if ($stmt && $stmt->bind_param('ssi', $strType, substr('push_'.$strType, 0, 15), $account_id) && $stmt->execute() && $result = $stmt->get_result()) { + $types = array_map(function($a){ return reset($a);}, $result->fetch_all(MYSQLI_ASSOC)); + $stmt->close(); + $result = true; + foreach ($types as $type){ + if (strpos($type, 'push_') === 0){ + if (PushNotification::Instance() instanceof PushNotification){ + $result &= PushNotification::Instance()->sendNotification($account_id, $strType, $aMailData); + } + } else { + $result &= $this->sendMail('notifications/' . $strType, $aMailData); + } + } + if ($result){ + $this->addNotification($account_id, $strType, $aMailData); + return true; + } else { + $this->setErrorMessage('SendMail call failed: ' . $this->getError()); + return false; + } } else { $this->setErrorMessage('User disabled ' . $strType . ' notifications'); return true; diff --git a/include/classes/push_notification/notifymyandroid.php b/include/classes/push_notification/notifymyandroid.php new file mode 100644 index 00000000..87f0b80e --- /dev/null +++ b/include/classes/push_notification/notifymyandroid.php @@ -0,0 +1,41 @@ +apiKey = $apikey; + } + + static $priorities = array( + 0 => 'info', + 2 => 'error', + ); + + public static function getName(){ + return "notifymyandroid.com"; + } + + public static function getParameters(){ + return array( + 'apikey' => 'API key', + ); + } + + public function notify($message, $severity = 'info', $event = null){ + curl_setopt_array($ch = curl_init(), array( + CURLOPT_URL => "https://www.notifymyandroid.com/publicapi/notify", + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POSTFIELDS => http_build_query($data = array( + "apikey" => $this->apiKey, + "application" => "CryptoGlance", + "description" => $message, + "content-type" => "text/html", + "event" => $event, + "priority" => array_search($severity, self::$priorities), + )), + )); + curl_exec($ch); + curl_close($ch); + } + } \ No newline at end of file diff --git a/include/classes/push_notification/pushover.php b/include/classes/push_notification/pushover.php new file mode 100644 index 00000000..3c232fed --- /dev/null +++ b/include/classes/push_notification/pushover.php @@ -0,0 +1,46 @@ +token = $token; + $this->user = $user; + } + + static $priorities = array( + 0 => 'info', + 1 => 'warning', + 2 => 'error', + ); + + public static function getName(){ + return "pushover.net"; + } + + public static function getParameters(){ + return array( + 'token' => 'API Token/Key', + 'user' => 'Your User Key', + ); + } + + public function notify($message, $severity = 'info', $event = null){ + curl_setopt_array($ch = curl_init(), array( + CURLOPT_URL => "https://api.pushover.net/1/messages.json", + CURLOPT_POST => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POSTFIELDS => http_build_query($data = array( + "token" => $this->token, + "user" => $this->user, + "message" => $code = strip_tags(preg_replace('/<([\/]?)span[^>]*>/i', '<\1b>', $message), "


"), + "title" => strip_tags($event), + "priority" => (int)array_search($severity, self::$priorities), + "timestamp" => time(), + "html" => preg_match('/<[^>]+>/', $code), + )), + )); + curl_exec($ch); + curl_close($ch); + } + } \ No newline at end of file diff --git a/include/classes/pushnotification.class.php b/include/classes/pushnotification.class.php new file mode 100644 index 00000000..05cfc5b6 --- /dev/null +++ b/include/classes/pushnotification.class.php @@ -0,0 +1,184 @@ +getExtension() != 'php') || $fileInfo->isDot()) { + continue; + } + foreach (self::getClassesInFile($fileInfo->getRealPath()) as $class){ + if (!class_exists($class)){ + include $fileInfo->getRealPath(); + } + $cr = new ReflectionClass($class); + if ($cr->isSubclassOf('IPushNotification')){ + self::$classes[$class] = array($fileInfo->getFilename(), $cr->getMethod('getName')->invoke(null), $cr->getMethod('getParameters')->invoke(null)); + } + } + } + } + return self::$classes; + } + + public function getClassesForSmarty(){ + $c = $this->getClasses(); + return array_map(function($a, $b){ + return array( + 'class' => $b, + 'file' => $a[0], + 'name' => $a[1], + 'parameters' => $a[2], + ); + }, $c, array_keys($c)); + } + + /** + * @param string|array $notificator + * @param array $data + * @return IPushNotification|bool + */ + public function getNotificatorInstance($notificator, $data){ + $class = null; + $file = null; + + if (is_array($notificator)){ + if (count($notificator) == 2){ + list($class, $file) = $notificator; + } else { + $class = reset($notificator); + } + } else { + $class = $notificator; + } + + if (!class_exists($class)){ + if ($file === null){ + foreach (self::getClasses() as $_class => $_info){ + if ($_class == $class){ + $file = $_info[0]; + break; + } + } + } else { + include __DIR__.'/push_notification/'.$file; + } + if (!class_exists($class)){ + return false; + } + } + $cr = new ReflectionClass($class); + $constructor = $cr->getConstructor(); + $constructorParameters = array(); + foreach (array_map(function($a){ return $a->getName();}, $constructor->getParameters()) as $param){ + $constructorParameters[] = array_key_exists($param, $data)?$data[$param]:null; + } + $instance = $cr->newInstanceArgs($constructorParameters); + return $instance; + } + + /** + * Update accounts push notification settings + * @param account_id int Account ID + * @param data array Data array + * @return bool + **/ + public function updateSettings($account_id, $data) { + $this->debug->append("STA " . __METHOD__, 4); + + $stmt = $this->mysqli->prepare("INSERT INTO $this->tableSettings (value, account_id) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)"); + if (!($stmt && $stmt->bind_param('si', json_encode($data), $account_id) && $stmt->execute())) { + $this->setErrorMessage($this->getErrorMsg('E0047', __CLASS__)); + return $this->sqlError(); + } + $this->log->log("info", "User $account_id updated notification settings"); + return true; + } + + /** + * Fetch notification settings for user account + * @param id int Account ID + * @return array Notification settings + **/ + public function getNotificationSettings($account_id) { + $this->debug->append("STA " . __METHOD__, 4); + $stmt = $this->mysqli->prepare("SELECT value FROM $this->tableSettings WHERE account_id = ?"); + if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) { + if ($result->num_rows) { + /* @var $result mysqli_result */ + $aData = json_decode(current($result->fetch_row()), true); + return $aData; + } else { + return array( + 'class' => false, + 'params' => null, + 'file' => null, + ); + } + } + return $this->sqlError('E0045'); + } + + private static $instance = null; + /** + * @param PushNotification $instance + */ + public static function Instance($instance = null){ + if (func_num_args() == 0){ + return self::$instance; + } + return self::$instance = $instance; + } + + public function sendNotification($account_id, $template, $aData){ + $settings = $this->getNotificationSettings($account_id); + if ($settings['class']){ + $instance = $this->getNotificatorInstance(array($settings['class'], $settings['file']), $settings['params']); + if ($instance){ + $this->smarty->assign('WEBSITENAME', $this->setting->getValue('website_name')); + $this->smarty->assign('SUBJECT', $aData['subject']); + $this->smarty->assign('DATA', $aData); + + $message = false; + foreach (array('/mail/push_notifications/', '/mail/notifications/') as $dir){ + $this->smarty->clearCache($templateFile = TEMPLATE_DIR.$dir.$template.'.tpl'); + try { + $message = $this->smarty->fetch($templateFile); + } catch (SmartyException $e){ + + } + } + if ($message){ + $instance->notify($message, 'info', $aData['subject']); + } + } + } + return true; + } + } + + $pushnotification = PushNotification::Instance(new PushNotification()); + $pushnotification->setDebug($debug); + $pushnotification->setLog($log); + $pushnotification->setMysql($mysqli); + $pushnotification->setSmarty($smarty); + $pushnotification->setConfig($config); + $pushnotification->setSetting($setting); + $pushnotification->setErrorCodes($aErrorCodes); + \ No newline at end of file diff --git a/include/pages/account/notifications.inc.php b/include/pages/account/notifications.inc.php index 2b5c850e..b6b910cd 100644 --- a/include/pages/account/notifications.inc.php +++ b/include/pages/account/notifications.inc.php @@ -8,7 +8,25 @@ if ($user->isAuthenticated()) { } else { if (@$_REQUEST['do'] == 'save') { if (!$config['csrf']['enabled'] || $config['csrf']['enabled'] && $csrftoken->valid) { - if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) { + + $pushSettings = array( + 'class' => $_REQUEST['pushnotification-class'], + 'params' => null, + 'file' => null, + ); + if ($pushSettings['class'] && array_key_exists($pushSettings['class'], $_REQUEST['pushnotification'])){ + $pushSettings['params'] = $_REQUEST['pushnotification'][$pushSettings['class']]; + } + if ($pushSettings['class']){ + $c = $pushnotification->getClasses(); + if (array_key_exists($pushSettings['class'], $c)){ + $pushSettings['file'] = $c[$pushSettings['class']][0]; + } + } + + if (!$pushnotification->updateSettings($_SESSION['USERDATA']['id'], $pushSettings)){ + $_SESSION['POPUP'][] = array('CONTENT' => $pushnotification->getError(), 'TYPE' => 'alert alert-danger'); + }elseif ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) { $_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings', 'TYPE' => 'alert alert-success'); } else { $_SESSION['POPUP'][] = array('CONTENT' => $notification->getError(), 'TYPE' => 'alert alert-danger'); @@ -29,8 +47,12 @@ if ($user->isAuthenticated()) { // Fetch user notification settings $aSettings = $notification->getNotificationSettings($_SESSION['USERDATA']['id']); + $aPushSettings = $pushnotification->getNotificationSettings($_SESSION['USERDATA']['id']); + $aSmartyClasses = $pushnotification->getClassesForSmarty(); $smarty->assign('NOTIFICATIONS', $aNotifications); + $smarty->assign('PUSHNOTIFICATIONS', $aSmartyClasses); + $smarty->assign('PUSHSETTINGS', $aPushSettings); $smarty->assign('SETTINGS', $aSettings); $smarty->assign('CONTENT', 'default.tpl'); } diff --git a/public/site_assets/bootstrap/css/mpos.css b/public/site_assets/bootstrap/css/mpos.css index 5defa9ee..5f52e288 100644 --- a/public/site_assets/bootstrap/css/mpos.css +++ b/public/site_assets/bootstrap/css/mpos.css @@ -660,3 +660,8 @@ div.fade { } /* END EDIT */ + +.push-notifications-params, +.push-notifications-disabled .push-notifications { + display : none; +} \ No newline at end of file diff --git a/public/site_assets/bootstrap/js/mpos.js b/public/site_assets/bootstrap/js/mpos.js index 830319f4..206989f7 100644 --- a/public/site_assets/bootstrap/js/mpos.js +++ b/public/site_assets/bootstrap/js/mpos.js @@ -88,3 +88,14 @@ $(function() { }); }); + +$(document).on('change', '#push-notifications', function(e){ + var notificationClass = $(this).val(); + $('#push-notifications-pannel').toggleClass('push-notifications-disabled', notificationClass == 0); + $('.push-notifications-params').each(function(){ + var $this = $(this); + $this.toggle($this.attr('data-class-name') == notificationClass); + }); +}).ready(function(){ + $('#push-notifications').trigger('change'); +}); \ No newline at end of file diff --git a/sql/000_base_structure.sql b/sql/000_base_structure.sql index 839789eb..45718525 100644 --- a/sql/000_base_structure.sql +++ b/sql/000_base_structure.sql @@ -142,7 +142,7 @@ CREATE TABLE IF NOT EXISTS `settings` ( UNIQUE KEY `setting` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -INSERT INTO `settings` (`name`, `value`) VALUES ('DB_VERSION', '1.0.1'); +INSERT INTO `settings` (`name`, `value`) VALUES ('DB_VERSION', '1.0.2'); CREATE TABLE IF NOT EXISTS `shares` ( `id` bigint(30) NOT NULL AUTO_INCREMENT, @@ -248,6 +248,12 @@ CREATE TABLE `statistics_users` ( KEY `account_id_timestamp` (`account_id`,`timestamp`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `push_notification_settings` ( + `account_id` int(11) NOT NULL, + `value` text DEFAULT NULL, + PRIMARY KEY (`account_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/templates/bootstrap/account/notifications/default.tpl b/templates/bootstrap/account/notifications/default.tpl index 12dbcd0b..3abd9dc3 100644 --- a/templates/bootstrap/account/notifications/default.tpl +++ b/templates/bootstrap/account/notifications/default.tpl @@ -1,72 +1,138 @@

-
- - - - -
-
- Notification Settings -
-
- - {if $DISABLE_IDLEWORKERNOTIFICATIONS|default:"" != 1} - - - - - {/if} - {if $DISABLE_BLOCKNOTIFICATIONS|default:"" != 1} - - - - - {/if} - - - - - - - - - {if $DISABLE_POOLNEWSLETTER|default:"" != 1} - - - - - {/if} -
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
-
- - +
+
+ + + + + +
+
+ Push Notification Settings +
+
+ + + + + + + {section pushnotification $PUSHNOTIFICATIONS} + + {foreach $PUSHNOTIFICATIONS[pushnotification].parameters key=name item=text} + + + + + {/foreach} + + {/section} +
+ + + +
+
+
+ +
+
+ Notification Settings +
+
+ + + + + + + + + + {if $DISABLE_IDLEWORKERNOTIFICATIONS|default:"" != 1} + + + + + + {/if} + {if $DISABLE_BLOCKNOTIFICATIONS|default:"" != 1} + + + + + + {/if} + + + + + + + + + + + {if $DISABLE_POOLNEWSLETTER|default:"" != 1} + + + + + + {/if} + +
EventEmailPush
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+
+ + +
diff --git a/upgrade/definitions/1.0.1_to_1.0.2.inc.php b/upgrade/definitions/1.0.1_to_1.0.2.inc.php new file mode 100644 index 00000000..8b18ac0d --- /dev/null +++ b/upgrade/definitions/1.0.1_to_1.0.2.inc.php @@ -0,0 +1,35 @@ +getValue('DB_VERSION'); // Our actual version installed + + // Upgrade specific variables + $aSql[] = " + CREATE TABLE IF NOT EXISTS `push_notification_settings` ( + `account_id` int(11) NOT NULL, + `value` text DEFAULT NULL, + PRIMARY KEY (`account_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + "; + + if ($db_version_now == $db_version_old && version_compare($db_version_now, DB_VERSION, '<')) { + // Run the upgrade + echo '- Starting database migration to version ' . $db_version_new . PHP_EOL; + foreach ($aSql as $sql) { + echo '- Preparing: ' . $sql . PHP_EOL; + $stmt = $mysqli->prepare($sql); + if ($stmt && $stmt->execute()) { + echo '- success' . PHP_EOL; + } else { + echo '- failed: ' . $mysqli->error . PHP_EOL; + exit(1); + } + } + } +} +?> From 893d92032770f74f2000e3bff121f53568d682b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Thu, 12 Jan 2017 21:22:27 +0100 Subject: [PATCH 2/9] #2539 - More generic class UserSettings --- include/autoloader.inc.php | 1 + include/classes/base.class.php | 8 ++ include/classes/pushnotification.class.php | 33 +++---- include/classes/usersettings.class.php | 100 +++++++++++++++++++++ include/config/error_codes.inc.php | 1 + sql/000_base_structure.sql | 11 +-- upgrade/definitions/1.0.1_to_1.0.2.inc.php | 11 +-- 7 files changed, 132 insertions(+), 33 deletions(-) create mode 100644 include/classes/usersettings.class.php diff --git a/include/autoloader.inc.php b/include/autoloader.inc.php index ab0dd64a..2cc2c64a 100644 --- a/include/autoloader.inc.php +++ b/include/autoloader.inc.php @@ -78,6 +78,7 @@ require_once(CLASS_DIR . '/transaction.class.php'); require_once(CLASS_DIR . '/roundstats.class.php'); require_once(CLASS_DIR . '/news.class.php'); require_once(CLASS_DIR . '/api.class.php'); +require_once(CLASS_DIR . '/usersettings.class.php'); require_once(CLASS_DIR . '/ipushnotification.interface.php'); require_once(CLASS_DIR . '/pushnotification.class.php'); require_once(INCLUDE_DIR . '/lib/Michelf/Markdown.php'); diff --git a/include/classes/base.class.php b/include/classes/base.class.php index 41b8d245..a886da6b 100644 --- a/include/classes/base.class.php +++ b/include/classes/base.class.php @@ -16,6 +16,8 @@ class Base { public function getTableName() { return $this->table; } + + protected $debug; public function setDebug($debug) { $this->debug = $debug; } @@ -25,9 +27,13 @@ class Base { public function setCoinAddress($coin_address) { $this->coin_address = $coin_address; } + + protected $log; public function setLog($log) { $this->log = $log; } + + protected $mysqli; public function setMysql($mysqli) { $this->mysqli = $mysqli; } @@ -56,6 +62,8 @@ class Base { public function setConfig($config) { $this->config = $config; } + + protected $aErrorCodes; public function setErrorCodes(&$aErrorCodes) { $this->aErrorCodes =& $aErrorCodes; } diff --git a/include/classes/pushnotification.class.php b/include/classes/pushnotification.class.php index 05cfc5b6..5c8e3ce3 100644 --- a/include/classes/pushnotification.class.php +++ b/include/classes/pushnotification.class.php @@ -1,4 +1,6 @@ debug->append("STA " . __METHOD__, 4); - - $stmt = $this->mysqli->prepare("INSERT INTO $this->tableSettings (value, account_id) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)"); - if (!($stmt && $stmt->bind_param('si', json_encode($data), $account_id) && $stmt->execute())) { - $this->setErrorMessage($this->getErrorMsg('E0047', __CLASS__)); - return $this->sqlError(); - } - $this->log->log("info", "User $account_id updated notification settings"); + UserSettings::construct($account_id)->PushNotifications = $data; return true; } @@ -117,22 +112,14 @@ * @return array Notification settings **/ public function getNotificationSettings($account_id) { - $this->debug->append("STA " . __METHOD__, 4); - $stmt = $this->mysqli->prepare("SELECT value FROM $this->tableSettings WHERE account_id = ?"); - if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) { - if ($result->num_rows) { - /* @var $result mysqli_result */ - $aData = json_decode(current($result->fetch_row()), true); - return $aData; - } else { - return array( - 'class' => false, - 'params' => null, - 'file' => null, - ); - } + if ($settings = UserSettings::construct($account_id)->PushNotifications){ + return $settings; } - return $this->sqlError('E0045'); + return array( + 'class' => false, + 'params' => null, + 'file' => null, + ); } private static $instance = null; diff --git a/include/classes/usersettings.class.php b/include/classes/usersettings.class.php new file mode 100644 index 00000000..f65d2355 --- /dev/null +++ b/include/classes/usersettings.class.php @@ -0,0 +1,100 @@ +account_id = $account_id; + $this->__lazyWrite = $lazy_write; + if (is_callable(self::$__setup_callbacks)){ + call_user_func(self::$__setup_callbacks, $this); + } + } + + private static $__GetSTMT = null; + private static $__SetSTMT = null; + + public function __destruct(){ + if ($this->__lazyWrite){ + foreach ($this->__cache as $name=>$value){ + $this->_storeValue($name, $value); + } + } + } + + private function _storeValue($name, $value){ + if (empty(self::$__SetSTMT)){ + self::$__SetSTMT = $this->mysqli->prepare('REPLACE INTO '.$this->table.' (`account_id`, `name`, `value`) VALUES (?, ?, ?)'); + } + if (!(self::$__SetSTMT && self::$__SetSTMT->bind_param('iss', $this->account_id, $name, serialize($value)) && self::$__SetSTMT->execute())) { + $this->setErrorMessage($this->getErrorMsg('E0084', $this->table)); + return $this->sqlError(); + } + return true; + } + + private function _getValue($name, $default = null){ + if (empty(self::$__GetSTMT)){ + self::$__GetSTMT = $this->mysqli->prepare('SELECT `value` FROM '.$this->table.' WHERE `account_id` = ? AND `name` = ? LIMIT 1'); + } + if (self::$__GetSTMT && self::$__GetSTMT->bind_param('is', $this->account_id, $name) && self::$__GetSTMT->execute() && $result = self::$__GetSTMT->get_result()) { + if ($result->num_rows > 0) { + return unserialize($result->fetch_object()->value); + } else { + return $default; + } + } + $this->sqlError(); + return $default; + } + + public function __get($name){ + if (!$this->__lazyWrite){ + return $this->_getValue($name); + } + if (!array_key_exists($name, $this->__cache)){ + $this->__cache[$name] = $this->_getValue($name); + } + return $this->__cache[$name]; + } + + public function __set($name, $value){ + if (!$this->__lazyWrite){ + $this->_storeValue($name, $value); + } else { + $this->__cache[$name] = $value; + } + } + + private static $__setup_callbacks = null; + public static function setup($callback = null){ + self::$__setup_callbacks = $callback; + } + + private static $__lastInstanceId; + private static $__lastInstance; + /** + * @param int $account_id + * @param string $lazy_write + * @return UserSettings + */ + public static function construct($account_id, $lazy_write = true){ + if ((self::$__lastInstanceId == $account_id) && (self::$__lastInstance instanceof UserSettings)){ + return self::$__lastInstance; + } + self::$__lastInstanceId = $account_id; + return self::$__lastInstance = new self($account_id, $lazy_write); + } + } + + UserSettings::setup(function($instance)use($debug, $log, $mysqli, $aErrorCodes){ + $instance->setDebug($debug); + $instance->setLog($log); + $instance->setMysql($mysqli); + $instance->setErrorCodes($aErrorCodes); + }); diff --git a/include/config/error_codes.inc.php b/include/config/error_codes.inc.php index f7a8d7a8..a4b33471 100644 --- a/include/config/error_codes.inc.php +++ b/include/config/error_codes.inc.php @@ -79,3 +79,4 @@ $aErrorCodes['E0080'] = 'No new unaccounted shares since last run'; $aErrorCodes['E0081'] = 'Failed to insert new block into database'; $aErrorCodes['E0082'] = 'Block does not supply any usable confirmation information'; $aErrorCodes['E0083'] = 'Maintenance mode enabled, skipped'; +$aErrorCodes['E0084'] = 'Error updating %s table'; diff --git a/sql/000_base_structure.sql b/sql/000_base_structure.sql index 45718525..9ab29f71 100644 --- a/sql/000_base_structure.sql +++ b/sql/000_base_structure.sql @@ -248,11 +248,12 @@ CREATE TABLE `statistics_users` ( KEY `account_id_timestamp` (`account_id`,`timestamp`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `push_notification_settings` ( - `account_id` int(11) NOT NULL, - `value` text DEFAULT NULL, - PRIMARY KEY (`account_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `user_settings` ( + `account_id` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `value` text DEFAULT NULL, + PRIMARY KEY (`account_id`,`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; diff --git a/upgrade/definitions/1.0.1_to_1.0.2.inc.php b/upgrade/definitions/1.0.1_to_1.0.2.inc.php index 8b18ac0d..d9c6aa80 100644 --- a/upgrade/definitions/1.0.1_to_1.0.2.inc.php +++ b/upgrade/definitions/1.0.1_to_1.0.2.inc.php @@ -10,11 +10,12 @@ function run_102() { // Upgrade specific variables $aSql[] = " - CREATE TABLE IF NOT EXISTS `push_notification_settings` ( - `account_id` int(11) NOT NULL, - `value` text DEFAULT NULL, - PRIMARY KEY (`account_id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TABLE IF NOT EXISTS `user_settings` ( + `account_id` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `value` text DEFAULT NULL, + PRIMARY KEY (`account_id`,`name`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; "; if ($db_version_now == $db_version_old && version_compare($db_version_now, DB_VERSION, '<')) { From 9f32f0119de2b270cb68436f01dc23e671a9b5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Thu, 12 Jan 2017 21:30:29 +0100 Subject: [PATCH 3/9] #2539 - Fixed upgrading DB version --- include/version.inc.php | 2 +- upgrade/definitions/1.0.1_to_1.0.2.inc.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/version.inc.php b/include/version.inc.php index 87f8a36d..ad0f43a1 100644 --- a/include/version.inc.php +++ b/include/version.inc.php @@ -2,7 +2,7 @@ $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1; define('MPOS_VERSION', '1.0.6'); -define('DB_VERSION', '1.0.1'); +define('DB_VERSION', '1.0.2'); define('CONFIG_VERSION', '1.0.1'); define('HASH_VERSION', 1); diff --git a/upgrade/definitions/1.0.1_to_1.0.2.inc.php b/upgrade/definitions/1.0.1_to_1.0.2.inc.php index d9c6aa80..72905a0a 100644 --- a/upgrade/definitions/1.0.1_to_1.0.2.inc.php +++ b/upgrade/definitions/1.0.1_to_1.0.2.inc.php @@ -1,7 +1,7 @@ getTableName() . " SET value = '".$db_version_new."' WHERE name = 'DB_VERSION'"; + if ($db_version_now == $db_version_old && version_compare($db_version_now, DB_VERSION, '<')) { // Run the upgrade echo '- Starting database migration to version ' . $db_version_new . PHP_EOL; From 5e564a4f81a13d6fe51d3fc7080267da574fa237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Thu, 12 Jan 2017 21:32:55 +0100 Subject: [PATCH 4/9] #2539 - fixed typo --- public/site_assets/bootstrap/css/mpos.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/site_assets/bootstrap/css/mpos.css b/public/site_assets/bootstrap/css/mpos.css index 5f52e288..23dec18e 100644 --- a/public/site_assets/bootstrap/css/mpos.css +++ b/public/site_assets/bootstrap/css/mpos.css @@ -659,9 +659,9 @@ div.fade { padding: 0px; } -/* END EDIT */ - .push-notifications-params, .push-notifications-disabled .push-notifications { display : none; -} \ No newline at end of file +} + +/* END EDIT */ From c9930d3d5288a28a78ff3066b23407be4f69b133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Thu, 12 Jan 2017 22:05:33 +0100 Subject: [PATCH 5/9] #2539 - PushNotification templates --- templates/mail/push_notifications/idle_worker.tpl | 5 +++++ templates/mail/push_notifications/new_block.tpl | 1 + templates/mail/push_notifications/payout.tpl | 2 ++ templates/mail/push_notifications/success_login.tpl | 5 +++++ 4 files changed, 13 insertions(+) create mode 100644 templates/mail/push_notifications/idle_worker.tpl create mode 100644 templates/mail/push_notifications/new_block.tpl create mode 100644 templates/mail/push_notifications/payout.tpl create mode 100644 templates/mail/push_notifications/success_login.tpl diff --git a/templates/mail/push_notifications/idle_worker.tpl b/templates/mail/push_notifications/idle_worker.tpl new file mode 100644 index 00000000..5036ae06 --- /dev/null +++ b/templates/mail/push_notifications/idle_worker.tpl @@ -0,0 +1,5 @@ +

One of your workers is currently IDLE: {nocache}{$DATA.worker}{/nocache}

+

We have not received any shares for this worker in the past 10 minutes.

+

Since monitoring is enabled for this worker, this notification was sent.

+
+

Please check your workers!

diff --git a/templates/mail/push_notifications/new_block.tpl b/templates/mail/push_notifications/new_block.tpl new file mode 100644 index 00000000..b8607b6f --- /dev/null +++ b/templates/mail/push_notifications/new_block.tpl @@ -0,0 +1 @@ +

{nocache}Block Number {$DATA.height} has been discovered by {$DATA.finder} with a total value of {$DATA.amount} {$DATA.currency}! The current difficulty is {$DATA.difficulty}.{/nocache}

diff --git a/templates/mail/push_notifications/payout.tpl b/templates/mail/push_notifications/payout.tpl new file mode 100644 index 00000000..7c0d8e35 --- /dev/null +++ b/templates/mail/push_notifications/payout.tpl @@ -0,0 +1,2 @@ +

You account has been debited and the coins have been sent to your wallet.

+

Amount: {nocache}{$DATA.amount}{/nocache}

diff --git a/templates/mail/push_notifications/success_login.tpl b/templates/mail/push_notifications/success_login.tpl new file mode 100644 index 00000000..97fcce9d --- /dev/null +++ b/templates/mail/push_notifications/success_login.tpl @@ -0,0 +1,5 @@ +

Your account has successfully logged in

+

User: {$DATA.LOGINUSER}

+

IP: {$DATA.LOGINIP}

+

Time: {$DATA.LOGINTIME}

+

If you initiated this login, you can ignore this message. If you did NOT, please notify an administrator.

From 41bd5e4e5024838fa182211d085d7812a8740bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Thu, 12 Jan 2017 22:11:50 +0100 Subject: [PATCH 6/9] #2539 - fixed doubled push notifications --- include/classes/pushnotification.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/classes/pushnotification.class.php b/include/classes/pushnotification.class.php index 5c8e3ce3..40244bec 100644 --- a/include/classes/pushnotification.class.php +++ b/include/classes/pushnotification.class.php @@ -144,9 +144,10 @@ $message = false; foreach (array('/mail/push_notifications/', '/mail/notifications/') as $dir){ - $this->smarty->clearCache($templateFile = TEMPLATE_DIR.$dir.$template.'.tpl'); + $this->smarty->clearCache($templateFile = TEMPLATE_DIR.$dir.$template.'.tpl'); try { $message = $this->smarty->fetch($templateFile); + break; } catch (SmartyException $e){ } @@ -168,4 +169,3 @@ $pushnotification->setConfig($config); $pushnotification->setSetting($setting); $pushnotification->setErrorCodes($aErrorCodes); - \ No newline at end of file From 96fb92d2375ca951fcd1baf4a0f963fa7c0cb389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Tue, 17 Jan 2017 06:39:54 +0100 Subject: [PATCH 7/9] FIX - change log to public,... --- include/classes/base.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/classes/base.class.php b/include/classes/base.class.php index a886da6b..c29534b2 100644 --- a/include/classes/base.class.php +++ b/include/classes/base.class.php @@ -28,7 +28,7 @@ class Base { $this->coin_address = $coin_address; } - protected $log; + public $log; public function setLog($log) { $this->log = $log; } From dad43012e924883c4b842636751cc61d3f0d61bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Tue, 17 Jan 2017 07:00:37 +0100 Subject: [PATCH 8/9] #2539 - FIXED user login push notification --- include/classes/user.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/classes/user.class.php b/include/classes/user.class.php index 4aa25f19..0d761fde 100644 --- a/include/classes/user.class.php +++ b/include/classes/user.class.php @@ -244,7 +244,7 @@ class User extends Base { $notifs->setSetting($this->setting); $notifs->setErrorCodes($this->aErrorCodes); $ndata = $notifs->getNotificationSettings($uid); - if (@$ndata['success_login'] == 1) { + if ((array_key_exists('push_success_lo', $ndata) && $ndata['push_success_lo']) || (array_key_exists('success_login', $ndata) && $ndata['success_login'])){ // seems to be active, let's send it $aDataN['username'] = $username; $aDataN['email'] = $this->getUserEmail($username); From bcfd7cfb30f831f93993de8b147268598249703f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Blon=C4=8F=C3=A1k?= Date: Mon, 6 Feb 2017 09:53:17 +0100 Subject: [PATCH 9/9] Updated push notifications format --- include/classes/transaction.class.php | 1 + templates/mail/push_notifications/idle_worker.tpl | 8 ++++---- templates/mail/push_notifications/new_block.tpl | 2 +- templates/mail/push_notifications/payout.tpl | 3 +-- templates/mail/push_notifications/success_login.tpl | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/classes/transaction.class.php b/include/classes/transaction.class.php index b2d30b59..923d306a 100644 --- a/include/classes/transaction.class.php +++ b/include/classes/transaction.class.php @@ -430,6 +430,7 @@ class Transaction extends Base { $aMailData['email'] = $this->user->getUserEmailById($account_id); $aMailData['subject'] = $type . ' Completed'; $aMailData['amount'] = $amount; + $aMailData['currency'] = $this->config['currency']; if (!$this->notification->sendNotification($account_id, 'payout', $aMailData)) { $this->setErrorMessage('Failed to send notification email to users address: ' . $aMailData['email'] . 'ERROR: ' . $this->notification->getCronError()); } diff --git a/templates/mail/push_notifications/idle_worker.tpl b/templates/mail/push_notifications/idle_worker.tpl index 5036ae06..8d66b75c 100644 --- a/templates/mail/push_notifications/idle_worker.tpl +++ b/templates/mail/push_notifications/idle_worker.tpl @@ -1,5 +1,5 @@ -

One of your workers is currently IDLE: {nocache}{$DATA.worker}{/nocache}

-

We have not received any shares for this worker in the past 10 minutes.

-

Since monitoring is enabled for this worker, this notification was sent.

+One of your workers is currently IDLE: {nocache}{$DATA.worker}{/nocache}
+We have not received any shares for this worker in the past 10 minutes.
+Since monitoring is enabled for this worker, this notification was sent.

-

Please check your workers!

+Please check your workers! diff --git a/templates/mail/push_notifications/new_block.tpl b/templates/mail/push_notifications/new_block.tpl index b8607b6f..a8237547 100644 --- a/templates/mail/push_notifications/new_block.tpl +++ b/templates/mail/push_notifications/new_block.tpl @@ -1 +1 @@ -

{nocache}Block Number {$DATA.height} has been discovered by {$DATA.finder} with a total value of {$DATA.amount} {$DATA.currency}! The current difficulty is {$DATA.difficulty}.{/nocache}

+{nocache}Block Number {$DATA.height} has been discovered by {$DATA.finder} with a total value of {$DATA.amount} {$DATA.currency}! The current difficulty is {$DATA.difficulty}.{/nocache} diff --git a/templates/mail/push_notifications/payout.tpl b/templates/mail/push_notifications/payout.tpl index 7c0d8e35..973cdecd 100644 --- a/templates/mail/push_notifications/payout.tpl +++ b/templates/mail/push_notifications/payout.tpl @@ -1,2 +1 @@ -

You account has been debited and the coins have been sent to your wallet.

-

Amount: {nocache}{$DATA.amount}{/nocache}

+You account has been debited and the coins have been sent to your wallet.Amount: {nocache}{$DATA.amount} {$DATA.currency}{/nocache} diff --git a/templates/mail/push_notifications/success_login.tpl b/templates/mail/push_notifications/success_login.tpl index 97fcce9d..eec15741 100644 --- a/templates/mail/push_notifications/success_login.tpl +++ b/templates/mail/push_notifications/success_login.tpl @@ -1,5 +1,5 @@ -

Your account has successfully logged in

-

User: {$DATA.LOGINUSER}

-

IP: {$DATA.LOGINIP}

-

Time: {$DATA.LOGINTIME}

-

If you initiated this login, you can ignore this message. If you did NOT, please notify an administrator.

+Your account has successfully logged in
+User: {$DATA.LOGINUSER}
+IP: {$DATA.LOGINIP}
+Time: {$DATA.LOGINTIME}
+If you initiated this login, you can ignore this message. If you did NOT, please notify an administrator.