├── .gitignore
├── .styleci.yml
├── LICENSE
├── README.md
├── composer.json
└── src
└── CallmanagerAXL
└── Callmanager.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | composer.lock
3 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: recommended
2 |
3 | linting: true
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP7-CallManager-AXL
2 | PHP Implementation to interface with Cisco unified call manager (CUCM) over the administrative XML (AXL) implememtation.
3 | This library requires a copy of the CORRECT .WSDL file for YOUR VERSION of callmanager.
4 | This library is under development so should be considered unstable and subject to major changes.
5 |
6 | ## Naming Convention
7 |
8 | ```
9 | This library is dependent on a naming convention specific to the owner's environment. Use at your own risk.
10 |
11 | ```
12 |
13 | |Object Type|Example Name|
14 | |------------------|--------------------|
15 | |Route Group|RG_{$SITE} |
16 | |Media Resourse Group List|MRGL_{$SITE} |
17 | |Media Resourse Group|MRG_{$SITE} |
18 | |Media Terminiation Point|{$SITE}_711 |
19 | |Media Terminiation Point|{$SITE}_729 |
20 | |Conference Bridge|{$SITE}_CFB |
21 | |Device Pool|DP_{$SITE} |
22 | |Call Manager Group|CMG-{$SITE} |
23 | |Region|R_{$SITE} |
24 | |Location|LOC_{$SITE} |
25 | |Calling Search Space|CSS_{$SITE} |
26 | |Partition|PT_{$SITE} |
27 | |SRST |SRST_{$SITE} |
28 |
29 |
30 | ## Install via Composer
31 |
32 | ```
33 | composer require iahunter/php5-callmanager-axl
34 | ```
35 | ### Example - List Device Pool Names
36 |
37 | ```php
38 | require_once "./vendor/autoload.php";
39 |
40 | $URL = "https://10.11.12.13:8443/axl"; // Prod CUCM
41 | $SCHEMA = "./axl/schema/10.5/AXLAPI.wsdl";
42 | $USER = "username";
43 | $PASS = "password";
44 |
45 | try {
46 | $CUCM = new \Iahunter\CallmanagerAXL\Callmanager($URL, $SCHEMA, $USER, $PASS);
47 |
48 | $DP = $CUCM->get_device_pool_names();
49 | print_r($DP);
50 |
51 | } catch (\Exception $E) {
52 | echo "Error communicating with callmanager: {$E->getMessage()}".PHP_EOL;
53 | }
54 | ```
55 |
56 | ### Example - List Phone Names
57 |
58 | ```php
59 | require_once "./vendor/autoload.php";
60 |
61 | $URL = "https://10.11.12.13:8443/axl"; // Prod CUCM
62 | $SCHEMA = "./axl/schema/10.5/AXLAPI.wsdl";
63 | $USER = "username";
64 | $PASS = "password";
65 |
66 | try {
67 | $CUCM = new \Iahunter\CallmanagerAXL\Callmanager($URL, $SCHEMA, $USER, $PASS);
68 |
69 | $PHONES = $CUCM->get_phone_names();
70 | print_r($PHONES);
71 |
72 | } catch (\Exception $E) {
73 | echo "Error communicating with callmanager: {$E->getMessage()}".PHP_EOL;
74 | }
75 | ```
76 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "iahunter/php5-callmanager-axl",
3 | "type": "library",
4 | "description": "PHP Cisco CallManager AXL SOAP/XML Library",
5 | "keywords": [
6 | "php5",
7 | "php7",
8 | "cisco",
9 | "callmanager",
10 | "call",
11 | "manager",
12 | "axl",
13 | "voip"
14 | ],
15 | "homepage": "http://github.com/iahunter/php5-callmanager-axl",
16 | "license": "LGPL3.0",
17 | "authors": [
18 | {
19 | "name": "John.Lavoie",
20 | "email": "composer@secureobscure.com",
21 | "role": "Developer"
22 | },
23 | {
24 | "name": "Travis Riesenberg",
25 | "email": "Travis.Riesenberg@kiewit.com",
26 | "role": "Developer"
27 | }
28 | ],
29 | "minimum-stability": "dev",
30 | "require-dev": {
31 | "phpunit/phpunit": "~4.0"
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "Iahunter\\": "src"
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/CallmanagerAXL/Callmanager.php:
--------------------------------------------------------------------------------
1 | true,
48 | 'exceptions' => true,
49 | 'stream_context' => stream_context_create(
50 | ['ssl' => [
51 | 'verify_peer' => false,
52 | 'verify_peer_name' => false,
53 | 'allow_self_signed' => true,
54 | ],
55 | ]),
56 | 'connection_timeout' => 10,
57 | 'location' => $URL,
58 | 'login' => $USERNAME,
59 | 'password' => $PASSWORD,
60 | ];
61 | $this->SOAPCLIENT = new \SoapClient($SCHEMA, $OPTIONS);
62 | $this->SOAPCALLS = [];
63 | }
64 |
65 | // Keep track of our soap calls for performance and debugging
66 |
67 | private function log_soap_call($CALL, $TIME, $QUERY, $REPLY)
68 | {
69 | array_push($this->SOAPCALLS,
70 | [
71 | 'call' => $CALL,
72 | 'time' => $TIME,
73 | 'query' => $QUERY,
74 | 'reply' => $REPLY,
75 | ]
76 | );
77 |
78 | return count($this->SOAPCALLS);
79 | }
80 |
81 | public function microtimeTicks()
82 | {
83 | // Turn microtime into an array (12345 0.7563262)
84 | $ticks = explode(' ', microtime());
85 | // Return the sum of the two numbers (double precision number)
86 | return $ticks[0] + $ticks[1];
87 | }
88 |
89 | // This converts an object returned by a soap reply from StdClass to associative array
90 |
91 | public function object_to_assoc($OBJECT)
92 | {
93 | return json_decode(json_encode($OBJECT), true);
94 | }
95 |
96 | // This decodes soap reply objects and ensures the format is correct
97 | // Every response will be an array of the responses, even if its just one response
98 |
99 | public function decode_soap_reply($SOAPREPLY)
100 | {
101 | if (!is_object($SOAPREPLY)) {
102 | throw new \Exception('SOAP reply is not an object');
103 | }
104 | if (!property_exists($SOAPREPLY, 'return')) {
105 | throw new \Exception('SOAP reply does not have the property return');
106 | }
107 | $SOAPRETURN = $SOAPREPLY->return;
108 | $SOAPOBJVARS = get_object_vars($SOAPRETURN);
109 | $RETURN = reset($SOAPOBJVARS);
110 | if (is_object($RETURN)) {
111 | // Single objects mean we recieved exactly one element in the reply
112 | $RETURN = [$this->object_to_assoc($RETURN)];
113 | } else {
114 | // Otherwise we recieved multiple elements in the reply.
115 | $RETURN = $this->object_to_assoc($RETURN);
116 | }
117 |
118 | return $RETURN;
119 | }
120 |
121 | // This converts an array of key=>value pairs into a flat array of one of the keys values
122 |
123 | public function assoc_key_values_to_array($ASSOC, $AKEY, $STOPONERROR = true)
124 | {
125 | $RETURN = [];
126 |
127 | // Make sure its $ASSOC is an array or it errors out.
128 | if (is_array($ASSOC)) {
129 | // Loop through the array of key=>value pairs
130 | foreach ($ASSOC as $KEY => $VALUE) {
131 | if (isset($VALUE[$AKEY]) && $VALUE[$AKEY] !== '') {
132 | if (isset($VALUE['uuid']) && $VALUE['uuid']) {
133 | // If the query returns a UUID, use that as our array key!
134 | $RETURN[$VALUE['uuid']] = $VALUE[$AKEY];
135 | } else {
136 | // If the query does NOT return a UUID, use sequencial keys
137 | array_push($RETURN, $VALUE[$AKEY]);
138 | }
139 | } elseif ($STOPONERROR) {
140 | throw new \Exception("Assoc array value does not have key {$KEY}");
141 | }
142 | }
143 | }
144 |
145 | return $RETURN;
146 | }
147 |
148 | // This builds a searchCriteria & returnedTags array pair for soap requests against CUCM AXL
149 |
150 | public function axl_search_return_array($SEARCH, $RETURN)
151 | {
152 | return [
153 | 'searchCriteria' => $SEARCH,
154 | 'returnedTags' => $RETURN,
155 | ];
156 | }
157 |
158 | // Kick off LDAP Sync Process in CUCM - Name of LDAP Dirctory and true to start or false to stop.
159 |
160 | public function do_ldap_sync($NAME, $BOOLEAN)
161 | {
162 | $SEARCH = ['name' => $NAME, 'sync' => $BOOLEAN];
163 | // Search the CUCM for all phones
164 | $BASETIME = $this->microtimeTicks();
165 | $RETURN = $this->SOAPCLIENT->doLdapSync($SEARCH);
166 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
167 | // log our soap call
168 | $this->log_soap_call('doLdapSync', $DIFFTIME, $SEARCH, $RETURN);
169 |
170 | if (!is_object($RETURN)) {
171 | throw new \Exception('SOAP reply is not an object');
172 | } else {
173 | return $RETURN;
174 | }
175 | }
176 |
177 | public function get_ldap_sync_status($NAME)
178 | {
179 | $SEARCH = ['name' => $NAME];
180 | // Search the CUCM for all phones
181 | $BASETIME = $this->microtimeTicks();
182 | $RETURN = $this->SOAPCLIENT->getLdapSyncStatus($SEARCH);
183 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
184 | // log our soap call
185 | $this->log_soap_call('getLdapSyncStatus', $DIFFTIME, $SEARCH, $RETURN);
186 |
187 | if (!is_object($RETURN)) {
188 | throw new \Exception('SOAP reply is not an object');
189 | } else {
190 | return $RETURN;
191 | }
192 | }
193 |
194 | public function reset_phone($NAME)
195 | {
196 | $SEARCH = ['name' => $NAME];
197 | // Search the CUCM for all phones
198 | $BASETIME = $this->microtimeTicks();
199 | $RETURN = $this->SOAPCLIENT->resetPhone($SEARCH);
200 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
201 | // log our soap call
202 | $this->log_soap_call('resetPhone', $DIFFTIME, $SEARCH, $RETURN);
203 |
204 | if (!is_object($RETURN)) {
205 | throw new \Exception('SOAP reply is not an object');
206 | } else {
207 | return $RETURN;
208 | }
209 | }
210 | // Get a complete list of the names of all phones
211 |
212 | public function get_phone_names()
213 | {
214 | $SEARCH = $this->axl_search_return_array(['devicePoolName' => '%'], ['name' => '']);
215 | // Search the CUCM for all phones
216 | $BASETIME = $this->microtimeTicks();
217 | $RETURN = $this->SOAPCLIENT->listPhone($SEARCH);
218 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
219 | // log our soap call
220 | $this->log_soap_call('listPhone', $DIFFTIME, $SEARCH, $RETURN);
221 | // Decode the reply into an array of results
222 | $RETURN = $this->decode_soap_reply($RETURN);
223 | // Turn the associative arrays into a single simensional array list
224 | $RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
225 |
226 | return $RETURN;
227 | }
228 |
229 | // Including specific fields to return in the list function.
230 |
231 | public function list_all_phones_summary_by_site($SITE)
232 | {
233 | $SEARCH = $this->axl_search_return_array(['devicePoolName' => "%{$SITE}%"], [
234 | 'name' => '',
235 | 'description' => '',
236 | 'product' => '',
237 | 'callingSearchSpaceName' => '',
238 | 'devicePoolName' => '',
239 | 'locationName' => '',
240 | 'phoneTemplateName' => '',
241 | 'ownerUserName' => '',
242 | ]);
243 | // Search the CUCM for phones from Site Device Pool
244 | $BASETIME = $this->microtimeTicks();
245 | $RETURN = $this->SOAPCLIENT->listPhone($SEARCH);
246 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
247 | // log our soap call
248 | $this->log_soap_call('listPhone', $DIFFTIME, $SEARCH, $RETURN);
249 | // Decode the reply into an array of results
250 | $RETURN = $this->decode_soap_reply($RETURN);
251 | // Turn the associative arrays into a single simensional array list
252 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
253 |
254 | return $RETURN;
255 | }
256 |
257 | // Search Phone by Name
258 | public function phone_search_by_name($NAME)
259 | {
260 | $SEARCH = $this->axl_search_return_array(['name' => "%{$NAME}%"], [
261 | 'name' => '',
262 | 'description' => '',
263 | 'product' => '',
264 | 'callingSearchSpaceName' => '',
265 | 'devicePoolName' => '',
266 | 'locationName' => '',
267 | 'phoneTemplateName' => '',
268 | 'ownerUserName' => '',
269 | ]);
270 | // Search the CUCM for phones from Site Device Pool
271 | $BASETIME = $this->microtimeTicks();
272 | $RETURN = $this->SOAPCLIENT->listPhone($SEARCH);
273 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
274 | // log our soap call
275 | $this->log_soap_call('listPhone', $DIFFTIME, $SEARCH, $RETURN);
276 | // Decode the reply into an array of results
277 | $RETURN = $this->decode_soap_reply($RETURN);
278 | // Turn the associative arrays into a single simensional array list
279 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
280 |
281 | return $RETURN;
282 | }
283 |
284 | // Search Phone by Key
285 | public function phone_search($KEY, $SEARCH)
286 | {
287 | /*
288 | $KEYS =
289 | ['name',
290 | 'description',
291 | 'protocol',
292 | 'callingSearchSpaceName',
293 | 'devicePoolName',
294 | 'securityProfileName']
295 |
296 | */
297 | $SEARCH = $this->axl_search_return_array([$KEY => "%{$SEARCH}%"], [
298 | 'name' => '',
299 | 'description' => '',
300 | 'product' => '',
301 | 'callingSearchSpaceName' => '',
302 | 'devicePoolName' => '',
303 | 'locationName' => '',
304 | 'ownerUserName' => '',
305 | ]);
306 | // Search the CUCM for phones from Site Device Pool
307 | $BASETIME = $this->microtimeTicks();
308 | $RETURN = $this->SOAPCLIENT->listPhone($SEARCH);
309 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
310 | // log our soap call
311 | $this->log_soap_call('listPhone', $DIFFTIME, $SEARCH, $RETURN);
312 | // Decode the reply into an array of results
313 | $RETURN = $this->decode_soap_reply($RETURN);
314 | // Turn the associative arrays into a single simensional array list
315 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
316 |
317 | return $RETURN;
318 | }
319 |
320 | // Get all the information regarding one specific phone by name
321 |
322 | public function get_phone_by_name($NAME)
323 | {
324 | $SEARCH = ['name' => $NAME];
325 | $BASETIME = $this->microtimeTicks();
326 | $RETURN = $this->SOAPCLIENT->getPhone($SEARCH);
327 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
328 | // log our soap call
329 | $this->log_soap_call('getPhone', $DIFFTIME, $SEARCH, $RETURN);
330 | // Decode the reply into an array of results
331 | $RETURN = $this->decode_soap_reply($RETURN);
332 | // Count the number of replies we recieved...
333 | $COUNT = count($RETURN);
334 | // It should be EXACTLY one result
335 | if ($COUNT !== 1) {
336 | throw new \Exception("Search returned {$COUNT} results, not exactly 1 as expected");
337 | }
338 | // Strip off the outer array
339 | $RETURN = reset($RETURN);
340 |
341 | return $RETURN;
342 | }
343 |
344 | // Get an array of directory numbers by phone name
345 |
346 | public function get_directory_numbers_by_name($NAME)
347 | {
348 | // Get our phone by name from the previous function
349 | $PHONE = $this->get_phone_by_name($NAME);
350 | if (!isset($PHONE['lines'])) {
351 | throw new \Exception('Phone record does not contain the lines element');
352 | }
353 | if (!is_array($PHONE['lines'])) {
354 | throw new \Exception('Phone record lines element is not an array');
355 | }
356 | // Suck out the array of phone numbers
357 | $RETURN = reset($PHONE['lines']);
358 | // Turn them into a flat array of DIRNs
359 | $RETURN = $this->assoc_key_values_to_array($RETURN, 'dirn');
360 | // Turn the DIRNs into patterns of phone numbers
361 | $RETURN = $this->assoc_key_values_to_array($RETURN, 'pattern');
362 |
363 | return $RETURN;
364 | }
365 |
366 | // Get an array of every device pool name
367 |
368 | public function get_device_pool_names()
369 | {
370 | $SEARCH = $this->axl_search_return_array(['name' => '%'], ['name' => '']);
371 | // Search the CUCM for all device pools
372 | $BASETIME = $this->microtimeTicks();
373 | $RETURN = $this->SOAPCLIENT->listDevicePool($SEARCH);
374 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
375 | // log our soap call
376 | $this->log_soap_call('listDevicePool', $DIFFTIME, $SEARCH, $RETURN);
377 | // Decode the reply into an array of results
378 | $RETURN = $this->decode_soap_reply($RETURN);
379 | // Turn the associative arrays into a single simensional array list
380 | $RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
381 |
382 | return $RETURN;
383 | }
384 |
385 | // Get an array of route plans by some search string
386 |
387 | public function get_route_plan_by_name($pattern, $partition = '%')
388 | {
389 | $SEARCH = $this->axl_search_return_array(['dnOrPattern' => $pattern, 'partition' => $partition],
390 | ['dnOrPattern' => '', 'partition' => '', 'type' => '', 'routeDetail' => '']);
391 | // Search the CUCM for all device pools
392 | $BASETIME = $this->microtimeTicks();
393 | $RETURN = $this->SOAPCLIENT->listRoutePlan($SEARCH);
394 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
395 | // log our soap call
396 | $this->log_soap_call('listRoutePlan', $DIFFTIME, $SEARCH, $RETURN);
397 | // Decode the reply into an array of results
398 | $RETURN = $this->decode_soap_reply($RETURN);
399 | // Turn the associative arrays into a single simensional array list
400 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
401 |
402 | return $RETURN;
403 | }
404 |
405 | // Get an array of route plans by some search string
406 |
407 | public function get_all_users()
408 | {
409 | $SEARCH = $this->axl_search_return_array(['userid' => '%'],
410 | ['firstName' => '', 'lastName' => '', 'userid' => '', 'primaryExtension' => '']);
411 | // Search the CUCM for all device pools
412 | $BASETIME = $this->microtimeTicks();
413 | $RETURN = $this->SOAPCLIENT->listUser($SEARCH);
414 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
415 | // log our soap call
416 | $this->log_soap_call('listUser', $DIFFTIME, $SEARCH, $RETURN);
417 | // Decode the reply into an array of results
418 | $RETURN = $this->decode_soap_reply($RETURN);
419 | // Turn the associative arrays into a single simensional array list
420 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
421 |
422 | return $RETURN;
423 | }
424 |
425 |
426 | public function list_all_usernames()
427 | {
428 | $SEARCH = $this->axl_search_return_array(['userid' => '%'],
429 | ['userid' => '']);
430 | // Search the CUCM for all device pools
431 | $BASETIME = $this->microtimeTicks();
432 | $RETURN = $this->SOAPCLIENT->listUser($SEARCH);
433 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
434 | // log our soap call
435 | $this->log_soap_call('listUser', $DIFFTIME, $SEARCH, $RETURN);
436 | // Decode the reply into an array of results
437 | $RETURN = $this->decode_soap_reply($RETURN);
438 | // Turn the associative arrays into a single simensional array list
439 | //$RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
440 |
441 | return $RETURN;
442 | }
443 |
444 |
445 | public function get_user_by_username($USERNAME)
446 | {
447 | $SEARCH = ['userid' => $USERNAME];
448 |
449 | $BASETIME = $this->microtimeTicks();
450 | $RETURN = $this->SOAPCLIENT->getUser($SEARCH);
451 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
452 | // log our soap call
453 | $this->log_soap_call('getUser', $DIFFTIME, $SEARCH, $RETURN);
454 | // Decode the reply into an array of results
455 | $RETURN = $this->decode_soap_reply($RETURN);
456 | // Count the number of replies we recieved...
457 | $COUNT = count($RETURN);
458 | // It should be EXACTLY one result
459 | if ($COUNT !== 1) {
460 | throw new \Exception("Search returned {$COUNT} results, not exactly 1 as expected");
461 | }
462 | // Strip off the outer array
463 | $RETURN = reset($RETURN);
464 |
465 | return $RETURN;
466 | }
467 |
468 | public function add_user($DATA)
469 | {
470 | $TYPE = "User";
471 | // Only the FIRST letter in the type needs to be lower case
472 | // so we cant do $TYPE = strtolower($TYPE);
473 | $FUNCTION = 'add'.$TYPE;
474 | $TYPE = lcfirst($TYPE);
475 | $QUERY = [$TYPE => $DATA];
476 | //print_r($QUERY);
477 | $BASETIME = $this->microtimeTicks();
478 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
479 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
480 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
481 | $RETURN = $this->object_to_assoc($RETURN);
482 | $RETURN = reset($RETURN);
483 | return $RETURN;
484 | }
485 |
486 | // Manage the list of types valid for our generalized dosomething_objecttypexyz_bysomething($1,$2)
487 |
488 | public function object_types()
489 | {
490 | // Valid object types this function works for
491 | $TYPES = ['DevicePool',
492 | 'Srst',
493 | 'RoutePartition',
494 | 'Css',
495 | 'Location',
496 | 'Region',
497 | 'CallManagerGroup',
498 | 'ConferenceBridge',
499 | 'Mtp',
500 | 'MediaResourceGroup',
501 | 'MediaResourceList',
502 | 'H323Gateway',
503 | 'RouteGroup',
504 | 'RouteList',
505 | 'RoutePattern',
506 | 'TransPattern',
507 | 'ApplicationDialRules',
508 | 'CallingPartyTransformationPattern',
509 | 'CalledPartyTransformationPattern',
510 | 'DateTimeGroup',
511 | 'Phone',
512 | 'Line',
513 | 'CtiRoutePoint',
514 | 'HuntPilot',
515 | 'RemoteDestinationProfile',
516 | 'CallPark'
517 | ];
518 |
519 | return $TYPES;
520 | }
521 |
522 | // Get an array of site names
523 |
524 | public function get_site_names()
525 | {
526 | // Get the list of device pools
527 | $DEVICEPOOLS = $this->get_device_pool_names();
528 | $SITES = [];
529 | // Loop through all of the device pools
530 | foreach ($DEVICEPOOLS as $DP) {
531 | // Detect the DP_SITECODE format and put it into an array
532 | $REGEX = "/^DP_(\w+)/";
533 | if (preg_match($REGEX, $DP, $HITS)) {
534 | array_push($SITES, $HITS[1]);
535 | } else {
536 | //print "{$DP} did not match {$REGEX}!
\n";
537 | }
538 | }
539 | // Return our array of sites
540 | return $SITES;
541 | }
542 |
543 | public function get_remoteDestinationProfiles()
544 | {
545 | $SEARCH = $this->axl_search_return_array(['name' => '%'],
546 | ['name' => '', 'model' => '', 'callingSearchSpaceName' => '', 'devicePoolName' => '', 'userId' => '', 'uuid' => '']);
547 | $BASETIME = $this->microtimeTicks();
548 | $RETURN = $this->SOAPCLIENT->listRemoteDestinationProfile($SEARCH);
549 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
550 | // log our soap call
551 | $this->log_soap_call('listRemoteDestinationProfile', $DIFFTIME, $SEARCH, $RETURN);
552 | // Decode the reply into an array of results
553 | $RETURN = $this->decode_soap_reply($RETURN);
554 | // Turn the associative arrays into a single simensional array list
555 | $RETURN = $this->assoc_key_values_to_array($RETURN, 'name');
556 |
557 | return $RETURN;
558 | }
559 |
560 | public function get_remoteDestinationProfilesbySite($SITE)
561 | {
562 | $SEARCH = $this->axl_search_return_array(['name' => '%'],
563 | ['name' => '', 'model' => '', 'callingSearchSpaceName' => '', 'devicePoolName' => '', 'userId' => '', 'uuid' => '']);
564 | $BASETIME = $this->microtimeTicks();
565 | $RETURN = $this->SOAPCLIENT->listRemoteDestinationProfile($SEARCH);
566 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
567 | // log our soap call
568 | $this->log_soap_call('listRemoteDestinationProfile', $DIFFTIME, $SEARCH, $RETURN);
569 | // Decode the reply into an array of results
570 | $RETURN = $this->decode_soap_reply($RETURN);
571 | $RETR = [];
572 |
573 | foreach ($RETURN as $RDP) {
574 | //print_r($RDP['devicePoolName']);
575 | //return $RDP;
576 | if (preg_match("/{$SITE}/", $RDP['devicePoolName']['_'])) {
577 | $RETR[] = $RDP;
578 | }
579 | }
580 | // Turn the associative arrays into a single simensional array list
581 | $RETURN = $this->assoc_key_values_to_array($RETR, 'name');
582 |
583 | return $RETURN;
584 | }
585 |
586 | // LIST STUFF IN SITES
587 |
588 | // Generalized function to return any type of object using the list/search functionality for a site
589 |
590 | public function get_object_type_by_site($SITE, $TYPE)
591 | {
592 | // Get our valid object types
593 | $TYPES = $this->object_types();
594 |
595 | // Check to see if the one we were passed is valid for this function
596 | if (!in_array($TYPE, $TYPES)) {
597 | throw new \Exception("Object type provided {$TYPE} is not supported");
598 | }
599 |
600 | // Lines is a special case due to highly nested indirect nature of its search selector relationships
601 | if ($TYPE == 'Line') {
602 | return $this->get_lines_by_site($SITE);
603 | }
604 | //$TYPES = array_diff($TYPES, ['Line']);
605 |
606 | // This is the default search and return criteria for MOST object types. There are a few exceptions
607 | $FIND = ['name' => "%{$SITE}%"];
608 | $RETR = ['name' => ''];
609 | // Phone search uses a different search name field
610 | if ($TYPE == 'Phone') {
611 | $FIND = ['devicePoolName' => "%{$SITE}%"];
612 | } elseif ($TYPE == 'CtiRoutePoint') {
613 | $FIND = ['devicePoolName' => "%{$SITE}%"];
614 | } elseif ($TYPE == 'H323Gateway') {
615 | $FIND = ['devicePoolName' => "%{$SITE}%"];
616 | // So does route pattern search and returns a different field - Need to search by specific Partition;
617 | } elseif ($TYPE == 'RoutePattern') {
618 | $FIND = ['routePartitionName' => "%{$SITE}%"];
619 | $RETR = ['pattern' => '', 'routePartitionName' => ''];
620 | // So does translation pattern search and returns a different field
621 | } elseif ($TYPE == 'TransPattern') {
622 | $FIND = ['routePartitionName' => "%{$SITE}%"];
623 | $RETR = ['pattern' => ''];
624 | // So does CallingPartyTransformationPattern pattern search and returns a different field
625 | } elseif ($TYPE == 'CallingPartyTransformationPattern') {
626 | $FIND = ['routePartitionName' => "%{$SITE}%"];
627 | $RETR = ['pattern' => ''];
628 | // So does CalledPartyTransformationPattern pattern search and returns a different field
629 | } elseif ($TYPE == 'CalledPartyTransformationPattern') {
630 | $FIND = ['routePartitionName' => "%{$SITE}%"];
631 | $RETR = ['pattern' => ''];
632 | } elseif ($TYPE == 'HuntPilot') {
633 | $FIND = ['routePartitionName' => "%{$SITE}%"];
634 | $RETR = ['pattern' => ''];
635 | } elseif ($TYPE == 'CallPark') {
636 | $FIND = ['routePartitionName' => "%{$SITE}%"];
637 | $RETR = ['pattern' => ''];
638 | } elseif ($TYPE == 'RemoteDestinationProfile') {
639 | $RETR = $this->get_remoteDestinationProfilesbySite($SITE);
640 |
641 | return $RETR;
642 | }
643 |
644 | $SEARCH = $this->axl_search_return_array($FIND, $RETR);
645 |
646 | $FUNCTION = 'list'.$TYPE;
647 | // Search the CUCM for matching SRST devices
648 | $BASETIME = $this->microtimeTicks();
649 | $RETURN = $this->SOAPCLIENT->$FUNCTION($SEARCH);
650 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
651 | // log our soap call
652 | $this->log_soap_call($FUNCTION, $DIFFTIME, $SEARCH, $RETURN);
653 | // Decode the reply into an array of results
654 | $RETURN = $this->decode_soap_reply($RETURN);
655 |
656 | // Turn the associative arrays into a single simensional array list
657 | $AKEYS = array_keys($RETR);
658 | $RESET = reset($AKEYS);
659 | $RETURN = $this->assoc_key_values_to_array($RETURN, $RESET);
660 |
661 | return $RETURN;
662 | }
663 |
664 | // List lines by site is indirect and dumb. phones are identified by device pool name of DP_SITE, lines are identified by owning phones.
665 | // This function will need to get every phone in a device pool and then build a list of every LINE that is returned.
666 | public function get_lines_by_site($SITE)
667 | {
668 | // Get all the phone object uuid=>names for a given site (based on device pool)
669 | $PHONES = $this->get_object_type_by_site($SITE, 'Phone');
670 | $LINES = [];
671 | // Loop through our phones at a site and use the UUID to get its detailed object information
672 | foreach ($PHONES as $UUID => $NAME) {
673 | $PHONE = $this->get_object_type_by_uuid($UUID, 'Phone');
674 | // if there are lines in the phone go get the uuid and name for each line dirn
675 | if (isset($PHONE['lines']) && is_array($PHONE['lines']) && count($PHONE['lines'])) {
676 | // loop through each line on the phone and suck out the uuid and dial pattern
677 | foreach ($PHONE['lines'] as $PHONELINE) {
678 | // If the phone has a dirn element with elements
679 | if (isset($PHONELINE['dirn']) && is_array($PHONELINE['dirn']) && count($PHONELINE['dirn'])) {
680 | // And the dirn has a uuid and pattern with value
681 | if (isset($PHONELINE['dirn']['pattern']) && $PHONELINE['dirn']['pattern'] && isset($PHONELINE['dirn']['uuid']) && $PHONELINE['dirn']['uuid']) {
682 | // Save this line to the list of site lines we return
683 | $LINES[$PHONELINE['dirn']['uuid']] = $PHONELINE['dirn']['pattern'];
684 | }
685 | }
686 | }
687 | }
688 | }
689 |
690 | return $LINES;
691 | }
692 |
693 | // Get Phone Line Details of the phone by Name
694 | public function get_lines_details_by_phone_name($NAME)
695 | {
696 | // Get all the phone object uuid=>names for a given site (based on device pool)
697 | $LINES = [];
698 |
699 | // get phone Line detailed object information
700 | $PHONE = $this->get_object_type_by_name($NAME, 'Phone');
701 | // if there are lines in the phone go get the uuid and name for each line dirn
702 | if (isset($PHONE['lines']) && is_array($PHONE['lines']) && count($PHONE['lines'])) {
703 | // loop through each line on the phone and suck out the uuid and dial pattern
704 | foreach ($PHONE['lines'] as $PHONELINE) {
705 | if (isset($PHONELINE['dirn']['pattern']) && $PHONELINE['dirn']['pattern'] && isset($PHONELINE['dirn']['uuid']) && $PHONELINE['dirn']['uuid']) {
706 | // Phone has single linee
707 | $UUID = $PHONELINE['dirn']['uuid'];
708 | $LINE = $this->get_object_type_by_uuid($UUID, 'Line');
709 | $LINES[$PHONELINE['dirn']['uuid']] = $LINE;
710 | } else {
711 | // Phone has multiple lines
712 | foreach ($PHONELINE as $SUBLINE) {
713 | if (isset($SUBLINE['dirn']['pattern']) && $SUBLINE['dirn']['pattern'] && isset($SUBLINE['dirn']['uuid']) && $SUBLINE['dirn']['uuid']) {
714 | // Save this line to the list of site lines we return
715 | //$LINES[$SUBLINE['dirn']['uuid']] = $SUBLINE['dirn']['pattern'];
716 | $UUID = $SUBLINE['dirn']['uuid'];
717 | $LINE = $this->get_object_type_by_uuid($UUID, 'Line');
718 | $LINES[$SUBLINE['dirn']['uuid']] = $LINE;
719 | }
720 | }
721 | }
722 | }
723 | }
724 |
725 | return $LINES;
726 | }
727 |
728 | // This returns an associative array for each of the above types
729 |
730 | public function get_all_object_types_by_site($SITE)
731 | {
732 | // Get our valid object types
733 | $TYPES = $this->object_types();
734 |
735 | // Do not get these objects by site. - They need to be requested directly.
736 | $DISCARD_TYPES = [
737 | 'Phone',
738 | 'Line',
739 | //'CtiRoutePoint',
740 | ];
741 |
742 | $RETURN = [];
743 | foreach ($TYPES as $TYPE) {
744 | if (in_array($TYPE, $DISCARD_TYPES)) {
745 | continue;
746 | }
747 | if (php_sapi_name() === 'cli') {
748 | //print "Getting {$SITE}s {$TYPE}...".PHP_EOL;
749 | }
750 | /*
751 | if ($TYPE == 'Line') {
752 | continue;
753 | }*/
754 | try {
755 | $RETURN[$TYPE] = $this->get_object_type_by_site($SITE, $TYPE);
756 | } catch (\Exception $E) {
757 | $RETURN[$TYPE] = [];
758 | }
759 | }
760 |
761 | return $RETURN;
762 | }
763 |
764 | public function get_all_object_type_details_by_site($SITE)
765 | {
766 | // Get our valid object types
767 | $TYPES = $this->object_types();
768 | // Do not get these objects by site. - They need to be requested directly.
769 | $DISCARD_TYPES = [
770 | 'Phone',
771 | 'Line',
772 | //'CtiRoutePoint',
773 | ];
774 |
775 | $RETURN = [];
776 | foreach ($TYPES as $TYPE) {
777 | if (in_array($TYPE, $DISCARD_TYPES)) {
778 | continue;
779 | }
780 |
781 | try {
782 | $RETURN[$TYPE] = $this->get_object_type_by_site($SITE, $TYPE);
783 | foreach ($RETURN[$TYPE] as $INDEX => $NAME) {
784 | unset($RETURN[$TYPE][$INDEX]);
785 | $RETURN[$TYPE][$INDEX] = $this->get_object_type_by_uuid($INDEX, $TYPE);
786 | }
787 | } catch (\Exception $E) {
788 | // If we encounter a specific error getting one TYPE of thing, continue on to the NEXT type of thing
789 | $RETURN[$TYPE] = [];
790 | }
791 | }
792 |
793 | return $RETURN;
794 | }
795 |
796 | // GET DETAILED STUFF
797 |
798 | public function get_object_type_by_name($NAME, $TYPE)
799 | {
800 | // Get our valid object types
801 | $TYPES = $this->object_types();
802 | // TransPattern is not valid for get-item-by-NAME, must use UUID or a combination of name and routepartitionname
803 | $TYPES = array_diff($TYPES, ['TransPattern']);
804 | // Lines is not valid for get-item-by-name, must be UUID
805 | $TYPES = array_diff($TYPES, ['Line']);
806 | // Check to see if the one we were passed is valid for this function
807 | if (!in_array($TYPE, $TYPES)) {
808 | throw new \Exception("Object type provided {$TYPE} is not supported");
809 | }
810 |
811 | $QUERY = ['name' => $NAME];
812 | $FUNCTION = 'get'.$TYPE;
813 | $BASETIME = $this->microtimeTicks();
814 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
815 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
816 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
817 | $RETURN = $this->decode_soap_reply($RETURN);
818 | $RETURN = reset($RETURN);
819 |
820 | return $RETURN;
821 | }
822 |
823 | public function get_object_type_by_pattern_and_partition($PATTERN, $PARTITION, $TYPE)
824 | {
825 | // Type must be a member of the TYPES Array for this function
826 |
827 | // Get our valid object types
828 | $TYPES = [
829 | 'TransPattern',
830 | 'Line',
831 | 'RoutePattern',
832 | ];
833 |
834 | // Check to see if the one we were passed is valid for this function
835 | if (!in_array($TYPE, $TYPES)) {
836 | throw new \Exception("Object type provided {$TYPE} is not supported");
837 | }
838 |
839 | $QUERY = ['pattern' => $PATTERN, 'routePartitionName' => $PARTITION];
840 | $FUNCTION = 'get'.$TYPE;
841 | $BASETIME = $this->microtimeTicks();
842 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
843 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
844 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
845 | $RETURN = $this->decode_soap_reply($RETURN);
846 | $RETURN = reset($RETURN);
847 |
848 | return $RETURN;
849 | }
850 |
851 | public function get_object_type_by_uuid($UUID, $TYPE)
852 | {
853 | // Get our valid object types
854 | $TYPES = $this->object_types();
855 | // Check to see if the one we were passed is valid for this function
856 | if (!in_array($TYPE, $TYPES)) {
857 | throw new \Exception("Object type provided {$TYPE} is not supported");
858 | }
859 |
860 | $QUERY = ['uuid' => $UUID];
861 | $FUNCTION = 'get'.$TYPE;
862 | $BASETIME = $this->microtimeTicks();
863 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
864 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
865 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
866 | $RETURN = $this->decode_soap_reply($RETURN);
867 | $RETURN = reset($RETURN);
868 |
869 | return $RETURN;
870 | }
871 |
872 | // DELETE STUFF
873 |
874 | // Only way I want to support removing items is by UUID, this is for safety because object names may not be unique
875 |
876 | public function delete_object_type_by_uuid($UUID, $TYPE)
877 | {
878 | // Get our valid object types
879 | $TYPES = $this->object_types();
880 | // Check to see if the one we were passed is valid for this function
881 | if (!in_array($TYPE, $TYPES)) {
882 | throw new \Exception("Object type provided {$TYPE} is not supported");
883 | }
884 |
885 | $QUERY = ['uuid' => $UUID];
886 | $FUNCTION = 'remove'.$TYPE;
887 | $BASETIME = $this->microtimeTicks();
888 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
889 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
890 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
891 |
892 | return $RETURN;
893 | }
894 |
895 | public function delete_all_object_types_by_site($SITE)
896 | {
897 | // This works - but do not call it!
898 | /* throw new \Exception("DO NOT CALL THIS FUNCTION");
899 | return;
900 | /**/
901 |
902 | $RESULT = [];
903 |
904 | // The order of this list is critical to successfully remove all the objects in a given site...
905 |
906 | $ORDER = [
907 | 'CallPark',
908 | 'RemoteDestinationProfile',
909 | 'HuntPilot',
910 | 'CtiRoutePoint',
911 | 'CalledPartyTransformationPattern',
912 | 'CallingPartyTransformationPattern',
913 | 'ApplicationDialRules',
914 | 'TransPattern',
915 | 'updateDevicePool',
916 | 'RoutePattern',
917 | 'RouteList',
918 | 'RouteGroup',
919 | 'H323Gateway',
920 | 'MediaResourceList',
921 | 'MediaResourceGroup',
922 | 'Mtp',
923 | 'ConferenceBridge',
924 | 'DevicePool',
925 | 'CallManagerGroup',
926 | 'Region',
927 | 'Location',
928 | 'Css',
929 | 'RoutePartition',
930 | 'Srst',
931 | ];
932 | $OBJECTS = $this->get_all_object_types_by_site($SITE);
933 | foreach ($ORDER as $STEP) {
934 | // This step is special
935 | if ($STEP == 'updateDevicePool') {
936 | // Go through all the device pools
937 | foreach ($OBJECTS['DevicePool'] as $UUID => $DP) {
938 | // Pull the device pool out of the database - do i even need to do this?
939 | //$DP = $this->get_object_type_by_uuid($UUID,'DevicePool');
940 | // Build a query to blank out the mediaResourceListName and localRouteGroup['value'] properties
941 | $QUERY = ['uuid' => $UUID];
942 | $QUERY['mediaResourceListName'] = '';
943 | $QUERY['localRouteGroup'] = ['name' => 'Standard Local Route Group', 'value' => ''];
944 | $BASETIME = $this->microtimeTicks();
945 | // Remove references to objects we plan to delete shortly from this
946 | $RETURN = $this->SOAPCLIENT->updateDevicePool($QUERY);
947 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
948 | $this->log_soap_call('updateSrst', $DIFFTIME, $QUERY, $RETURN);
949 | // Now we can continue deleting the other object types
950 | }
951 | } else {
952 | foreach ($OBJECTS[$STEP] as $UUID => $NAME) {
953 | //echo "Attempting to delete object type {$STEP} name {$NAME} UUID {$UUID}";
954 | try {
955 | $RESULT[$STEP][$UUID] = $this->delete_object_type_by_uuid($UUID, $STEP);
956 | } catch (\Exception $E) {
957 | $RESULT[$STEP][$UUID] = "Error deleteing object! {$E->getmessage()}";
958 | }
959 | }
960 | }
961 | }
962 |
963 | return $RESULT;
964 | }
965 |
966 | // ADD STUFF
967 |
968 | // This generalized add function expects $DATA to be correct for $TYPE objects
969 |
970 | public function add_object_type_by_assoc($DATA, $TYPE)
971 | {
972 | // Get our valid object types
973 | $TYPES = $this->object_types();
974 | // Check to see if the one we were passed is valid for this function
975 | if (!in_array($TYPE, $TYPES)) {
976 | throw new \Exception("Object type provided {$TYPE} is not supported");
977 | }
978 |
979 | // Only the FIRST letter in the type needs to be lower case
980 | // so we cant do $TYPE = strtolower($TYPE);
981 | $FUNCTION = 'add'.$TYPE;
982 | $TYPE = lcfirst($TYPE);
983 | $QUERY = [$TYPE => $DATA];
984 | //print_r($QUERY);
985 | $BASETIME = $this->microtimeTicks();
986 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
987 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
988 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
989 | $RETURN = $this->object_to_assoc($RETURN);
990 | $RETURN = reset($RETURN);
991 |
992 | return $RETURN;
993 | }
994 |
995 | // UPDATE STUFF
996 |
997 | // This generalized update function expects $DATA to be correct for $TYPE objects
998 |
999 | public function update_object_type_by_assoc($DATA, $TYPE)
1000 | {
1001 | // Get our valid object types
1002 | $TYPES = $this->object_types();
1003 | // Check to see if the one we were passed is valid for this function
1004 | if (!in_array($TYPE, $TYPES)) {
1005 | throw new \Exception("Object type provided {$TYPE} is not supported");
1006 | }
1007 | // There may be a case where the name is not actually called name
1008 | $NAMEFIELD = 'name';
1009 | if (!isset($DATA[$NAMEFIELD]) || !$DATA[$NAMEFIELD]) {
1010 | throw new \Exception('Data does not contain a valid name to update');
1011 | }
1012 | $NAME = $DATA[$NAMEFIELD];
1013 | // Get their object information out of the database
1014 | $OBJECT = $this->get_object_type_by_name($NAME, $TYPE);
1015 | //print "DUMP OF OBJECT WE FOUND TO EDIT:\n"; dumper($OBJECT);
1016 | // TODO: Make sure this is a valid object? Do some other checks?
1017 | // Force the query to use our name as search criteria
1018 | $QUERY = [$NAMEFIELD => $NAME];
1019 | // Loop through object keys and see if the value passed has changed
1020 | foreach ($OBJECT as $KEY => $VALUE) {
1021 | // Make sure the object key val pair is defined in the new data passed
1022 | // AND check if the value of the new data has changed from the original
1023 | if (isset($DATA[$KEY]) && $DATA[$KEY] != $VALUE) {
1024 | // Build our update query of different values
1025 | $QUERY[$KEY] = $DATA[$KEY];
1026 | } elseif (isset($DATA['addMembers'])) {
1027 | // Add it to query if the addMembersis set. This is for CSS updates
1028 | $QUERY['addMembers'] = $DATA['addMembers'];
1029 | } elseif (isset($DATA['removeMembers'])) {
1030 | // Add it to query if the removeMembers is set. This is for CSS updates
1031 | $QUERY['removeMembers'] = $DATA['removeMembers'];
1032 | } elseif (isset($DATA['newName'])) {
1033 | // Add it to query if the newName is set. This is for name changes.
1034 | $QUERY['newName'] = $DATA['newName'];
1035 | }
1036 | }
1037 | //print "QUERY CALCULATED ON OBJECT TO UPDATE:\n"; dumper($QUERY);
1038 | // Update our object
1039 | $FUNCTION = 'update'.$TYPE;
1040 | $BASETIME = $this->microtimeTicks();
1041 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
1042 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
1043 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
1044 | $RETURN = $this->object_to_assoc($RETURN);
1045 | $RETURN = reset($RETURN);
1046 |
1047 | return $RETURN;
1048 | }
1049 |
1050 | public function update_object_type_by_uuid_assoc($DATA, $TYPE)
1051 | {
1052 | // Get our valid object types
1053 | $TYPES = $this->object_types();
1054 | // Check to see if the one we were passed is valid for this function
1055 | if (!in_array($TYPE, $TYPES)) {
1056 | throw new \Exception("Object type provided {$TYPE} is not supported");
1057 | }
1058 | // There may be a case where the name is not actually called name
1059 | $NAMEFIELD = 'uuid';
1060 | if (!isset($DATA[$NAMEFIELD]) || !$DATA[$NAMEFIELD]) {
1061 | throw new \Exception('Data does not contain a valid uuid to update');
1062 | }
1063 | $NAME = $DATA[$NAMEFIELD];
1064 | // Get their object information out of the database
1065 | $OBJECT = $this->get_object_type_by_uuid($NAME, $TYPE);
1066 | //print "DUMP OF OBJECT WE FOUND TO EDIT:\n"; dumper($OBJECT);
1067 | // TODO: Make sure this is a valid object? Do some other checks?
1068 | // Force the query to use our name as search criteria
1069 | $QUERY = [$NAMEFIELD => $NAME];
1070 | // Loop through object keys and see if the value passed has changed
1071 | foreach ($OBJECT as $KEY => $VALUE) {
1072 | // Make sure the object key val pair is defined in the new data passed
1073 | // AND check if the value of the new data has changed from the original
1074 | if (isset($DATA[$KEY]) && $DATA[$KEY] != $VALUE) {
1075 | // Build our update query of different values
1076 | $QUERY[$KEY] = $DATA[$KEY];
1077 | } elseif (isset($DATA['addMembers'])) {
1078 | // Add it to query if the addMembersis set. This is for CSS updates
1079 | $QUERY['addMembers'] = $DATA['addMembers'];
1080 | } elseif (isset($DATA['removeMembers'])) {
1081 | // Add it to query if the removeMembers is set. This is for CSS updates
1082 | $QUERY['removeMembers'] = $DATA['removeMembers'];
1083 | } elseif (isset($DATA['newName'])) {
1084 | // Add it to query if the newName is set. This is for name changes.
1085 | $QUERY['newName'] = $DATA['newName'];
1086 | }
1087 | }
1088 | //print "QUERY CALCULATED ON OBJECT TO UPDATE:\n"; dumper($QUERY);
1089 | // Update our object
1090 | $FUNCTION = 'update'.$TYPE;
1091 | $BASETIME = $this->microtimeTicks();
1092 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
1093 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
1094 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
1095 | $RETURN = $this->object_to_assoc($RETURN);
1096 | $RETURN = reset($RETURN);
1097 |
1098 | return $RETURN;
1099 | }
1100 |
1101 | public function update_object_type_by_pattern_and_partition($DATA, $TYPE)
1102 | {
1103 | if (!$DATA['pattern']) {
1104 | throw new \Exception('No Pattern set');
1105 | } else {
1106 | $PATTERN = $DATA['pattern'];
1107 | }
1108 |
1109 | if (!$DATA['routePartitionName']) {
1110 | throw new \Exception('No Partition set');
1111 | } else {
1112 | $PARTITION = $DATA['routePartitionName'];
1113 | }
1114 |
1115 | // Get our valid object types
1116 | $TYPES = $this->object_types();
1117 | // Check to see if the one we were passed is valid for this function
1118 | if (!in_array($TYPE, $TYPES)) {
1119 | throw new \Exception("Object type provided {$TYPE} is not supported");
1120 | }
1121 |
1122 | // Get their object information out of the database
1123 | $OBJECT = $this->get_object_type_by_pattern_and_partition($PATTERN, $PARTITION, $TYPE);
1124 | //print "DUMP OF OBJECT WE FOUND TO EDIT:\n"; dumper($OBJECT);
1125 |
1126 | // TODO: Make sure this is a valid object? Do some other checks?
1127 |
1128 | // Force the query to use our name as search criteria
1129 | $QUERY = ['pattern' => $PATTERN, 'routePartitionName' => $PARTITION];
1130 | // Loop through object keys and see if the value passed has changed
1131 | foreach ($OBJECT as $KEY => $VALUE) {
1132 | // Make sure the object key val pair is defined in the new data passed
1133 | // AND check if the value of the new data has changed from the original
1134 | if (isset($DATA[$KEY]) && $DATA[$KEY] != $VALUE) {
1135 | // Build our update query of different values
1136 | $QUERY[$KEY] = $DATA[$KEY];
1137 | } elseif (isset($DATA['addMembers'])) {
1138 | // Add it to query if the addMembersis set. This is for CSS updates
1139 | $QUERY['addMembers'] = $DATA['addMembers'];
1140 | } elseif (isset($DATA['removeMembers'])) {
1141 | // Add it to query if the removeMembers is set. This is for CSS updates
1142 | $QUERY['removeMembers'] = $DATA['removeMembers'];
1143 | }
1144 | }
1145 | //print "QUERY CALCULATED ON OBJECT TO UPDATE:\n"; dumper($QUERY);
1146 | // Update our object
1147 | $FUNCTION = 'update'.$TYPE;
1148 | $BASETIME = $this->microtimeTicks();
1149 | $RETURN = $this->SOAPCLIENT->$FUNCTION($QUERY);
1150 | $DIFFTIME = $this->microtimeTicks() - $BASETIME;
1151 | $this->log_soap_call($FUNCTION, $DIFFTIME, $QUERY, $RETURN);
1152 | $RETURN = $this->object_to_assoc($RETURN);
1153 | $RETURN = reset($RETURN);
1154 |
1155 | return $RETURN;
1156 | }
1157 | }
1158 |
--------------------------------------------------------------------------------