1: <?php
2: /**
3: * Fetch query object for use with Horde_Imap_Client_Base#fetch().
4: *
5: * Copyright 2011-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (LGPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9: *
10: * @author Michael Slusarz <slusarz@horde.org>
11: * @category Horde
12: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
13: * @package Imap_Client
14: */
15: class Horde_Imap_Client_Fetch_Query implements ArrayAccess, Countable, Iterator
16: {
17: /**
18: * Internal data array.
19: *
20: * @var array
21: */
22: protected $_data = array();
23:
24: /**
25: * Get the full text of the message.
26: *
27: * @param array $opts The following options are available:
28: * - length: (integer) The length of the substring to return.
29: * DEFAULT: The entire text is returned.
30: * - peek: (boolean) If set, does not set the '\Seen' flag on the
31: * message.
32: * DEFAULT: The seen flag is set.
33: * - start: (integer) If a portion of the full text is desired to be
34: * returned, the starting position is identified here.
35: * DEFAULT: The entire text is returned.
36: */
37: public function fullText(array $opts = array())
38: {
39: $this->_data[Horde_Imap_Client::FETCH_FULLMSG] = $opts;
40: }
41:
42: /**
43: * Return header text.
44: *
45: * Header text is defined only for the base RFC 2822 message or
46: * message/rfc822 parts.
47: *
48: * @param array $opts The following options are available:
49: * - id: (string) The MIME ID to obtain the header text for.
50: * DEFAULT: The header text for the base message will be
51: * returned.
52: * - length: (integer) The length of the substring to return.
53: * DEFAULT: The entire text is returned.
54: * - peek: (boolean) If set, does not set the '\Seen' flag on the
55: * message.
56: * DEFAULT: The seen flag is set.
57: * - start: (integer) If a portion of the full text is desired to be
58: * returned, the starting position is identified here.
59: * DEFAULT: The entire text is returned.
60: */
61: public function headerText(array $opts = array())
62: {
63: $id = isset($opts['id'])
64: ? $opts['id']
65: : 0;
66: $this->_data[Horde_Imap_Client::FETCH_HEADERTEXT][$id] = $opts;
67: }
68:
69: /**
70: * Return body text.
71: *
72: * Body text is defined only for the base RFC 2822 message or
73: * message/rfc822 parts.
74: *
75: * @param array $opts The following options are available:
76: * - id: (string) The MIME ID to obtain the body text for.
77: * DEFAULT: The body text for the entire message will be
78: * returned.
79: * - length: (integer) The length of the substring to return.
80: * DEFAULT: The entire text is returned.
81: * - peek: (boolean) If set, does not set the '\Seen' flag on the
82: * message.
83: * DEFAULT: The seen flag is set.
84: * - start: (integer) If a portion of the full text is desired to be
85: * returned, the starting position is identified here.
86: * DEFAULT: The entire text is returned.
87: */
88: public function bodyText(array $opts = array())
89: {
90: $id = isset($opts['id'])
91: ? $opts['id']
92: : 0;
93: $this->_data[Horde_Imap_Client::FETCH_BODYTEXT][$id] = $opts;
94: }
95:
96: /**
97: * Return MIME header text.
98: *
99: * MIME header text is defined only for non-RFC 2822 messages and
100: * non-message/rfc822 parts.
101: *
102: * @param string $id The MIME ID to obtain the MIME header text for.
103: * @param array $opts The following options are available:
104: * - length: (integer) The length of the substring to return.
105: * DEFAULT: The entire text is returned.
106: * - peek: (boolean) If set, does not set the '\Seen' flag on the
107: * message.
108: * DEFAULT: The seen flag is set.
109: * - start: (integer) If a portion of the full text is desired to be
110: * returned, the starting position is identified here.
111: * DEFAULT: The entire text is returned.
112: */
113: public function mimeHeader($id, array $opts = array())
114: {
115: $this->_data[Horde_Imap_Client::FETCH_MIMEHEADER][$id] = $opts;
116: }
117:
118: /**
119: * Return the body part data for a MIME ID.
120: *
121: * @param string $id The MIME ID to obtain the body part text for.
122: * @param array $opts The following options are available:
123: * - decode: (boolean) Attempt to server-side decode the bodypart data
124: * if it is MIME transfer encoded.
125: * DEFAULT: false
126: * - length: (integer) The length of the substring to return.
127: * DEFAULT: The entire text is returned.
128: * - peek: (boolean) If set, does not set the '\Seen' flag on the
129: * message.
130: * DEFAULT: The seen flag is set.
131: * - start: (integer) If a portion of the full text is desired to be
132: * returned, the starting position is identified here.
133: * DEFAULT: The entire text is returned.
134: */
135: public function bodyPart($id, array $opts = array())
136: {
137: $this->_data[Horde_Imap_Client::FETCH_BODYPART][$id] = $opts;
138: }
139:
140: /**
141: * Returns the decoded body part size for a MIME ID.
142: *
143: * @param string $id The MIME ID to obtain the decoded body part size
144: * for.
145: */
146: public function bodyPartSize($id)
147: {
148: $this->_data[Horde_Imap_Client::FETCH_BODYPARTSIZE][$id] = true;
149: }
150:
151: /**
152: * Returns RFC 2822 header text that matches a search string.
153: *
154: * This header search work only with the base RFC 2822 message or
155: * message/rfc822 parts.
156: *
157: * @param string $label A unique label associated with this particular
158: * search. This is how the results are stored.
159: * @param array $search The search string(s) (case-insensitive).
160: * @param array $opts The following options are available:
161: * - cache: (boolean) If true, and 'peek' is also true, will cache
162: * the result of this call.
163: * DEFAULT: false
164: * - id: (string) The MIME ID to search.
165: * DEFAULT: The base message part
166: * - length: (integer) The length of the substring to return.
167: * DEFAULT: The entire text is returned.
168: * - notsearch: (boolean) Do a 'NOT' search on the headers.
169: * DEFAULT: false
170: * - peek: (boolean) If set, does not set the '\Seen' flag on the
171: * message.
172: * DEFAULT: The seen flag is set.
173: * - start: (integer) If a portion of the full text is desired to be
174: * returned, the starting position is identified here.
175: * DEFAULT: The entire text is returned.
176: */
177: public function headers($label, $search, array $opts = array())
178: {
179: $this->_data[Horde_Imap_Client::FETCH_HEADERS][$label] = array_merge($opts, array(
180: 'headers' => $search
181: ));
182: }
183:
184: /**
185: * Return MIME structure information.
186: */
187: public function structure()
188: {
189: $this->_data[Horde_Imap_Client::FETCH_STRUCTURE] = true;
190: }
191:
192: /**
193: * Return envelope header data.
194: */
195: public function envelope()
196: {
197: $this->_data[Horde_Imap_Client::FETCH_ENVELOPE] = true;
198: }
199:
200: /**
201: * Return flags set for the message.
202: */
203: public function flags()
204: {
205: $this->_data[Horde_Imap_Client::FETCH_FLAGS] = true;
206: }
207:
208: /**
209: * Return the internal (IMAP) date of the message.
210: */
211: public function imapDate()
212: {
213: $this->_data[Horde_Imap_Client::FETCH_IMAPDATE] = true;
214: }
215:
216: /**
217: * Return the size (in bytes) of the message.
218: */
219: public function size()
220: {
221: $this->_data[Horde_Imap_Client::FETCH_SIZE] = true;
222: }
223:
224: /**
225: * Return the unique ID of the message.
226: */
227: public function uid()
228: {
229: $this->_data[Horde_Imap_Client::FETCH_UID] = true;
230: }
231:
232: /**
233: * Return the sequence number of the message.
234: */
235: public function seq()
236: {
237: $this->_data[Horde_Imap_Client::FETCH_SEQ] = true;
238: }
239:
240: /**
241: * Return the mod-sequence value for the message.
242: *
243: * The server must support the CONDSTORE IMAP extension, and the mailbox
244: * must support mod-sequences.
245: */
246: public function modseq()
247: {
248: $this->_data[Horde_Imap_Client::FETCH_MODSEQ] = true;
249: }
250:
251: /**
252: * Does the query contain the given criteria?
253: *
254: * @param integer $criteria The criteria to remove.
255: *
256: * @return boolean True if the query contains the given criteria.
257: */
258: public function contains($criteria)
259: {
260: return isset($this->_data[$criteria]);
261: }
262:
263: /**
264: * Remove an entry under a given criteria.
265: *
266: * @param integer $criteria Criteria ID.
267: * @param string $key The key to remove.
268: */
269: public function remove($criteria, $key)
270: {
271: if (isset($this->_data[$criteria]) &&
272: is_array($this->_data[$criteria])) {
273: unset($this->_data[$criteria][$key]);
274: if (empty($this->_data[$criteria])) {
275: unset($this->_data[$criteria]);
276: }
277: }
278: }
279:
280: /**
281: * Returns a MD5 hash of the current query object.
282: *
283: * @return string MD5 hash.
284: */
285: public function hash()
286: {
287: return hash('md5', serialize($this));
288: }
289:
290: /* ArrayAccess methods. */
291:
292: /**
293: */
294: public function offsetExists($offset)
295: {
296: return isset($this->_data[$offset]);
297: }
298:
299: /**
300: */
301: public function offsetGet($offset)
302: {
303: return isset($this->_data[$offset])
304: ? $this->_data[$offset]
305: : null;
306: }
307:
308: /**
309: */
310: public function offsetSet($offset, $value)
311: {
312: $this->_data[$offset] = $value;
313: }
314:
315: /**
316: */
317: public function offsetUnset($offset)
318: {
319: unset($this->_data[$offset]);
320: }
321:
322: /* Countable methods. */
323:
324: /**
325: */
326: public function count()
327: {
328: return count($this->_data);
329: }
330:
331: /* Iterator methods. */
332:
333: /**
334: */
335: public function current()
336: {
337: $opts = current($this->_data);
338:
339: return (!empty($opts) && ($this->key() == Horde_Imap_Client::FETCH_BODYPARTSIZE))
340: ? array_keys($opts)
341: : $opts;
342: }
343:
344: /**
345: */
346: public function key()
347: {
348: return key($this->_data);
349: }
350:
351: /**
352: */
353: public function next()
354: {
355: next($this->_data);
356: }
357:
358: /**
359: */
360: public function rewind()
361: {
362: reset($this->_data);
363: }
364:
365: /**
366: */
367: public function valid()
368: {
369: return !is_null($this->key());
370: }
371:
372: }
373: