3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Mail\Storage\Folder
;
12 use Zend\Mail\Storage
;
13 use Zend\Mail\Storage\Exception
;
14 use Zend\Stdlib\ErrorHandler
;
16 class Maildir
extends Storage\Maildir
implements FolderInterface
19 * root folder for folder structure
20 * @var \Zend\Mail\Storage\Folder
22 protected $rootFolder;
25 * rootdir of folder structure
31 * name of current folder
34 protected $currentFolder;
37 * delim char for subfolders
43 * Create instance with parameters
44 * 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 \Zend\Mail\Storage\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;
73 * find all subfolders and mbox files for folder structure
75 * Result is save in \Zend\Mail\Storage\Folder instances with the root in $this->rootFolder.
76 * $parentFolder and $parentGlobalName are only used internally for recursion.
78 * @throws \Zend\Mail\Storage\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();
89 throw new Exception\
RuntimeException("can't read folders in maildir", 0, $error);
93 while (($entry = readdir($dh)) !== false) {
95 // maildir++ defines folders must start with .
96 if ($entry[0] != '.' ||
$entry == '.' ||
$entry == '..') {
100 if ($this->_isMaildir($this->rootdir
. $entry)) {
107 $stack = array(null);
108 $folderStack = array(null);
109 $parentFolder = $this->rootFolder
;
112 foreach ($dirs as $dir) {
114 if (strpos($dir, $parent) === 0) {
115 $local = substr($dir, strlen($parent));
116 if (strpos($local, $this->delim
) !== false) {
117 throw new Exception\
RuntimeException('error while reading maildir');
119 array_push($stack, $parent);
120 $parent = $dir . $this->delim
;
121 $folder = new Storage\
Folder($local, substr($dir, 1), true);
122 $parentFolder->$local = $folder;
123 array_push($folderStack, $parentFolder);
124 $parentFolder = $folder;
127 $parent = array_pop($stack);
128 $parentFolder = array_pop($folderStack);
132 throw new Exception\
RuntimeException('error while reading maildir');
138 * get root folder or given folder
140 * @param string $rootFolder get folder structure for given folder, else root
141 * @throws \Zend\Mail\Storage\Exception\InvalidArgumentException
142 * @return \Zend\Mail\Storage\Folder root or wanted folder
144 public function getFolders($rootFolder = null)
146 if (!$rootFolder ||
$rootFolder == 'INBOX') {
147 return $this->rootFolder
;
150 // rootdir is same as INBOX in maildir
151 if (strpos($rootFolder, 'INBOX' . $this->delim
) === 0) {
152 $rootFolder = substr($rootFolder, 6);
154 $currentFolder = $this->rootFolder
;
155 $subname = trim($rootFolder, $this->delim
);
157 while ($currentFolder) {
158 ErrorHandler
::start(E_NOTICE
);
159 list($entry, $subname) = explode($this->delim
, $subname, 2);
160 ErrorHandler
::stop();
161 $currentFolder = $currentFolder->$entry;
167 if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->delim
)) {
168 throw new Exception\
InvalidArgumentException("folder $rootFolder not found");
170 return $currentFolder;
174 * select given folder
176 * folder must be selectable!
178 * @param \Zend\Mail\Storage\Folder|string $globalName global name of folder or instance for subfolder
179 * @throws \Zend\Mail\Storage\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
);
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('seems like the maildir has vanished, I\'ve rebuild the ' .
198 'folder tree, search for an other folder and try again', 0, $e);
203 * get \Zend\Mail\Storage\Folder instance for current folder
205 * @return \Zend\Mail\Storage\Folder instance of current folder
207 public function getCurrentFolder()
209 return $this->currentFolder
;