Completed
Push — master ( b1b8c7...b37043 )
by Timo
06:43
created

Apache_Solr_Document   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 328
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 328
rs 10
c 0
b 0
f 0
wmc 29
lcom 1
cbo 0
1
<?php
2
/**
3
 * Copyright (c) 2007-2011, Servigistics, Inc.
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 *  - Redistributions of source code must retain the above copyright notice,
10
 *    this list of conditions and the following disclaimer.
11
 *  - Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *  - Neither the name of Servigistics, Inc. nor the names of
15
 *    its contributors may be used to endorse or promote products derived from
16
 *    this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @copyright Copyright 2007-2011 Servigistics, Inc. (http://servigistics.com)
31
 * @license http://solr-php-client.googlecode.com/svn/trunk/COPYING New BSD
32
 * @version $Id$
33
 *
34
 * @package Apache
35
 * @subpackage Solr
36
 * @author Donovan Jimenez <[email protected]>
37
 */
38
39
/**
40
 * Holds Key / Value pairs that represent a Solr Document along with any associated boost
41
 * values. Field values can be accessed by direct dereferencing such as:
42
 * <code>
43
 * ...
44
 * $document->title = 'Something';
45
 * echo $document->title;
46
 * ...
47
 * </code>
48
 *
49
 * Additionally, the field values can be iterated with foreach
50
 *
51
 * <code>
52
 * foreach ($document as $fieldName => $fieldValue)
53
 * {
54
 * ...
55
 * }
56
 * </code>
57
 */
58
class Apache_Solr_Document implements IteratorAggregate
59
{
60
    /**
61
     * SVN Revision meta data for this class
62
     */
63
    const SVN_REVISION = '$Revision$';
64
65
    /**
66
     * SVN ID meta data for this class
67
     */
68
    const SVN_ID = '$Id$';
69
70
    /**
71
     * Document boost value
72
     *
73
     * @var float
74
     */
75
    protected $_documentBoost = false;
76
77
    /**
78
     * Document field values, indexed by name
79
     *
80
     * @var array
81
     */
82
    protected $_fields = array();
83
84
    /**
85
     * Document field boost values, indexed by name
86
     *
87
     * @var array array of floats
88
     */
89
    protected $_fieldBoosts = array();
90
91
    /**
92
     * Clear all boosts and fields from this document
93
     */
94
    public function clear()
95
    {
96
        $this->_documentBoost = false;
97
98
        $this->_fields = array();
99
        $this->_fieldBoosts = array();
100
    }
101
102
    /**
103
     * Get current document boost
104
     *
105
     * @return mixed will be false for default, or else a float
106
     */
107
    public function getBoost()
108
    {
109
        return $this->_documentBoost;
110
    }
111
112
    /**
113
     * Set document boost factor
114
     *
115
     * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
116
     */
117
    public function setBoost($boost)
118
    {
119
        $boost = (float)$boost;
120
121
        if ($boost > 0.0) {
122
            $this->_documentBoost = $boost;
123
        } else {
124
            $this->_documentBoost = false;
125
        }
126
    }
127
128
    /**
129
     * Handle the array manipulation for a multi-valued field
130
     *
131
     * @param string $key
132
     * @param string $value
133
     * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
134
     *
135
     * @deprecated Use addField(...) instead
136
     */
137
    public function setMultiValue($key, $value, $boost = false)
138
    {
139
        $this->addField($key, $value, $boost);
140
    }
141
142
    /**
143
     * Add a value to a multi-valued field
144
     *
145
     * NOTE: the solr XML format allows you to specify boosts
146
     * PER value even though the underlying Lucene implementation
147
     * only allows a boost per field. To remedy this, the final
148
     * field boost value will be the product of all specified boosts
149
     * on field values - this is similar to SolrJ's functionality.
150
     *
151
     * <code>
152
     * $doc = new Apache_Solr_Document();
153
     *
154
     * $doc->addField('foo', 'bar', 2.0);
155
     * $doc->addField('foo', 'baz', 3.0);
156
     *
157
     * // resultant field boost will be 6!
158
     * echo $doc->getFieldBoost('foo');
159
     * </code>
160
     *
161
     * @param string $key
162
     * @param mixed $value
163
     * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
164
     */
165
    public function addField($key, $value, $boost = false)
166
    {
167
        if (!isset($this->_fields[$key])) {
168
            // create holding array if this is the first value
169
            $this->_fields[$key] = array();
170
        } else {
171
            if (!is_array($this->_fields[$key])) {
172
                // move existing value into array if it is not already an array
173
                $this->_fields[$key] = array($this->_fields[$key]);
174
            }
175
        }
176
177
        if ($this->getFieldBoost($key) === false) {
178
            // boost not already set, set it now
179
            $this->setFieldBoost($key, $boost);
180
        } else {
181
            if ((float)$boost > 0.0) {
182
                // multiply passed boost with current field boost - similar to SolrJ implementation
183
                $this->_fieldBoosts[$key] *= (float)$boost;
184
            }
185
        }
186
187
        // add value to array
188
        $this->_fields[$key][] = $value;
189
    }
190
191
    /**
192
     * Get the currently set field boost for a document field
193
     *
194
     * @param string $key
195
     * @return float currently set field boost, false if one is not set
196
     */
197
    public function getFieldBoost($key)
198
    {
199
        return isset($this->_fieldBoosts[$key]) ? $this->_fieldBoosts[$key] : false;
200
    }
201
202
    /**
203
     * Set the field boost for a document field
204
     *
205
     * @param string $key field name for the boost
206
     * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
207
     */
208
    public function setFieldBoost($key, $boost)
209
    {
210
        $boost = (float)$boost;
211
212
        if ($boost > 0.0) {
213
            $this->_fieldBoosts[$key] = $boost;
214
        } else {
215
            $this->_fieldBoosts[$key] = false;
216
        }
217
    }
218
219
    /**
220
     * Get field information
221
     *
222
     * @param string $key
223
     * @return mixed associative array of info if field exists, false otherwise
224
     */
225
    public function getField($key)
226
    {
227
        if (isset($this->_fields[$key])) {
228
            return array(
229
                'name' => $key,
230
                'value' => $this->_fields[$key],
231
                'boost' => $this->getFieldBoost($key)
232
            );
233
        }
234
235
        return false;
236
    }
237
238
    /**
239
     * Return current field boosts, indexed by field name
240
     *
241
     * @return array
242
     */
243
    public function getFieldBoosts()
244
    {
245
        return $this->_fieldBoosts;
246
    }
247
248
    /**
249
     * Get the names of all fields in this document
250
     *
251
     * @return array
252
     */
253
    public function getFieldNames()
254
    {
255
        return array_keys($this->_fields);
256
    }
257
258
    /**
259
     * Get the values of all fields in this document
260
     *
261
     * @return array
262
     */
263
    public function getFieldValues()
264
    {
265
        return array_values($this->_fields);
266
    }
267
268
    /**
269
     * IteratorAggregate implementation function. Allows usage:
270
     *
271
     * <code>
272
     * foreach ($document as $key => $value)
273
     * {
274
     *    ...
275
     * }
276
     * </code>
277
     */
278
    public function getIterator()
279
    {
280
        $arrayObject = new ArrayObject($this->_fields);
281
282
        return $arrayObject->getIterator();
283
    }
284
285
    /**
286
     * Magic get for field values
287
     *
288
     * @param string $key
289
     * @return mixed
290
     */
291
    public function __get($key)
292
    {
293
        if (isset($this->_fields[$key])) {
294
            return $this->_fields[$key];
295
        }
296
297
        return null;
298
    }
299
300
    /**
301
     * Magic set for field values. Multi-valued fields should be set as arrays
302
     * or instead use the addField(...) function which will automatically
303
     * make sure the field is an array.
304
     *
305
     * @param string $key
306
     * @param mixed $value
307
     */
308
    public function __set($key, $value)
309
    {
310
        $this->setField($key, $value);
311
    }
312
313
    /**
314
     * Set a field value. Multi-valued fields should be set as arrays
315
     * or instead use the addField(...) function which will automatically
316
     * make sure the field is an array.
317
     *
318
     * @param string $key
319
     * @param mixed $value
320
     * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
321
     */
322
    public function setField($key, $value, $boost = false)
323
    {
324
        $this->_fields[$key] = $value;
325
        $this->setFieldBoost($key, $boost);
326
    }
327
328
    /**
329
     * Magic isset for fields values.  Do not call directly. Allows usage:
330
     *
331
     * <code>
332
     * isset($document->some_field);
333
     * </code>
334
     *
335
     * @param string $key
336
     * @return boolean
337
     */
338
    public function __isset($key)
339
    {
340
        return isset($this->_fields[$key]);
341
    }
342
343
    /**
344
     * Magic unset for field values. Do not call directly. Allows usage:
345
     *
346
     * <code>
347
     * unset($document->some_field);
348
     * </code>
349
     *
350
     * @param string $key
351
     */
352
    public function __unset($key)
353
    {
354
        unset($this->_fields[$key]);
355
        unset($this->_fieldBoosts[$key]);
356
    }
357
358
    /**
359
     * Magic call method used to emulate getters as used by the template engine.
360
     *
361
     * @param    string $name method name
362
     * @param    array $arguments method arguments
363
     */
364
    public function __call($name, $arguments)
365
    {
366
        if (substr($name, 0, 3) == 'get') {
367
            $field = substr($name, 3);
368
            $field = strtolower($field[0]) . substr($field, 1);
369
370
            if (!isset($this->_fields[$field])) {
371
                throw new RuntimeException(
372
                    'Tried to access non-existent field "' . $field . '".',
373
                    1311006894
374
                );
375
            }
376
377
            return $this->_fields[$field];
378
        } else {
379
            throw new RuntimeException(
380
                'Call to undefined method. Supports magic getters only.',
381
                1311006605
382
            );
383
        }
384
    }
385
}
386