Users::search()   F
last analyzed

Complexity

Conditions 19
Paths 1024

Size

Total Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
nc 1024
nop 2
dl 0
loc 71
rs 0.3499
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Scriptotek\Alma\Users;
4
5
use Scriptotek\Alma\Client;
6
use Scriptotek\Alma\Exception\InvalidQuery;
7
use Scriptotek\Alma\Model\ReadOnlyArrayAccess;
8
9
/**
10
 * Non-iterable collection of User resources.
11
 */
12
class Users implements \ArrayAccess
13
{
14
    use ReadOnlyArrayAccess;
15
16
    /* @var Client */
17
    protected $client;
18
19
    public function __construct(Client $client)
20
    {
21
        $this->client = $client;
22
    }
23
24
    /**
25
     * Get a User object by id.
26
     *
27
     * @param $user_id int
28
     * @param $params array Additional query string parameters
29
     *
30
     * @return User
31
     */
32
    public function get($user_id, $params = [])
33
    {
34
        return User::make($this->client, $user_id)
35
            ->setParams($params);
36
    }
37
38
    /**
39
     * Get the first user matching a given query, or NULL if not found.
40
     *
41
     * @param string $query
42
     * @param array  $options
43
     *
44
     * @return User|null
45
     */
46
    public function findOne($query, array $options = [])
47
    {
48
        return $this->search($query, $options)->current();
49
    }
50
51
    /**
52
     * Iterates over all users matching the given query.
53
     * Handles continuation.
54
     *
55
     * @param string $query
56
     * @param array  $options
57
     *
58
     * @return \Generator
59
     */
60
    public function search($query, array $options = [])
61
    {
62
        // Max number of records to fetch. Set to 0 to fetch all.
63
        $limit = array_key_exists('limit', $options) ? $options['limit'] : 0;
64
65
        // Set to true to do a phrase search
66
        $phrase = array_key_exists('phrase', $options) ? $options['phrase'] : false;
67
68
        // Set to true to expand all query results to full records.
69
        // Please note that this will make queries significantly slower!
70
        $expand = array_key_exists('expand', $options) ? $options['expand'] : false;
71
72
        // Number of records to fetch each batch. Usually no need to change this.
73
        $batchSize = array_key_exists('batchSize', $options) ? $options['batchSize'] : 10;
74
75
        if ($limit != 0 && $limit < $batchSize) {
76
            $batchSize = $limit;
77
        }
78
79
        // The API will throw a 400 response if you include properly encoded spaces,
80
        // but underscores work as a substitute.
81
        $query = explode(' AND ', $query);
82
        $query = $phrase ? str_replace(' ', '_', $query) : str_replace(' ', ',', $query);
83
        $query = implode(' AND ', $query);
84
85
        $offset = 0;
86
        while (true) {
87
            $response = $this->client->getJSON('/users', ['q' => $query, 'limit' => $batchSize, 'offset' => $offset]);
88
89
            // The API sometimes returns total_record_count: -1, with no further error message.
90
            // Seems to indicate that the query was not understood.
91
            // See: https://github.com/scriptotek/php-alma-client/issues/8
92
            if ($response->total_record_count == -1) {
93
                throw new InvalidQuery($query);
94
            }
95
96
            if ($response->total_record_count == 0) {
97
                break;
98
            }
99
100
            if (!isset($response->user) || empty($response->user)) {
101
                // We cannot trust the value in 'total_record_count', so if there are no more records,
102
                // we have to assume the result set is depleted.
103
                // See: https://github.com/scriptotek/php-alma-client/issues/7
104
                break;
105
            }
106
107
            foreach ($response->user as $data) {
108
                $offset++;
109
                // Contacts without a primary identifier will have the primary_id
110
                // field populated with something weird like "no primary id (123456789023)".
111
                // We ignore those.
112
                // See: https://github.com/scriptotek/php-alma-client/issues/6
113
                if (strpos($data->primary_id, 'no primary id') === 0) {
114
                    continue;
115
                }
116
                $user = User::make($this->client, $data->primary_id)
117
                    ->init($data);
118
                if ($expand) {
119
                    $user->init();
120
                }
121
                yield $user;
122
            }
123
            if ($offset >= $response->total_record_count) {
124
                break;
125
            }
126
            if ($limit != 0 && $offset >= $limit) {
127
                break;
128
            }
129
        }
130
    }
131
}
132