1<?php
2/**
3 * Copyright 2013-2017 Horde LLC (http://www.horde.org/)
4 *
5 * See the enclosed file COPYING for license information (LGPL). If you
6 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
7 *
8 * @category  Horde
9 * @copyright 2013-2017 Horde LLC
10 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 * @package   Imap_Client
12 */
13
14/**
15 * An object representing a series of IMAP client commands (RFC 3501 [2.2.1])
16 * to be processed at the same time.
17 *
18 * @author    Michael Slusarz <slusarz@horde.org>
19 * @category  Horde
20 * @copyright 2013-2017 Horde LLC
21 * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
22 * @package   Imap_Client
23 * @since     2.10.0
24 *
25 * @property-read boolean $finished  True if all commands have finished.
26 */
27class Horde_Imap_Client_Interaction_Pipeline implements Countable, IteratorAggregate
28{
29    /**
30     * Data storage from server responses.
31     *
32     * @var array
33     */
34    public $data = array(
35        'modseqs' => array(),
36        'modseqs_nouid' => array()
37    );
38
39    /**
40     * Fetch results.
41     *
42     * @var Horde_Imap_Client_Fetch_Results
43     */
44    public $fetch;
45
46    /**
47     * The list of commands.
48     *
49     * @var array
50     */
51    protected $_commands = array();
52
53    /**
54     * The list of commands to complete.
55     *
56     * @var array
57     */
58    protected $_todo = array();
59
60    /**
61     * Constructor.
62     *
63     * @param Horde_Imap_Client_Fetch_Results $fetch  Fetch results object.
64     */
65    public function __construct(Horde_Imap_Client_Fetch_Results $fetch)
66    {
67        $this->fetch = $fetch;
68    }
69
70    /**
71     */
72    public function __get($name)
73    {
74        switch ($name) {
75        case 'finished':
76            return empty($this->_todo);
77        }
78    }
79
80    /**
81     * Add a command to the pipeline.
82     *
83     * @param Horde_Imap_Client_Interaction_Command $cmd  Command object.
84     * @param boolean $top                                Add command to top
85     *                                                    of queue?
86     */
87    public function add(Horde_Imap_Client_Interaction_Command $cmd,
88                        $top = false)
89    {
90        if ($top) {
91            // This won't re-index keys, which may be numerical.
92            $this->_commands = array($cmd->tag => $cmd) + $this->_commands;
93        } else {
94            $this->_commands[$cmd->tag] = $cmd;
95        }
96        $this->_todo[$cmd->tag] = true;
97    }
98
99    /**
100     * Mark a command as completed.
101     *
102     * @param Horde_Imap_Client_Interaction_Server_Tagged $resp  Tagged server
103     *                                                           response.
104     *
105     * @return Horde_Imap_Client_Interaction_Command  Command that was
106     *                                                completed. Returns null
107     *                                                if tagged response
108     *                                                is not contained in this
109     *                                                pipeline object.
110     */
111    public function complete(Horde_Imap_Client_Interaction_Server_Tagged $resp)
112    {
113        if (isset($this->_commands[$resp->tag])) {
114            $cmd = $this->_commands[$resp->tag];
115            $cmd->response = $resp;
116            unset($this->_todo[$resp->tag]);
117        } else {
118            /* This can be reached if a previous pipeline action was aborted,
119             * e.g. via an Exception. */
120            $cmd = null;
121        }
122
123        return $cmd;
124    }
125
126    /**
127     * Return the command for a given tag.
128     *
129     * @param string $tag  The command tag.
130     *
131     * @return Horde_Imap_Client_Interaction_Command  A command object (or
132     *                                                null if the tag does
133     *                                                not exist).
134     */
135    public function getCmd($tag)
136    {
137        return isset($this->_commands[$tag])
138            ? $this->_commands[$tag]
139            : null;
140    }
141
142    /* Countable methods. */
143
144    /**
145     */
146    public function count()
147    {
148        return count($this->_commands);
149    }
150
151    /* IteratorAggregate methods. */
152
153    /**
154     */
155    public function getIterator()
156    {
157        return new ArrayIterator($this->_commands);
158    }
159
160}
161