Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

Elgg/Notifications/SubscriptionsService.php (3 issues)

1
<?php
2
namespace Elgg\Notifications;
3
4
use Elgg\Database;
5
6
/**
7
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
8
 *
9
 * @access private
10
 *
11
 * @package    Elgg.Core
12
 * @subpackage Notifications
13
 * @since      1.9.0
14
 */
15
class SubscriptionsService {
16
17
	/**
18
	 *  Elgg has historically stored subscriptions as relationships with the prefix 'notify'
19
	 */
20
	const RELATIONSHIP_PREFIX = 'notify';
21
22
	/**
23
	 *  @var array Array of strings. Delivery names as registered with
24
	 *             elgg_register_notification_method()
25
	 */
26
	public $methods;
27
28
	/** @var Database */
29
	protected $db;
30
31
	/**
32
	 * Constructor
33
	 *
34
	 * @param Database $db      Database object
35
	 * @param array    $methods Notification delivery method names
36
	 */
37 135
	public function __construct(Database $db, array $methods = []) {
38 135
		$this->db = $db;
39 135
		$this->methods = $methods;
40 135
	}
41
42
	/**
43
	 * Get the subscriptions for this notification event
44
	 *
45
	 * The return array is of the form:
46
	 *
47
	 * array(
48
	 *     <user guid> => array('email', 'sms', 'ajax'),
49
	 * );
50
	 *
51
	 * @param NotificationEvent $event Notification event
52
	 * @return array
53
	 */
54 4
	public function getSubscriptions(NotificationEvent $event) {
55
56 4
		$subscriptions = [];
57
58 4
		if (!$this->methods) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->methods of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
59 1
			return $subscriptions;
60
		}
61
62 3
		$object = $event->getObject();
63 3
		if (!$object) {
64 1
			return $subscriptions;
65
		}
66
		
67
		// get subscribers only for \ElggEntity if it isn't private
68 2
		if (($object instanceof \ElggEntity) && ($object->access_id !== ACCESS_PRIVATE)) {
69 2
			$prefixLength = strlen(self::RELATIONSHIP_PREFIX);
70 2
			$records = $this->getSubscriptionRecords($object->getContainerGUID());
71 2
			foreach ($records as $record) {
72 1
				$deliveryMethods = explode(',', $record->methods);
73 1
				$subscriptions[$record->guid] = substr_replace($deliveryMethods, '', 0, $prefixLength);
74
			}
75
		}
76
77 2
		$params = ['event' => $event, 'origin' => Notification::ORIGIN_SUBSCRIPTIONS];
78 2
		return _elgg_services()->hooks->trigger('get', 'subscriptions', $params, $subscriptions);
79
	}
80
81
	/**
82
	 * Get the subscriptions for the content created inside this container.
83
	 *
84
	 * The return array is of the form:
85
	 *
86
	 * array(
87
	 *     <user guid> => array('email', 'sms', 'ajax'),
88
	 * );
89
	 *
90
	 * @param int $container_guid GUID of the entity acting as a container
91
	 * @return array User GUIDs (keys) and their subscription types (values).
92
	 */
93 2
	public function getSubscriptionsForContainer($container_guid) {
94
95 2
		$subscriptions = [];
96
97 2
		if (!$this->methods) {
98 1
			return $subscriptions;
99
		}
100
101 1
		$prefixLength = strlen(self::RELATIONSHIP_PREFIX);
102 1
		$records = $this->getSubscriptionRecords($container_guid);
103 1
		foreach ($records as $record) {
104 1
			$deliveryMethods = explode(',', $record->methods);
105 1
			$subscriptions[$record->guid] = substr_replace($deliveryMethods, '', 0, $prefixLength);
106
		}
107
108 1
		return $subscriptions;
109
	}
110
111
	/**
112
	 * Subscribe a user to notifications about a target entity
113
	 *
114
	 * This method will return false if the subscription already exists.
115
	 *
116
	 * @param int    $userGuid   The GUID of the user to subscribe to notifications
117
	 * @param string $method     The delivery method of the notifications
118
	 * @param int    $targetGuid The entity to receive notifications about
119
	 * @return boolean
120
	 */
121
	public function addSubscription($userGuid, $method, $targetGuid) {
122
		if (!in_array($method, $this->methods)) {
123
			return false;
124
		}
125
		$prefix = self::RELATIONSHIP_PREFIX;
126
		return add_entity_relationship($userGuid, "$prefix$method", $targetGuid);
127
	}
128
129
	/**
130
	 * Unsubscribe a user to notifications about a target entity
131
	 *
132
	 * @param int    $userGuid   The GUID of the user to unsubscribe to notifications
133
	 * @param string $method     The delivery method of the notifications to stop
134
	 * @param int    $targetGuid The entity to stop receiving notifications about
135
	 * @return boolean
136
	 */
137 2
	public function removeSubscription($userGuid, $method, $targetGuid) {
138 2
		$prefix = self::RELATIONSHIP_PREFIX;
139 2
		return remove_entity_relationship($userGuid, "$prefix$method", $targetGuid);
140
	}
141
142
	/**
143
	 * Get subscription records from the database
144
	 *
145
	 * Records are an object with two vars: guid and methods with the latter
146
	 * being a comma-separated list of subscription relationship names.
147
	 *
148
	 * @param int $container_guid The GUID of the subscription target
149
	 * @return array
150
	 */
151 3
	protected function getSubscriptionRecords($container_guid) {
152
153 3
		$container_guid = $this->db->sanitizeInt($container_guid);
0 ignored issues
show
Deprecated Code introduced by
The function Elgg\Database::sanitizeInt() has been deprecated: Use query parameters where possible ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

153
		$container_guid = /** @scrutinizer ignore-deprecated */ $this->db->sanitizeInt($container_guid);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
154
155
		// create IN clause
156 3
		$rels = $this->getMethodRelationships();
157 3
		if (!$rels) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rels of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
158
			return [];
159
		}
160 3
		array_walk($rels, [$this->db, 'sanitizeString']);
161 3
		$methods_string = "'" . implode("','", $rels) . "'";
162
163 3
		$db_prefix = $this->db->prefix;
164
		$query = "SELECT guid_one AS guid, GROUP_CONCAT(relationship SEPARATOR ',') AS methods
165 3
			FROM {$db_prefix}entity_relationships
166 3
			WHERE guid_two = $container_guid AND
167 3
					relationship IN ($methods_string) GROUP BY guid_one";
168 3
		return $this->db->getData($query);
169
	}
170
171
	/**
172
	 * Get the relationship names for notifications
173
	 *
174
	 * @return array
175
	 */
176 3
	protected function getMethodRelationships() {
177 3
		$prefix = self::RELATIONSHIP_PREFIX;
178 3
		$names = [];
179 3
		foreach ($this->methods as $method) {
180 3
			$names[] = "$prefix$method";
181
		}
182 3
		return $names;
183
	}
184
}
185
186