Entities::findMany()   B
last analyzed

Complexity

Conditions 7
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 3
nop 5
dl 0
loc 20
rs 8.6666
c 0
b 0
f 0
1
<?php
2
/**
3
* Vtiger Web Services PHP Client Library
4
*
5
* The MIT License (MIT)
6
*
7
* Copyright (c) 2015, Zhmayev Yaroslav <[email protected]>
8
*
9
* Permission is hereby granted, free of charge, to any person obtaining a copy
10
* of this software and associated documentation files (the "Software"), to deal
11
* in the Software without restriction, including without limitation the rights
12
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
* copies of the Software, and to permit persons to whom the Software is
14
* furnished to do so, subject to the following conditions:
15
*
16
* The above copyright notice and this permission notice shall be included in
17
* all copies or substantial portions of the Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
* THE SOFTWARE.
26
*
27
* @author    Zhmayev Yaroslav <[email protected]>
28
* @copyright 2015-2016 Zhmayev Yaroslav
29
* @license   The MIT License (MIT)
30
*/
31
32
namespace Salaros\Vtiger\VTWSCLib;
33
34
use Salaros\Vtiger\VTWSCLib\WSClient;
35
36
/**
37
* Vtiger Web Services PHP Client Session class
38
*
39
* Class Entities
40
* @package Salaros\Vtiger\VTWSCLib
41
*/
42
class Entities
43
{
44
    private $wsClient;
45
46
    /**
47
     * Class constructor
48
     * @param object $wsClient  Parent WSClient instance
49
     */
50
    public function __construct($wsClient)
51
    {
52
        $this->wsClient = $wsClient;
53
    }
54
55
    /**
56
     * Retrieves an entity by ID
57
     * @param  string  $moduleName The name of the module / entity type
58
     * @param  string  $entityID The ID of the entity to retrieve
59
     * @return array   $select  The list of fields to select (defaults to SQL-like '*' - all the fields)
60
     * @return array  Entity data
61
     */
62
    public function findOneByID($moduleName, $entityID, array $select = [ ])
63
    {
64
        $entityID = $this->wsClient->modules->getTypedID($moduleName, $entityID);
65
        $record = $this->wsClient->invokeOperation('retrieve', [ 'id' => $entityID ], 'GET');
66
        if (!is_array($record)) {
67
            return null;
68
        }
69
70
        return (empty($select))
71
            ? $record
72
            : array_intersect_key($record, array_flip($select));
73
    }
74
75
    /**
76
     * Retrieve the entity matching a list of constraints
77
     * @param  string  $moduleName   The name of the module / entity type
78
     * @param  array   $params  Data used to find a matching entry
79
     * @return array   $select  The list of fields to select (defaults to SQL-like '*' - all the fields)
80
     * @return array  The matching record
81
     */
82
    public function findOne($moduleName, array $params, array $select = [ ])
83
    {
84
        $entityID = $this->getID($moduleName, $params);
85
        return (empty($entityID))
86
            ? null
87
            : $this->findOneByID($moduleName, $entityID, $select);
88
    }
89
90
    /**
91
     * Retrieves the ID of the entity matching a list of constraints + prepends '<module_id>x' string to it
92
     * @param  string $moduleName   The name of the module / entity type
93
     * @param  array   $params  Data used to find a matching entry
94
     * @return string  Type ID (a numeric ID + '<module_id>x')
95
     */
96
    public function getID($moduleName, array $params)
97
    {
98
        $query = self::getQueryString($moduleName, $params, [ 'id' ], 1);
99
        $records = $this->wsClient->runQuery($query);
100
        if (false === $records || !is_array($records) || empty($records)) {
101
            return null;
102
        }
103
104
        $record = $records[ 0 ];
105
        return (!is_array($record) || !isset($record[ 'id' ]) || empty($record[ 'id' ]))
106
            ? null
107
            : $record[ 'id' ];
108
    }
109
110
    /**
111
     * Retrieve a numeric ID of the entity matching a list of constraints
112
     * @param  string  $moduleName   The name of the module / entity type
113
     * @param  array   $params  Data used to find a matching entry
114
     * @return integer  Numeric ID
115
     */
116
    public function getNumericID($moduleName, array $params)
117
    {
118
        $entityID = $this->getID($moduleName, $params);
119
        $entityIDParts = explode('x', $entityID, 2);
120
        return (is_array($entityIDParts) && count($entityIDParts) === 2)
121
            ? intval($entityIDParts[ 1 ])
122
            : -1;
123
    }
124
125
    /**
126
     * Creates an entity for the giving module
127
     * @param  string  $moduleName   Name of the module / entity type for which the entry has to be created
128
     * @param  array  $params Entity data
129
     * @return array  Entity creation results
130
     */
131
    public function createOne($moduleName, array $params)
132
    {
133
        if (!is_assoc_array($params)) {
134
            throw new WSException(
135
                "You have to specify at least one search parameter (prop => value) 
136
                in order to be able to create an entity"
137
            );
138
        }
139
140
        // Assign record to logged in user if not specified
141
        if (!isset($params[ 'assigned_user_id' ])) {
142
            $currentUser = $this->wsClient->getCurrentUser();
143
            $params[ 'assigned_user_id' ] = $currentUser[ 'id' ];
144
        }
145
146
        $requestData = [
147
            'elementType' => $moduleName,
148
            'element'     => json_encode($params)
149
        ];
150
151
        return $this->wsClient->invokeOperation('create', $requestData);
152
    }
153
154
    /**
155
     * Updates an entity
156
     * @param  string $moduleName   The name of the module / entity type
157
     * @param  array $params Entity data
158
     * @return array  Entity update result
159
     */
160
    public function updateOne($moduleName, $entityID, array $params)
161
    {
162
        if (!is_assoc_array($params)) {
163
            throw new WSException(
164
                "You have to specify at least one search parameter (prop => value) 
165
                in order to be able to update the entity(ies)"
166
            );
167
        }
168
169
        // Fail if no ID was supplied
170
        if (empty($entityID)) {
171
            throw new WSException("The list of contraints must contain a valid ID");
172
        }
173
174
        // Preprend so-called moduleid if needed
175
        $entityID = $this->wsClient->modules->getTypedID($moduleName, $entityID);
176
177
        // Check if the entity exists + retrieve its data so it can be used below
178
        $entityData = $this->findOneByID($moduleName, $entityID);
179
        if ($entityData === false && !is_array($entityData)) {
180
            throw new WSException("Such entity doesn't exist, so it cannot be updated");
181
        }
182
183
        // The new data overrides the existing one needed to provide
184
        // mandatory field values to WS 'update' operation
185
        $params = array_merge(
186
            $entityData,
187
            $params
188
        );
189
190
        $requestData = [
191
            'elementType' => $moduleName,
192
            'element'     => json_encode($params)
193
        ];
194
195
        return $this->wsClient->invokeOperation('update', $requestData);
196
    }
197
198
    /**
199
     * Provides entity removal functionality
200
     * @param  string $moduleName   The name of the module / entity type
201
     * @param  string $entityID The ID of the entity to delete
202
     * @return array  Removal status object
203
     */
204
    public function deleteOne($moduleName, $entityID)
205
    {
206
        // Preprend so-called moduleid if needed
207
        $entityID = $this->wsClient->modules->getTypedID($moduleName, $entityID);
208
        return $this->wsClient->invokeOperation('delete', [ 'id' => $entityID ]);
209
    }
210
211
    /**
212
     * Retrieves multiple records using module name and a set of constraints
213
     * @param  string   $moduleName  The name of the module / entity type
214
     * @param  array    $params  Data used to find matching entries
215
     * @return array    $select  The list of fields to select (defaults to SQL-like '*' - all the fields)
216
     * @return integer  $limit   Limit the list of entries to N records (acts like LIMIT in SQL)
217
     * @return integer  $offset  Integer values to specify the offset of the query
218
     * @return array  The array containing matching entries or false if nothing was found
219
     */
220
    public function findMany($moduleName, array $params, array $select = [ ], $limit = 0, $offset = 0)
221
    {
222
        if (!is_array($params) || (!empty($params) && !is_assoc_array($params))) {
223
            throw new WSException(
224
                "You have to specify at least one search parameter (prop => value) 
225
                in order to be able to retrieve entity(ies)"
226
            );
227
        }
228
229
        // Builds the query
230
        $query = self::getQueryString($moduleName, $params, $select, $limit, $offset);
231
232
        // Run the query
233
        $records = $this->wsClient->runQuery($query);
234
        if (false === $records || !is_array($records) || empty($records)) {
235
            return null;
236
        }
237
238
        return $records;
239
    }
240
241
    /**
242
     * Sync will return a sync result object containing details of changes after modifiedTime
243
     * @param  integer [$modifiedTime = null]    The date of the first change
244
     * @param  string [$moduleName = null]   The name of the module / entity type
245
     * @param  string [$syncType = null]   Sync type determines the scope of the query
246
     * @return array  Sync result object
247
     */
248
    public function sync($modifiedTime = null, $moduleName = null, $syncType = null)
249
    {
250
        $modifiedTime = (empty($modifiedTime))
251
            ? strtotime('today midnight')
252
            : intval($modifiedTime);
253
254
        $requestData = [
255
            'modifiedTime' => $modifiedTime
256
        ];
257
258
        if (!empty($moduleName)) {
259
            $requestData[ 'elementType' ] = $moduleName;
260
        }
261
262
        if ($syncType) {
263
            $requestData[ 'syncType' ] = $syncType;
264
        }
265
266
        return $this->wsClient->invokeOperation('sync', $requestData, 'GET');
267
    }
268
269
    /**
270
     * Builds the query using the supplied parameters
271
     * @access public
272
     * @static
273
     * @param  string   $moduleName  The name of the module / entity type
274
     * @param  array    $params  Data used to find matching entries
275
     * @return string   $select  The list of fields to select (defaults to SQL-like '*' - all the fields)
276
     * @return integer  $limit   Limit the list of entries to N records (acts like LIMIT in SQL)
277
     * @return integer  $offset  Integer values to specify the offset of the query
278
     * @return string   The query build out of the supplied parameters
279
     */
280
    public static function getQueryString($moduleName, array $params, array $select = [ ], $limit = 0, $offset = 0)
281
    {
282
        $criteria = array();
283
        $select = (empty($select)) ? '*' : implode(',', $select);
284
        $query = sprintf("SELECT %s FROM $moduleName", $select);
285
        
286
        if (!empty($params)) {
287
            foreach ($params as $param => $value) {
288
                $criteria[ ] = "{$param} LIKE '{$value}'";
289
            }
290
291
            $query .= sprintf(' WHERE %s', implode(" AND ", $criteria));
292
        }
293
294
        if (intval($limit) > 0) {
295
            $query .= (intval($offset) > 0)
296
                ? sprintf(" LIMIT %s, %s", intval($offset), intval($limit))
297
                : sprintf(" LIMIT %s", intval($limit));
298
        }
299
300
        return $query;
301
    }
302
}
303