composer package updates
[openemr.git] / vendor / zendframework / zend-mail / src / Storage / Folder / Maildir.php
blob6eabd54214b9fda7c4ab30fb2036003658830e89
1 <?php
2 /**
3 * @see https://github.com/zendframework/zend-mail for the canonical source repository
4 * @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (https://www.zend.com)
5 * @license https://github.com/zendframework/zend-mail/blob/master/LICENSE.md New BSD License
6 */
8 namespace Zend\Mail\Storage\Folder;
10 use Zend\Mail\Storage;
11 use Zend\Mail\Storage\Exception;
12 use Zend\Stdlib\ErrorHandler;
14 class Maildir extends Storage\Maildir implements FolderInterface
16 /**
17 * root folder for folder structure
18 * @var Storage\Folder
20 protected $rootFolder;
22 /**
23 * rootdir of folder structure
24 * @var string
26 protected $rootdir;
28 /**
29 * name of current folder
30 * @var string
32 protected $currentFolder;
34 /**
35 * delim char for subfolders
36 * @var string
38 protected $delim;
40 /**
41 * Create instance with parameters
43 * Supported parameters are:
45 * - dirname rootdir of maildir structure
46 * - delim delim char for folder structure, default is '.'
47 * - folder initial selected folder, default is 'INBOX'
49 * @param $params array mail reader specific parameters
50 * @throws Exception\InvalidArgumentException
52 public function __construct($params)
54 if (is_array($params)) {
55 $params = (object) $params;
58 if (! isset($params->dirname) || ! is_dir($params->dirname)) {
59 throw new Exception\InvalidArgumentException('no valid dirname given in params');
62 $this->rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
64 $this->delim = isset($params->delim) ? $params->delim : '.';
66 $this->buildFolderTree();
67 $this->selectFolder(! empty($params->folder) ? $params->folder : 'INBOX');
68 $this->has['top'] = true;
69 $this->has['flags'] = true;
72 /**
73 * find all subfolders and mbox files for folder structure
75 * Result is save in Storage\Folder instances with the root in $this->rootFolder.
76 * $parentFolder and $parentGlobalName are only used internally for recursion.
78 * @throws Exception\RuntimeException
80 protected function buildFolderTree()
82 $this->rootFolder = new Storage\Folder('/', '/', false);
83 $this->rootFolder->INBOX = new Storage\Folder('INBOX', 'INBOX', true);
85 ErrorHandler::start(E_WARNING);
86 $dh = opendir($this->rootdir);
87 $error = ErrorHandler::stop();
88 if (! $dh) {
89 throw new Exception\RuntimeException("can't read folders in maildir", 0, $error);
91 $dirs = [];
93 while (($entry = readdir($dh)) !== false) {
94 // maildir++ defines folders must start with .
95 if ($entry[0] != '.' || $entry == '.' || $entry == '..') {
96 continue;
99 if ($this->_isMaildir($this->rootdir . $entry)) {
100 $dirs[] = $entry;
103 closedir($dh);
105 sort($dirs);
106 $stack = [null];
107 $folderStack = [null];
108 $parentFolder = $this->rootFolder;
109 $parent = '.';
111 foreach ($dirs as $dir) {
112 do {
113 if (strpos($dir, $parent) === 0) {
114 $local = substr($dir, strlen($parent));
115 if (strpos($local, $this->delim) !== false) {
116 throw new Exception\RuntimeException('error while reading maildir');
118 array_push($stack, $parent);
119 $parent = $dir . $this->delim;
120 $folder = new Storage\Folder($local, substr($dir, 1), true);
121 $parentFolder->$local = $folder;
122 array_push($folderStack, $parentFolder);
123 $parentFolder = $folder;
124 break;
125 } elseif ($stack) {
126 $parent = array_pop($stack);
127 $parentFolder = array_pop($folderStack);
129 } while ($stack);
130 if (! $stack) {
131 throw new Exception\RuntimeException('error while reading maildir');
137 * get root folder or given folder
139 * @param string $rootFolder get folder structure for given folder, else root
140 * @throws \Zend\Mail\Storage\Exception\InvalidArgumentException
141 * @return \Zend\Mail\Storage\Folder root or wanted folder
143 public function getFolders($rootFolder = null)
145 if (! $rootFolder || $rootFolder == 'INBOX') {
146 return $this->rootFolder;
149 // rootdir is same as INBOX in maildir
150 if (strpos($rootFolder, 'INBOX' . $this->delim) === 0) {
151 $rootFolder = substr($rootFolder, 6);
153 $currentFolder = $this->rootFolder;
154 $subname = trim($rootFolder, $this->delim);
156 while ($currentFolder) {
157 ErrorHandler::start(E_NOTICE);
158 list($entry, $subname) = explode($this->delim, $subname, 2);
159 ErrorHandler::stop();
160 $currentFolder = $currentFolder->$entry;
161 if (! $subname) {
162 break;
166 if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->delim)) {
167 throw new Exception\InvalidArgumentException("folder $rootFolder not found");
169 return $currentFolder;
173 * select given folder
175 * folder must be selectable!
177 * @param Storage\Folder|string $globalName global name of folder or
178 * instance for subfolder
179 * @throws Exception\RuntimeException
181 public function selectFolder($globalName)
183 $this->currentFolder = (string) $globalName;
185 // getting folder from folder tree for validation
186 $folder = $this->getFolders($this->currentFolder);
188 try {
189 $this->_openMaildir($this->rootdir . '.' . $folder->getGlobalName());
190 } catch (Exception\ExceptionInterface $e) {
191 // check what went wrong
192 if (! $folder->isSelectable()) {
193 throw new Exception\RuntimeException("{$this->currentFolder} is not selectable", 0, $e);
195 // seems like file has vanished; rebuilding folder tree - but it's still an exception
196 $this->buildFolderTree();
197 throw new Exception\RuntimeException(
198 'seems like the maildir has vanished; I have rebuilt the folder tree; '
199 . 'search for another folder and try again',
207 * get Storage\Folder instance for current folder
209 * @return Storage\Folder instance of current folder
211 public function getCurrentFolder()
213 return $this->currentFolder;