| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- <?php
- /*
- * File: Folder.php
- * Category: -
- * Author: M. Goldenbaum
- * Created: 19.01.17 22:21
- * Updated: -
- *
- * Description:
- * -
- */
- namespace Webklex\PHPIMAP;
- use Carbon\Carbon;
- use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
- use Webklex\PHPIMAP\Query\WhereQuery;
- use Webklex\PHPIMAP\Support\FolderCollection;
- use Webklex\PHPIMAP\Traits\HasEvents;
- /**
- * Class Folder
- *
- * @package Webklex\PHPIMAP
- */
- class Folder {
- use HasEvents;
- /**
- * Client instance
- *
- * @var Client
- */
- protected $client;
- /**
- * Folder full path
- *
- * @var string
- */
- public $path;
- /**
- * Folder name
- *
- * @var string
- */
- public $name;
- /**
- * Folder fullname
- *
- * @var string
- */
- public $full_name;
- /**
- * Children folders
- *
- * @var FolderCollection|array
- */
- public $children = [];
- /**
- * Delimiter for folder
- *
- * @var string
- */
- public $delimiter;
- /**
- * Indicates if folder can't containg any "children".
- * CreateFolder won't work on this folder.
- *
- * @var boolean
- */
- public $no_inferiors;
- /**
- * Indicates if folder is only container, not a mailbox - you can't open it.
- *
- * @var boolean
- */
- public $no_select;
- /**
- * Indicates if folder is marked. This means that it may contain new messages since the last time it was checked.
- * Not provided by all IMAP servers.
- *
- * @var boolean
- */
- public $marked;
- /**
- * Indicates if folder containg any "children".
- * Not provided by all IMAP servers.
- *
- * @var boolean
- */
- public $has_children;
- /**
- * Indicates if folder refers to other.
- * Not provided by all IMAP servers.
- *
- * @var boolean
- */
- public $referral;
- /**
- * Folder constructor.
- * @param Client $client
- * @param string $folder_name
- * @param string $delimiter
- * @param string[] $attributes
- */
- public function __construct(Client $client, $folder_name, $delimiter, $attributes) {
- $this->client = $client;
- $this->events["message"] = $client->getDefaultEvents("message");
- $this->events["folder"] = $client->getDefaultEvents("folder");
- $this->setDelimiter($delimiter);
- $this->path = $folder_name;
- $this->full_name = $this->decodeName($folder_name);
- $this->name = $this->getSimpleName($this->delimiter, $this->full_name);
- $this->parseAttributes($attributes);
- }
- /**
- * Get a new search query instance
- * @param string $charset
- *
- * @return WhereQuery
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function query($charset = 'UTF-8'){
- $this->getClient()->checkConnection();
- $this->getClient()->openFolder($this->path);
- return new WhereQuery($this->getClient(), $charset);
- }
- /**
- * @inheritdoc self::query($charset = 'UTF-8')
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function search($charset = 'UTF-8'){
- return $this->query($charset);
- }
- /**
- * @inheritdoc self::query($charset = 'UTF-8')
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function messages($charset = 'UTF-8'){
- return $this->query($charset);
- }
- /**
- * Determine if folder has children.
- *
- * @return bool
- */
- public function hasChildren() {
- return $this->has_children;
- }
- /**
- * Set children.
- * @param FolderCollection|array $children
- *
- * @return self
- */
- public function setChildren($children = []) {
- $this->children = $children;
- return $this;
- }
- /**
- * Decode name.
- * It converts UTF7-IMAP encoding to UTF-8.
- * @param $name
- *
- * @return mixed|string
- */
- protected function decodeName($name) {
- return mb_convert_encoding($name, "UTF-8", "UTF7-IMAP");
- }
- /**
- * Get simple name (without parent folders).
- * @param $delimiter
- * @param $full_name
- *
- * @return mixed
- */
- protected function getSimpleName($delimiter, $full_name) {
- $arr = explode($delimiter, $full_name);
- return end($arr);
- }
- /**
- * Parse attributes and set it to object properties.
- * @param $attributes
- */
- protected function parseAttributes($attributes) {
- $this->no_inferiors = in_array('\NoInferiors', $attributes) ? true : false;
- $this->no_select = in_array('\NoSelect', $attributes) ? true : false;
- $this->marked = in_array('\Marked', $attributes) ? true : false;
- $this->referral = in_array('\Referral', $attributes) ? true : false;
- $this->has_children = in_array('\HasChildren', $attributes) ? true : false;
- }
- /**
- * Move or rename the current folder
- * @param string $new_name
- * @param boolean $expunge
- *
- * @return bool
- * @throws ConnectionFailedException
- * @throws Exceptions\EventNotFoundException
- * @throws Exceptions\FolderFetchingException
- * @throws Exceptions\RuntimeException
- */
- public function move($new_name, $expunge = true) {
- $this->client->checkConnection();
- $status = $this->client->getConnection()->renameFolder($this->full_name, $new_name);
- if($expunge) $this->client->expunge();
- $folder = $this->client->getFolder($new_name);
- $event = $this->getEvent("folder", "moved");
- $event::dispatch($this, $folder);
- return $status;
- }
- /**
- * Get a message overview
- * @param string|null $sequence uid sequence
- *
- * @return array
- * @throws ConnectionFailedException
- * @throws Exceptions\InvalidMessageDateException
- * @throws Exceptions\MessageNotFoundException
- * @throws Exceptions\RuntimeException
- */
- public function overview($sequence = null){
- $this->client->openFolder($this->path);
- $sequence = $sequence === null ? "1:*" : $sequence;
- $uid = ClientManager::get('options.sequence', IMAP::ST_MSGN) == IMAP::ST_UID;
- return $this->client->getConnection()->overview($sequence, $uid);
- }
- /**
- * Append a string message to the current mailbox
- * @param string $message
- * @param string $options
- * @param string $internal_date
- *
- * @return bool
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function appendMessage($message, $options = null, $internal_date = null) {
- /**
- * Check if $internal_date is parsed. If it is null it should not be set. Otherwise the message can't be stored.
- * If this parameter is set, it will set the INTERNALDATE on the appended message. The parameter should be a
- * date string that conforms to the rfc2060 specifications for a date_time value or be a Carbon object.
- */
- if ($internal_date != null) {
- if ($internal_date instanceof Carbon){
- $internal_date = $internal_date->format('d-M-Y H:i:s O');
- }
- }
- return $this->client->getConnection()->appendMessage($this->full_name, $message, $options, $internal_date);
- }
- /**
- * Rename the current folder
- * @param string $new_name
- * @param boolean $expunge
- *
- * @return bool
- * @throws ConnectionFailedException
- * @throws Exceptions\EventNotFoundException
- * @throws Exceptions\FolderFetchingException
- * @throws Exceptions\RuntimeException
- */
- public function rename($new_name, $expunge = true) {
- return $this->move($new_name, $expunge);
- }
- /**
- * Delete the current folder
- * @param boolean $expunge
- *
- * @return bool
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- * @throws Exceptions\EventNotFoundException
- */
- public function delete($expunge = true) {
- $status = $this->client->getConnection()->deleteFolder($this->path);
- if($expunge) $this->client->expunge();
- $event = $this->getEvent("folder", "deleted");
- $event::dispatch($this);
- return $status;
- }
- /**
- * Subscribe the current folder
- *
- * @return bool
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function subscribe() {
- $this->client->openFolder($this->path);
- return $this->client->getConnection()->subscribeFolder($this->path);
- }
- /**
- * Unsubscribe the current folder
- *
- * @return bool
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function unsubscribe() {
- $this->client->openFolder($this->path);
- return $this->client->getConnection()->unsubscribeFolder($this->path);
- }
- /**
- * Idle the current connection
- * @param callable $callback
- * @param integer $timeout max 1740 seconds - recommended by rfc2177 §3
- * @param boolean $auto_reconnect try to reconnect on connection close
- *
- * @throws ConnectionFailedException
- * @throws Exceptions\InvalidMessageDateException
- * @throws Exceptions\MessageContentFetchingException
- * @throws Exceptions\MessageHeaderFetchingException
- * @throws Exceptions\RuntimeException
- * @throws Exceptions\EventNotFoundException
- * @throws Exceptions\MessageFlagException
- * @throws Exceptions\MessageNotFoundException
- */
- public function idle(callable $callback, $timeout = 1200, $auto_reconnect = false) {
- $this->client->getConnection()->setConnectionTimeout($timeout);
- $this->client->reconnect();
- $this->client->openFolder($this->path, true);
- $connection = $this->client->getConnection();
- $sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN);
- $connection->idle();
- while (true) {
- try {
- $line = $connection->nextLine();
- if (($pos = strpos($line, "EXISTS")) !== false) {
- $msgn = (int) substr($line, 2, $pos -2);
- $connection->done();
- $this->client->openFolder($this->path, true);
- $message = $this->query()->getMessageByMsgn($msgn);
- $message->setSequence($sequence);
- $callback($message);
- $event = $this->getEvent("message", "new");
- $event::dispatch($message);
- $connection->idle();
- }
- }catch (Exceptions\RuntimeException $e) {
- if(strpos($e->getMessage(), "connection closed") === false) {
- throw $e;
- }
- if ($auto_reconnect === true) {
- $this->client->reconnect();
- $this->client->openFolder($this->path, true);
- $connection = $this->client->getConnection();
- $connection->idle();
- }
- }
- }
- }
- /**
- * Get folder status information
- *
- * @return array|bool
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function getStatus() {
- return $this->examine();
- }
- /**
- * Examine the current folder
- *
- * @return array
- * @throws Exceptions\ConnectionFailedException
- * @throws Exceptions\RuntimeException
- */
- public function examine() {
- return $this->client->getConnection()->examineFolder($this->path);
- }
- /**
- * Get the current Client instance
- *
- * @return Client
- */
- public function getClient() {
- return $this->client;
- }
- /**
- * Set the delimiter
- * @param $delimiter
- */
- public function setDelimiter($delimiter){
- if(in_array($delimiter, [null, '', ' ', false]) === true) {
- $delimiter = ClientManager::get('options.delimiter', '/');
- }
- $this->delimiter = $delimiter;
- }
- }
|