mailbox, messageiterator and message class connected

This commit is contained in:
Clivern 2017-08-11 22:56:23 +02:00
parent bf6fb8c3ed
commit f7faa6541d
10 changed files with 612 additions and 537 deletions

View file

@ -15,261 +15,268 @@ use Clivern\Imap\Core\Exception\ConnectionError;
class Connection class Connection
{ {
/** /**
* @var string * @var string
*/ */
protected $server; protected $server;
/** /**
* @var integer * @var integer
*/ */
protected $port; protected $port;
/** /**
* @var string * @var string
*/ */
protected $email; protected $email;
/** /**
* @var string * @var string
*/ */
protected $password; protected $password;
/** /**
* @var string * @var string
*/ */
protected $flag; protected $flag;
/** /**
* @var string * @var string
*/ */
protected $folder; protected $folder;
/** /**
* @var mixed * @var mixed
*/ */
protected $stream; protected $stream;
/** /**
* @var mixed * @var mixed
*/ */
protected $timeout_type; protected $timeout_type;
/** /**
* @var mixed * @var mixed
*/ */
protected $timeout; protected $timeout;
/** /**
* Class Constructor * Class Constructor
* *
* @param string $server * @param string $server
* @param string $port * @param string $port
* @param string $email * @param string $email
* @param string $password * @param string $password
* @param string $flag * @param string $flag
* @param string $folder * @param string $folder
* @return void * @return void
*/ */
public function __construct($server, $port, $email, $password, $flag = "/ssl", $folder = "INBOX") public function __construct($server, $port, $email, $password, $flag = "/ssl", $folder = "INBOX")
{ {
$this->server = $server; $this->server = $server;
$this->port = $port; $this->port = $port;
$this->email = $email; $this->email = $email;
$this->password = $password; $this->password = $password;
$this->flag = $flag; $this->flag = $flag;
$this->folder = $folder; $this->folder = $folder;
} }
/** /**
* Connect to IMAP Email * Connect to IMAP Email
* *
* @return Connection * @return Connection
* @throws ConnectionError * @throws ConnectionError
*/ */
public function connect() public function connect()
{ {
try { try {
$this->stream = imap_open("{" . $this->server . ":" . $this->port . $this->flag . "}" . $this->folder, $this->email, $this->password); $this->stream = imap_open("{" . $this->server . ":" . $this->port . $this->flag . "}" . $this->folder, $this->email, $this->password);
} catch (\Exception $e) { } catch (\Exception $e) {
throw new ConnectionError("Error! Connecting to Imap Email."); throw new ConnectionError("Error! Connecting to Imap Email.");
} }
return $this; return $this;
} }
public function reconnect($folder) public function reconnect($folder = "INBOX")
{ {
try { try {
imap_reopen($this->stream, "{" . $this->server . ":" . $this->port . $this->flag . "}" . $folder); imap_reopen($this->stream, "{" . $this->server . ":" . $this->port . $this->flag . "}" . $folder);
} catch (\Exception $e) { } catch (\Exception $e) {
throw new ConnectionError("Error! Connecting to Imap Email."); throw new ConnectionError("Error! Connecting to Imap Email.");
} }
} }
/** public function survive($folder = "INBOX")
* Set Timeout {
* if( !$this->ping() || ($this->folder != $folder) ) {
* @param string $timeout_type it may be IMAP_OPENTIMEOUT, IMAP_READTIMEOUT, IMAP_WRITETIMEOUT, or IMAP_CLOSETIMEOUT $this->reconnect($folder);
* @param integer $timeout time in seconds or -1 }
* @return void }
*/
public function setTimeout($timeout_type, $timeout)
{
$this->timeout_type = $timeout_type;
$this->timeout = $timeout;
return (boolean) imap_timeout($timeout_type, $timeout); /**
} * Set Timeout
*
* @param string $timeout_type it may be IMAP_OPENTIMEOUT, IMAP_READTIMEOUT, IMAP_WRITETIMEOUT, or IMAP_CLOSETIMEOUT
* @param integer $timeout time in seconds or -1
* @return void
*/
public function setTimeout($timeout_type, $timeout)
{
$this->timeout_type = $timeout_type;
$this->timeout = $timeout;
/** return (boolean) imap_timeout($timeout_type, $timeout);
* Get Stream }
*
* @return mixed
*/
public function getStream()
{
return $this->stream;
}
/** /**
* Get Server * Get Stream
* *
* @return string * @return mixed
*/ */
public function getServer() public function getStream()
{ {
return $this->server; return $this->stream;
} }
/** /**
* Check Connection * Get Server
* *
* @return boolean * @return string
*/ */
public function checkConnection() public function getServer()
{ {
return (!is_null($this->stream) && imap_ping($this->stream)); return $this->server;
} }
/** /**
* Get Quota * Check Connection
* *
* @param string $folder * @return boolean
* @return array */
*/ public function checkConnection()
public function getQuota($folder = 'INBOX') {
{ return (!is_null($this->stream) && imap_ping($this->stream));
$data = imap_get_quotaroot($this->stream, $folder); }
return [ /**
'usage' => (isset($data['usage'])) ? $data['usage'] : false, * Get Quota
'limit' => (isset($data['limit'])) ? $data['limit'] : false *
]; * @param string $folder
} * @return array
*/
public function getQuota($folder = 'INBOX')
{
$data = imap_get_quotaroot($this->stream, $folder);
/** return [
* Get Status 'usage' => (isset($data['usage'])) ? $data['usage'] : false,
* 'limit' => (isset($data['limit'])) ? $data['limit'] : false
* @param string $folder ];
* @param string $flag }
* @return array
*/
public function getStatus($folder = 'INBOX', $flag = SA_ALL)
{
$data = imap_status($this->stream, "{" . $this->server . "}" . $folder, $flag);
return [ /**
'flags' => (isset($data->flags)) ? $data->flags : false, * Get Status
'messages' => (isset($data->messages)) ? $data->messages : false, *
'recent' => (isset($data->recent)) ? $data->recent : false, * @param string $folder
'unseen' => (isset($data->unseen)) ? $data->unseen : false, * @param string $flag
'uidnext' => (isset($data->uidnext)) ? $data->uidnext : false, * @return array
'uidvalidity' => (isset($data->uidvalidity)) ? $data->uidvalidity : false */
]; public function getStatus($folder = 'INBOX', $flag = SA_ALL)
} {
$data = imap_status($this->stream, "{" . $this->server . "}" . $folder, $flag);
/** return [
* Check MailBox Data 'flags' => (isset($data->flags)) ? $data->flags : false,
* 'messages' => (isset($data->messages)) ? $data->messages : false,
* @return array 'recent' => (isset($data->recent)) ? $data->recent : false,
*/ 'unseen' => (isset($data->unseen)) ? $data->unseen : false,
public function check() 'uidnext' => (isset($data->uidnext)) ? $data->uidnext : false,
{ 'uidvalidity' => (isset($data->uidvalidity)) ? $data->uidvalidity : false
$data = imap_check($this->stream); ];
}
return [ /**
'date' => (isset($data->Date)) ? $data->Date : false, * Check MailBox Data
'driver' => (isset($data->Driver)) ? $data->Driver : false, *
'mailbox' => (isset($data->Mailbox)) ? $data->Mailbox : false, * @return array
'nmsgs' => (isset($data->Nmsgs)) ? $data->Nmsgs : false, */
'recent' => (isset($data->Recent)) ? $data->Recent : false public function check()
]; {
} $data = imap_check($this->stream);
/** return [
* Ping Connection 'date' => (isset($data->Date)) ? $data->Date : false,
* 'driver' => (isset($data->Driver)) ? $data->Driver : false,
* @return boolean 'mailbox' => (isset($data->Mailbox)) ? $data->Mailbox : false,
*/ 'nmsgs' => (isset($data->Nmsgs)) ? $data->Nmsgs : false,
public function ping() 'recent' => (isset($data->Recent)) ? $data->Recent : false
{ ];
return (boolean) imap_ping($this->stream); }
}
/** /**
* Get Errors * Ping Connection
* *
* @return array * @return boolean
*/ */
public function getErrors() public function ping()
{ {
$errors = imap_errors(); return (boolean) imap_ping($this->stream);
}
return (is_array($errors)) ? $errors : []; /**
} * Get Errors
*
* @return array
*/
public function getErrors()
{
$errors = imap_errors();
/** return (is_array($errors)) ? $errors : [];
* Get Alerts }
*
* @return array
*/
public function getAlerts()
{
$alerts = imap_alerts();
return (is_array($alerts)) ? $alerts : []; /**
} * Get Alerts
*
* @return array
*/
public function getAlerts()
{
$alerts = imap_alerts();
/** return (is_array($alerts)) ? $alerts : [];
* Get Last Error }
*
* @return string
*/
public function getLastError()
{
$error = imap_last_error();
return !(empty($error)) ? $error : ''; /**
} * Get Last Error
*
* @return string
*/
public function getLastError()
{
$error = imap_last_error();
/** return !(empty($error)) ? $error : '';
* Disconnect }
*
* @param integer $flag
* @return boolean
*/
public function disconnect($flag = 0)
{
if( !is_null($this->stream) && imap_ping($this->stream) ){
if( imap_close($this->stream, $flag) ){
$this->stream = null;
return true;
}else{
return false;
}
}
return false; /**
} * Disconnect
*
* @param integer $flag
* @return boolean
*/
public function disconnect($flag = 0)
{
if( !is_null($this->stream) && imap_ping($this->stream) ){
if( imap_close($this->stream, $flag) ){
$this->stream = null;
return true;
}else{
return false;
}
}
return false;
}
} }

View file

@ -1,16 +0,0 @@
<?php
/**
* @author clivern <hello@clivern.com>
*/
namespace Clivern\Imap\Core;
/**
* Folder Class
*
* @package Clivern\Imap\Core
*/
class Folder
{
#~
}

View file

@ -14,203 +14,203 @@ use Clivern\Imap\Core\Connection;
*/ */
class Message class Message
{ {
/** /**
* @var Connection * @var Connection
*/ */
protected $connection; protected $connection;
/** /**
* @var integer * @var integer
*/ */
protected $uid; protected $uid;
/** /**
* @var integer * @var integer
*/ */
protected $msg_number; protected $msg_number;
/** /**
* Message Constructor * Message Constructor
* *
* @param Connection $connection * @param Connection $connection
*/ */
public function __construct(Connection $connection) public function __construct(Connection $connection)
{ {
$this->connection = $connection; $this->connection = $connection;
} }
/** /**
* Set Message Number * Set Message Number
* *
* @param integer $id * @param integer $id
* @return Message * @return Message
*/ */
public function setMsgNo($msg_number) public function setMsgNo($msg_number)
{ {
$this->msg_number = $msg_number; $this->msg_number = $msg_number;
return $this; return $this;
} }
/** /**
* Get Message Number * Get Message Number
* *
* @return integer * @return integer
*/ */
public function getMsgNo() public function getMsgNo()
{ {
return $this->msg_number; return $this->msg_number;
} }
/** /**
* Set UID * Set UID
* *
* @param integer $uid * @param integer $uid
* @return Message * @return Message
*/ */
public function setUid($uid) public function setUid($uid)
{ {
$this->uid = $uid; $this->uid = $uid;
return $this; return $this;
} }
/** /**
* Get UID * Get UID
* *
* @return integer * @return integer
*/ */
public function getUid() public function getUid()
{ {
return $this->uid; return $this->uid;
} }
/** /**
* Config Message Number & UID * Config Message Number & UID
* *
* @return Message * @return Message
*/ */
public function config() public function config()
{ {
if( !this->msg_number && $this->uid ){ if( !$this->msg_number && $this->uid ){
$this->msg_number = imap_msgno($this->connection->getStream(), $this->uid); $this->msg_number = imap_msgno($this->connection->getStream(), $this->uid);
} }
if( !this->uid && $this->msg_number ){ if( !$this->uid && $this->msg_number ){
$this->uid = imap_uid($this->connection->getStream(), $this->msg_number); $this->uid = imap_uid($this->connection->getStream(), $this->msg_number);
} }
return $this; return $this;
} }
/** /**
* Get Body * Get Body
* *
* @param integer $options * @param integer $options
* @return string * @return string
*/ */
public function getBody($options = 0) public function getBody($options = 0)
{ {
$body = imap_body($this->connection->getStream(), $this->msg_number, $options); $body = imap_body($this->connection->getStream(), $this->msg_number, $options);
return $body; return $body;
} }
/** /**
* Parse Address List * Parse Address List
* *
* @param string $address_string * @param string $address_string
* @return array * @return array
*/ */
public function parseAddressList($address_string, $default_host = "example.com") public function parseAddressList($address_string, $default_host = "example.com")
{ {
$address_array = imap_rfc822_parse_adrlist($address_string, $default_host); $address_array = imap_rfc822_parse_adrlist($address_string, $default_host);
$address_list = []; $address_list = [];
foreach ($address_array as $id => $val) { foreach ($address_array as $id => $val) {
$address_list[] = [ $address_list[] = [
'mailbox' => $val->mailbox, 'mailbox' => $val->mailbox,
'host' => $val->host, 'host' => $val->host,
'personal' => $val->personal, 'personal' => $val->personal,
'adl' => $val->adl 'adl' => $val->adl
]; ];
} }
return $address_list; return $address_list;
} }
/** /**
* Fetch Body * Fetch Body
* *
* @param mixed $section * @param mixed $section
* @param mixed $options * @param mixed $options
* @return string * @return string
*/ */
public function fetchBody($section = 0, $options = 0) public function fetchBody($section = 0, $options = 0)
{ {
return imap_fetchbody($this->connection->getStream(), $this->msg_number, $section, $options); return imap_fetchbody($this->connection->getStream(), $this->msg_number, $section, $options);
} }
/** /**
* Fetch Overview * Fetch Overview
* *
* @param boolean $sequence * @param boolean $sequence
* @param mixed $options * @param mixed $options
* @return array * @return array
*/ */
public function fetchOverview($sequence = false, $options = 0) public function fetchOverview($sequence = false, $options = 0)
{ {
if( $sequence == false ){ if( $sequence == false ){
$overview = imap_fetch_overview($this->connection->getStream(), $this->msg_number, $options); $overview = imap_fetch_overview($this->connection->getStream(), $this->msg_number, $options);
}else{ }else{
$overview = imap_fetch_overview($this->connection->getStream(), $sequence, $options); $overview = imap_fetch_overview($this->connection->getStream(), $sequence, $options);
} }
$items_overview = []; $items_overview = [];
foreach ($overview as $key => $item_overview) { foreach ($overview as $key => $item_overview) {
$items_overview[] = [ $items_overview[] = [
'subject' => (isset($item_overview->subject)) ? $item_overview->subject : false, 'subject' => (isset($item_overview->subject)) ? $item_overview->subject : false,
'from' => (isset($item_overview->from)) ? $item_overview->from : false, 'from' => (isset($item_overview->from)) ? $item_overview->from : false,
'to' => (isset($item_overview->to)) ? $item_overview->to : false, 'to' => (isset($item_overview->to)) ? $item_overview->to : false,
'date' => (isset($item_overview->date)) ? $item_overview->date : false, 'date' => (isset($item_overview->date)) ? $item_overview->date : false,
'message_id' => (isset($item_overview->message_id)) ? $item_overview->message_id : false, 'message_id' => (isset($item_overview->message_id)) ? $item_overview->message_id : false,
'size' => (isset($item_overview->size)) ? $item_overview->size : false, 'size' => (isset($item_overview->size)) ? $item_overview->size : false,
'uid' => (isset($item_overview->uid)) ? $item_overview->uid : false, 'uid' => (isset($item_overview->uid)) ? $item_overview->uid : false,
'msgno' => (isset($item_overview->msgno)) ? $item_overview->msgno : false, 'msgno' => (isset($item_overview->msgno)) ? $item_overview->msgno : false,
'recent' => (isset($item_overview->recent)) ? $item_overview->recent : false, 'recent' => (isset($item_overview->recent)) ? $item_overview->recent : false,
'flagged' => (isset($item_overview->flagged)) ? $item_overview->flagged : false, 'flagged' => (isset($item_overview->flagged)) ? $item_overview->flagged : false,
'answered' => (isset($item_overview->answered)) ? $item_overview->answered : false, 'answered' => (isset($item_overview->answered)) ? $item_overview->answered : false,
'deleted' => (isset($item_overview->deleted)) ? $item_overview->deleted : false, 'deleted' => (isset($item_overview->deleted)) ? $item_overview->deleted : false,
'seen' => (isset($item_overview->seen)) ? $item_overview->seen : false, 'seen' => (isset($item_overview->seen)) ? $item_overview->seen : false,
'draft' => (isset($item_overview->draft)) ? $item_overview->draft : false, 'draft' => (isset($item_overview->draft)) ? $item_overview->draft : false,
'udate' => (isset($item_overview->udate)) ? $item_overview->udate : false 'udate' => (isset($item_overview->udate)) ? $item_overview->udate : false
]; ];
} }
return $items_overview; return $items_overview;
} }
/** /**
* Fetch Header * Fetch Header
* *
* @param mixed $options * @param mixed $options
* @return string * @return string
*/ */
public function fetchHeader($options = 0) public function fetchHeader($options = 0)
{ {
return imap_fetchheader($this->connection->getStream(), $this->msg_number, $options); return imap_fetchheader($this->connection->getStream(), $this->msg_number, $options);
} }
/** /**
* Fetch Structure * Fetch Structure
* *
* @param mixed $options * @param mixed $options
* @return stdClass * @return stdClass
*/ */
public function fetchStructure($options = 0) public function fetchStructure($options = 0)
{ {
$structure = imap_fetchstructure($connection->getStream(), $this->msg_number, $options); $structure = imap_fetchstructure($connection->getStream(), $this->msg_number, $options);
return $structure; return $structure;
} }
} }

View file

@ -6,61 +6,38 @@
namespace Clivern\Imap\Core; namespace Clivern\Imap\Core;
use Clivern\Imap\Core\Message; use Clivern\Imap\Core\Message;
use Clivern\Imap\Core\Connection;
/** /**
* Message Iterator Class * Message Iterator Class
* *
* @package Clivern\Imap\Core * @package Clivern\Imap\Core
*/ */
class MessageIterator class MessageIterator extends \ArrayIterator
{ {
/** protected $connection;
* @var array
*/
protected $messages = [];
/** /**
* Add Message * Constructor
* *
* @param Message $message * @param Connection $connection
* @return void * @param array $message_numbers
*/ */
public function add(Message $message) public function __construct(Connection $connection, array $message_numbers)
{ {
$this->messages[$message->getId()] = $message; $this->connection = $connection;
} parent::__construct($message_numbers);
}
/** /**
* Check if Message Exists * Get current message
* *
* @param integer $message_id * @return Message
* @return boolean */
*/ public function current()
public function has($message_id) {
{ $message = new Message($this->connection);
return (boolean) isset($this->messages[$message_id]); return $message->setUid(parent::current())->config();
} }
/**
* Get Message
*
* @param integer $message_id
* @return Message
*/
public function get($message_id)
{
return $this->messages[$message_id];
}
/**
* Remove Message
*
* @param integer $message_id
* @return boolean
*/
public function remove($message_id)
{
return (boolean) unset($this->messages[$message_id]);
}
} }

53
src/Core/Search.php Normal file
View file

@ -0,0 +1,53 @@
<?php
/**
* @author clivern <hello@clivern.com>
*/
namespace Clivern\Imap\Core;
/**
* Search Class
*
* @package Clivern\Imap\Core
*/
class Search
{
/**
* @var array
*/
protected $conditions = [];
/**
* Add Condition
*
* @param string $condition
* @return Search
*/
public function addCondition($condition)
{
$this->conditions[] = $condition;
return $this;
}
/**
* Get Conditions
*
* @return array
*/
public function getConditions()
{
return $this->conditions;
}
/**
* Get Conditions Query
*
* @return string
*/
public function __toString()
{
return (!empty($this->conditions)) ? implode(" ", $this->conditions) : "";
}
}

View file

@ -1,16 +0,0 @@
<?php
/**
* @author clivern <hello@clivern.com>
*/
namespace Clivern\Imap\Core;
/**
* Tools Class
*
* @package Clivern\Imap\Core
*/
class Tools
{
#~
}

View file

@ -6,9 +6,9 @@
namespace Clivern\Imap; namespace Clivern\Imap;
use Clivern\Imap\Core\Connection; use Clivern\Imap\Core\Connection;
use Clivern\Imap\Core\Folder;
use Clivern\Imap\Core\MessageIterator; use Clivern\Imap\Core\MessageIterator;
use Clivern\Imap\Core\Tools; use Clivern\Imap\Core\Message;
use Clivern\Imap\Core\Search;
/** /**
* MailBox Class * MailBox Class
@ -18,56 +18,107 @@ use Clivern\Imap\Core\Tools;
class MailBox class MailBox
{ {
/** /**
* @var Connection * @var string
*/ */
protected $connection; protected $folder;
/** /**
* @var Folder * @var Connection
*/ */
protected $folder; protected $connection;
/** /**
* @var MessageIterator * Constructor
*/ *
protected $message_iterator; * @param Connection $connection IMAP connection
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/** /**
* @var Tools * Set Folder Name
*/ *
protected $tools; * @param string $folder
* @return MailBox
*/
public function setFolder($folder)
{
$this->folder = $folder;
return $this;
}
/** /**
* MailBox Constructor * Get Folder name
* *
* @param Connection $connection * @return string
* @param Folder $folder */
* @param MessageIterator $message_iterator public function getFolder()
* @param Tools $tools {
*/ return $this->folder;
public function __construct(Connection $connection, Folder $folder, MessageIterator $message_iterator, Tools $tools) }
{
$this->connection = $connection;
$this->folder = $folder;
$this->message_iterator = $message_iterator;
$this->tools = $tools
}
/** /**
* Get Message Iterator * Get number of messages in this mailbox
* *
* @return MessageIterator * @return int
*/ */
public function getMessageIterator() public function count()
{ {
return $this->message_iterator; $this->connection->survive($this->folder);
} return imap_num_msg($this->connection->getStream());
}
/**
* Get message ids
*
* @param Search $search
* @return MessageIterator|Message[]
*/
public function getMessages(Search $search = null)
{
$this->connection->survive($this->folder);
$query = ($search) ? (string) $search : 'ALL';
$message_numbers = imap_search($this->connection->getStream(), $query, \SE_UID);
if (false == $message_numbers) {
// imap_search can also return false
$message_numbers = [];
}
public function get() return new MessageIterator($this->connection, $message_numbers);
{ }
return "test";
} /**
* Get a message by message number or uid
*
* @param int|boolean $message_number
* @param int|boolean $message_uid
* @return Message
*/
public function getMessage($message_number = false, $message_uid = false)
{
$this->connection->survive($this->folder);
$message = new Message($this->connection);
if( $message_number == false ){
return $message->setUid($message_uid)->config();
}else{
return $message->setMsgNo($message_number)->config();
}
}
/**
* Delete all messages marked for deletion
*
* @return Mailbox
*/
public function expunge()
{
$this->connection->survive($this->folder);
imap_expunge($this->connection->getStream());
}
} }

View file

@ -5,12 +5,12 @@ use PHPUnit\Framework\TestCase;
class ConnectionTest extends TestCase class ConnectionTest extends TestCase
{ {
public function testConnect() public function testConnect()
{ {
$email = getenv("TEST_EMAIL"); $email = getenv("TEST_EMAIL");
$password = getenv("TEST_EMAIL_PASS"); $password = getenv("TEST_EMAIL_PASS");
$connection = new \Clivern\Imap\Core\Connection("imap.gmail.com", "993", $email, $password, "/ssl", "INBOX"); $connection = new \Clivern\Imap\Core\Connection("imap.gmail.com", "993", $email, $password, "/ssl", "INBOX");
$this->assertTrue($connection->connect()->checkConnection()); $this->assertTrue($connection->connect()->checkConnection());
$this->assertTrue($connection->connect()->disconnect()); $this->assertTrue($connection->connect()->disconnect());
} }
} }

19
tests/Core/SearchTest.php Normal file
View file

@ -0,0 +1,19 @@
<?php
namespace Tests\Core;
use PHPUnit\Framework\TestCase;
class SearchTest extends TestCase
{
public function testConditionBuilder()
{
$search = new \Clivern\Imap\Core\Search();
$search->addCondition('RECENT')->addCondition('BCC "string"')->addCondition('NEW');
$this->assertEquals($search->getConditions(), [
'RECENT',
'BCC "string"',
'NEW'
]);
$this->assertEquals((string) $search, 'RECENT BCC "string" NEW');
}
}

View file

@ -14,8 +14,8 @@ use PHPUnit\Framework\TestCase;
*/ */
class MailBoxTest extends TestCase class MailBoxTest extends TestCase
{ {
public function testGet() public function testGet()
{ {
$this->assertTrue(true); $this->assertTrue(true);
} }
} }