db = JFactory :: getDBO(); $this -> databasePrefix = JFactory :: getApplication() -> getCfg('dbprefix'); $parameters = JComponentHelper :: getParams('com_openaire'); $this -> pageSize = intval($parameters -> get('alertsPageSize')); $this -> atomUrn = $parameters -> get('alertsAtomUrn'); $this -> jdbcUri = $parameters -> get('alertsJdbcUri'); $this -> newsCategory = intval($parameters -> get('alertsNewsCategory')); $this -> newsUser = intval($parameters -> get('alertsNewsUser')); $this -> twitterAccessToken = $parameters -> get('alertsTwitterAcccessToken'); $this -> twitterAccessTokenSecret = $parameters -> get('alertsTwitterAccessTokenSecret'); $socket = new TSocket($parameters -> get('thriftHost'), intval($parameters -> get('thriftPort'))); $socket -> setRecvTimeout(intval($parameters -> get('thriftTimeout'))); $this -> transport = new TBufferedTransport($socket); $this -> client = new OpenAireConnectorClient(new TBinaryProtocol($this -> transport)); $this -> transport -> open(); $this -> cache = JCache :: getInstance(); } // Close Thrift transport. public function __destruct() { $this -> transport -> close(); } // Retrieve the subscriptions of a user using cache if enabled. // $user the user to retrieve subscriptions for // return the subscriptions of the user specified (array) public function getSubscriptions($user) { if ($this -> cache -> getCaching()) { $id = self :: SUBSCRIPTIONS_CACHE_ID . '.' . $user -> get('username'); $subscriptions = $this -> cache -> get($id, self :: CACHE_GROUP); if ($subscriptions === FALSE) { $subscriptions = $this -> _getSubscriptions($user); if ($subscriptions !== NULL) $this -> cache -> store($subscriptions, $id, self :: CACHE_GROUP); } } else $subscriptions = $this -> _getSubscriptions($user); return $subscriptions; } // Retrieve alert topics using cache if enabled. // $parent the id of the parent topic of the topics to retrieve // $name retrieve only topics whose name contains this substring // $limit the maximum number of topics to retrieve // return the alert topics matching the criteria specified (array) public function getTopics($parent, $name, $limit) { if ($this -> cache -> getCaching()) { $id = self :: TOPICS_CACHE_ID . '.' . $parent . '.' . $name . '.' . $limit; $topics = $this -> cache -> get($id, self :: CACHE_GROUP); if ($topics === FALSE) { $topics = $this -> _getTopics($parent, $name, $limit); if ($topics !== NULL) $this -> cache -> store($topics, $id, self :: CACHE_GROUP); } } else $topics = $this -> _getTopics($parent, $name, $limit); return $topics; } // Retrieve the alert modes available to a user using cache if enabled. // $user the user to retrieve alert modes for // return the alert modes available to the user specified (array) public function getAlertModes($user) { if ($this -> cache -> getCaching()) { $id = self :: ALERT_MODES_CACHE_ID . '.' . $user -> get('username'); $alertModes = $this -> cache -> get($id, self :: CACHE_GROUP); if ($alertModes === FALSE) { $alertModes = $this -> _getAlertModes($user); if ($alertModes !== NULL) $this -> cache -> store($alertModes, $id, self :: CACHE_GROUP); } } else $alertModes = $this -> _getAlertModes($user); return $alertModes; } // Add a new subcsription using cache if enabled. // $templateId the unique identifier of the template of the new subscription // $notificationService the notification service of the new subscription // $queryId the unique identifier of the query of the new subscription // $resultId the unique identifier of the result of the new subscription // $alertMode the alert mode of the new subscription // $batchPeriod the batch period of the new subscription // $user the user to add the new subscription for public function addSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $batchPeriod, $user) { $this -> _addSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $batchPeriod, $user); if ($this -> cache -> getCaching()) { $id = self :: SUBSCRIPTIONS_CACHE_ID . $user -> get('username'); $this -> cache -> remove($id, self :: CACHE_GROUP); } } // Remove a subscription using cache if enabled. // $templateId the unique identifier of the template of the subscription to remove // $notificationService the notification service of the subscription to remove // $queryId the unique identifier of the query of the subscription to remove // $resultId the unique identifier of the result of the subscription to remove // $alertMode the alert mode of the subscription to remove // $subscriber the subscriber URI of the subscription to remove // $user the user whose subscription to remove public function removeSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $subscriber, $user) { $this -> _removeSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $subscriber); if ($this -> cache -> getCaching()) { $id = self :: SUBSCRIPTIONS_CACHE_ID . $user -> get('username'); $this -> cache -> remove($id, self :: CACHE_GROUP); } } // Retrieve the subscriptions of a user using cache if enabled. // $user the user to retrieve subscriptions for // return the subscriptions of the user specified (array) or NULL if any errors occur private function _getSubscriptions($user) { try { $result = array(); foreach ($this -> getAlertModes($user) as $alertMode) { // for each alert mode that the current user may use list($alertMode -> id, $subscriber) = $this -> getAlertModeAndSubscriber($alertMode -> id, 0, $user); for ($offset = 0; ; $offset += $this -> pageSize) { $subscriptions = $this -> client -> getSubscriptions($alertMode -> id, $subscriber, $this -> pageSize, $offset); foreach ($subscriptions as $subscription) { $subscription -> topic = $this -> getFullTopicName($subscription -> templateId, $subscription -> notificationService, $subscription -> queryId, $subscription -> resultId); list($subscription -> alertModeName, $subscription -> batchPeriod) = $this -> getAlertModeNameAndBatchPeriod($subscription -> alertMode, $subscription -> subscriber); $result[] = $subscription; } if (count($subscriptions) < $this -> pageSize) break; } if ($alertMode -> batch) { // alert mode is a batch alert mode too list($alertMode -> id, $subscriber) = $this -> getAlertModeAndSubscriber($alertMode -> id, NULL, $user); for ($offset = 0; ; $offset += $this -> pageSize) { $subscriptions = $this -> client -> getSubscriptions($alertMode -> id, $subscriber, $this -> pageSize, $offset); foreach ($subscriptions as $subscription) { $subscription -> topic = $this -> getFullTopicName($subscription -> templateId, $subscription -> notificationService, $subscription -> queryId, $subscription -> resultId); list($subscription -> alertModeName, $subscription -> batchPeriod) = $this -> getAlertModeNameAndBatchPeriod($subscription -> alertMode, $subscription -> subscriber); $result[] = $subscription; } if (count($subscriptions) < $this -> pageSize) break; } } } // sort subscriptions usort($result, function ($subscription1, $subscription2) { $topicComparison = strcmp($subscription1 -> topic, $subscription2 -> topic); $alertModeComparison = strcmp($subscription1 -> alertModeName, $subscription2 -> alertModeName); $batchPeriodComparison = strcmp($subscription1 -> batchPeriod, $subscription2 -> batchPeriod); return ($topicComparison == 0) ? (($alertModeComparison == 0) ? $batchPeriodComparison : $alertModeComparison) : $topicComparison; }); JLog :: add ('Retrieved ' . count($result) . ' subscriptions (user: ' . $user -> get('username') . ')', JLog :: INFO, self :: LOG); return $result; } catch (Exception $e) { JLog :: add('Error retrieving subscriptions (user: ' . $user -> get('username') . '): ' . $e -> getMessage(), JLog :: ERROR, self :: LOG); return NULL; } } // Retrieve alert topics. // $parent the id of the parent topic of the topcis to retrieve // $name retrieve only topics whose name contains this substring // $limit the maximum number of topics to retrieve // return the alert topics matching the criteria specified (array) or NULL if any errors occur private function _getTopics($parent, $name, $limit) { try { $query = $this -> db -> getQuery(TRUE); $query -> select('id, name, description, templateId, notificationService, queryId, resultId'); $query -> from('#__openaire_topic_hierarchy'); $query -> where(($parent == NULL) ? 'parent IS NULL' : ('parent = ' . intval($parent))); $query -> where('name LIKE CONCAT(\'%\', ' . $this -> db -> quote($name) . ', \'%\')'); $query -> order('id'); $this -> db -> setQuery($query, 0, intval($limit)); $topics = $this -> db -> loadObjectList(); if ($topics === NULL) throw new Exception($this -> db -> getErrorMsg() . ' (' . $this -> db -> getErrorNum() . ')'); JLog :: add('Retrieved ' . count($topics) . ' topics (parent: ' . (($parent == NULL) ? 'NULL' : $parent) . ', name: ' . $name . ', limit: ' . $limit . ')', JLog :: INFO, self :: LOG); return $topics; } catch (Exception $e) { JLog :: add('Error retrieving topics (parent: ' . (($parent == NULL) ? 'NULL' : $parent) . ', name: ' . $name . ', limit: ' . $limit . '): ' . $e -> getMessage(), JLog :: ERROR, self :: LOG); return NULL; } } // Retrieve the alert modes available to a user. // $user the user to retrieve alert modes for // return the alert modes available to the user specified (array) or NULL if any errors occur private function _getAlertModes($user) { try { $query = $this -> db -> getQuery(TRUE); $query -> select(array('id', 'name', 'description', 'batch')); $query -> from('#__openaire_alert_modes'); if ($user -> username != 'admin') $query -> where('NOT `adminOnly`'); $this -> db -> setQuery($query); $alertModes = $this -> db -> loadObjectList(); if ($alertModes === NULL) throw new Exception($this -> db -> getErrorMsg() . ' (' . $this -> db -> getErrorNum() . ')'); JLog :: add('Retrieved ' . count($alertModes) . ' alert modes (user: ' . $user -> get('username') . ')', JLog :: INFO, self :: LOG); return $alertModes; } catch (Exception $e) { JLog :: add('Error retrieving alert modes (user: ' . $user -> get('username') . '): ' . $e -> getMessage(), JLog :: ERROR, self :: LOG); return NULL; } } // Add a new subscription. // $templateId the unique identifier of the template of the new subscription // $notificationService the notification service of the new subscription // $queryId the unique identifier of the query of the new subscription // $resultId the unique identifier of the result of the new subscription // $alertMode the alert mode of the new subscription // $batchPeriod the batch period of the new subscription // $user the user to add the new subscription for private function _addSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $batchPeriod, $user) { try { list($alertMode, $subscriber) = $this -> getAlertModeAndSubscriber($alertMode, $batchPeriod, $user); $this -> client -> addSubscription(new AlertSubscription(array('templateId' => $templateId, 'notificationService' => $notificationService, 'queryId' => $queryId, 'resultId' => $resultId, 'alertMode' => $alertMode, 'subscriber' => $subscriber))); JLog :: add('Added subscription (template: ' . $templateId . ', notification service: ' . $notificationService . ', query: ' . $queryId . ', result: ' . $resultId . ', alert mode: ' . $alertMode . ', batch period: ' . $batchPeriod . ', user: ' . $user -> get('username') . ')', JLog :: INFO, self :: LOG); } catch (Exception $e) { JLog :: add('Error adding subscription (template: ' . $templateId . ', notification service: ' . $notificationService . ', query: ' . $queryId . ', result: ' . $resultId . ', alert mode: ' . $alertMode . ', batch period: ' . $batchPeriod . ', user: ' . $user -> get('username') . '): ' . $e -> getMessage(), JLog :: ERROR, self :: LOG); } } // Remove a subscription. // $templateId the unique identifier of the template of the subscription to remove // $notificationService the notification service of the subscription to remove // $queryId the unique identifier of the query of the subscription to remove // $resultId the unique identifier of the result of the subscription to remove // $alertMode the alert mode of the subscription to remove // $subscriber the subscriber URI of the subscription to remove private function _removeSubscription($templateId, $notificationService, $queryId, $resultId, $alertMode, $subscriber) { try { $this -> client -> removeSubscription(new AlertSubscription(array('templateId' => $templateId, 'notificationService' => $notificationService, 'queryId' => $queryId, 'resultId' => $resultId, 'alertMode' => $alertMode, 'subscriber' => $subscriber))); JLog :: add('Removed subscription (template: ' . $templateId . ', notification service: ' . $notificationService . ', query: ' . $queryId . ', result: ' . $resultId . ', alert mode: ' . $alertMode . ', subscriber: ' . $subscriber . ')', JLog :: INFO, self :: LOG); } catch (Exception $e) { JLog :: add('Error removing subscription (template: ' . $templateId . ', notification service: ' . $notificationService . ', query: ' . $queryId . ', result: ' . $resultId . ', alert mode: ' . $alertMode . ', subscriber: ' . $subscriber . '): ' . $e -> getMessage(), JLog :: ERROR, self :: LOG); } } private function getAlertModeAndSubscriber($alertMode, $batchPeriod, $user) { switch($alertMode) { case 'Atom': $subscriber = $this -> atomUrn; break; case 'JDBC': $subscriber = $this -> jdbcUri . '&table=' . urlencode($this -> databasePrefix . 'openaire_alerts') . '&username=' . urlencode($user -> get('username')) . '&time=' . urlencode('$time') . '&title=' . urlencode('$title') . '&message=' . urlencode('$message') . '&link=' . urlencode('$link'); break; case 'Joomla!': $subscriber = $this -> jdbcUri . '&tablePrefix=' . urlencode($this -> databasePrefix) . '&category=' . urlencode($this -> newsCategory) . '&userId=' . urlencode($this -> newsUser); break; case 'SMTP': $subscriber = 'mailto:' . $user -> get('email'); break; case 'twitter': $subscriber = 'data:accessToken=' . urlencode($this -> twitterAccessToken) . '&accessTokenSecret=' . urlencode($this -> twitterAccessTokenSecret); break; } if (($batchPeriod !== 0) && ($batchPeriod !== '0')) { // convert alert mode to batch alert mode $alertMode = 'Batch ' . $alertMode; $subscriber = 'batch:' . $subscriber . '#' . $batchPeriod; } return array($alertMode, $subscriber); } private function getAlertModeNameAndBatchPeriod($alertMode, $subscriberUri) { if ((strpos($alertMode, 'Batch ') === 0) && (strpos($subscriberUri, 'batch:') === 0)) { // alert mode is a batch alert mode $alertMode = substr($alertMode, strlen('Batch ')); // ommit 'Batch ' to get alert mode $batchPeriod = substr($subscriberUri, strpos($subscriberUri, '#') + 1); // find batch period switch ($batchPeriod) { case 30 * 24 * 60: $batchPeriod = 'monthly'; break; case 15 * 24 * 60: $batchPeriod = 'bi-monthly'; break; case 7 * 24 * 60: $batchPeriod = 'weekly'; break; case 24 * 60: $batchPeriod = 'daily'; break; case 0: // batch period is either zero or null; make it non-batch case '0': case NULL: $batchPeriod = 'as it happens'; break; default: $batchPeriod = 'every ' . $batchPeriod . ' minute(s)'; } } else // alert mode is not a batch alert mode $batchPeriod = 'as it happens'; $query = $this -> db -> getQuery(TRUE); $query -> select('name'); $query -> from('#__openaire_alert_modes'); $query -> where('id = ' . $this -> db -> quote($alertMode)); $this -> db -> setQuery($query); $alertModeName = $this -> db -> loadResult(); if ($alertModeName === NULL) throw new Exception($this -> db -> getErrorMsg() . ' (' . $this -> db -> getErrorNum() . ')'); return array($alertModeName, $batchPeriod); } private function getFullTopicName($templateId, $notificationService, $queryId, $resultId) { $query = $this -> db -> getQuery(TRUE); $query -> select('parent, name'); $query -> from('#__openaire_topic_hierarchy'); $query -> where('templateId = ' . $this -> db -> quote($templateId)); $query -> where('notificationService = ' . $this -> db -> quote($notificationService)); $query -> where('queryId = ' . $this -> db -> quote($queryId)); $query -> where('resultId = ' . $this -> db -> quote($resultId)); $this -> db -> setQuery($query); $topic = $this -> db -> loadObject(); if ($topic === NULL) throw new Exception($this -> db -> getErrorMsg() . ' (' . $this -> db -> getErrorNum() . ')'); return ($topic -> parent == NULL) ? $topic -> name : ($this -> getTopicNameById($topic -> parent) . ' ' . $topic -> name); } private function getTopicNameById($id) { $query = $this -> db -> getQuery(TRUE); $query -> select('parent, name'); $query -> from('#__openaire_topic_hierarchy'); $query -> where('id = ' . intval($id)); $this -> db -> setQuery($query); $topic = $this -> db -> loadObject(); if ($topic === NULL) throw new Exception($this -> db -> getErrorMsg() . ' (' . $this -> db -> getErrorNum() . ')'); return ($topic -> parent == NULL) ? $topic -> name : ($this -> getTopicNameById($topic -> parent) . ' ' . $topic -> name); } }