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 Cash Costello
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) {
0 ignored issues
show
Bug Best Practice introduced by Juho Jaakkola
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...
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);
154
155
		// create IN clause
156 3
		$rels = $this->getMethodRelationships();
157 3
		if (!$rels) {
0 ignored issues
show
Bug Best Practice introduced by Cash Costello
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