/libraries/Zend/Mail/Storage/Folder/Mbox.php

https://github.com/kiranatama/sagalaya · PHP · 213 lines · 133 code · 15 blank · 65 comment · 6 complexity · c789d7de75d0dec656299066da144c99 MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. * @package Zend_Mail
  9. */
  10. namespace Zend\Mail\Storage\Folder;
  11. use Zend\Mail\Storage;
  12. use Zend\Mail\Storage\Exception;
  13. use Zend\Stdlib\ErrorHandler;
  14. /**
  15. * @category Zend
  16. * @package Zend_Mail
  17. * @subpackage Storage
  18. */
  19. class Mbox extends Storage\Mbox implements FolderInterface
  20. {
  21. /**
  22. * \Zend\Mail\Storage\Folder root folder for folder structure
  23. * @var \Zend\Mail\Storage\Folder
  24. */
  25. protected $_rootFolder;
  26. /**
  27. * rootdir of folder structure
  28. * @var string
  29. */
  30. protected $_rootdir;
  31. /**
  32. * name of current folder
  33. * @var string
  34. */
  35. protected $_currentFolder;
  36. /**
  37. * Create instance with parameters
  38. *
  39. * Disallowed parameters are:
  40. * - filename use \Zend\Mail\Storage\Mbox for a single file
  41. * Supported parameters are:
  42. * - dirname rootdir of mbox structure
  43. * - folder intial selected folder, default is 'INBOX'
  44. *
  45. * @param $params array mail reader specific parameters
  46. * @throws \Zend\Mail\Storage\Exception\InvalidArgumentException
  47. */
  48. public function __construct($params)
  49. {
  50. if (is_array($params)) {
  51. $params = (object)$params;
  52. }
  53. if (isset($params->filename)) {
  54. throw new Exception\InvalidArgumentException('use \Zend\Mail\Storage\Mbox for a single file');
  55. }
  56. if (!isset($params->dirname) || !is_dir($params->dirname)) {
  57. throw new Exception\InvalidArgumentException('no valid dirname given in params');
  58. }
  59. $this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
  60. $this->_buildFolderTree($this->_rootdir);
  61. $this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
  62. $this->_has['top'] = true;
  63. $this->_has['uniqueid'] = false;
  64. }
  65. /**
  66. * find all subfolders and mbox files for folder structure
  67. *
  68. * Result is save in \Zend\Mail\Storage\Folder instances with the root in $this->_rootFolder.
  69. * $parentFolder and $parentGlobalName are only used internally for recursion.
  70. *
  71. * @param string $currentDir call with root dir, also used for recursion.
  72. * @param \Zend\Mail\Storage\Folder|null $parentFolder used for recursion
  73. * @param string $parentGlobalName used for recursion
  74. * @throws \Zend\Mail\Storage\Exception\InvalidArgumentException
  75. */
  76. protected function _buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '')
  77. {
  78. if (!$parentFolder) {
  79. $this->_rootFolder = new Storage\Folder('/', '/', false);
  80. $parentFolder = $this->_rootFolder;
  81. }
  82. ErrorHandler::start(E_WARNING);
  83. $dh = opendir($currentDir);
  84. ErrorHandler::stop();
  85. if (!$dh) {
  86. throw new Exception\InvalidArgumentException("can't read dir $currentDir");
  87. }
  88. while (($entry = readdir($dh)) !== false) {
  89. // ignore hidden files for mbox
  90. if ($entry[0] == '.') {
  91. continue;
  92. }
  93. $absoluteEntry = $currentDir . $entry;
  94. $globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry;
  95. if (is_file($absoluteEntry) && $this->_isMboxFile($absoluteEntry)) {
  96. $parentFolder->$entry = new Storage\Folder($entry, $globalName);
  97. continue;
  98. }
  99. if (!is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) {
  100. continue;
  101. }
  102. $folder = new Storage\Folder($entry, $globalName, false);
  103. $parentFolder->$entry = $folder;
  104. $this->_buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName);
  105. }
  106. closedir($dh);
  107. }
  108. /**
  109. * get root folder or given folder
  110. *
  111. * @param string $rootFolder get folder structure for given folder, else root
  112. * @throws \Zend\Mail\Storage\Exception\InvalidArgumentException
  113. * @return \Zend\Mail\Storage\Folder root or wanted folder
  114. */
  115. public function getFolders($rootFolder = null)
  116. {
  117. if (!$rootFolder) {
  118. return $this->_rootFolder;
  119. }
  120. $currentFolder = $this->_rootFolder;
  121. $subname = trim($rootFolder, DIRECTORY_SEPARATOR);
  122. while ($currentFolder) {
  123. ErrorHandler::start(E_NOTICE);
  124. list($entry, $subname) = explode(DIRECTORY_SEPARATOR, $subname, 2);
  125. ErrorHandler::stop();
  126. $currentFolder = $currentFolder->$entry;
  127. if (!$subname) {
  128. break;
  129. }
  130. }
  131. if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) {
  132. throw new Exception\InvalidArgumentException("folder $rootFolder not found");
  133. }
  134. return $currentFolder;
  135. }
  136. /**
  137. * select given folder
  138. *
  139. * folder must be selectable!
  140. *
  141. * @param \Zend\Mail\Storage\Folder|string $globalName global name of folder or instance for subfolder
  142. * @throws \Zend\Mail\Storage\Exception\RuntimeException
  143. */
  144. public function selectFolder($globalName)
  145. {
  146. $this->_currentFolder = (string)$globalName;
  147. // getting folder from folder tree for validation
  148. $folder = $this->getFolders($this->_currentFolder);
  149. try {
  150. $this->_openMboxFile($this->_rootdir . $folder->getGlobalName());
  151. } catch(Exception\ExceptionInterface $e) {
  152. // check what went wrong
  153. if (!$folder->isSelectable()) {
  154. throw new Exception\RuntimeException("{$this->_currentFolder} is not selectable", 0, $e);
  155. }
  156. // seems like file has vanished; rebuilding folder tree - but it's still an exception
  157. $this->_buildFolderTree($this->_rootdir);
  158. throw new Exception\RuntimeException('seems like the mbox file has vanished, I\'ve rebuild the ' .
  159. 'folder tree, search for an other folder and try again', 0, $e);
  160. }
  161. }
  162. /**
  163. * get \Zend\Mail\Storage\Folder instance for current folder
  164. *
  165. * @return \Zend\Mail\Storage\Folder instance of current folder
  166. * @throws \Zend\Mail\Storage\Exception\ExceptionInterface
  167. */
  168. public function getCurrentFolder()
  169. {
  170. return $this->_currentFolder;
  171. }
  172. /**
  173. * magic method for serialize()
  174. *
  175. * with this method you can cache the mbox class
  176. *
  177. * @return array name of variables
  178. */
  179. public function __sleep()
  180. {
  181. return array_merge(parent::__sleep(), array('_currentFolder', '_rootFolder', '_rootdir'));
  182. }
  183. /**
  184. * magic method for unserialize(), with this method you can cache the mbox class
  185. */
  186. public function __wakeup()
  187. {
  188. // if cache is stall selectFolder() rebuilds the tree on error
  189. parent::__wakeup();
  190. }
  191. }