PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.20
VikAppointments Services Booking Calendar v1.2.20
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / helpers / libraries / webhook / webhook.php
vikappointments / site / helpers / libraries / webhook Last commit date
classes 1 month ago index.html 1 month ago queue.php 1 month ago webhook.php 1 month ago
webhook.php
344 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Web hook payload encapsulation.
16 *
17 * @since 1.7
18 */
19 class VAPWebHook
20 {
21 /**
22 * A list of include paths.
23 *
24 * @var array
25 */
26 protected static $includePaths = array();
27
28 /**
29 * The hook name.
30 *
31 * @var string
32 */
33 protected $hook;
34
35 /**
36 * The payload to send to the end-point.
37 *
38 * @var mixed
39 */
40 protected $payload;
41
42 /**
43 * Returns the proper instance able to handle the specified
44 * web hook action.
45 *
46 * @param string $hook The hook name.
47 * @param mixed $payload The payload to deliver.
48 *
49 * @return self
50 */
51 public static function getInstance($hook, $payload = array())
52 {
53 // get rid of initial "on"
54 $name = preg_replace("/^on/", '', $hook);
55 $filename = strtolower($name);
56
57 // use the default class name
58 $classname = 'VAPWebHook' . $name;
59
60 // save time by immediately checking whether the class already exists
61 if (!class_exists($name))
62 {
63 $found = false;
64
65 // iterate all include paths
66 foreach (static::getIncludePaths() as $path)
67 {
68 // attempt to load file from given include path
69 $found = $found || VAPLoader::import($classname, $path);
70 }
71
72 // check whether the file exists or has been already imported
73 if ($found || VAPLoader::import('libraries.webhook.classes.' . $filename))
74 {
75 if (!class_exists($classname))
76 {
77 // invalid class, throw exception
78 throw new RuntimeException(sprintf('Web Hook [%s] not found', $classname), 500);
79 }
80 }
81 else
82 {
83 // missing handler, use default class
84 $classname = 'VAPWebHook';
85 }
86 }
87
88 // instantiate matching class
89 return new $classname($hook, $payload);
90 }
91
92 /**
93 * Returns a list of supported web hook handlers.
94 *
95 * @param boolean $object True to return web hook instances, false to include
96 * only their names.
97 *
98 * @return array An associative array containing the hook event (key) and the
99 * hook name/instance (value).
100 */
101 public static function getSupportedHooks($object = false)
102 {
103 $hooks = array();
104
105 // get all include paths
106 $paths = static::getIncludePaths();
107 // append the default directory
108 $paths[] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classes';
109
110 foreach ($paths as $dir)
111 {
112 // get all PHP files contained within this folder
113 $files = glob(rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*.php');
114
115 foreach ($files as $file)
116 {
117 // extract hook name from file path
118 $hookname = preg_replace("/\.php$/i", '', basename($file));
119
120 try
121 {
122 // create webhook instance
123 $webhook = static::getInstance($hookname);
124
125 if ($object)
126 {
127 // save the whole webhook instance
128 $hooks[$webhook->getHook()] = $webhook;
129 }
130 else
131 {
132 // register only the webhook name
133 $hooks[$webhook->getHook()] = $webhook->getName();
134 // free space
135 unset($webhook);
136 }
137 }
138 catch (Exception $e)
139 {
140 // catch error and propagate system message without breaking the flow
141 JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error');
142 }
143 }
144 }
145
146 // sort web hooks by name (preserve association)
147 uasort($hooks, function($a, $b)
148 {
149 if ($a instanceof VAPWebHook)
150 {
151 $a = $a->getName();
152 }
153
154 if ($b instanceof VAPWebHook)
155 {
156 $b = $b->getName();
157 }
158
159 return strcmp($a, $b);
160 });
161
162 return $hooks;
163 }
164
165 /**
166 * Class constructor.
167 *
168 * @param string $hook The hook name.
169 * @param mixed $payload The payload to deliver.
170 */
171 public function __construct($hook, $payload)
172 {
173 $this->hook = $hook;
174 $this->payload = $payload;
175 }
176
177 /**
178 * Returns a readable name of the hook.
179 *
180 * @return string
181 */
182 public function getName()
183 {
184 // by default use the hook as name
185 return $this->hook;
186 }
187
188 /**
189 * Returns an associative array of supported parameters.
190 *
191 * @return array
192 */
193 public function getForm()
194 {
195 // by default no supported parameters
196 return array();
197 }
198
199 /**
200 * Returns the registered hook name.
201 *
202 * @return string
203 */
204 public function getHook()
205 {
206 return $this->hook;
207 }
208
209 /**
210 * Returns the registered payload.
211 *
212 * @param mixed $options Either an array or an object, which should contain
213 * the value of the specified parameters.
214 *
215 * @return mixed
216 */
217 public function getPayload($options = array())
218 {
219 if (is_array($this->payload) && array_keys($this->payload) === range(0, count($this->payload) - 1))
220 {
221 $arr = array();
222
223 // we have a sequential array, we need to name the properties of the list so that
224 // the receiver can fetch them in a better way
225 foreach ($this->payload as $i => $v)
226 {
227 $arr['arg' . $i] = $v;
228 }
229
230 return $arr;
231 }
232
233 return $this->payload;
234 }
235
236 /**
237 * Comparator to check whether 2 instances share the same payload parent.
238 *
239 * @return boolean
240 */
241 public function equalsTo($webhook)
242 {
243 // always different by default
244 return false;
245 }
246
247 /**
248 * Extends the current payload with the specified data.
249 *
250 * @param mixed $data The additional details to inject.
251 *
252 * @return void
253 */
254 public function extend($data)
255 {
256 if ($data instanceof VAPWebHook)
257 {
258 // extract payload from object
259 $data = $data->getPayload();
260 }
261
262 // convert both the payloads into associative arrays
263 $tmp = json_decode(json_encode($this->payload), true);
264 $data = json_decode(json_encode($data), true);
265
266 $tmp = is_array($tmp) ? $tmp : (array) $tmp;
267 $data = is_array($data) ? $data : (array) $data;
268
269 // merge both the payload details
270 $this->payload = array_merge($tmp, $data);
271 }
272
273 /**
274 * Gets a list of supported include paths.
275 *
276 * @return array
277 */
278 public static function getIncludePaths()
279 {
280 return static::$includePaths;
281 }
282
283 /**
284 * Adds one path to include in driver search.
285 * Proxy of addIncludePaths().
286 *
287 * @param string $path The path to search for drivers.
288 *
289 * @return array A list of include paths.
290 *
291 * @uses addIncludePaths()
292 */
293 public static function addIncludePath($path)
294 {
295 return static::addIncludePaths($path);
296 }
297
298 /**
299 * Adds one or more paths to include in driver search.
300 *
301 * @param mixed $paths The path or array of paths to search for drivers.
302 *
303 * @return array A list of include paths.
304 *
305 * @uses getIncludePaths()
306 * @uses setIncludePaths()
307 */
308 public static function addIncludePaths($paths)
309 {
310 $includePaths = static::getIncludePaths();
311
312 if (!empty($paths))
313 {
314 // in case the path is an array, merge all the paths and make sure we have no duplicates
315 if (is_array($paths))
316 {
317 $includePaths = array_unique(array_merge($includePaths, $paths));
318 }
319 // otherwise add the path as first element
320 else
321 {
322 $includePaths[] = $paths;
323 }
324
325 // update include paths
326 static::setIncludePaths($includePaths);
327 }
328
329 return $includePaths;
330 }
331
332 /**
333 * Sets the include paths to search for drivers.
334 *
335 * @param array $paths Array with paths to search in.
336 *
337 * @return void
338 */
339 public static function setIncludePaths($paths)
340 {
341 static::$includePaths = (array) $paths;
342 }
343 }
344