1<?php
2/**
3 * The basic list query.
4 *
5 * PHP version 5
6 *
7 * @category Kolab
8 * @package  Kolab_Storage
9 * @author   Gunnar Wrobel <wrobel@pardus.de>
10 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
11 */
12
13/**
14 * The basic list query.
15 *
16 * Copyright 2010-2017 Horde LLC (http://www.horde.org/)
17 *
18 * See the enclosed file COPYING for license information (LGPL). If you
19 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
20 *
21 * @category Kolab
22 * @package  Kolab_Storage
23 * @author   Gunnar Wrobel <wrobel@pardus.de>
24 * @license  http://www.horde.org/licenses/lgpl21 LGPL 2.1
25 */
26class Horde_Kolab_Storage_List_Query_List_Base
27extends Horde_Kolab_Storage_List_Query_List
28{
29    /**
30     * The IMAP driver to query the backend.
31     *
32     * @var Horde_Kolab_Storage_Driver
33     */
34    private $_driver;
35
36    /**
37     * The factory for folder types.
38     *
39     * @var Horde_Kolab_Storage_Folder_Types
40     */
41    private $_folder_types;
42
43    /**
44     * Handles default folders.
45     *
46     * @var Horde_Kolab_Storage_List_Query_List_Defaults
47     */
48    private $_defaults;
49
50    /**
51     * Constructor.
52     *
53     * @param Horde_Kolab_Storage_Driver $driver The driver to access the backend.
54     * @param Horde_Kolab_Storage_Folder_Types $types Handler of folder types.
55     * @param Horde_Kolab_Storage_List_Query_List_Defaults $defaults Handler of defaults.
56     */
57    public function __construct(Horde_Kolab_Storage_Driver $driver,
58                                Horde_Kolab_Storage_Folder_Types $types,
59                                Horde_Kolab_Storage_List_Query_List_Defaults $defaults)
60    {
61        $this->_driver = $driver;
62        $this->_folder_types = $types;
63        $this->_defaults = $defaults;
64    }
65
66    /**
67     * Returns the folder type annotation as associative array.
68     *
69     * @return array The list folder types with the folder names as key and the
70     *               type handler as values.
71     */
72    private function listFolderTypeAnnotations()
73    {
74        $result = array();
75        foreach ($this->_driver->listAnnotation(self::ANNOTATION_FOLDER_TYPE) as $folder => $annotation) {
76            $result[$folder] = $this->_folder_types->create($annotation);
77        }
78        return $result;
79    }
80
81    /**
82     * Returns the folder types as associative array.
83     *
84     * @return array The list folder types with the folder names as key and the
85     *               type as values.
86     */
87    public function listTypes()
88    {
89        $result = array();
90        foreach ($this->listFolderTypeAnnotations() as $folder => $annotation) {
91            $result[$folder] = $annotation->getType();
92        }
93        return $result;
94    }
95
96    /**
97     * List all folders of a specific type.
98     *
99     * @param string $type The folder type the listing should be limited to.
100     *
101     * @return array The list of folders.
102     */
103    public function listByType($type)
104    {
105        $result = array();
106        foreach ($this->listTypes() as $folder => $folder_type) {
107            if ($folder_type == $type) {
108                $result[] = $folder;
109            }
110        }
111        return $result;
112    }
113
114    /**
115     * List basic folder data for the folders of a specific type.
116     *
117     * @param string $type The folder type the listing should be limited to.
118     *
119     * @return array The list of folders.
120     */
121    public function dataByType($type)
122    {
123        $result = array();
124        $namespace = $this->_driver->getNamespace();
125        foreach ($this->listFolderTypeAnnotations() as $folder => $folder_type) {
126            if ($folder_type->getType() == $type) {
127                $data = new Horde_Kolab_Storage_Folder_Data(
128                    $folder, $folder_type, $namespace
129                );
130                $result[$folder] = $data->toArray();
131            }
132        }
133        return $result;
134    }
135
136    /**
137     * List basic folder data for the specified folder.
138     *
139     * @param string $folder The folder path.
140     *
141     * @return array The folder data.
142     */
143    public function folderData($folder)
144    {
145        $list = $this->_driver->listFolders();
146        if (!in_array($folder, $list)) {
147            throw new Horde_Kolab_Storage_List_Exception(
148                sprintf('Folder %s does not exist!', $folder)
149            );
150        }
151        $annotations = $this->listFolderTypeAnnotations();
152        if (!isset($annotations[$folder])) {
153            $type = $this->_folder_types->create('mail');
154        } else {
155            $type = $annotations[$folder];
156        }
157        $data = new Horde_Kolab_Storage_Folder_Data(
158            $folder, $type, $this->_driver->getNamespace()
159        );
160        return $data->toArray();
161    }
162
163    /**
164     * Get the folder owners.
165     *
166     * @return array The folder owners with the folder names as key and the
167     *               owner as values.
168     */
169    public function listOwners()
170    {
171        $result = array();
172        $namespace = $this->_driver->getNamespace();
173        foreach ($this->_driver->listFolders() as $folder) {
174            $result[$folder] = $namespace->getOwner($folder);
175        }
176        return $result;
177    }
178
179    /**
180     * Set the specified folder as default for its current type.
181     *
182     * @param string $folder The folder name.
183     */
184    public function setDefault($folder)
185    {
186        $types = $this->listTypes();
187        if (!isset($types[$folder])) {
188            throw new Horde_Kolab_Storage_List_Exception(
189                sprintf(
190                    "The folder %s has no Kolab type. It cannot be marked as 'default' folder!",
191                    $folder
192                )
193            );
194        }
195        $previous = $this->getDefault($types[$folder]);
196        if ($previous) {
197            $this->_driver->setAnnotation($previous, self::ANNOTATION_FOLDER_TYPE, $types[$folder]);
198        }
199        $this->_driver->setAnnotation($folder, self::ANNOTATION_FOLDER_TYPE, $types[$folder] . '.default');
200    }
201
202    /**
203     * Return the list of personal default folders.
204     *
205     * @return array An array that associates type (key) with the corresponding
206     *               default folder name (value).
207     */
208    public function listPersonalDefaults()
209    {
210        return $this->_getPersonalDefaults();
211    }
212
213    /**
214     * Return the list of default folders.
215     *
216     * @return array An array with owners as keys and another array as
217     *               value. The second array associates type (key) with the
218     *               corresponding default folder (value).
219     */
220    public function listDefaults()
221    {
222        return $this->_getDefaults();
223    }
224
225    /**
226     * Get the default folder for a certain type.
227     *
228     * @param string $type The type of the share/folder.
229     *
230     * @return string|boolean The name of the default folder, false if there is no default.
231     */
232    public function getDefault($type)
233    {
234        $defaults = $this->_getPersonalDefaults();
235        if (!isset($defaults[$type])) {
236            return false;
237        } else {
238            return $defaults[$type];
239        }
240    }
241
242    /**
243     * Get the default folder for a certain type from a different owner.
244     *
245     * @param string $owner The folder owner.
246     * @param string $type  The type of the share/folder.
247     *
248     * @return string|boolean The name of the default folder, false if there is no default.
249     */
250    public function getForeignDefault($owner, $type)
251    {
252        $defaults = $this->_getDefaults();
253        if (!isset($defaults[$owner][$type])) {
254            return false;
255        } else {
256            return $defaults[$owner][$type];
257        }
258    }
259
260    /**
261     * Return the list of personal defaults.
262     */
263    private function _getPersonalDefaults()
264    {
265        $this->_initDefaults();
266        return $this->_defaults->getPersonalDefaults();
267    }
268
269    /**
270     * Return the complete list of defaults.
271     */
272    private function _getDefaults()
273    {
274        $this->_initDefaults();
275        return $this->_defaults->getDefaults();
276    }
277
278    /**
279     * Initialize the list of defaults.
280     */
281    private function _initDefaults()
282    {
283        if (!$this->_defaults->isComplete()) {
284            $namespace = $this->_driver->getNamespace();
285            foreach ($this->listFolderTypeAnnotations() as $folder => $annotation) {
286                if ($annotation->isDefault()) {
287                    $this->_defaults->rememberDefault(
288                        $folder,
289                        $annotation->getType(),
290                        $namespace->getOwner($folder),
291                        $namespace->matchNamespace($folder)->getType() == Horde_Kolab_Storage_Folder_Namespace::PERSONAL
292                    );
293                }
294            }
295            $this->_defaults->markComplete();
296        }
297    }
298
299    /**
300     * Return the last sync stamp.
301     *
302     * @return string The stamp.
303     */
304    public function getStamp()
305    {
306        return pack('Nn', time(), mt_rand());
307    }
308}