2
0
forked from Wavyzz/dolibarr

Merge IMAP with phpimap

This commit is contained in:
Laurent Destailleur
2022-08-23 22:34:24 +02:00
444 changed files with 76162 additions and 298 deletions

View File

@@ -289,7 +289,7 @@ script:
--exclude htdocs/includes/sabre --exclude htdocs/includes/phpoffice/PhpSpreadsheet --exclude htdocs/includes/sebastian \
--exclude htdocs/includes/squizlabs/php_codesniffer --exclude htdocs/includes/jakub-onderka --exclude htdocs/includes/php-parallel-lint --exclude htdocs/includes/symfony \
--exclude htdocs/includes/mike42/escpos-php/example --exclude htdocs/includes/maximebf \
--exclude htdocs/includes/phpunit/ --exclude htdocs/includes/tecnickcom/tcpdf/include/barcodes --exclude htdocs/includes/webmozart --blame .
--exclude htdocs/includes/phpunit/ --exclude htdocs/includes/tecnickcom/tcpdf/include/barcodes --exclude htdocs/includes/webmozart --exclude htdocs/includes/webklex --blame .
fi
set +e
echo

View File

@@ -91,9 +91,9 @@ include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be includ
//$isdraft = (($object->statut == MyObject::STATUS_DRAFT) ? 1 : 0);
//$result = restrictedArea($user, 'mymodule', $object->id, '', '', 'fk_soc', 'rowid', $isdraft);
$permissionnote = $user->rights->emailcollector->write; // Used by the include of actions_setnotes.inc.php
$permissiondellink = $user->rights->emailcollector->write; // Used by the include of actions_dellink.inc.php
$permissiontoadd = $user->rights->emailcollector->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
$permissionnote = $user->admin; // Used by the include of actions_setnotes.inc.php
$permissiondellink = $user->admin; // Used by the include of actions_dellink.inc.php
$permissiontoadd = $user->admin; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
$debuginfo = '';
@@ -337,14 +337,12 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Confirmation of action process
if ($action == 'collect') {
$formquestion = array(
'text' => $langs->trans("EmailCollectorConfirmCollect"),
);
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('EmailCollectorConfirmCollectTitle'), $text, 'confirm_collect', $formquestion, 0, 1, 220);
$formquestion = array();
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('EmailCollectorConfirmCollectTitle'), $langs->trans('EmailCollectorConfirmCollect'), 'confirm_collect', $formquestion, 0, 1, 220);
}
// Call Hook formConfirm
$parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
$parameters = array('formConfirm' => $formconfirm);
$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
if (empty($reshook)) {
$formconfirm .= $hookmanager->resPrint;
@@ -679,7 +677,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken().'">'.$langs->trans("Edit").'</a></div>';
// Clone
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&socid='.$object->socid.'&action=clone&token='.newToken().'&object=order">'.$langs->trans("ToClone").'</a></div>';
print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&token='.newToken().'&object=order">'.$langs->trans("ToClone").'</a></div>';
// Collect now
if (count($object->actions) > 0) {

View File

@@ -40,7 +40,19 @@ require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class
require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php'; // reception
include_once DOL_DOCUMENT_ROOT.'/emailcollector/lib/emailcollector.lib.php';
//require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; // Holidays (leave request)
//require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; // expernse report
//require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; // expernse repor
// use Webklex\PHPIMAP;
require DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php';
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
use Webklex\PHPIMAP\Exceptions\InvalidWhereQueryCriteriaException;
use Webklex\PHPIMAP\Exceptions\GetMessagesFailedException;
use OAuth\Common\Storage\DoliStorage;
use OAuth\Common\Consumer\Credentials;
/**
@@ -117,9 +129,11 @@ class EmailCollector extends CommonObject
'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>90, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com', 'csslist'=>'tdoverflow125'),
'port' => array('type'=>'varchar(10)', 'label'=>'EMailHostPort', 'visible'=>1, 'enabled'=>1, 'position'=>91, 'notnull'=>1, 'searchall'=>0, 'comment'=>"IMAP server port", 'help'=>'Example: 993', 'csslist'=>'tdoverflow125', 'default'=>'993'),
'hostcharset' => array('type'=>'varchar(16)', 'label'=>'HostCharset', 'visible'=>-1, 'enabled'=>1, 'position'=>92, 'notnull'=>0, 'searchall'=>0, 'comment'=>"IMAP server charset", 'help'=>'Example: "UTF-8" (May be "US-ASCII" with some Office365)', 'default'=>'UTF-8'),
'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>-1, 'enabled'=>1, 'position'=>101, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'),
'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'),
'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'),
'acces_type' => array('type'=>'integer', 'label'=>'accessType', 'visible'=>-1, 'enabled'=>1, 'position'=>101, 'notnull'=>0, 'index'=>1, 'comment'=>"IMAP login type", 'arrayofkeyval'=>array('0'=>'loginPassword', '1'=>'oauthToken'), 'default'=>'0', 'help'=>'OnlyOneFieldBelowToBeFilled'),
'login' => array('type'=>'varchar(128)', 'label'=>'Login', 'visible'=>-1, 'enabled'=>1, 'position'=>102, 'notnull'=>-1, 'index'=>1, 'comment'=>"IMAP login", 'help'=>'Example: myaccount@gmail.com'),
'oauth_service' => array('type'=>'varchar(128)', 'label'=>'oauthService', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>0, 'index'=>1, 'comment'=>"IMAP login oauthService", 'arrayofkeyval'=>array(), 'help'=>'TokenMustHaveBeenCreated'),
'password' => array('type'=>'password', 'label'=>'Password', 'visible'=>-1, 'enabled'=>1, 'position'=>103, 'notnull'=>-1, 'comment'=>"IMAP password", 'help'=>'WithGMailYouCanCreateADedicatedPassword'),
'source_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxSourceDirectory', 'visible'=>-1, 'enabled'=>1, 'position'=>104, 'notnull'=>1, 'default' => 'Inbox', 'help'=>'Example: INBOX'),
//'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105),
//'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106),
'target_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxTargetDirectory', 'visible'=>1, 'enabled'=>1, 'position'=>110, 'notnull'=>0, 'help'=>"EmailCollectorTargetDir"),
@@ -198,6 +212,8 @@ class EmailCollector extends CommonObject
public $hostcharset;
public $login;
public $password;
public $acces_type;
public $oauth_service;
public $source_directory;
public $target_directory;
public $maxemailpercollect;
@@ -239,6 +255,27 @@ class EmailCollector extends CommonObject
$this->fields['entity']['enabled'] = 0;
}
// List of oauth services
$oauthservices = array();
foreach ($conf->global as $key => $val) {
if (!empty($val) && preg_match('/^OAUTH_.*_ID$/', $key)) {
$key = preg_replace('/^OAUTH_/', '', $key);
$key = preg_replace('/_ID$/', '', $key);
if (preg_match('/^.*-/', $key)) {
$name = preg_replace('/^.*-/', '', $key);
} else {
$name = $langs->trans("NoName");
}
$provider = preg_replace('/-.*$/', '', $key);
$provider = ucfirst(strtolower($provider));
$oauthservices[$key] = $name." (".$provider.")";
}
}
$this->fields['oauth_service']['arrayofkeyval'] = $oauthservices;
// Unset fields that are disabled
foreach ($this->fields as $key => $val) {
if (isset($val['enabled']) && empty($val['enabled'])) {
@@ -951,7 +988,7 @@ class EmailCollector extends CommonObject
*/
public function doCollectOneCollector()
{
global $conf, $langs, $user;
global $db, $conf, $langs, $user;
global $hookmanager;
//$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
@@ -968,6 +1005,7 @@ class EmailCollector extends CommonObject
$now = dol_now();
if (empty($this->host)) {
$this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('EMailHost'));
return -1;
@@ -980,14 +1018,94 @@ class EmailCollector extends CommonObject
$this->error = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('MailboxSourceDirectory'));
return -1;
}
if (!function_exists('imap_open')) {
$this->error = 'IMAP function not enabled on your PHP';
return -2;
}
$this->fetchFilters();
$this->fetchActions();
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php'; // define $supportedoauth2array
$keyforsupportedoauth2array = $this->oauth_service;
if (preg_match('/^.*-/', $keyforsupportedoauth2array)) {
$keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array);
} else {
$keyforprovider = '';
}
$keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
$keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
$OAUTH_SERVICENAME = (empty($supportedoauth2array[$keyforsupportedoauth2array]['name']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['name'].($keyforprovider ? '-'.$keyforprovider : ''));
require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
$debugtext = "Host: ".$this->host."<br>Port: ".$this->port."<br>Login: ".$this->login."<br>Password: ".$this->password."<br>access type: ".$this->acces_type."<br>oauth service: ".$this->oauth_service."<br>Max email per collect: ".$this->maxemailpercollect;
$storage = new DoliStorage($db, $conf);
try {
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
$expire = true;
// Is token expired or will token expire in the next 30 seconds
// if (is_object($tokenobj)) {
// $expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30));
// }
// Token expired so we refresh it
if (is_object($tokenobj) && $expire) {
$credentials = new Credentials(
getDolGlobalString('OAUTH_'.$this->oauth_service.'_ID'),
getDolGlobalString('OAUTH_'.$this->oauth_service.'_SECRET'),
getDolGlobalString('OAUTH_'.$this->oauth_service.'_URLAUTHORIZE')
);
$serviceFactory = new \OAuth\ServiceFactory();
$oauthname = explode('-', $OAUTH_SERVICENAME);
// ex service is Google-Emails we need only the first part Google
$apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array());
// We have to save the token because Google give it only once
$refreshtoken = $tokenobj->getRefreshToken();
$tokenobj = $apiService->refreshAccessToken($tokenobj);
$tokenobj->setRefreshToken($refreshtoken);
$storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);
}
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
if (is_object($tokenobj)) {
$token = $tokenobj->getAccessToken();
} else {
$this->error = "Token not found";
return -1;
}
} catch (Exception $e) {
// Return an error if token not found
$this->error = $e->getMessage();
dol_syslog("CMailFile::sendfile: mail end error=".$this->error, LOG_ERR);
return -1;
}
$cm = new ClientManager();
$client = $cm->make([
'host' => $this->host,
'port' => 993,
'encryption' => 'ssl',
'validate_cert' => true,
'protocol' => 'imap',
'username' => $this->login,
'password' => $token,
'authentication' => "oauth",
]);
try {
$client->connect();
} catch (ConnectionFailedException $e) {
$this->error = $e->getMessage();
$this->errors[] = $this->error;
dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
return -1;
}
$host = dol_getprefix('email');
} else {
if (!function_exists('imap_open')) {
$this->error = 'IMAP function not enabled on your PHP';
return -2;
}
$sourcedir = $this->source_directory;
$targetdir = ($this->target_directory ? $this->target_directory : ''); // Can be '[Gmail]/Trash' or 'mytag'
@@ -1009,6 +1127,112 @@ class EmailCollector extends CommonObject
// See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible)
// See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2
//$search='ALL';
}
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
$criteria = array(array('UNDELETED')); // Seems not supported by some servers
$search = '';
$searchhead = '';
$searchfilterdoltrackid = 0;
$searchfilternodoltrackid = 0;
$searchfilterisanswer = 0;
$searchfilterisnotanswer = 0;
foreach ($this->filters as $rule) {
if (empty($rule['status'])) {
continue;
}
if ($rule['type'] == 'to') {
$tmprulevaluearray = explode('*', $rule['rulevalue']);
if (count($tmprulevaluearray) >= 2) {
foreach ($tmprulevaluearray as $tmprulevalue) {
array_push($criteria, array("TO" => $tmprulevalue));
}
} else {
array_push($criteria, array("TO" => $rule['rulevalue']));
}
}
if ($rule['type'] == 'bcc') {
array_push($criteria, array("BCC" => $rule['rulevalue']));
}
if ($rule['type'] == 'cc') {
array_push($criteria, array("CC" => $rule['rulevalue']));
}
if ($rule['type'] == 'from') {
array_push($criteria, array("FROM" => $rule['rulevalue']));
}
if ($rule['type'] == 'subject') {
array_push($criteria, array("SUBJECT" => $rule['rulevalue']));
}
if ($rule['type'] == 'body') {
array_push($criteria, array("BODY" => $rule['rulevalue']));
}
if ($rule['type'] == 'header') {
array_push($criteria, array("HEADER" => $rule['rulevalue']));
}
if ($rule['type'] == 'notinsubject') {
array_push($criteria, array("SUBJECT NOT" => $rule['rulevalue']));
}
if ($rule['type'] == 'notinbody') {
array_push($criteria, array("BODY NOT" => $rule['rulevalue']));
}
if ($rule['type'] == 'seen') {
array_push($criteria, array("SEEN"));
}
if ($rule['type'] == 'unseen') {
array_push($criteria, array("UNSEEN"));
}
if ($rule['type'] == 'unanswered') {
array_push($criteria, array("UNANSWERED"));
}
if ($rule['type'] == 'answered') {
array_push($criteria, array("ANSWERED"));
}
if ($rule['type'] == 'smaller') {
array_push($criteria, array("SMALLER"));
}
if ($rule['type'] == 'larger') {
array_push($criteria, array("LARGER"));
}
// Rules to filter after the search imap
if ($rule['type'] == 'withtrackingidinmsgid') {
$searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/';
}
if ($rule['type'] == 'withouttrackingidinmsgid') {
$searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/';
}
if ($rule['type'] == 'withtrackingid') {
$searchfilterdoltrackid++; $searchhead .= '/References.*@'.preg_quote($host, '/').'/';
}
if ($rule['type'] == 'withouttrackingid') {
$searchfilternodoltrackid++; $searchhead .= '! /References.*@'.preg_quote($host, '/').'/';
}
if ($rule['type'] == 'isanswer') {
$searchfilterisanswer++; $searchhead .= '/References.*@.*/';
}
if ($rule['type'] == 'isnotanswer') {
$searchfilterisnotanswer++; $searchhead .= '! /References.*@.*/';
}
}
if (empty($targetdir)) { // Use last date as filter if there is no targetdir defined.
$fromdate = 0;
if ($this->datelastok) {
$fromdate = $this->datelastok;
}
if ($fromdate > 0) {
// $search .= ($search ? ' ' : '').'SINCE '.date('j-M-Y', $fromdate - 1); // SENTSINCE not supported. Date must be X-Abc-9999 (X on 1 digit if < 10)
array_push($criteria, array("SINCE" => date('j-M-Y', $fromdate - 1)));
}
//$search.=($search?' ':'').'SINCE 8-Apr-2022';
}
dol_syslog("IMAP search string = ".var_export($criteria, true));
$search = var_export($criteria, true);
} else {
$search = 'UNDELETED'; // Seems not supported by some servers
$searchhead = '';
$searchfilterdoltrackid = 0;
@@ -1075,6 +1299,7 @@ class EmailCollector extends CommonObject
$search .= ($search ? ' ' : '').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"';
}
// Rules to filter after the search imap
if ($rule['type'] == 'withtrackingidinmsgid') {
$searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/';
}
@@ -1106,14 +1331,45 @@ class EmailCollector extends CommonObject
}
//$search.=($search?' ':'').'SINCE 8-Apr-2018';
}
dol_syslog("IMAP search string = ".$search);
//var_dump($search);
}
$nbemailprocessed = 0;
$nbemailok = 0;
$nbactiondone = 0;
$charset = ($this->hostcharset ? $this->hostcharset : "UTF-8");
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
try {
//$criteria = [['ALL']];
//$Query = $client->getFolders()[0]->messages()->where($criteria);
$f = $client->getFolders(false, $this->source_directory);
$Query = $f[0]->messages()->where($criteria);
} catch (InvalidWhereQueryCriteriaException $e) {
$this->error = $e->getMessage();
$this->errors[] = $this->error;
dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
return -1;
} catch (Exception $e) {
$this->error = $e->getMessage();
$this->errors[] = $this->error;
dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
return -1;
}
try {
//var_dump($Query->count());
$arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder("asc")->get();
//var_dump($arrayofemail);
} catch (Exception $e) {
$this->error = $e->getMessage();
$this->errors[] = $this->error;
dol_syslog("EmailCollector::doCollectOneCollector ".$this->error, LOG_ERR);
return -1;
}
} else {
// Scan IMAP inbox
$arrayofemail = imap_search($connection, $search, null, $charset);
if ($arrayofemail === false) {
@@ -1125,6 +1381,7 @@ class EmailCollector extends CommonObject
$this->errors[] = $this->error;
}
}
}
// Loop on each email found
if (!$error && !empty($arrayofemail) && count($arrayofemail) > 0) {
@@ -1144,63 +1401,6 @@ class EmailCollector extends CommonObject
2.2.1 text/plain
2.2.2 text/html
*/
/**
* create_part_array
*
* @param Object $structure Structure
* @param string $prefix prefix
* @return array Array with number and object
*/
/*function createPartArray($structure, $prefix = "")
{
//print_r($structure);
$part_array=array();
if (count($structure->parts) > 0) { // There some sub parts
foreach ($structure->parts as $count => $part) {
addPartToArray($part, $prefix.($count+1), $part_array);
}
}else{ // Email does not have a seperate mime attachment for text
$part_array[] = array('part_number' => $prefix.'1', 'part_object' => $structure);
}
return $part_array;
}*/
/**
* Sub function for createPartArray(). Only called by createPartArray() and itself.
*
* @param Object $obj Structure
* @param string $partno Part no
* @param array $part_array array
* @return void
*/
/*function addPartToArray($obj, $partno, &$part_array)
{
$part_array[] = array('part_number' => $partno, 'part_object' => $obj);
if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type
//print_r($obj);
if (array_key_exists('parts', $obj)) { // Check to see if the email has parts
foreach ($obj->parts as $count => $part) {
// Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments
if (count($part->parts) > 0) {
foreach ($part->parts as $count2 => $part2) {
addPartToArray($part2, $partno.".".($count2+1), $part_array);
}
}else{ // Attached email does not have a seperate mime attachment for text
$part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj);
}
}
}else{ // Not sure if this is possible
$part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj);
}
}else{ // If there are more sub-parts, expand them out.
if (array_key_exists('parts', $obj)) {
foreach ($obj->parts as $count => $p) {
addPartToArray($p, $partno.".".($count+1), $part_array);
}
}
}
}*/
dol_syslog("Start of loop on email", LOG_INFO, 1);
$iforemailloop = 0;
@@ -1208,23 +1408,24 @@ class EmailCollector extends CommonObject
if ($nbemailprocessed > 1000) {
break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect)
}
$iforemailloop++;
// GET header and overview datas
$header = imap_fetchheader($connection, $imapemail, 0);
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
$header = $imapemail->getHeader()->raw;
$overview = $imapemail->getAttributes();
} else {
$header = imap_headerinfo($connection, $imapemail);
$overview = imap_fetch_overview($connection, $imapemail, 0);
}
// print $header;
// var_dump($overview);
// Process $header of email
$header = preg_replace('/\r\n\s+/m', ' ', $header); // When a header line is on several lines, merge lines
$matches = array();
preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header, $matches);
$headers = array_combine($matches[1], $matches[2]);
//var_dump($headers);exit;
if (!empty($headers['in-reply-to']) && empty($headers['In-Reply-To'])) {
$headers['In-Reply-To'] = $headers['in-reply-to'];
@@ -1235,12 +1436,16 @@ class EmailCollector extends CommonObject
if (!empty($headers['message-id']) && empty($headers['Message-ID'])) {
$headers['Message-ID'] = $headers['message-id'];
}
if (!empty($headers['subject']) && empty($headers['Subject'])) {
$headers['Subject'] = $headers['subject'];
}
$headers['Subject'] = $this->decodeSMTPSubject($headers['Subject']);
dol_syslog("** Process email ".$iforemailloop." References: ".$headers['References']." Subject: ".$headers['Subject']);
//print "Process mail ".$iforemailloop." Subject: ".dol_escape_htmltag($headers['Subject'])." References: ".dol_escape_htmltag($headers['References'])." In-Reply-To: ".dol_escape_htmltag($headers['In-Reply-To'])."<br>\n";
// If there is a filter on trackid
if ($searchfilterdoltrackid > 0) {
@@ -1315,6 +1520,11 @@ class EmailCollector extends CommonObject
$this->db->begin();
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
dol_syslog("msgid=".$overview['message_id']." date=".dol_print_date($overview['date'], 'dayrfc', 'gmt')." from=".$overview['from']." to=".$overview['to']." subject=".$overview['subject']);
$overview['subject'] = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $overview['subject']);
} else {
dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject);
$overview[0]->subject = $this->decodeSMTPSubject($overview[0]->subject);
@@ -1323,13 +1533,24 @@ class EmailCollector extends CommonObject
// Removed emojis
$overview[0]->subject = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $overview[0]->subject);
}
// GET IMAP email structure/content
global $htmlmsg, $plainmsg, $charset, $attachments;
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
if ($imapemail->hasHTMLBody()) {
$htmlmsg = $imapemail->getHTMLBody();
}
if ($imapemail->hasTextBody()) {
$plainmsg = $imapemail->getTextBody();
}
if ($imapemail->hasAttachments()) {
$attachments = $imapemail->getAttachments();
}
} else {
$this->getmsg($connection, $imapemail);
}
//print $plainmsg;
//var_dump($plainmsg); exit;
@@ -1393,6 +1614,17 @@ class EmailCollector extends CommonObject
//print $messagetext;
//exit;
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
$fromstring = $overview['from'];
$sender = $overview['sender'];
$to = $overview['to'];
$sendtocc = empty($overview['cc']) ? '' : $overview['cc'];
$sendtobcc = empty($overview['bcc']) ? '' : $overview['bcc'];
$date = $overview['date'];
$msgid = str_replace(array('<', '>'), '', $overview['message_id']);
$subject = $overview['subject'];
} else {
$fromstring = $overview[0]->from;
$sender = $overview[0]->sender;
@@ -1403,6 +1635,8 @@ class EmailCollector extends CommonObject
$msgid = str_replace(array('<', '>'), '', $overview[0]->message_id);
$subject = $overview[0]->subject;
//var_dump($msgid);exit;
}
$reg = array();
if (preg_match('/^(.*)<(.*)>$/', $fromstring, $reg)) {
@@ -1780,8 +2014,9 @@ class EmailCollector extends CommonObject
dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found");
$errorforactions++;
$this->error = 'ErrorFailedToLoadThirdParty';
$this->errors[] = 'ErrorFailedToLoadThirdParty';
$langs->load("errors");
$this->error = $langs->trans('ErrorFailedToLoadThirdParty', $idtouseforthirdparty, $emailtouseforthirdparty, $nametouseforthirdparty);
$this->errors[] = $this->error;
} elseif ($operation['type'] == 'loadandcreatethirdparty') {
dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found. We try to create it.");
@@ -1911,7 +2146,7 @@ class EmailCollector extends CommonObject
$data[$val['filename']] = getFileData($imapemail, $val['pos'], $val['type'], $connection);
}
if (count($pj) > 0) {
$sql = "SELECT rowid as id FROM " . MAIN_DB_PREFIX . "user WHERE email LIKE '%" . $from . "%'";
$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."user WHERE email LIKE '%".$this->db->escape($from)."%'";
$resql = $this->db->query($sql);
if ($this->db->num_rows($resql) == 0) {
$this->errors[] = 'User Not allowed to add documents';
@@ -2072,7 +2307,6 @@ class EmailCollector extends CommonObject
} elseif ($operation['type'] == 'project') {
// Create project / lead
$projecttocreate = new Project($this->db);
$alreadycreated = $projecttocreate->fetch(0, '', '', $msgid);
if ($alreadycreated == 0) {
if ($thirdpartystatic->id > 0) {
@@ -2156,6 +2390,7 @@ class EmailCollector extends CommonObject
$projecttocreate->ref = $defaultref;
}
if ($errorforthisaction) {
$errorforactions++;
} else {
@@ -2279,8 +2514,10 @@ class EmailCollector extends CommonObject
$this->errors = $tickettocreate->errors;
} else {
if ($attachments) {
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
$destdir = $conf->ticket->dir_output.'/'.$tickettocreate->ref;
if (!dol_is_dir($destdir)) {
return -1;
dol_mkdir($destdir);
$this->getmsg($connection, $imapemail, $destdir);
}
@@ -2289,6 +2526,7 @@ class EmailCollector extends CommonObject
}
}
}
}
} elseif ($operation['type'] == 'candidature') {
// Create candidature
$candidaturetocreate = new RecruitmentCandidature($this->db);
@@ -2406,7 +2644,7 @@ class EmailCollector extends CommonObject
'header'=>$header,
'attachments'=>$attachments,
);
$reshook = $hookmanager->executeHooks('doCollectOneCollector', $parameters, $this, $operation['type']);
$reshook = $hookmanager->executeHooks('doColleimapctOneCollector', $parameters, $this, $operation['type']);
if ($reshook < 0) {
$errorforthisaction++;
@@ -2417,6 +2655,7 @@ class EmailCollector extends CommonObject
}
}
if (!$errorforactions) {
$nbactiondoneforemail++;
}
@@ -2424,6 +2663,7 @@ class EmailCollector extends CommonObject
// Error for email or not ?
if (!$errorforactions) {
if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP) || $this->acces_type != 1) {
if ($targetdir) {
dol_syslog("EmailCollector::doCollectOneCollector move message ".$imapemail." to ".$connectstringtarget, LOG_DEBUG);
$res = imap_mail_move($connection, $imapemail, $targetdir, 0);
@@ -2436,10 +2676,12 @@ class EmailCollector extends CommonObject
} else {
dol_syslog("EmailCollector::doCollectOneCollector message ".$imapemail." to ".$connectstringtarget." was set to read", LOG_DEBUG);
}
}
} else {
$errorforemail++;
}
unset($objectemail);
unset($projectstatic);
unset($thirdpartystatic);
@@ -2472,10 +2714,13 @@ class EmailCollector extends CommonObject
$output = $langs->trans('NoNewEmailToProcess');
}
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP) && $this->acces_type == 1) {
$client->disconnect();
} else {
imap_expunge($connection); // To validate any move
imap_close($connection);
}
$this->datelastresult = $now;
$this->lastresult = $output;
$this->debuginfo = 'IMAP search string used : '.$search;
@@ -2488,7 +2733,7 @@ class EmailCollector extends CommonObject
}
if (!empty($this->errors)) {
$this->lastresult .= " - ".join(" - ", $this->errors);
$this->lastresult .= "<br>".join("<br>", $this->errors);
}
$this->codelastresult = ($error ? 'KO' : 'OK');
$this->update($user);

View File

@@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**Used config**
Please provide the used config, if you are not using the package default config.
**Code to Reproduce**
The troubling code section which produces the reported bug.
```php
echo "Bug";
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop / Server (please complete the following information):**
- OS: [e.g. Debian 10]
- PHP: [e.g. 5.5.9]
- Version [e.g. v2.3.1]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,12 @@
---
name: General help request
about: Feel free to ask about any project related stuff
---
Please be aware that these issues will be closed if inactive for more then 14 days.
Also make sure to use https://github.com/Webklex/php-imap/issues/new?template=bug_report.md if you want to report a bug
or https://github.com/Webklex/php-imap/issues/new?template=feature_request.md if you want to suggest a feature.
Still here? Well clean this out and go ahead :)

View File

@@ -0,0 +1,3 @@
composer.lock
.idea
/build/

View File

@@ -0,0 +1,577 @@
# Changelog
All notable changes to `webklex/php-imap` will be documented in this file.
Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [UNRELEASED]
### Fixed
- NaN
### Added
- NaN
### Affected Classes
- NaN
### Breaking changes
- NaN
## [2.7.2] - 2021-09-27
### Fixed
- Fixed problem with skipping last line of the response. #166 (thanks @szymekjanaczek)
## [2.7.1] - 2021-09-08
### Added
- Added `UID` as available search criteria #161 (thanks @szymekjanaczek)
## [2.7.0] - 2021-09-04
### Fixed
- Fixes handling of long header lines which are seperated by `\r\n\t` (thanks @Oliver-Holz)
- Fixes to line parsing with multiple addresses (thanks @Oliver-Holz)
### Added
- Expose message folder path #154 (thanks @Magiczne)
- Adds mailparse_rfc822_parse_addresses integration (thanks @Oliver-Holz)
- Added moveManyMessages method (thanks @Magiczne)
- Added copyManyMessages method (thanks @Magiczne)
### Affected Classes
- [Header::class](src/Header.php)
- [Message::class](src/Message.php)
## [2.6.0] - 2021-08-20
### Fixed
- POP3 fixes #151 (thanks @Korko)
### Added
- Added imap 4 handling. #146 (thanks @szymekjanaczek)
- Added laravel's conditionable methods. #147 (thanks @szymekjanaczek)
### Affected Classes
- [Query::class](src/Query/Query.php)
- [Client::class](src/Client.php)
## [2.5.1] - 2021-06-19
### Fixed
- Fix setting default mask from config #133 (thanks @shacky)
- Chunked fetch fails in case of less available mails than page size #114
- Protocol::createStream() exception information fixed #137
- Legacy methods (headers, content, flags) fixed #125
- Legacy connection cycle fixed #124 (thanks @zssarkany)
### Added
- Disable rfc822 header parsing via config option #115
## [2.5.0] - 2021-02-01
### Fixed
- Attachment saving filename fixed
- Unnecessary parameter removed from `Client::getTimeout()`
- Missing encryption variable added - could have caused problems with unencrypted communications
- Prefer attachment filename attribute over name attribute #82
- Missing connection settings added to `Folder:idle()` auto mode #89
- Message move / copy expect a folder path #79
- `Client::getFolder()` updated to circumvent special edge cases #79
- Missing connection status checks added to various methods
- Unused default attribute `message_no` removed from `Message::class`
### Added
- Dynamic Attribute access support added (e.g `$message->from[0]`)
- Message not found exception added #93
- Chunked fetching support added `Query::chunked()`. Just in case you can't fetch all messages at once
- "Soft fail" support added
- Count method added to `Attribute:class`
- Convert an Attribute instance into a Carbon date object #95
### Affected Classes
- [Attachment::class](src/Attachment.php)
- [Attribute::class](src/Attribute.php)
- [Query::class](src/Query/Query.php)
- [Message::class](src/Message.php)
- [Client::class](src/Client.php)
- [Folder::class](src/Folder.php)
### Breaking changes
- A new exception can occur if a message can't be fetched (`\Webklex\PHPIMAP\Exceptions\MessageNotFoundException::class`)
- `Message::move()` and `Message::copy()` no longer accept folder names as folder path
- A `Message::class` instance might no longer have a `message_no` attribute
## [2.4.4] - 2021-01-22
### Fixed
- Boundary detection simplified #90
- Prevent potential body overwriting #90
- CSV files are no longer regarded as plain body
- Boundary detection overhauled to support "related" and "alternative" multipart messages #90 #91
### Affected Classes
- [Structure::class](src/Structure.php)
- [Message::class](src/Message.php)
- [Header::class](src/Header.php)
- [Part::class](src/Part.php)
## [2.4.3] - 2021-01-21
### Fixed
- Attachment detection updated #82 #90
- Timeout handling improved
- Additional utf-8 checks added to prevent decoding of unencoded values #76
### Added
- Auto reconnect option added to `Folder::idle()` #89
### Affected Classes
- [Folder::class](src/Folder.php)
- [Part::class](src/Part.php)
- [Client::class](src/Client.php)
- [Header::class](src/Header.php)
## [2.4.2] - 2021-01-09
### Fixed
- Attachment::save() return error 'A facade root has not been set' #87
- Unused dependencies removed
- Fix PHP 8 error that changes null back in to an empty string. #88 (thanks @mennovanhout)
- Fix regex to be case insensitive #88 (thanks @mennovanhout)
### Affected Classes
- [Attachment::class](src/Attachment.php)
- [Address::class](src/Address.php)
- [Attribute::class](src/Attribute.php)
- [Structure::class](src/Structure.php)
## [2.4.1] - 2021-01-06
### Fixed
- Debug line position fixed
- Handle incomplete address to string conversion #83
- Configured message key gets overwritten by the first fetched message #84
### Affected Classes
- [Address::class](src/Address.php)
- [Query::class](src/Query/Query.php)
## [2.4.0] - 2021-01-03
### Fixed
- Get partial overview when `IMAP::ST_UID` is set #74
- Unnecessary "'" removed from address names
- Folder referral typo fixed
- Legacy protocol fixed
- Treat message collection keys always as strings
### Added
- Configurable supported default flags added
- Message attribute class added to unify value handling
- Address class added and integrated
- Alias `Message::attachments()` for `Message::getAttachments()` added
- Alias `Message::addFlag()` for `Message::setFlag()` added
- Alias `Message::removeFlag()` for `Message::unsetFlag()` added
- Alias `Message::flags()` for `Message::getFlags()` added
- New Exception `MessageFlagException::class` added
- New method `Message::setSequenceId($id)` added
- Optional Header attributizion option added
### Affected Classes
- [Folder::class](src/Folder.php)
- [Header::class](src/Header.php)
- [Message::class](src/Message.php)
- [Address::class](src/Address.php)
- [Query::class](src/Query/Query.php)
- [Attribute::class](src/Attribute.php)
### Breaking changes
- Stringified message headers are now separated by ", " instead of " ".
- All message header values such as subject, message_id, from, to, etc now consists of an `Àttribute::class` instance (should behave the same way as before, but might cause some problem in certain edge cases)
- The formal address object "from", "to", etc now consists of an `Address::class` instance (should behave the same way as before, but might cause some problem in certain edge cases)
- When fetching or manipulating message flags a `MessageFlagException::class` exception can be thrown if a runtime error occurs
- Learn more about the new `Attribute` class here: [www.php-imap.com/api/attribute](https://www.php-imap.com/api/attribute)
- Learn more about the new `Address` class here: [www.php-imap.com/api/address](https://www.php-imap.com/api/address)
- Folder attribute "referal" is now called "referral"
## [2.3.1] - 2020-12-30
### Fixed
- Missing RFC attributes added
- Set the message sequence when idling
- Missing UID commands added #64
### Added
- Get a message by its message number
- Get a message by its uid #72 #66 #63
### Affected Classes
- [Message::class](src/Message.php)
- [Folder::class](src/Folder.php)
- [Query::class](src/Query/Query.php)
## [2.3.0] - 2020-12-21
### Fixed
- Cert validation issue fixed
- Allow boundaries ending with a space or semicolon (thanks [@smartilabs](https://github.com/smartilabs))
- Ignore IMAP DONE command response #57
- Default `options.fetch` set to `IMAP::FT_PEEK`
- Address parsing fixed #60
- Alternative rfc822 header parsing fixed #60
- Parse more than one Received: header #61
- Fetch folder overview fixed
- `Message::getTextBody()` fallback value fixed
### Added
- Proxy support added
- Flexible disposition support added #58
- New `options.message_key` option `uid` added
- Protocol UID support added
- Flexible sequence type support added
### Affected Classes
- [Structure::class](src/Structure.php)
- [Query::class](src/Query/Query.php)
- [Client::class](src/Client.php)
- [Header::class](src/Header.php)
- [Folder::class](src/Folder.php)
- [Part::class](src/Part.php)
### Breaking changes
- Depending on your configuration, your certificates actually get checked. Which can cause an aborted connection if the certificate can not be validated.
- Messages don't get flagged as read unless you are using your own custom config.
- All `Header::class` attribute keys are now in a snake_format and no longer minus-separated.
- `Message::getTextBody()` no longer returns false if no text body is present. `null` is returned instead.
## [2.2.5] - 2020-12-11
### Fixed
- Missing array decoder method added #51 (thanks [@lutchin](https://github.com/lutchin))
- Additional checks added to prevent message from getting marked as seen #33
- Boundary parsing improved #39 #36 (thanks [@AntonioDiPassio-AppSys](https://github.com/AntonioDiPassio-AppSys))
- Idle operation updated #44
### Added
- Force a folder to be opened
### Affected Classes
- [Header::class](src/Header.php)
- [Folder::class](src/Folder.php)
- [Query::class](src/Query/Query.php)
- [Message::class](src/Message.php)
- [Structure::class](src/Structure.php)
## [2.2.4] - 2020-12-08
### Fixed
- Search performance increased by fetching all headers, bodies and flags at once #42
- Legacy protocol support updated
- Fix Query pagination. (#52 [@mikemiller891](https://github.com/mikemiller891))
### Added
- Missing message setter methods added
- `Folder::overview()` method added to fetch all headers of all messages in the current folder
### Affected Classes
- [Message::class](src/Message.php)
- [Folder::class](src/Folder.php)
- [Query::class](src/Query/Query.php)
- [PaginatedCollection::class](src/Support/PaginatedCollection.php)
## [2.2.3] - 2020-11-02
### Fixed
- Text/Html body fetched as attachment if subtype is null #34
- Potential header overwriting through header extensions #35
- Prevent empty attachments #37
### Added
- Set fetch order during query #41 [@Max13](https://github.com/Max13)
### Affected Classes
- [Message::class](src/Message.php)
- [Part::class](src/Part.php)
- [Header::class](src/Header.php)
- [Query::class](src/Query/Query.php)
## [2.2.2] - 2020-10-20
### Fixed
- IMAP::FT_PEEK removing "Seen" flag issue fixed #33
### Affected Classes
- [Message::class](src/Message.php)
## [2.2.1] - 2020-10-19
### Fixed
- Header decoding problem fixed #31
### Added
- Search for messages by message-Id
- Search for messages by In-Reply-To
- Message threading added `Message::thread()`
- Default folder locations added
### Affected Classes
- [Query::class](src/Query/Query.php)
- [Message::class](src/Message.php)
- [Header::class](src/Header.php)
## [2.2.0] - 2020-10-16
### Fixed
- Prevent text bodies from being fetched as attachment #27
- Missing variable check added to prevent exception while parsing an address [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356)
- Missing variable check added to prevent exception while parsing a part subtype #27
- Missing variable check added to prevent exception while parsing a part content-type [webklex/laravel-imap #356](https://github.com/Webklex/laravel-imap/issues/356)
- Mixed message header attribute `in_reply_to` "unified" to be always an array #26
- Potential message moving / copying problem fixed #29
- Move messages by using `Protocol::moveMessage()` instead of `Protocol::copyMessage()` and `Message::delete()` #29
### Added
- `Protocol::moveMessage()` method added #29
### Affected Classes
- [Message::class](src/Message.php)
- [Header::class](src/Header.php)
- [Part::class](src/Part.php)
### Breaking changes
- Text bodies might no longer get fetched as attachment
- `Message::$in_reply_to` type changed from mixed to array
## [2.1.13] - 2020-10-13
### Fixed
- Boundary detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel))
- Content-Type detection problem fixed (#28 [@DasTobbel](https://github.com/DasTobbel))
### Affected Classes
- [Structure::class](src/Structure.php)
## [2.1.12] - 2020-10-13
### Fixed
- If content disposition is multiline, implode the array to a simple string (#25 [@DasTobbel](https://github.com/DasTobbel))
### Affected Classes
- [Part::class](src/Part.php)
## [2.1.11] - 2020-10-13
### Fixed
- Potential problematic prefixed white-spaces removed from header attributes
### Added
- Expended `Client::getFolder($name, $deleimiter = null)` to accept either a folder name or path ([@DasTobbel](https://github.com/DasTobbel))
- Special MS-Exchange header decoding support added
### Affected Classes
- [Client::class](src/Client.php)
- [Header::class](src/Header.php)
## [2.1.10] - 2020-10-09
### Added
- `ClientManager::make()` method added to support undefined accounts
### Affected Classes
- [ClientManager::class](src/ClientManager.php)
## [2.1.9] - 2020-10-08
### Fixed
- Fix inline attachments and embedded images (#22 [@dwalczyk](https://github.com/dwalczyk))
### Added
- Alternative attachment names support added (#20 [@oneFoldSoftware](https://github.com/oneFoldSoftware))
- Fetch message content without leaving a "Seen" flag behind
### Affected Classes
- [Attachment::class](src/Attachment.php)
- [Message::class](src/Message.php)
- [Part::class](src/Part.php)
- [Query::class](src/Query/Query.php)
## [2.1.8] - 2020-10-08
### Fixed
- Possible error during address decoding fixed (#16 [@Slauta](https://github.com/Slauta))
- Flag event dispatching fixed #15
### Added
- Support multiple boundaries (#17, #19 [@dwalczyk](https://github.com/dwalczyk))
### Affected Classes
- [Structure::class](src/Structure.php)
## [2.1.7] - 2020-10-03
### Fixed
- Fixed `Query::paginate()` (#13 #14 by [@Max13](https://github.com/Max13))
### Affected Classes
- [Query::class](src/Query/Query.php)
## [2.1.6] - 2020-10-02
### Fixed
- `Message::getAttributes()` hasn't returned all parameters
### Affected Classes
- [Message::class](src/Message.php)
### Added
- Part number added to attachment
- `Client::getFolderByPath()` added (#12 by [@Max13](https://github.com/Max13))
- `Client::getFolderByName()` added (#12 by [@Max13](https://github.com/Max13))
- Throws exceptions if the authentication fails (#11 by [@Max13](https://github.com/Max13))
### Affected Classes
- [Client::class](src/Client.php)
## [2.1.5] - 2020-09-30
### Fixed
- Wrong message content property reference fixed (#10)
## [2.1.4] - 2020-09-30
### Fixed
- Fix header extension values
- Part header detection method changed (#10)
### Affected Classes
- [Header::class](src/Header.php)
- [Part::class](src/Part.php)
## [2.1.3] - 2020-09-29
### Fixed
- Possible decoding problem fixed
- `Str::class` dependency removed from `Header::class`
### Affected Classes
- [Header::class](src/Header.php)
## [2.1.2] - 2020-09-28
### Fixed
- Dependency problem in `Attachement::getExtension()` fixed (#9)
### Affected Classes
- [Attachment::class](src/Attachment.php)
## [2.1.1] - 2020-09-23
### Fixed
- Missing default config parameter added
### Added
- Default account config fallback added
### Affected Classes
- [Client::class](src/Client.php)
## [2.1.0] - 2020-09-22
### Fixed
- Quota handling fixed
### Added
- Event system and callbacks added
### Affected Classes
- [Client::class](src/Client.php)
- [Folder::class](src/Folder.php)
- [Message::class](src/Message.php)
## [2.0.1] - 2020-09-20
### Fixed
- Carbon dependency fixed
## [2.0.0] - 2020-09-20
### Fixed
- Missing pagination item records fixed
### Added
- php-imap module replaced by direct socket communication
- Legacy support added
- IDLE support added
- oAuth support added
- Charset detection method updated
- Decoding fallback charsets added
### Affected Classes
- All
## [1.4.5] - 2019-01-23
### Fixed
- .csv attachement is not processed
- mail part structure property comparison changed to lowercase
- Replace helper functions for Laravel 6.0 #4 (@koenhoeijmakers)
- Date handling in Folder::appendMessage() fixed
- Carbon Exception Parse Data
- Convert sender name from non-utf8 to uf8 (@hwilok)
- Convert encoding of personal data struct
### Added
- Path prefix option added to Client::getFolder() method
- Attachment size handling added
- Find messages by custom search criteria
### Affected Classes
- [Query::class](src/Query/WhereQuery.php)
- [Mask::class](src/Support/Masks/Mask.php)
- [Attachment::class](src/Attachment.php)
- [Client::class](src/Client.php)
- [Folder::class](src/Folder.php)
- [Message::class](src/Message.php)
## [1.4.2.1] - 2019-07-03
### Fixed
- Error in Attachment::__construct #3
- Examples added
## [1.4.2] - 2019-07-02
### Fixed
- Pagination count total bug #213
- Changed internal message move and copy methods #210
- Query::since() query returning empty response #215
- Carbon Exception Parse Data #45
- Reading a blank body (text / html) but only from this sender #203
- Problem with Message::moveToFolder() and multiple moves #31
- Problem with encoding conversion #203
- Message null value attribute problem fixed
- Client connection path handling changed to be handled inside the calling method #31
- iconv(): error suppressor for //IGNORE added #184
- Typo Folder attribute fullName changed to full_name
- Query scope error fixed #153
- Replace embedded image with URL #151
- Fix sender name in non-latin emails sent from Gmail (#155)
- Fix broken non-latin characters in body in ASCII (us-ascii) charset #156
- Message::getMessageId() returns wrong value #197
- Message date validation extended #45 #192
- Removed "-i" from "iso-8859-8-i" in Message::parseBody #146
### Added
- Message::getFolder() method
- Create a fast count method for queries #216
- STARTTLS encryption alias added
- Mailbox fetching exception added #201
- Message::moveToFolder() fetches new Message::class afterwards #31
- Message structure accessor added #182
- Shadow Imap const class added #188
- Connectable "NOT" queries added
- Additional where methods added
- Message attribute handling changed
- Attachment attribute handling changed
- Message flag handling updated
- Message::getHTMLBody($callback) extended
- Masks added (take look at the examples for more information on masks)
- More examples added
- Query::paginate() method added
- Imap client timeout can be modified and read #186
- Decoder config options added #175
- Message search criteria "NOT" added #181
- Invalid message date exception added
- Blade examples
### Breaking changes
- Message::moveToFolder() returns either a Message::class instance or null and not a boolean
- Folder::fullName is now Folder::full_name
- Attachment::image_src might no longer work as expected - use Attachment::getImageSrc() instead
### Affected Classes
- [Folder::class](src/Folder.php)
- [Client::class](src/Client.php)
- [Message::class](src/Message.php)
- [Attachment::class](src/Attachment.php)
- [Query::class](src/Query/Query.php)
- [WhereQuery::class](src/Query/WhereQuery.php)
## 0.0.3 - 2018-12-02
### Fixed
- Folder delimiter check added #137
- Config setting not getting loaded
- Date parsing updated
### Affected Classes
- [Folder::class](src/IMAP/Client.php)
- [Folder::class](src/IMAP/Message.php)
## 0.0.1 - 2018-08-13
### Added
- new php-imap package (fork from [webklex/laravel-imap](https://github.com/Webklex/laravel-imap))

View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@webklex.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Webklex
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright (c) 2016 Malte Goldenbaum <info@webklex.com>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

View File

@@ -0,0 +1,158 @@
# IMAP Library for PHP
[![Latest Version on Packagist][ico-version]][link-packagist]
[![Software License][ico-license]][link-license]
[![Build Status][ico-travis]][link-scrutinizer]
[![Total Downloads][ico-downloads]][link-downloads]
[![Hits][ico-hits]][link-hits]
## Description
PHP-IMAP is a wrapper for common IMAP communication without the need to have the php-imap module installed / enabled.
The protocol is completely integrated and therefore supports IMAP IDLE operation and the "new" oAuth authentication
process as well.
You can enable the `php-imap` module in order to handle edge cases, improve message decoding quality and is required if
you want to use legacy protocols such as pop3.
Official documentation: [php-imap.com](https://www.php-imap.com/)
Laravel wrapper: [webklex/laravel-imap](https://github.com/Webklex/laravel-imap)
## Table of Contents
- [Documentations](#documentations)
- [Basic usage example](#basic-usage-example)
- [Known issues](#known-issues)
- [Support](#support)
- [Features & pull requests](#features--pull-requests)
- [Security](#security)
- [Credits](#credits)
- [License](#license)
## Documentations
- Legacy (< v2.0.0): [legacy documentation](https://github.com/Webklex/php-imap/tree/1.4.5)
- Core documentation: [php-imap.com](https://www.php-imap.com/)
## Basic usage example
This is a basic example, which will echo out all Mails within all imap folders
and will move every message into INBOX.read. Please be aware that this should not be
tested in real life and is only meant to gives an impression on how things work.
```php
use Webklex\PHPIMAP\ClientManager;
$cm = new ClientManager('path/to/config/imap.php');
/** @var \Webklex\PHPIMAP\Client $client */
$client = $cm->account('account_identifier');
//Connect to the IMAP Server
$client->connect();
//Get all Mailboxes
/** @var \Webklex\PHPIMAP\Support\FolderCollection $folders */
$folders = $client->getFolders();
//Loop through every Mailbox
/** @var \Webklex\PHPIMAP\Folder $folder */
foreach($folders as $folder){
//Get all Messages of the current Mailbox $folder
/** @var \Webklex\PHPIMAP\Support\MessageCollection $messages */
$messages = $folder->messages()->all()->get();
/** @var \Webklex\PHPIMAP\Message $message */
foreach($messages as $message){
echo $message->getSubject().'<br />';
echo 'Attachments: '.$message->getAttachments()->count().'<br />';
echo $message->getHTMLBody();
//Move the current Message to 'INBOX.read'
if($message->move('INBOX.read') == true){
echo 'Message has ben moved';
}else{
echo 'Message could not be moved';
}
}
}
```
### Known issues
| Error | Solution |
| ------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Kerberos error: No credentials cache file found (try running kinit) (...) | Uncomment "DISABLE_AUTHENTICATOR" inside your config and use the `legacy-imap` protocol |
## Support
If you encounter any problems or if you find a bug, please don't hesitate to create a new [issue](https://github.com/Webklex/php-imap/issues).
However please be aware that it might take some time to get an answer.
Off topic, rude or abusive issues will be deleted without any notice.
If you need **commercial** support, feel free to send me a mail at github@webklex.com.
##### A little notice
If you write source code in your issue, please consider to format it correctly. This makes it so much nicer to read
and people are more likely to comment and help :)
&#96;&#96;&#96;php
echo 'your php code...';
&#96;&#96;&#96;
will turn into:
```php
echo 'your php code...';
```
## Features & pull requests
Everyone can contribute to this project. Every pull request will be considered but it can also happen to be declined.
To prevent unnecessary work, please consider to create a [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md)
first, if you're planning to do bigger changes. Of course you can also create a new [feature issue](https://github.com/Webklex/php-imap/issues/new?template=feature_request.md)
if you're just wishing a feature ;)
## Change log
Please see [CHANGELOG][link-changelog] for more information what has changed recently.
## Security
If you discover any security related issues, please email github@webklex.com instead of using the issue tracker.
## Credits
- [Webklex][link-author]
- [All Contributors][link-contributors]
## License
The MIT License (MIT). Please see [License File][link-license] for more information.
[ico-version]: https://img.shields.io/packagist/v/Webklex/php-imap.svg?style=flat-square
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
[ico-travis]: https://img.shields.io/travis/Webklex/php-imap/master.svg?style=flat-square
[ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/Webklex/php-imap.svg?style=flat-square
[ico-code-quality]: https://img.shields.io/scrutinizer/g/Webklex/php-imap.svg?style=flat-square
[ico-downloads]: https://img.shields.io/packagist/dt/Webklex/php-imap.svg?style=flat-square
[ico-build]: https://img.shields.io/scrutinizer/build/g/Webklex/php-imap/master?style=flat-square
[ico-quality]: https://img.shields.io/scrutinizer/quality/g/Webklex/php-imap/master?style=flat-square
[ico-hits]: https://hits.webklex.com/svg/webklex/php-imap
[link-packagist]: https://packagist.org/packages/Webklex/php-imap
[link-travis]: https://travis-ci.org/Webklex/php-imap
[link-scrutinizer]: https://scrutinizer-ci.com/g/Webklex/php-imap/code-structure
[link-code-quality]: https://scrutinizer-ci.com/g/Webklex/php-imap
[link-downloads]: https://packagist.org/packages/Webklex/php-imap
[link-author]: https://github.com/webklex
[link-contributors]: https://github.com/Webklex/php-imap/graphs/contributors
[link-license]: https://github.com/Webklex/php-imap/blob/master/LICENSE
[link-changelog]: https://github.com/Webklex/php-imap/blob/master/CHANGELOG.md
[link-jetbrains]: https://www.jetbrains.com
[link-hits]: https://hits.webklex.com

View File

@@ -0,0 +1,55 @@
{
"name": "webklex/php-imap",
"type": "library",
"description": "PHP IMAP client",
"keywords": [
"webklex",
"imap",
"pop3",
"php-imap",
"mail"
],
"homepage": "https://github.com/webklex/php-imap",
"license": "MIT",
"authors": [
{
"name": "Malte Goldenbaum",
"email": "github@webklex.com",
"role": "Developer"
}
],
"require": {
"php": ">=5.5.9",
"ext-openssl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-iconv": "*",
"ext-fileinfo": "*",
"nesbot/carbon": ">=1.0",
"symfony/http-foundation": ">=2.8.0",
"illuminate/pagination": ">=5.0.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"autoload": {
"psr-4": {
"Webklex\\PHPIMAP\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests"
}
},
"scripts": {
"test": "phpunit"
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@@ -0,0 +1,16 @@
./vendor/carbon
./vendor/nesbot/carbon/bin
./vendor/phpunit
./vendor/sebastian
./vendor/psr
./vendor/webmozart
./vendor/symfony/http-foundation
./vendor/symfony/translation
./vendor/symfony/translation-contracts
./vendor/symfony/yaml
./vendor/voku
./vendor/phpspec
./vendor/phpdocumentor
./vendor/nesbot/carbon/src/Carbon/Lang
./vendor/doctrine
./tests

View File

@@ -0,0 +1,90 @@
<?php
/*
* File: Address.php
* Category: -
* Author: M. Goldenbaum
* Created: 01.01.21 21:17
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
/**
* Class Address
*
* @package Webklex\PHPIMAP
*/
class Address {
/**
* Address attributes
* @var string $personal
* @var string $mailbox
* @var string $host
* @var string $mail
* @var string $full
*/
public $personal = "";
public $mailbox = "";
public $host = "";
public $mail = "";
public $full = "";
/**
* Address constructor.
* @param object $object
*/
public function __construct($object) {
if (property_exists($object, "personal")){ $this->personal = $object->personal; }
if (property_exists($object, "mailbox")){ $this->mailbox = $object->mailbox; }
if (property_exists($object, "host")){ $this->host = $object->host; }
if (property_exists($object, "mail")){ $this->mail = $object->mail; }
if (property_exists($object, "full")){ $this->full = $object->full; }
}
/**
* Return the stringified address
*
* @return string
*/
public function __toString() {
return $this->full ? $this->full : "";
}
/**
* Return the serialized address
*
* @return array
*/
public function __serialize(){
return [
"personal" => $this->personal,
"mailbox" => $this->mailbox,
"host" => $this->host,
"mail" => $this->mail,
"full" => $this->full,
];
}
/**
* Convert instance to array
*
* @return array
*/
public function toArray(){
return $this->__serialize();
}
/**
* Return the stringified attribute
*
* @return string
*/
public function toString(){
return $this->__toString();
}
}

View File

@@ -0,0 +1,344 @@
<?php
/*
* File: Attachment.php
* Category: -
* Author: M. Goldenbaum
* Created: 16.03.18 19:37
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use Illuminate\Support\Str;
use Webklex\PHPIMAP\Exceptions\MaskNotFoundException;
use Webklex\PHPIMAP\Exceptions\MethodNotFoundException;
use Webklex\PHPIMAP\Support\Masks\AttachmentMask;
/**
* Class Attachment
*
* @package Webklex\PHPIMAP
*
* @property integer part_number
* @property integer size
* @property string content
* @property string type
* @property string content_type
* @property string id
* @property string name
* @property string disposition
* @property string img_src
*
* @method integer getPartNumber()
* @method integer setPartNumber(integer $part_number)
* @method string getContent()
* @method string setContent(string $content)
* @method string getType()
* @method string setType(string $type)
* @method string getContentType()
* @method string setContentType(string $content_type)
* @method string getId()
* @method string setId(string $id)
* @method string getSize()
* @method string setSize(integer $size)
* @method string getName()
* @method string getDisposition()
* @method string setDisposition(string $disposition)
* @method string setImgSrc(string $img_src)
*/
class Attachment {
/**
* @var Message $oMessage
*/
protected $oMessage;
/**
* Used config
*
* @var array $config
*/
protected $config = [];
/** @var Part $part */
protected $part;
/**
* Attribute holder
*
* @var array $attributes
*/
protected $attributes = [
'content' => null,
'type' => null,
'part_number' => 0,
'content_type' => null,
'id' => null,
'name' => null,
'disposition' => null,
'img_src' => null,
'size' => null,
];
/**
* Default mask
*
* @var string $mask
*/
protected $mask = AttachmentMask::class;
/**
* Attachment constructor.
* @param Message $oMessage
* @param Part $part
*/
public function __construct(Message $oMessage, Part $part) {
$this->config = ClientManager::get('options');
$this->oMessage = $oMessage;
$this->part = $part;
$this->part_number = $part->part_number;
$default_mask = $this->oMessage->getClient()->getDefaultAttachmentMask();
if($default_mask != null) {
$this->mask = $default_mask;
}
$this->findType();
$this->fetch();
}
/**
* Call dynamic attribute setter and getter methods
* @param string $method
* @param array $arguments
*
* @return mixed
* @throws MethodNotFoundException
*/
public function __call($method, $arguments) {
if(strtolower(substr($method, 0, 3)) === 'get') {
$name = Str::snake(substr($method, 3));
if(isset($this->attributes[$name])) {
return $this->attributes[$name];
}
return null;
}elseif (strtolower(substr($method, 0, 3)) === 'set') {
$name = Str::snake(substr($method, 3));
$this->attributes[$name] = array_pop($arguments);
return $this->attributes[$name];
}
throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
}
/**
* Magic setter
* @param $name
* @param $value
*
* @return mixed
*/
public function __set($name, $value) {
$this->attributes[$name] = $value;
return $this->attributes[$name];
}
/**
* magic getter
* @param $name
*
* @return mixed|null
*/
public function __get($name) {
if(isset($this->attributes[$name])) {
return $this->attributes[$name];
}
return null;
}
/**
* Determine the structure type
*/
protected function findType() {
switch ($this->part->type) {
case IMAP::ATTACHMENT_TYPE_MESSAGE:
$this->type = 'message';
break;
case IMAP::ATTACHMENT_TYPE_APPLICATION:
$this->type = 'application';
break;
case IMAP::ATTACHMENT_TYPE_AUDIO:
$this->type = 'audio';
break;
case IMAP::ATTACHMENT_TYPE_IMAGE:
$this->type = 'image';
break;
case IMAP::ATTACHMENT_TYPE_VIDEO:
$this->type = 'video';
break;
case IMAP::ATTACHMENT_TYPE_MODEL:
$this->type = 'model';
break;
case IMAP::ATTACHMENT_TYPE_TEXT:
$this->type = 'text';
break;
case IMAP::ATTACHMENT_TYPE_MULTIPART:
$this->type = 'multipart';
break;
default:
$this->type = 'other';
break;
}
}
/**
* Fetch the given attachment
*/
protected function fetch() {
$content = $this->part->content;
$this->content_type = $this->part->content_type;
$this->content = $this->oMessage->decodeString($content, $this->part->encoding);
if (($id = $this->part->id) !== null) {
$this->id = str_replace(['<', '>'], '', $id);
}
$this->size = $this->part->bytes;
$this->disposition = $this->part->disposition;
if (($filename = $this->part->filename) !== null) {
$this->setName($filename);
} elseif (($name = $this->part->name) !== null) {
$this->setName($name);
}else {
$this->setName("undefined");
}
if (IMAP::ATTACHMENT_TYPE_MESSAGE == $this->part->type) {
if ($this->part->ifdescription) {
$this->setName($this->part->description);
} else {
$this->setName($this->part->subtype);
}
}
}
/**
* Save the attachment content to your filesystem
* @param string $path
* @param string|null $filename
*
* @return boolean
*/
public function save($path, $filename = null) {
$filename = $filename ? $filename : $this->getName();
return file_put_contents($path.$filename, $this->getContent()) !== false;
}
/**
* Set the attachment name and try to decode it
* @param $name
*/
public function setName($name) {
$decoder = $this->config['decoder']['attachment'];
if ($name !== null) {
if($decoder === 'utf-8' && extension_loaded('imap')) {
$this->name = \imap_utf8($name);
}else{
$this->name = mb_decode_mimeheader($name);
}
}
}
/**
* Get the attachment mime type
*
* @return string|null
*/
public function getMimeType(){
return (new \finfo())->buffer($this->getContent(), FILEINFO_MIME_TYPE);
}
/**
* Try to guess the attachment file extension
*
* @return string|null
*/
public function getExtension(){
$deprecated_guesser = "\Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser";
if (class_exists($deprecated_guesser) !== false){
return $deprecated_guesser::getInstance()->guess($this->getMimeType());
}
$guesser = "\Symfony\Component\Mime\MimeTypes";
$extensions = $guesser::getDefault()->getExtensions($this->getMimeType());
return isset($extensions[0]) ? $extensions[0] : null;
}
/**
* Get all attributes
*
* @return array
*/
public function getAttributes(){
return $this->attributes;
}
/**
* @return Message
*/
public function getMessage(){
return $this->oMessage;
}
/**
* Set the default mask
* @param $mask
*
* @return $this
*/
public function setMask($mask){
if(class_exists($mask)){
$this->mask = $mask;
}
return $this;
}
/**
* Get the used default mask
*
* @return string
*/
public function getMask(){
return $this->mask;
}
/**
* Get a masked instance by providing a mask name
* @param string|null $mask
*
* @return mixed
* @throws MaskNotFoundException
*/
public function mask($mask = null){
$mask = $mask !== null ? $mask : $this->mask;
if(class_exists($mask)){
return new $mask($this);
}
throw new MaskNotFoundException("Unknown mask provided: ".$mask);
}
}

View File

@@ -0,0 +1,274 @@
<?php
/*
* File: Attribute.php
* Category: -
* Author: M. Goldenbaum
* Created: 01.01.21 20:17
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use ArrayAccess;
use Carbon\Carbon;
/**
* Class Attribute
*
* @package Webklex\PHPIMAP
*/
class Attribute implements ArrayAccess {
/** @var string $name */
protected $name;
/**
* Value holder
*
* @var array $values
*/
protected $values = [];
/**
* Attribute constructor.
* @param string $name
* @param array|mixed $value
*/
public function __construct($name, $value = null) {
$this->setName($name);
$this->add($value);
}
/**
* Return the stringified attribute
*
* @return string
*/
public function __toString() {
return implode(", ", $this->values);
}
/**
* Return the stringified attribute
*
* @return string
*/
public function toString(){
return $this->__toString();
}
/**
* Return the serialized attribute
*
* @return array
*/
public function __serialize(){
return $this->values;
}
/**
* Convert instance to array
*
* @return array
*/
public function toArray(){
return $this->__serialize();
}
/**
* Convert first value to a date object
*
* @return Carbon|null
*/
public function toDate(){
$date = $this->first();
if ($date instanceof Carbon) return $date;
return Carbon::parse($date);
}
/**
* Determine if a value exists at an offset.
*
* @param mixed $key
* @return bool
*/
public function offsetExists($key) {
return array_key_exists($key, $this->values);
}
/**
* Get a value at a given offset.
*
* @param mixed $key
* @return mixed
*/
public function offsetGet($key) {
return $this->values[$key];
}
/**
* Set the value at a given offset.
*
* @param mixed $key
* @param mixed $value
* @return void
*/
public function offsetSet($key, $value) {
if (is_null($key)) {
$this->values[] = $value;
} else {
$this->values[$key] = $value;
}
}
/**
* Unset the value at a given offset.
*
* @param string $key
* @return void
*/
public function offsetUnset($key) {
unset($this->values[$key]);
}
/**
* Add one or more values to the attribute
* @param array|mixed $value
* @param boolean $strict
*
* @return Attribute
*/
public function add($value, $strict = false) {
if (is_array($value)) {
return $this->merge($value, $strict);
}elseif ($value !== null) {
$this->attach($value, $strict);
}
return $this;
}
/**
* Merge a given array of values with the current values array
* @param array $values
* @param boolean $strict
*
* @return Attribute
*/
public function merge($values, $strict = false) {
if (is_array($values)) {
foreach ($values as $value) {
$this->attach($value, $strict);
}
}
return $this;
}
/**
* Check if the attribute contains the given value
* @param mixed $value
*
* @return bool
*/
public function contains($value) {
foreach ($this->values as $v) {
if ($v === $value) {
return true;
}
}
return false;
}
/**
* Attach a given value to the current value array
* @param $value
* @param bool $strict
*/
public function attach($value, $strict = false) {
if ($strict === true) {
if ($this->contains($value) === false) {
$this->values[] = $value;
}
}else{
$this->values[] = $value;
}
}
/**
* Set the attribute name
* @param $name
*
* @return Attribute
*/
public function setName($name){
$this->name = $name;
return $this;
}
/**
* Get the attribute name
*
* @return string
*/
public function getName(){
return $this->name;
}
/**
* Get all values
*
* @return array
*/
public function get(){
return $this->values;
}
/**
* Alias method for self::get()
*
* @return array
*/
public function all(){
return $this->get();
}
/**
* Get the first value if possible
*
* @return mixed|null
*/
public function first(){
if ($this->offsetExists(0)) {
return $this->values[0];
}
return null;
}
/**
* Get the last value if possible
*
* @return mixed|null
*/
public function last(){
if (($cnt = $this->count()) > 0) {
return $this->values[$cnt - 1];
}
return null;
}
/**
* Get the number of values
*
* @return int
*/
public function count(){
return count($this->values);
}
}

View File

@@ -0,0 +1,669 @@
<?php
/*
* File: Client.php
* Category: -
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use ErrorException;
use Exception;
use Webklex\PHPIMAP\Connection\Protocols\ImapProtocol;
use Webklex\PHPIMAP\Connection\Protocols\LegacyProtocol;
use Webklex\PHPIMAP\Connection\Protocols\Protocol;
use Webklex\PHPIMAP\Connection\Protocols\ProtocolInterface;
use Webklex\PHPIMAP\Exceptions\AuthFailedException;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
use Webklex\PHPIMAP\Exceptions\FolderFetchingException;
use Webklex\PHPIMAP\Exceptions\MaskNotFoundException;
use Webklex\PHPIMAP\Exceptions\ProtocolNotSupportedException;
use Webklex\PHPIMAP\Support\FolderCollection;
use Webklex\PHPIMAP\Support\Masks\AttachmentMask;
use Webklex\PHPIMAP\Support\Masks\MessageMask;
use Webklex\PHPIMAP\Traits\HasEvents;
/**
* Class Client
*
* @package Webklex\PHPIMAP
*/
class Client {
use HasEvents;
/**
* Connection resource
*
* @var boolean|Protocol|ProtocolInterface
*/
public $connection = false;
/**
* Server hostname.
*
* @var string
*/
public $host;
/**
* Server port.
*
* @var int
*/
public $port;
/**
* Service protocol.
*
* @var int
*/
public $protocol;
/**
* Server encryption.
* Supported: none, ssl, tls, or notls.
*
* @var string
*/
public $encryption;
/**
* If server has to validate cert.
*
* @var bool
*/
public $validate_cert = true;
/**
* Proxy settings
* @var array
*/
protected $proxy = [
'socket' => null,
'request_fulluri' => false,
'username' => null,
'password' => null,
];
/**
* Connection timeout
* @var int $timeout
*/
public $timeout;
/**
* Account username/
*
* @var mixed
*/
public $username;
/**
* Account password.
*
* @var string
*/
public $password;
/**
* Account authentication method.
*
* @var string
*/
public $authentication;
/**
* Active folder path.
*
* @var string
*/
protected $active_folder = null;
/**
* Default message mask
*
* @var string $default_message_mask
*/
protected $default_message_mask = MessageMask::class;
/**
* Default attachment mask
*
* @var string $default_attachment_mask
*/
protected $default_attachment_mask = AttachmentMask::class;
/**
* Used default account values
*
* @var array $default_account_config
*/
protected $default_account_config = [
'host' => 'localhost',
'port' => 993,
'protocol' => 'imap',
'encryption' => 'ssl',
'validate_cert' => true,
'username' => '',
'password' => '',
'authentication' => null,
'proxy' => [
'socket' => null,
'request_fulluri' => false,
'username' => null,
'password' => null,
],
"timeout" => 30
];
/**
* Client constructor.
* @param array $config
*
* @throws MaskNotFoundException
*/
public function __construct($config = []) {
$this->setConfig($config);
$this->setMaskFromConfig($config);
$this->setEventsFromConfig($config);
}
/**
* Client destructor
*/
public function __destruct() {
$this->disconnect();
}
/**
* Set the Client configuration
* @param array $config
*
* @return self
*/
public function setConfig(array $config) {
$default_account = ClientManager::get('default');
$default_config = ClientManager::get("accounts.$default_account");
foreach ($this->default_account_config as $key => $value) {
$this->setAccountConfig($key, $config, $default_config);
}
return $this;
}
/**
* Set a specific account config
* @param string $key
* @param array $config
* @param array $default_config
*/
private function setAccountConfig($key, $config, $default_config){
$value = $this->default_account_config[$key];
if(isset($config[$key])) {
$value = $config[$key];
}elseif(isset($default_config[$key])) {
$value = $default_config[$key];
}
$this->$key = $value;
}
/**
* Look for a possible events in any available config
* @param $config
*/
protected function setEventsFromConfig($config) {
$this->events = ClientManager::get("events");
if(isset($config['events'])){
foreach($config['events'] as $section => $events) {
$this->events[$section] = array_merge($this->events[$section], $events);
}
}
}
/**
* Look for a possible mask in any available config
* @param $config
*
* @throws MaskNotFoundException
*/
protected function setMaskFromConfig($config) {
$default_config = ClientManager::get("masks");
if(isset($config['masks'])){
if(isset($config['masks']['message'])) {
if(class_exists($config['masks']['message'])) {
$this->default_message_mask = $config['masks']['message'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['message']);
}
}else{
if(class_exists($default_config['message'])) {
$this->default_message_mask = $default_config['message'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']);
}
}
if(isset($config['masks']['attachment'])) {
if(class_exists($config['masks']['attachment'])) {
$this->default_attachment_mask = $config['masks']['attachment'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$config['masks']['attachment']);
}
}else{
if(class_exists($default_config['attachment'])) {
$this->default_attachment_mask = $default_config['attachment'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']);
}
}
}else{
if(class_exists($default_config['message'])) {
$this->default_message_mask = $default_config['message'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$default_config['message']);
}
if(class_exists($default_config['attachment'])) {
$this->default_attachment_mask = $default_config['attachment'];
}else{
throw new MaskNotFoundException("Unknown mask provided: ".$default_config['attachment']);
}
}
}
/**
* Get the current imap resource
*
* @return bool|Protocol|ProtocolInterface
* @throws ConnectionFailedException
*/
public function getConnection() {
$this->checkConnection();
return $this->connection;
}
/**
* Determine if connection was established.
*
* @return bool
*/
public function isConnected() {
return $this->connection ? $this->connection->connected() : false;
}
/**
* Determine if connection was established and connect if not.
*
* @throws ConnectionFailedException
*/
public function checkConnection() {
if (!$this->isConnected()) {
$this->connect();
}
}
/**
* Force a reconnect
*
* @throws ConnectionFailedException
*/
public function reconnect() {
if ($this->isConnected()) {
$this->disconnect();
}
$this->connect();
}
/**
* Connect to server.
*
* @return $this
* @throws ConnectionFailedException
*/
public function connect() {
$this->disconnect();
$protocol = strtolower($this->protocol);
if (in_array($protocol, ['imap', 'imap4', 'imap4rev1'])) {
$this->connection = new ImapProtocol($this->validate_cert, $this->encryption);
$this->connection->setConnectionTimeout($this->timeout);
$this->connection->setProxy($this->proxy);
}else{
if (extension_loaded('imap') === false) {
throw new ConnectionFailedException("connection setup failed - no imap function", 0, new ProtocolNotSupportedException($protocol." is an unsupported protocol"));
}
$this->connection = new LegacyProtocol($this->validate_cert, $this->encryption);
if (strpos($protocol, "legacy-") === 0) {
$protocol = substr($protocol, 7);
}
$this->connection->setProtocol($protocol);
}
try {
$this->connection->connect($this->host, $this->port);
} catch (ErrorException $e) {
throw new ConnectionFailedException("connection setup failed - connect exception", 0, $e);
} catch (Exceptions\RuntimeException $e) {
throw new ConnectionFailedException("connection setup failed - run exception", 0, $e);
}
$this->authenticate();
return $this;
}
/**
* Authenticate the current session
*
* @throws ConnectionFailedException
*/
protected function authenticate() {
try {
if ($this->authentication == "oauth") {
if (!$this->connection->authenticate($this->username, $this->password)) {
throw new AuthFailedException();
}
} elseif (!$this->connection->login($this->username, $this->password)) {
throw new AuthFailedException();
}
} catch (AuthFailedException $e) {
throw new ConnectionFailedException("connection setup failed - authenticate", 0, $e);
}
}
/**
* Disconnect from server.
*
* @return $this
*/
public function disconnect() {
if ($this->isConnected() && $this->connection !== false) {
$this->connection->logout();
}
$this->active_folder = null;
return $this;
}
/**
* Get a folder instance by a folder name
* @param string $folder_name
* @param string|bool|null $delimiter
*
* @return mixed
* @throws ConnectionFailedException
* @throws FolderFetchingException
* @throws Exceptions\RuntimeException
*/
public function getFolder($folder_name, $delimiter = null) {
if ($delimiter !== false && $delimiter !== null) {
return $this->getFolderByPath($folder_name);
}
// Set delimiter to false to force selection via getFolderByName (maybe useful for uncommon folder names)
$delimiter = is_null($delimiter) ? ClientManager::get('options.delimiter', "/") : $delimiter;
if (strpos($folder_name, (string)$delimiter) !== false) {
return $this->getFolderByPath($folder_name);
}
return $this->getFolderByName($folder_name);
}
/**
* Get a folder instance by a folder name
* @param $folder_name
*
* @return mixed
* @throws ConnectionFailedException
* @throws FolderFetchingException
* @throws Exceptions\RuntimeException
*/
public function getFolderByName($folder_name) {
return $this->getFolders(false)->where("name", $folder_name)->first();
}
/**
* Get a folder instance by a folder path
* @param $folder_path
*
* @return mixed
* @throws ConnectionFailedException
* @throws FolderFetchingException
* @throws Exceptions\RuntimeException
*/
public function getFolderByPath($folder_path) {
return $this->getFolders(false)->where("path", $folder_path)->first();
}
/**
* Get folders list.
* If hierarchical order is set to true, it will make a tree of folders, otherwise it will return flat array.
*
* @param boolean $hierarchical
* @param string|null $parent_folder
*
* @return FolderCollection
* @throws ConnectionFailedException
* @throws FolderFetchingException
* @throws Exceptions\RuntimeException
*/
public function getFolders($hierarchical = true, $parent_folder = null) {
$this->checkConnection();
$folders = FolderCollection::make([]);
$pattern = $parent_folder.($hierarchical ? '%' : '*');
$items = $this->connection->folders('', $pattern);
if(is_array($items)){
foreach ($items as $folder_name => $item) {
$folder = new Folder($this, $folder_name, $item["delimiter"], $item["flags"]);
if ($hierarchical && $folder->hasChildren()) {
$pattern = $folder->full_name.$folder->delimiter.'%';
$children = $this->getFolders(true, $pattern);
$folder->setChildren($children);
}
$folders->push($folder);
}
return $folders;
}else{
throw new FolderFetchingException("failed to fetch any folders");
}
}
/**
* Open a given folder.
* @param string $folder_path
* @param boolean $force_select
*
* @return mixed
* @throws ConnectionFailedException
* @throws Exceptions\RuntimeException
*/
public function openFolder($folder_path, $force_select = false) {
if ($this->active_folder == $folder_path && $this->isConnected() && $force_select === false) {
return true;
}
$this->checkConnection();
$this->active_folder = $folder_path;
return $this->connection->selectFolder($folder_path);
}
/**
* Create a new Folder
* @param string $folder
* @param boolean $expunge
*
* @return bool
* @throws ConnectionFailedException
* @throws FolderFetchingException
* @throws Exceptions\EventNotFoundException
* @throws Exceptions\RuntimeException
*/
public function createFolder($folder, $expunge = true) {
$this->checkConnection();
$status = $this->connection->createFolder($folder);
if($expunge) $this->expunge();
$folder = $this->getFolder($folder);
if($status && $folder) {
$event = $this->getEvent("folder", "new");
$event::dispatch($folder);
}
return $folder;
}
/**
* Check a given folder
* @param $folder
*
* @return false|object
* @throws ConnectionFailedException
* @throws Exceptions\RuntimeException
*/
public function checkFolder($folder) {
$this->checkConnection();
return $this->connection->examineFolder($folder);
}
/**
* Get the current active folder
*
* @return string
*/
public function getFolderPath(){
return $this->active_folder;
}
/**
* Retrieve the quota level settings, and usage statics per mailbox
*
* @return array
* @throws ConnectionFailedException
* @throws Exceptions\RuntimeException
*/
public function getQuota() {
$this->checkConnection();
return $this->connection->getQuota($this->username);
}
/**
* Retrieve the quota settings per user
* @param string $quota_root
*
* @return array
* @throws ConnectionFailedException
*/
public function getQuotaRoot($quota_root = 'INBOX') {
$this->checkConnection();
return $this->connection->getQuotaRoot($quota_root);
}
/**
* Delete all messages marked for deletion
*
* @return bool
* @throws ConnectionFailedException
* @throws Exceptions\RuntimeException
*/
public function expunge() {
$this->checkConnection();
return $this->connection->expunge();
}
/**
* Set the connection timeout
* @param integer $timeout
*
* @return Protocol
* @throws ConnectionFailedException
*/
public function setTimeout($timeout) {
$this->checkConnection();
return $this->connection->setConnectionTimeout($timeout);
}
/**
* Get the connection timeout
*
* @return int
* @throws ConnectionFailedException
*/
public function getTimeout(){
$this->checkConnection();
return $this->connection->getConnectionTimeout();
}
/**
* Get the default message mask
*
* @return string
*/
public function getDefaultMessageMask(){
return $this->default_message_mask;
}
/**
* Get the default events for a given section
* @param $section
*
* @return array
*/
public function getDefaultEvents($section){
return $this->events[$section];
}
/**
* Set the default message mask
* @param $mask
*
* @return $this
* @throws MaskNotFoundException
*/
public function setDefaultMessageMask($mask) {
if(class_exists($mask)) {
$this->default_message_mask = $mask;
return $this;
}
throw new MaskNotFoundException("Unknown mask provided: ".$mask);
}
/**
* Get the default attachment mask
*
* @return string
*/
public function getDefaultAttachmentMask(){
return $this->default_attachment_mask;
}
/**
* Set the default attachment mask
* @param $mask
*
* @return $this
* @throws MaskNotFoundException
*/
public function setDefaultAttachmentMask($mask) {
if(class_exists($mask)) {
$this->default_attachment_mask = $mask;
return $this;
}
throw new MaskNotFoundException("Unknown mask provided: ".$mask);
}
}

View File

@@ -0,0 +1,262 @@
<?php
/*
* File: ClientManager.php
* Category: -
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
/**
* Class ClientManager
*
* @package Webklex\IMAP
*
* @mixin Client
*/
class ClientManager {
/**
* All library config
*
* @var array $config
*/
public static $config = [];
/**
* @var array $accounts
*/
protected $accounts = [];
/**
* ClientManager constructor.
* @param array|string $config
*/
public function __construct($config = []) {
$this->setConfig($config);
}
/**
* Dynamically pass calls to the default account.
* @param string $method
* @param array $parameters
*
* @return mixed
* @throws Exceptions\MaskNotFoundException
*/
public function __call($method, $parameters) {
$callable = [$this->account(), $method];
return call_user_func_array($callable, $parameters);
}
/**
* Safely create a new client instance which is not listed in accounts
* @param array $config
*
* @return Client
* @throws Exceptions\MaskNotFoundException
*/
public function make($config) {
return new Client($config);
}
/**
* Get a dotted config parameter
* @param string $key
* @param null $default
*
* @return mixed|null
*/
public static function get($key, $default = null) {
$parts = explode('.', $key);
$value = null;
foreach($parts as $part) {
if($value === null) {
if(isset(self::$config[$part])) {
$value = self::$config[$part];
}else{
break;
}
}else{
if(isset($value[$part])) {
$value = $value[$part];
}else{
break;
}
}
}
return $value === null ? $default : $value;
}
/**
* Resolve a account instance.
* @param string $name
*
* @return Client
* @throws Exceptions\MaskNotFoundException
*/
public function account($name = null) {
$name = $name ?: $this->getDefaultAccount();
// If the connection has not been resolved yet we will resolve it now as all
// of the connections are resolved when they are actually needed so we do
// not make any unnecessary connection to the various queue end-points.
if (!isset($this->accounts[$name])) {
$this->accounts[$name] = $this->resolve($name);
}
return $this->accounts[$name];
}
/**
* Resolve a account.
*
* @param string $name
*
* @return Client
* @throws Exceptions\MaskNotFoundException
*/
protected function resolve($name) {
$config = $this->getClientConfig($name);
return new Client($config);
}
/**
* Get the account configuration.
* @param string $name
*
* @return array
*/
protected function getClientConfig($name) {
if ($name === null || $name === 'null') {
return ['driver' => 'null'];
}
return self::$config["accounts"][$name];
}
/**
* Get the name of the default account.
*
* @return string
*/
public function getDefaultAccount() {
return self::$config['default'];
}
/**
* Set the name of the default account.
* @param string $name
*
* @return void
*/
public function setDefaultAccount($name) {
self::$config['default'] = $name;
}
/**
* Merge the vendor settings with the local config
*
* The default account identifier will be used as default for any missing account parameters.
* If however the default account is missing a parameter the package default account parameter will be used.
* This can be disabled by setting imap.default in your config file to 'false'
*
* @param array|string $config
*
* @return $this
*/
public function setConfig($config) {
if(is_array($config) === false) {
$config = require $config;
}
$config_key = 'imap';
$path = __DIR__.'/config/'.$config_key.'.php';
$vendor_config = require $path;
$config = $this->array_merge_recursive_distinct($vendor_config, $config);
if(is_array($config)){
if(isset($config['default'])){
if(isset($config['accounts']) && $config['default'] != false){
$default_config = $vendor_config['accounts']['default'];
if(isset($config['accounts'][$config['default']])){
$default_config = array_merge($default_config, $config['accounts'][$config['default']]);
}
if(is_array($config['accounts'])){
foreach($config['accounts'] as $account_key => $account){
$config['accounts'][$account_key] = array_merge($default_config, $account);
}
}
}
}
}
self::$config = $config;
return $this;
}
/**
* Marge arrays recursively and distinct
*
* Merges any number of arrays / parameters recursively, replacing
* entries with string keys with values from latter arrays.
* If the entry or the next value to be assigned is an array, then it
* automatically treats both arguments as an array.
* Numeric entries are appended, not replaced, but only if they are
* unique
*
* @param array $array1 Initial array to merge.
* @param array ... Variable list of arrays to recursively merge.
*
* @return array|mixed
*
* @link http://www.php.net/manual/en/function.array-merge-recursive.php#96201
* @author Mark Roduner <mark.roduner@gmail.com>
*/
private function array_merge_recursive_distinct() {
$arrays = func_get_args();
$base = array_shift($arrays);
if(!is_array($base)) $base = empty($base) ? array() : array($base);
foreach($arrays as $append) {
if(!is_array($append)) $append = array($append);
foreach($append as $key => $value) {
if(!array_key_exists($key, $base) and !is_numeric($key)) {
$base[$key] = $append[$key];
continue;
}
if(is_array($value) or is_array($base[$key])) {
$base[$key] = $this->array_merge_recursive_distinct($base[$key], $append[$key]);
} else if(is_numeric($key)) {
if(!in_array($value, $base)) $base[] = $value;
} else {
$base[$key] = $value;
}
}
}
return $base;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,607 @@
<?php
/*
* File: LegacyProtocol.php
* Category: Protocol
* Author: M.Goldenbaum
* Created: 16.09.20 18:27
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Connection\Protocols;
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Exceptions\AuthFailedException;
use Webklex\PHPIMAP\Exceptions\MethodNotSupportedException;
use Webklex\PHPIMAP\Exceptions\RuntimeException;
use Webklex\PHPIMAP\IMAP;
/**
* Class LegacyProtocol
*
* @package Webklex\PHPIMAP\Connection\Protocols
*/
class LegacyProtocol extends Protocol {
protected $protocol = "imap";
protected $host = null;
protected $port = null;
protected $encryption = null;
/**
* Imap constructor.
* @param bool $cert_validation set to false to skip SSL certificate validation
* @param mixed $encryption Connection encryption method
*/
public function __construct($cert_validation = true, $encryption = false) {
$this->setCertValidation($cert_validation);
$this->encryption = $encryption;
}
/**
* Public destructor
*/
public function __destruct() {
$this->logout();
}
/**
* Save the information for a nw connection
* @param string $host
* @param null $port
*/
public function connect($host, $port = null) {
if ($this->encryption) {
$encryption = strtolower($this->encryption);
if ($encryption == "ssl") {
$port = $port === null ? 993 : $port;
}
}
$port = $port === null ? 143 : $port;
$this->host = $host;
$this->port = $port;
}
/**
* Login to a new session.
* @param string $user username
* @param string $password password
*
* @return bool
* @throws AuthFailedException
* @throws RuntimeException
*/
public function login($user, $password) {
try {
$this->stream = \imap_open(
$this->getAddress(),
$user,
$password,
0,
$attempts = 3,
ClientManager::get('options.open')
);
} catch (\ErrorException $e) {
$errors = \imap_errors();
$message = $e->getMessage().'. '.implode("; ", (is_array($errors) ? $errors : array()));
throw new AuthFailedException($message);
}
if(!$this->stream) {
$errors = \imap_errors();
$message = implode("; ", (is_array($errors) ? $errors : array()));
throw new AuthFailedException($message);
}
$errors = \imap_errors();
if(is_array($errors)) {
$status = $this->examineFolder();
if($status['exists'] !== 0) {
$message = implode("; ", (is_array($errors) ? $errors : array()));
throw new RuntimeException($message);
}
}
return $this->stream;
}
/**
* Authenticate your current session.
* @param string $user username
* @param string $token access token
*
* @return bool|resource
* @throws AuthFailedException|RuntimeException
*/
public function authenticate($user, $token) {
return $this->login($user, $token);
}
/**
* Get full address of mailbox.
*
* @return string
*/
protected function getAddress() {
$address = "{".$this->host.":".$this->port."/".$this->protocol;
if (!$this->cert_validation) {
$address .= '/novalidate-cert';
}
if (in_array($this->encryption,['tls', 'notls', 'ssl'])) {
$address .= '/'.$this->encryption;
} elseif ($this->encryption === "starttls") {
$address .= '/tls';
}
$address .= '}';
return $address;
}
/**
* Logout of the current session
*
* @return bool success
*/
public function logout() {
if ($this->stream) {
$result = \imap_close($this->stream, IMAP::CL_EXPUNGE);
$this->stream = false;
return $result;
}
return false;
}
/**
* Check if the current session is connected
*
* @return bool
*/
public function connected(){
return boolval($this->stream);
}
/**
* Get an array of available capabilities
*
* @throws MethodNotSupportedException
*/
public function getCapabilities() {
throw new MethodNotSupportedException();
}
/**
* Change the current folder
* @param string $folder change to this folder
*
* @return bool|array see examineOrselect()
* @throws RuntimeException
*/
public function selectFolder($folder = 'INBOX') {
\imap_reopen($this->stream, $folder, IMAP::OP_READONLY, 3);
return $this->examineFolder($folder);
}
/**
* Examine a given folder
* @param string $folder examine this folder
*
* @return bool|array
* @throws RuntimeException
*/
public function examineFolder($folder = 'INBOX') {
if (strpos($folder, ".") === 0) {
throw new RuntimeException("Segmentation fault prevented. Folders starts with an illegal char '.'.");
}
$folder = $this->getAddress().$folder;
$status = \imap_status($this->stream, $folder, IMAP::SA_ALL);
return [
"flags" => [],
"exists" => $status->messages,
"recent" => $status->recent,
"unseen" => $status->unseen,
"uidnext" => $status->uidnext,
];
}
/**
* Fetch message content
* @param array|int $uids
* @param string $rfc
* @param bool $uid set to true if passing a unique id
*
* @return array
*/
public function content($uids, $rfc = "RFC822", $uid = false) {
$result = [];
$uids = is_array($uids) ? $uids : [$uids];
foreach ($uids as $id) {
$result[$id] = \imap_fetchbody($this->stream, $id, "", $uid ? IMAP::FT_UID : IMAP::NIL);
}
return $result;
}
/**
* Fetch message headers
* @param array|int $uids
* @param string $rfc
* @param bool $uid set to true if passing a unique id
*
* @return array
*/
public function headers($uids, $rfc = "RFC822", $uid = false){
$result = [];
$uids = is_array($uids) ? $uids : [$uids];
foreach ($uids as $id) {
$result[$id] = \imap_fetchheader($this->stream, $id, $uid ? IMAP::FT_UID : IMAP::NIL);
}
return $result;
}
/**
* Fetch message flags
* @param array|int $uids
* @param bool $uid set to true if passing a unique id
*
* @return array
*/
public function flags($uids, $uid = false){
$result = [];
$uids = is_array($uids) ? $uids : [$uids];
foreach ($uids as $id) {
$raw_flags = \imap_fetch_overview($this->stream, $id, $uid ? IMAP::FT_UID : IMAP::NIL);
$flags = [];
if (is_array($raw_flags) && isset($raw_flags[0])) {
$raw_flags = (array) $raw_flags[0];
foreach($raw_flags as $flag => $value) {
if ($value === 1 && in_array($flag, ["size", "uid", "msgno", "update"]) === false){
$flags[] = "\\".ucfirst($flag);
}
}
}
$result[$uid] = $flags;
}
return $result;
}
/**
* Get uid for a given id
* @param int|null $id message number
*
* @return array|string message number for given message or all messages as array
*/
public function getUid($id = null) {
if ($id === null) {
$overview = $this->overview("1:*");
$uids = [];
foreach($overview as $set){
$uids[$set->msgno] = $set->uid;
}
return $uids;
}
return \imap_uid($this->stream, $id);
}
/**
* Get a message number for a uid
* @param string $id uid
*
* @return int message number
*/
public function getMessageNumber($id) {
return \imap_msgno($this->stream, $id);
}
/**
* Get a message overview
* @param string $sequence uid sequence
* @param bool $uid set to true if passing a unique id
*
* @return array
*/
public function overview($sequence, $uid = false) {
return \imap_fetch_overview($this->stream, $sequence,$uid ? IMAP::FT_UID : IMAP::NIL);
}
/**
* Get a list of available folders
* @param string $reference mailbox reference for list
* @param string $folder mailbox name match with wildcards
*
* @return array folders that matched $folder as array(name => array('delimiter' => .., 'flags' => ..))
* @throws RuntimeException
*/
public function folders($reference = '', $folder = '*') {
$result = [];
$items = \imap_getmailboxes($this->stream, $this->getAddress(), $reference.$folder);
if(is_array($items)){
foreach ($items as $item) {
$name = $this->decodeFolderName($item->name);
$result[$name] = ['delimiter' => $item->delimiter, 'flags' => []];
}
}else{
throw new RuntimeException(\imap_last_error());
}
return $result;
}
/**
* Manage flags
* @param array $flags flags to set, add or remove - see $mode
* @param int $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given
* @param bool $silent if false the return values are the new flags for the wanted messages
* @param bool $uid set to true if passing a unique id
*
* @return bool|array new flags if $silent is false, else true or false depending on success
*/
public function store(array $flags, $from, $to = null, $mode = null, $silent = true, $uid = false) {
$flag = trim(is_array($flags) ? implode(" ", $flags) : $flags);
if ($mode == "+"){
$status = \imap_setflag_full($this->stream, $from, $flag, $uid ? IMAP::FT_UID : IMAP::NIL);
}else{
$status = \imap_clearflag_full($this->stream, $from, $flag, $uid ? IMAP::FT_UID : IMAP::NIL);
}
if ($silent === true) {
return $status;
}
return $this->flags($from);
}
/**
* Append a new message to given folder
* @param string $folder name of target folder
* @param string $message full message content
* @param array $flags flags for new message
* @param string $date date for new message
*
* @return bool success
*/
public function appendMessage($folder, $message, $flags = null, $date = null) {
if ($date != null) {
if ($date instanceof \Carbon\Carbon){
$date = $date->format('d-M-Y H:i:s O');
}
return \imap_append($this->stream, $folder, $message, $flags, $date);
}
return \imap_append($this->stream, $folder, $message, $flags);
}
/**
* Copy message set from current folder to other folder
* @param string $folder destination folder
* @param $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
*
* @return bool success
*/
public function copyMessage($folder, $from, $to = null, $uid = false) {
return \imap_mail_copy($this->stream, $from, $folder, $uid ? IMAP::FT_UID : IMAP::NIL);
}
/**
* Copy multiple messages to the target folder
*
* @param array<string> $messages List of message identifiers
* @param string $folder Destination folder
* @param bool $uid Set to true if you pass message unique identifiers instead of numbers
* @return array|bool Tokens if operation successful, false if an error occurred
*/
public function copyManyMessages($messages, $folder, $uid = false) {
foreach($messages as $msg) {
if ($this->copyMessage($folder, $msg, null, $uid) == false) {
return false;
}
}
return $messages;
}
/**
* Move a message set from current folder to an other folder
* @param string $folder destination folder
* @param $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
*
* @return bool success
*/
public function moveMessage($folder, $from, $to = null, $uid = false) {
return \imap_mail_move($this->stream, $from, $folder, $uid ? IMAP::FT_UID : IMAP::NIL);
}
/**
* Move multiple messages to the target folder
*
* @param array<string> $messages List of message identifiers
* @param string $folder Destination folder
* @param bool $uid Set to true if you pass message unique identifiers instead of numbers
* @return array|bool Tokens if operation successful, false if an error occurred
*/
public function moveManyMessages($messages, $folder, $uid = false) {
foreach($messages as $msg) {
if ($this->moveMessage($folder, $msg, null, $uid) == false) {
return false;
}
}
return $messages;
}
/**
* Create a new folder (and parent folders if needed)
* @param string $folder folder name
*
* @return bool success
*/
public function createFolder($folder) {
return \imap_createmailbox($this->stream, $folder);
}
/**
* Rename an existing folder
* @param string $old old name
* @param string $new new name
*
* @return bool success
*/
public function renameFolder($old, $new) {
return \imap_renamemailbox($this->stream, $old, $new);
}
/**
* Delete a folder
* @param string $folder folder name
*
* @return bool success
*/
public function deleteFolder($folder) {
return \imap_deletemailbox($this->stream, $folder);
}
/**
* Subscribe to a folder
* @param string $folder folder name
*
* @throws MethodNotSupportedException
*/
public function subscribeFolder($folder) {
throw new MethodNotSupportedException();
}
/**
* Unsubscribe from a folder
* @param string $folder folder name
*
* @throws MethodNotSupportedException
*/
public function unsubscribeFolder($folder) {
throw new MethodNotSupportedException();
}
/**
* Apply session saved changes to the server
*
* @return bool success
*/
public function expunge() {
return \imap_expunge($this->stream);
}
/**
* Send noop command
*
* @throws MethodNotSupportedException
*/
public function noop() {
throw new MethodNotSupportedException();
}
/**
* Send idle command
*
* @throws MethodNotSupportedException
*/
public function idle() {
throw new MethodNotSupportedException();
}
/**
* Send done command
*
* @throws MethodNotSupportedException
*/
public function done() {
throw new MethodNotSupportedException();
}
/**
* Search for matching messages
*
* @param array $params
* @return array message ids
*/
public function search(array $params, $uid = false) {
return \imap_search($this->stream, $params[0], $uid ? IMAP::FT_UID : IMAP::NIL);
}
/**
* Enable the debug mode
*/
public function enableDebug(){
$this->debug = true;
}
/**
* Disable the debug mode
*/
public function disableDebug(){
$this->debug = false;
}
/**
* Decode name.
* It converts UTF7-IMAP encoding to UTF-8.
*
* @param $name
*
* @return mixed|string
*/
protected function decodeFolderName($name) {
preg_match('#\{(.*)\}(.*)#', $name, $preg);
return mb_convert_encoding($preg[2], "UTF-8", "UTF7-IMAP");
}
/**
* @return string
*/
public function getProtocol() {
return $this->protocol;
}
/**
* Retrieve the quota level settings, and usage statics per mailbox
* @param $username
*
* @return array
*/
public function getQuota($username) {
return \imap_get_quota($this->stream, 'user.'.$username);
}
/**
* Retrieve the quota settings per user
* @param string $quota_root
*
* @return array
*/
public function getQuotaRoot($quota_root = 'INBOX') {
return \imap_get_quotaroot($this->stream, $quota_root);
}
/**
* @param string $protocol
* @return LegacyProtocol
*/
public function setProtocol($protocol) {
if (($pos = strpos($protocol, "legacy")) > 0) {
$protocol = substr($protocol, 0, ($pos + 2) * -1);
}
$this->protocol = $protocol;
return $this;
}
}

View File

@@ -0,0 +1,224 @@
<?php
/*
* File: ImapProtocol.php
* Category: Protocol
* Author: M.Goldenbaum
* Created: 16.09.20 18:27
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Connection\Protocols;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
/**
* Class Protocol
*
* @package Webklex\PHPIMAP\Connection\Protocols
*/
abstract class Protocol implements ProtocolInterface {
/**
* Default connection timeout in seconds
*/
protected $connection_timeout = 30;
/**
* @var boolean
*/
protected $debug = false;
/**
* @var false|resource
*/
public $stream = false;
/**
* Connection encryption method
* @var mixed $encryption
*/
protected $encryption = false;
/**
* Set to false to ignore SSL certificate validation
* @var bool
*/
protected $cert_validation = true;
/**
* Proxy settings
* @var array
*/
protected $proxy = [
'socket' => null,
'request_fulluri' => false,
'username' => null,
'password' => null,
];
/**
* Get an available cryptographic method
*
* @return int
*/
public function getCryptoMethod() {
// Allow the best TLS version(s) we can
$cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT;
// PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
// so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
}elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) {
$cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
return $cryptoMethod;
}
/**
* Enable SSL certificate validation
*
* @return $this
*/
public function enableCertValidation() {
$this->cert_validation = true;
return $this;
}
/**
* Disable SSL certificate validation
* @return $this
*/
public function disableCertValidation() {
$this->cert_validation = false;
return $this;
}
/**
* Set SSL certificate validation
* @var int $cert_validation
*
* @return $this
*/
public function setCertValidation($cert_validation) {
$this->cert_validation = $cert_validation;
return $this;
}
/**
* Should we validate SSL certificate?
*
* @return bool
*/
public function getCertValidation() {
return $this->cert_validation;
}
/**
* Set connection proxy settings
* @var array $options
*
* @return $this
*/
public function setProxy($options) {
foreach ($this->proxy as $key => $val) {
if (isset($options[$key])) {
$this->proxy[$key] = $options[$key];
}
}
return $this;
}
/**
* Get the current proxy settings
*
* @return array
*/
public function getProxy() {
return $this->proxy;
}
/**
* Prepare socket options
* @var string $transport
*
* @return array
*/
private function defaultSocketOptions($transport) {
$options = [];
if ($this->encryption != false) {
$options["ssl"] = [
'verify_peer_name' => $this->getCertValidation(),
'verify_peer' => $this->getCertValidation(),
];
}
if ($this->proxy["socket"] != null) {
$options[$transport]["proxy"] = $this->proxy["socket"];
$options[$transport]["request_fulluri"] = $this->proxy["request_fulluri"];
if ($this->proxy["username"] != null) {
$auth = base64_encode($this->proxy["username"].':'.$this->proxy["password"]);
$options[$transport]["header"] = [
"Proxy-Authorization: Basic $auth"
];
}
}
return $options;
}
/**
* Create a new resource stream
* @param $transport
* @param string $host hostname or IP address of IMAP server
* @param int $port of IMAP server, default is 143 (993 for ssl)
* @param int $timeout timeout in seconds for initiating session
*
* @return resource|boolean The socket created.
* @throws ConnectionFailedException
*/
protected function createStream($transport, $host, $port, $timeout) {
$socket = "$transport://$host:$port";
$stream = stream_socket_client($socket, $errno, $errstr, $timeout,
STREAM_CLIENT_CONNECT,
stream_context_create($this->defaultSocketOptions($transport))
);
stream_set_timeout($stream, $timeout);
if (!$stream) {
throw new ConnectionFailedException($errstr, $errno);
}
if (false === stream_set_timeout($stream, $timeout)) {
throw new ConnectionFailedException('Failed to set stream timeout');
}
return $stream;
}
/**
* @return int
*/
public function getConnectionTimeout() {
return $this->connection_timeout;
}
/**
* @param int $connection_timeout
* @return Protocol
*/
public function setConnectionTimeout($connection_timeout) {
if ($connection_timeout !== null) {
$this->connection_timeout = $connection_timeout;
}
return $this;
}
}

View File

@@ -0,0 +1,375 @@
<?php
/*
* File: ImapProtocol.php
* Category: Protocol
* Author: M.Goldenbaum
* Created: 16.09.20 18:27
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Connection\Protocols;
use ErrorException;
use Webklex\PHPIMAP\Exceptions\AuthFailedException;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
use Webklex\PHPIMAP\Exceptions\MessageNotFoundException;
use Webklex\PHPIMAP\Exceptions\RuntimeException;
/**
* Interface ProtocolInterface
*
* @package Webklex\PHPIMAP\Connection\Protocols
*/
interface ProtocolInterface {
/**
* Protocol constructor.
* @param bool $cert_validation set to false to skip SSL certificate validation
*/
public function __construct($cert_validation = true);
/**
* Public destructor
*/
public function __destruct();
/**
* Open a new connection / session
* @param string $host hostname or IP address of IMAP server
* @param int|null $port of service server
*
* @throws ErrorException
* @throws ConnectionFailedException
* @throws RuntimeException
*/
public function connect($host, $port = null);
/**
* Login to a new session.
*
* @param string $user username
* @param string $password password
* @return bool success
* @throws AuthFailedException
*/
public function login($user, $password);
/**
* Authenticate your current session.
* @param string $user username
* @param string $token access token
*
* @return bool|mixed
* @throws AuthFailedException
*/
public function authenticate($user, $token);
/**
* Logout of the current server session
*
* @return bool success
*/
public function logout();
/**
* Check if the current session is connected
*
* @return bool
*/
public function connected();
/**
* Get an array of available capabilities
*
* @return array list of capabilities
* @throws RuntimeException
*/
public function getCapabilities();
/**
* Change the current folder
*
* @param string $folder change to this folder
* @return bool|array see examineOrselect()
* @throws RuntimeException
*/
public function selectFolder($folder = 'INBOX');
/**
* Examine a given folder
*
* @param string $folder
* @return bool|array
* @throws RuntimeException
*/
public function examineFolder($folder = 'INBOX');
/**
* Fetch message headers
* @param array|int $uids
* @param string $rfc
* @param bool $uid set to true if passing a unique id
*
* @return array
* @throws RuntimeException
*/
public function content($uids, $rfc = "RFC822", $uid = false);
/**
* Fetch message headers
* @param array|int $uids
* @param string $rfc
* @param bool $uid set to true if passing a unique id
*
* @return array
* @throws RuntimeException
*/
public function headers($uids, $rfc = "RFC822", $uid = false);
/**
* Fetch message flags
* @param array|int $uids
* @param bool $uid set to true if passing a unique id
*
* @return array
* @throws RuntimeException
*/
public function flags($uids, $uid = false);
/**
* Get uid for a given id
* @param int|null $id message number
*
* @return array|string message number for given message or all messages as array
* @throws MessageNotFoundException
*/
public function getUid($id = null);
/**
* Get a message number for a uid
* @param string $id uid
*
* @return int message number
* @throws MessageNotFoundException
*/
public function getMessageNumber($id);
/**
* Get a list of available folders
*
* @param string $reference mailbox reference for list
* @param string $folder mailbox / folder name match with wildcards
* @return array mailboxes that matched $folder as array(globalName => array('delim' => .., 'flags' => ..))
* @throws RuntimeException
*/
public function folders($reference = '', $folder = '*');
/**
* Set message flags
*
* @param array $flags flags to set, add or remove
* @param int $from message for items or start message if $to !== null
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given
* @param bool $silent if false the return values are the new flags for the wanted messages
* @param bool $uid set to true if passing a unique id
*
* @return bool|array new flags if $silent is false, else true or false depending on success
* @throws RuntimeException
*/
public function store(array $flags, $from, $to = null, $mode = null, $silent = true, $uid = false);
/**
* Append a new message to given folder
*
* @param string $folder name of target folder
* @param string $message full message content
* @param array $flags flags for new message
* @param string $date date for new message
* @return bool success
* @throws RuntimeException
*/
public function appendMessage($folder, $message, $flags = null, $date = null);
/**
* Copy message set from current folder to other folder
*
* @param string $folder destination folder
* @param $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
*
* @return bool success
* @throws RuntimeException
*/
public function copyMessage($folder, $from, $to = null, $uid = false);
/**
* Copy multiple messages to the target folder
*
* @param array<string> $messages List of message identifiers
* @param string $folder Destination folder
* @param bool $uid Set to true if you pass message unique identifiers instead of numbers
* @return array|bool Tokens if operation successful, false if an error occurred
*
* @throws RuntimeException
*/
public function copyManyMessages($messages, $folder, $uid = false);
/**
* Move a message set from current folder to an other folder
* @param string $folder destination folder
* @param $from
* @param int|null $to if null only one message ($from) is fetched, else it's the
* last message, INF means last message available
* @param bool $uid set to true if passing a unique id
*
* @return bool success
*/
public function moveMessage($folder, $from, $to = null, $uid = false);
/**
* Move multiple messages to the target folder
*
* @param array<string> $messages List of message identifiers
* @param string $folder Destination folder
* @param bool $uid Set to true if you pass message unique identifiers instead of numbers
* @return array|bool Tokens if operation successful, false if an error occurred
*
* @throws RuntimeException
*/
public function moveManyMessages($messages, $folder, $uid = false);
/**
* Create a new folder
*
* @param string $folder folder name
* @return bool success
* @throws RuntimeException
*/
public function createFolder($folder);
/**
* Rename an existing folder
*
* @param string $old old name
* @param string $new new name
* @return bool success
* @throws RuntimeException
*/
public function renameFolder($old, $new);
/**
* Delete a folder
*
* @param string $folder folder name
* @return bool success
* @throws RuntimeException
*/
public function deleteFolder($folder);
/**
* Subscribe to a folder
*
* @param string $folder folder name
* @return bool success
* @throws RuntimeException
*/
public function subscribeFolder($folder);
/**
* Unsubscribe from a folder
* @param string $folder folder name
*
* @return bool success
* @throws RuntimeException
*/
public function unsubscribeFolder($folder);
/**
* Send idle command
*
* @throws RuntimeException
*/
public function idle();
/**
* Send done command
* @throws RuntimeException
*/
public function done();
/**
* Apply session saved changes to the server
*
* @return bool success
* @throws RuntimeException
*/
public function expunge();
/**
* Retrieve the quota level settings, and usage statics per mailbox
* @param $username
*
* @return array
* @throws RuntimeException
*/
public function getQuota($username);
/**
* Retrieve the quota settings per user
*
* @param string $quota_root
*
* @return array
* @throws ConnectionFailedException
*/
public function getQuotaRoot($quota_root = 'INBOX');
/**
* Send noop command
*
* @return bool success
* @throws RuntimeException
*/
public function noop();
/**
* Do a search request
*
* @param array $params
* @param bool $uid set to true if passing a unique id
*
* @return array message ids
* @throws RuntimeException
*/
public function search(array $params, $uid = false);
/**
* Get a message overview
* @param string $sequence uid sequence
* @param bool $uid set to true if passing a unique id
*
* @return array
* @throws RuntimeException
* @throws MessageNotFoundException
* @throws InvalidMessageDateException
*/
public function overview($sequence, $uid = false);
/**
* Enable the debug mode
*/
public function enableDebug();
/**
* Disable the debug mode
*/
public function disableDebug();
}

View File

@@ -0,0 +1,482 @@
<?php
/*
* File: EncodingAliases.php
* Category: -
* Author: S. Todorov (https://github.com/todorowww)
* Created: 23.04.18 14:16
* Updated: -
*
* Description:
* Contains email encoding aliases, thta can occur when fetching emails. These sometimes can break icvon()
* This file attempts to correct this by using a list of aliases and their mappings to supported iconv() encodings
*/
namespace Webklex\PHPIMAP;
/**
* Class EncodingAliases
*
* @package Webklex\PHPIMAP
*/
class EncodingAliases {
/**
* Contains email encoding mappings
*
* @var array
*/
private static $aliases = [
/*
|--------------------------------------------------------------------------
| Email encoding aliases
|--------------------------------------------------------------------------
|
| Email encoding aliases used to convert to iconv supported charsets
|
|
| This Source Code Form is subject to the terms of the Mozilla Public
| License, v. 2.0. If a copy of the MPL was not distributed with this
| file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| This Original Code has been modified by IBM Corporation.
| Modifications made by IBM described herein are
| Copyright (c) International Business Machines
| Corporation, 1999
|
| Modifications to Mozilla code or documentation
| identified per MPL Section 3.3
|
| Date Modified by Description of modification
| 12/09/1999 IBM Corp. Support for IBM codepages - 850,852,855,857,862,864
|
| Rule of this file:
| 1. key should always be in lower case ascii so we can do case insensitive
| comparison in the code faster.
| 2. value should be the one used in unicode converter
|
| 3. If the charset is not used for document charset, but font charset
| (e.g. XLFD charset- such as JIS x0201, JIS x0208), don't put here
|
*/
"ascii" => "us-ascii",
"us-ascii" => "us-ascii",
"ansi_x3.4-1968" => "us-ascii",
"646" => "us-ascii",
"iso-8859-1" => "ISO-8859-1",
"iso-8859-2" => "ISO-8859-2",
"iso-8859-3" => "ISO-8859-3",
"iso-8859-4" => "ISO-8859-4",
"iso-8859-5" => "ISO-8859-5",
"iso-8859-6" => "ISO-8859-6",
"iso-8859-6-i" => "ISO-8859-6-I",
"iso-8859-6-e" => "ISO-8859-6-E",
"iso-8859-7" => "ISO-8859-7",
"iso-8859-8" => "ISO-8859-8",
"iso-8859-8-i" => "ISO-8859-8-I",
"iso-8859-8-e" => "ISO-8859-8-E",
"iso-8859-9" => "ISO-8859-9",
"iso-8859-10" => "ISO-8859-10",
"iso-8859-11" => "ISO-8859-11",
"iso-8859-13" => "ISO-8859-13",
"iso-8859-14" => "ISO-8859-14",
"iso-8859-15" => "ISO-8859-15",
"iso-8859-16" => "ISO-8859-16",
"iso-ir-111" => "ISO-IR-111",
"iso-2022-cn" => "ISO-2022-CN",
"iso-2022-cn-ext" => "ISO-2022-CN",
"iso-2022-kr" => "ISO-2022-KR",
"iso-2022-jp" => "ISO-2022-JP",
"utf-16be" => "UTF-16BE",
"utf-16le" => "UTF-16LE",
"utf-16" => "UTF-16",
"windows-1250" => "windows-1250",
"windows-1251" => "windows-1251",
"windows-1252" => "windows-1252",
"windows-1253" => "windows-1253",
"windows-1254" => "windows-1254",
"windows-1255" => "windows-1255",
"windows-1256" => "windows-1256",
"windows-1257" => "windows-1257",
"windows-1258" => "windows-1258",
"ibm866" => "IBM866",
"ibm850" => "IBM850",
"ibm852" => "IBM852",
"ibm855" => "IBM855",
"ibm857" => "IBM857",
"ibm862" => "IBM862",
"ibm864" => "IBM864",
"utf-8" => "UTF-8",
"utf-7" => "UTF-7",
"shift_jis" => "Shift_JIS",
"big5" => "Big5",
"euc-jp" => "EUC-JP",
"euc-kr" => "EUC-KR",
"gb2312" => "GB2312",
"gb18030" => "gb18030",
"viscii" => "VISCII",
"koi8-r" => "KOI8-R",
"koi8_r" => "KOI8-R",
"cskoi8r" => "KOI8-R",
"koi" => "KOI8-R",
"koi8" => "KOI8-R",
"koi8-u" => "KOI8-U",
"tis-620" => "TIS-620",
"t.61-8bit" => "T.61-8bit",
"hz-gb-2312" => "HZ-GB-2312",
"big5-hkscs" => "Big5-HKSCS",
"gbk" => "gbk",
"cns11643" => "x-euc-tw",
//
// Aliases for ISO-8859-1
//
"latin1" => "ISO-8859-1",
"iso_8859-1" => "ISO-8859-1",
"iso8859-1" => "ISO-8859-1",
"iso8859-2" => "ISO-8859-2",
"iso8859-3" => "ISO-8859-3",
"iso8859-4" => "ISO-8859-4",
"iso8859-5" => "ISO-8859-5",
"iso8859-6" => "ISO-8859-6",
"iso8859-7" => "ISO-8859-7",
"iso8859-8" => "ISO-8859-8",
"iso8859-9" => "ISO-8859-9",
"iso8859-10" => "ISO-8859-10",
"iso8859-11" => "ISO-8859-11",
"iso8859-13" => "ISO-8859-13",
"iso8859-14" => "ISO-8859-14",
"iso8859-15" => "ISO-8859-15",
"iso_8859-1:1987" => "ISO-8859-1",
"iso-ir-100" => "ISO-8859-1",
"l1" => "ISO-8859-1",
"ibm819" => "ISO-8859-1",
"cp819" => "ISO-8859-1",
"csisolatin1" => "ISO-8859-1",
//
// Aliases for ISO-8859-2
//
"latin2" => "ISO-8859-2",
"iso_8859-2" => "ISO-8859-2",
"iso_8859-2:1987" => "ISO-8859-2",
"iso-ir-101" => "ISO-8859-2",
"l2" => "ISO-8859-2",
"csisolatin2" => "ISO-8859-2",
//
// Aliases for ISO-8859-3
//
"latin3" => "ISO-8859-3",
"iso_8859-3" => "ISO-8859-3",
"iso_8859-3:1988" => "ISO-8859-3",
"iso-ir-109" => "ISO-8859-3",
"l3" => "ISO-8859-3",
"csisolatin3" => "ISO-8859-3",
//
// Aliases for ISO-8859-4
//
"latin4" => "ISO-8859-4",
"iso_8859-4" => "ISO-8859-4",
"iso_8859-4:1988" => "ISO-8859-4",
"iso-ir-110" => "ISO-8859-4",
"l4" => "ISO-8859-4",
"csisolatin4" => "ISO-8859-4",
//
// Aliases for ISO-8859-5
//
"cyrillic" => "ISO-8859-5",
"iso_8859-5" => "ISO-8859-5",
"iso_8859-5:1988" => "ISO-8859-5",
"iso-ir-144" => "ISO-8859-5",
"csisolatincyrillic" => "ISO-8859-5",
//
// Aliases for ISO-8859-6
//
"arabic" => "ISO-8859-6",
"iso_8859-6" => "ISO-8859-6",
"iso_8859-6:1987" => "ISO-8859-6",
"iso-ir-127" => "ISO-8859-6",
"ecma-114" => "ISO-8859-6",
"asmo-708" => "ISO-8859-6",
"csisolatinarabic" => "ISO-8859-6",
//
// Aliases for ISO-8859-6-I
//
"csiso88596i" => "ISO-8859-6-I",
//
// Aliases for ISO-8859-6-E",
//
"csiso88596e" => "ISO-8859-6-E",
//
// Aliases for ISO-8859-7",
//
"greek" => "ISO-8859-7",
"greek8" => "ISO-8859-7",
"sun_eu_greek" => "ISO-8859-7",
"iso_8859-7" => "ISO-8859-7",
"iso_8859-7:1987" => "ISO-8859-7",
"iso-ir-126" => "ISO-8859-7",
"elot_928" => "ISO-8859-7",
"ecma-118" => "ISO-8859-7",
"csisolatingreek" => "ISO-8859-7",
//
// Aliases for ISO-8859-8",
//
"hebrew" => "ISO-8859-8",
"iso_8859-8" => "ISO-8859-8",
"visual" => "ISO-8859-8",
"iso_8859-8:1988" => "ISO-8859-8",
"iso-ir-138" => "ISO-8859-8",
"csisolatinhebrew" => "ISO-8859-8",
//
// Aliases for ISO-8859-8-I",
//
"csiso88598i" => "ISO-8859-8-I",
"iso-8859-8i" => "ISO-8859-8-I",
"logical" => "ISO-8859-8-I",
//
// Aliases for ISO-8859-8-E",
//
"csiso88598e" => "ISO-8859-8-E",
//
// Aliases for ISO-8859-9",
//
"latin5" => "ISO-8859-9",
"iso_8859-9" => "ISO-8859-9",
"iso_8859-9:1989" => "ISO-8859-9",
"iso-ir-148" => "ISO-8859-9",
"l5" => "ISO-8859-9",
"csisolatin5" => "ISO-8859-9",
//
// Aliases for UTF-8",
//
"unicode-1-1-utf-8" => "UTF-8",
// nl_langinfo(CODESET) in HP/UX returns 'utf8' under UTF-8 locales",
"utf8" => "UTF-8",
//
// Aliases for Shift_JIS",
//
"x-sjis" => "Shift_JIS",
"shift-jis" => "Shift_JIS",
"ms_kanji" => "Shift_JIS",
"csshiftjis" => "Shift_JIS",
"windows-31j" => "Shift_JIS",
"cp932" => "Shift_JIS",
"sjis" => "Shift_JIS",
//
// Aliases for EUC_JP",
//
"cseucpkdfmtjapanese" => "EUC-JP",
"x-euc-jp" => "EUC-JP",
//
// Aliases for ISO-2022-JP",
//
"csiso2022jp" => "ISO-2022-JP",
// The following are really not aliases ISO-2022-JP, but sharing the same decoder",
"iso-2022-jp-2" => "ISO-2022-JP",
"csiso2022jp2" => "ISO-2022-JP",
//
// Aliases for Big5",
//
"csbig5" => "Big5",
"cn-big5" => "Big5",
// x-x-big5 is not really a alias for Big5, add it only for MS FrontPage",
"x-x-big5" => "Big5",
// Sun Solaris",
"zh_tw-big5" => "Big5",
//
// Aliases for EUC-KR",
//
"cseuckr" => "EUC-KR",
"ks_c_5601-1987" => "EUC-KR",
"iso-ir-149" => "EUC-KR",
"ks_c_5601-1989" => "EUC-KR",
"ksc_5601" => "EUC-KR",
"ksc5601" => "EUC-KR",
"korean" => "EUC-KR",
"csksc56011987" => "EUC-KR",
"5601" => "EUC-KR",
"windows-949" => "EUC-KR",
//
// Aliases for GB2312",
//
// The following are really not aliases GB2312, add them only for MS FrontPage",
"gb_2312-80" => "GB2312",
"iso-ir-58" => "GB2312",
"chinese" => "GB2312",
"csiso58gb231280" => "GB2312",
"csgb2312" => "GB2312",
"zh_cn.euc" => "GB2312",
// Sun Solaris",
"gb_2312" => "GB2312",
//
// Aliases for windows-125x ",
//
"x-cp1250" => "windows-1250",
"x-cp1251" => "windows-1251",
"x-cp1252" => "windows-1252",
"x-cp1253" => "windows-1253",
"x-cp1254" => "windows-1254",
"x-cp1255" => "windows-1255",
"x-cp1256" => "windows-1256",
"x-cp1257" => "windows-1257",
"x-cp1258" => "windows-1258",
//
// Aliases for windows-874 ",
//
"windows-874" => "windows-874",
"ibm874" => "windows-874",
"dos-874" => "windows-874",
//
// Aliases for macintosh",
//
"macintosh" => "macintosh",
"x-mac-roman" => "macintosh",
"mac" => "macintosh",
"csmacintosh" => "macintosh",
//
// Aliases for IBM866",
//
"cp866" => "IBM866",
"cp-866" => "IBM866",
"866" => "IBM866",
"csibm866" => "IBM866",
//
// Aliases for IBM850",
//
"cp850" => "IBM850",
"850" => "IBM850",
"csibm850" => "IBM850",
//
// Aliases for IBM852",
//
"cp852" => "IBM852",
"852" => "IBM852",
"csibm852" => "IBM852",
//
// Aliases for IBM855",
//
"cp855" => "IBM855",
"855" => "IBM855",
"csibm855" => "IBM855",
//
// Aliases for IBM857",
//
"cp857" => "IBM857",
"857" => "IBM857",
"csibm857" => "IBM857",
//
// Aliases for IBM862",
//
"cp862" => "IBM862",
"862" => "IBM862",
"csibm862" => "IBM862",
//
// Aliases for IBM864",
//
"cp864" => "IBM864",
"864" => "IBM864",
"csibm864" => "IBM864",
"ibm-864" => "IBM864",
//
// Aliases for T.61-8bit",
//
"t.61" => "T.61-8bit",
"iso-ir-103" => "T.61-8bit",
"csiso103t618bit" => "T.61-8bit",
//
// Aliases for UTF-7",
//
"x-unicode-2-0-utf-7" => "UTF-7",
"unicode-2-0-utf-7" => "UTF-7",
"unicode-1-1-utf-7" => "UTF-7",
"csunicode11utf7" => "UTF-7",
//
// Aliases for ISO-10646-UCS-2",
//
"csunicode" => "UTF-16BE",
"csunicode11" => "UTF-16BE",
"iso-10646-ucs-basic" => "UTF-16BE",
"csunicodeascii" => "UTF-16BE",
"iso-10646-unicode-latin1" => "UTF-16BE",
"csunicodelatin1" => "UTF-16BE",
"iso-10646" => "UTF-16BE",
"iso-10646-j-1" => "UTF-16BE",
//
// Aliases for ISO-8859-10",
//
"latin6" => "ISO-8859-10",
"iso-ir-157" => "ISO-8859-10",
"l6" => "ISO-8859-10",
// Currently .properties cannot handle : in key",
//iso_8859-10:1992" => "ISO-8859-10",
"csisolatin6" => "ISO-8859-10",
//
// Aliases for ISO-8859-15",
//
"iso_8859-15" => "ISO-8859-15",
"csisolatin9" => "ISO-8859-15",
"l9" => "ISO-8859-15",
//
// Aliases for ISO-IR-111",
//
"ecma-cyrillic" => "ISO-IR-111",
"csiso111ecmacyrillic" => "ISO-IR-111",
//
// Aliases for ISO-2022-KR",
//
"csiso2022kr" => "ISO-2022-KR",
//
// Aliases for VISCII",
//
"csviscii" => "VISCII",
//
// Aliases for x-euc-tw",
//
"zh_tw-euc" => "x-euc-tw",
//
// Following names appears in unix nl_langinfo(CODESET)",
// They can be compiled as platform specific if necessary",
// DONT put things here if it does not look generic enough (like hp15CN)",
//
"iso88591" => "ISO-8859-1",
"iso88592" => "ISO-8859-2",
"iso88593" => "ISO-8859-3",
"iso88594" => "ISO-8859-4",
"iso88595" => "ISO-8859-5",
"iso88596" => "ISO-8859-6",
"iso88597" => "ISO-8859-7",
"iso88598" => "ISO-8859-8",
"iso88599" => "ISO-8859-9",
"iso885910" => "ISO-8859-10",
"iso885911" => "ISO-8859-11",
"iso885912" => "ISO-8859-12",
"iso885913" => "ISO-8859-13",
"iso885914" => "ISO-8859-14",
"iso885915" => "ISO-8859-15",
"cp1250" => "windows-1250",
"cp1251" => "windows-1251",
"cp1252" => "windows-1252",
"cp1253" => "windows-1253",
"cp1254" => "windows-1254",
"cp1255" => "windows-1255",
"cp1256" => "windows-1256",
"cp1257" => "windows-1257",
"cp1258" => "windows-1258",
"x-gbk" => "gbk",
"windows-936" => "gbk",
"ansi-1251" => "windows-1251",
];
/**
* Returns proper encoding mapping, if exsists. If it doesn't, return unchanged $encoding
* @param string $encoding
* @param string|null $fallback
*
* @return string
*/
public static function get($encoding, $fallback = null) {
if (isset(self::$aliases[strtolower($encoding)])) {
return self::$aliases[strtolower($encoding)];
}
return $fallback !== null ? $fallback : $encoding;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/*
* File: Event.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class Event
*
* @package Webklex\PHPIMAP\Events
*/
abstract class Event {
/**
* Dispatch the event with the given arguments.
*/
public static function dispatch() {
return new static(func_get_args());
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: FlagDeletedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class FlagDeletedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class FlagDeletedEvent extends FlagNewEvent {
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* File: FlagNewEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
use Webklex\PHPIMAP\Message;
/**
* Class FlagNewEvent
*
* @package Webklex\PHPIMAP\Events
*/
class FlagNewEvent extends Event {
/** @var Message $message */
public $message;
/** @var string $flag */
public $flag;
/**
* Create a new event instance.
* @var mixed[] $arguments
* @return void
*/
public function __construct($arguments) {
$this->message = $arguments[0];
$this->flag = $arguments[1];
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: FolderDeletedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class FolderDeletedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class FolderDeletedEvent extends FolderNewEvent {
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* File: FolderMovedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
use Webklex\PHPIMAP\Folder;
/**
* Class FolderMovedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class FolderMovedEvent extends Event {
/** @var Folder $old_folder */
public $old_folder;
/** @var Folder $new_folder */
public $new_folder;
/**
* Create a new event instance.
* @var Folder[] $folders
* @return void
*/
public function __construct($folders) {
$this->old_folder = $folders[0];
$this->new_folder = $folders[1];
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* File: FolderNewEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
use Webklex\PHPIMAP\Folder;
/**
* Class FolderNewEvent
*
* @package Webklex\PHPIMAP\Events
*/
class FolderNewEvent extends Event {
/** @var Folder $folder */
public $folder;
/**
* Create a new event instance.
* @var Folder[] $folders
* @return void
*/
public function __construct($folders) {
$this->folder = $folders[0];
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: MessageCopiedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class MessageCopiedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class MessageCopiedEvent extends MessageMovedEvent {
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: MessageDeletedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class MessageDeletedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class MessageDeletedEvent extends MessageNewEvent {
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* File: MessageMovedEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
use Webklex\PHPIMAP\Message;
/**
* Class MessageMovedEvent
*
* @package Webklex\PHPIMAP\Events
*/
class MessageMovedEvent extends Event {
/** @var Message $old_message */
public $old_message;
/** @var Message $new_message */
public $new_message;
/**
* Create a new event instance.
* @var Message[] $messages
* @return void
*/
public function __construct($messages) {
$this->old_message = $messages[0];
$this->new_message = $messages[1];
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* File: MessageNewEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
use Webklex\PHPIMAP\Message;
/**
* Class MessageNewEvent
*
* @package Webklex\PHPIMAP\Events
*/
class MessageNewEvent extends Event {
/** @var Message $message */
public $message;
/**
* Create a new event instance.
* @var Message[] $messages
* @return void
*/
public function __construct($messages) {
$this->message = $messages[0];
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: MessageRestoredEvent.php
* Category: Event
* Author: M. Goldenbaum
* Created: 25.11.20 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Events;
/**
* Class MessageRestoredEvent
*
* @package Webklex\PHPIMAP\Events
*/
class MessageRestoredEvent extends MessageNewEvent {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: AuthFailedException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class AuthFailedException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class AuthFailedException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: ConnectionFailedException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class ConnectionFailedException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class ConnectionFailedException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: EventNotFoundException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class EventNotFoundException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class EventNotFoundException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: FolderFetchingException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class FolderFetchingException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class FolderFetchingException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: GetMessagesFailedException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class GetMessagesFailedException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class GetMessagesFailedException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: InvalidMessageDateException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 10.03.19 04:31
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class InvalidMessageDateException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class InvalidMessageDateException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: InvalidWhereQueryCriteriaException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 21.07.18 19:04
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class InvalidWhereQueryCriteriaException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class InvalidWhereQueryCriteriaException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MaskNotFoundException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MaskNotFoundException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MaskNotFoundException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MessageContentFetchingException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MessageContentFetchingException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MessageContentFetchingException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MessageFlagException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 02.01.21 02:47
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MessageFlagException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MessageFlagException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MessageHeaderFetchingException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MessageHeaderFetchingException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MessageHeaderFetchingException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MessageNotFoundException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 25.01.21 18:19
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MessageNotFoundException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MessageNotFoundException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MessageSearchValidationException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MessageSearchValidationException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MessageSearchValidationException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MethodNotFoundException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MethodNotFoundException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MethodNotFoundException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: MethodNotSupportedException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 05.03.18 23:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class MethodNotSupportedException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class MethodNotSupportedException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: ProtocolNotSupportedException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class ProtocolNotSupportedException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class ProtocolNotSupportedException extends Exception {
}

View File

@@ -0,0 +1,24 @@
<?php
/*
* File: RuntimeException.php
* Category: Exception
* Author: M. Goldenbaum
* Created: 19.01.17 22:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Exceptions;
use \Exception;
/**
* Class RuntimeException
*
* @package Webklex\PHPIMAP\Exceptions
*/
class RuntimeException extends Exception {
}

View File

@@ -0,0 +1,444 @@
<?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;
}
}

View File

@@ -0,0 +1,753 @@
<?php
/*
* File: Header.php
* Category: -
* Author: M.Goldenbaum
* Created: 17.09.20 20:38
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use Carbon\Carbon;
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
use Webklex\PHPIMAP\Exceptions\MethodNotFoundException;
/**
* Class Header
*
* @package Webklex\PHPIMAP
*/
class Header {
/**
* Raw header
*
* @var string $raw
*/
public $raw = "";
/**
* Attribute holder
*
* @var Attribute[]|array $attributes
*/
protected $attributes = [];
/**
* Config holder
*
* @var array $config
*/
protected $config = [];
/**
* Fallback Encoding
*
* @var string
*/
public $fallback_encoding = 'UTF-8';
/**
* Convert parsed values to attributes
*
* @var bool
*/
protected $attributize = false;
/**
* Header constructor.
* @param string $raw_header
* @param boolean $attributize
*
* @throws InvalidMessageDateException
*/
public function __construct($raw_header, $attributize = true) {
$this->raw = $raw_header;
$this->config = ClientManager::get('options');
$this->attributize = $attributize;
$this->parse();
}
/**
* Call dynamic attribute setter and getter methods
* @param string $method
* @param array $arguments
*
* @return Attribute|mixed
* @throws MethodNotFoundException
*/
public function __call($method, $arguments) {
if(strtolower(substr($method, 0, 3)) === 'get') {
$name = preg_replace('/(.)(?=[A-Z])/u', '$1_', substr(strtolower($method), 3));
if(in_array($name, array_keys($this->attributes))) {
return $this->attributes[$name];
}
}
throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
}
/**
* Magic getter
* @param $name
*
* @return Attribute|null
*/
public function __get($name) {
return $this->get($name);
}
/**
* Get a specific header attribute
* @param $name
*
* @return Attribute|mixed
*/
public function get($name) {
if(isset($this->attributes[$name])) {
return $this->attributes[$name];
}
return null;
}
/**
* Set a specific attribute
* @param string $name
* @param array|mixed $value
* @param boolean $strict
*
* @return Attribute
*/
public function set($name, $value, $strict = false) {
if(isset($this->attributes[$name]) && $strict === false) {
if ($this->attributize) {
$this->attributes[$name]->add($value, true);
}else{
if(isset($this->attributes[$name])) {
if (is_array($this->attributes[$name]) == false) {
$this->attributes[$name] = [$this->attributes[$name], $value];
}else{
$this->attributes[$name][] = $value;
}
}else{
$this->attributes[$name] = $value;
}
}
}elseif($this->attributize == false){
$this->attributes[$name] = $value;
}else{
$this->attributes[$name] = new Attribute($name, $value);
}
return $this->attributes[$name];
}
/**
* Perform a regex match all on the raw header and return the first result
* @param $pattern
*
* @return mixed|null
*/
public function find($pattern) {
if (preg_match_all($pattern, $this->raw, $matches)) {
if (isset($matches[1])) {
if(count($matches[1]) > 0) {
return $matches[1][0];
}
}
}
return null;
}
/**
* Try to find a boundary if possible
*
* @return string|null
*/
public function getBoundary(){
$boundary = $this->find("/boundary\=(.*)/i");
if ($boundary === null) {
return null;
}
return $this->clearBoundaryString($boundary);
}
/**
* Remove all unwanted chars from a given boundary
* @param string $str
*
* @return string
*/
private function clearBoundaryString($str) {
return str_replace(['"', '\r', '\n', "\n", "\r", ";", "\s"], "", $str);
}
/**
* Parse the raw headers
*
* @throws InvalidMessageDateException
*/
protected function parse(){
$header = $this->rfc822_parse_headers($this->raw);
$this->extractAddresses($header);
if (property_exists($header, 'subject')) {
$this->set("subject", $this->decode($header->subject));
}
if (property_exists($header, 'references')) {
$this->set("references", $this->decode($header->references));
}
if (property_exists($header, 'message_id')) {
$this->set("message_id", str_replace(['<', '>'], '', $header->message_id));
}
$this->parseDate($header);
foreach ($header as $key => $value) {
$key = trim(rtrim(strtolower($key)));
if(!isset($this->attributes[$key])){
$this->set($key, $value);
}
}
$this->extractHeaderExtensions();
$this->findPriority();
}
/**
* Parse mail headers from a string
* @link https://php.net/manual/en/function.imap-rfc822-parse-headers.php
* @param $raw_headers
*
* @return object
*/
public function rfc822_parse_headers($raw_headers){
$headers = [];
$imap_headers = [];
if (extension_loaded('imap') && $this->config["rfc822"]) {
$raw_imap_headers = (array) \imap_rfc822_parse_headers($this->raw);
foreach($raw_imap_headers as $key => $values) {
$key = str_replace("-", "_", $key);
$imap_headers[$key] = $values;
}
}
$lines = explode("\r\n", str_replace("\r\n\t", ' ', $raw_headers));
$prev_header = null;
foreach($lines as $line) {
if (substr($line, 0, 1) === "\n") {
$line = substr($line, 1);
}
if (substr($line, 0, 1) === "\t") {
$line = substr($line, 1);
$line = trim(rtrim($line));
if ($prev_header !== null) {
$headers[$prev_header][] = $line;
}
}elseif (substr($line, 0, 1) === " ") {
$line = substr($line, 1);
$line = trim(rtrim($line));
if ($prev_header !== null) {
if (!isset($headers[$prev_header])) {
$headers[$prev_header] = "";
}
if (is_array($headers[$prev_header])) {
$headers[$prev_header][] = $line;
}else{
$headers[$prev_header] .= $line;
}
}
}else{
if (($pos = strpos($line, ":")) > 0) {
$key = trim(rtrim(strtolower(substr($line, 0, $pos))));
$key = str_replace("-", "_", $key);
$value = trim(rtrim(substr($line, $pos + 1)));
if (isset($headers[$key])) {
$headers[$key][] = $value;
}else{
$headers[$key] = [$value];
}
$prev_header = $key;
}
}
}
foreach($headers as $key => $values) {
if (isset($imap_headers[$key])) continue;
$value = null;
switch($key){
case 'from':
case 'to':
case 'cc':
case 'bcc':
case 'reply_to':
case 'sender':
$value = $this->decodeAddresses($values);
$headers[$key."address"] = implode(", ", $values);
break;
case 'subject':
$value = implode(" ", $values);
break;
default:
if (is_array($values)) {
foreach($values as $k => $v) {
if ($v == "") {
unset($values[$k]);
}
}
$available_values = count($values);
if ($available_values === 1) {
$value = array_pop($values);
} elseif ($available_values === 2) {
$value = implode(" ", $values);
} elseif ($available_values > 2) {
$value = array_values($values);
} else {
$value = "";
}
}
break;
}
$headers[$key] = $value;
}
return (object) array_merge($headers, $imap_headers);
}
/**
* Decode MIME header elements
* @link https://php.net/manual/en/function.imap-mime-header-decode.php
* @param string $text The MIME text
*
* @return array The decoded elements are returned in an array of objects, where each
* object has two properties, charset and text.
*/
public function mime_header_decode($text){
if (extension_loaded('imap')) {
return \imap_mime_header_decode($text);
}
$charset = $this->getEncoding($text);
return [(object)[
"charset" => $charset,
"text" => $this->convertEncoding($text, $charset)
]];
}
/**
* Check if a given pair of strings has ben decoded
* @param $encoded
* @param $decoded
*
* @return bool
*/
private function notDecoded($encoded, $decoded) {
return 0 === strpos($decoded, '=?')
&& strlen($decoded) - 2 === strpos($decoded, '?=')
&& false !== strpos($encoded, $decoded);
}
/**
* Convert the encoding
* @param $str
* @param string $from
* @param string $to
*
* @return mixed|string
*/
public function convertEncoding($str, $from = "ISO-8859-2", $to = "UTF-8") {
$from = EncodingAliases::get($from, $this->fallback_encoding);
$to = EncodingAliases::get($to, $this->fallback_encoding);
if ($from === $to) {
return $str;
}
// We don't need to do convertEncoding() if charset is ASCII (us-ascii):
// ASCII is a subset of UTF-8, so all ASCII files are already UTF-8 encoded
// https://stackoverflow.com/a/11303410
//
// us-ascii is the same as ASCII:
// ASCII is the traditional name for the encoding system; the Internet Assigned Numbers Authority (IANA)
// prefers the updated name US-ASCII, which clarifies that this system was developed in the US and
// based on the typographical symbols predominantly in use there.
// https://en.wikipedia.org/wiki/ASCII
//
// convertEncoding() function basically means convertToUtf8(), so when we convert ASCII string into UTF-8 it gets broken.
if (strtolower($from) == 'us-ascii' && $to == 'UTF-8') {
return $str;
}
try {
if (function_exists('iconv') && $from != 'UTF-7' && $to != 'UTF-7') {
return iconv($from, $to, $str);
} else {
if (!$from) {
return mb_convert_encoding($str, $to);
}
return mb_convert_encoding($str, $to, $from);
}
} catch (\Exception $e) {
if (strstr($from, '-')) {
$from = str_replace('-', '', $from);
return $this->convertEncoding($str, $from, $to);
} else {
return $str;
}
}
}
/**
* Get the encoding of a given abject
* @param object|string $structure
*
* @return string
*/
public function getEncoding($structure) {
if (property_exists($structure, 'parameters')) {
foreach ($structure->parameters as $parameter) {
if (strtolower($parameter->attribute) == "charset") {
return EncodingAliases::get($parameter->value, $this->fallback_encoding);
}
}
}elseif (property_exists($structure, 'charset')) {
return EncodingAliases::get($structure->charset, $this->fallback_encoding);
}elseif (is_string($structure) === true){
return mb_detect_encoding($structure);
}
return $this->fallback_encoding;
}
/**
* Test if a given value is utf-8 encoded
* @param $value
*
* @return bool
*/
private function is_uft8($value) {
return strpos(strtolower($value), '=?utf-8?') === 0;
}
/**
* Try to decode a specific header
* @param mixed $value
*
* @return mixed
*/
private function decode($value) {
if (is_array($value)) {
return $this->decodeArray($value);
}
$original_value = $value;
$decoder = $this->config['decoder']['message'];
if ($value !== null) {
$is_utf8_base = $this->is_uft8($value);
if($decoder === 'utf-8' && extension_loaded('imap')) {
$value = \imap_utf8($value);
$is_utf8_base = $this->is_uft8($value);
if ($is_utf8_base) {
$value = mb_decode_mimeheader($value);
}
if ($this->notDecoded($original_value, $value)) {
$decoded_value = $this->mime_header_decode($value);
if (count($decoded_value) > 0) {
if(property_exists($decoded_value[0], "text")) {
$value = $decoded_value[0]->text;
}
}
}
}elseif($decoder === 'iconv' && $is_utf8_base) {
$value = iconv_mime_decode($value);
}elseif($is_utf8_base){
$value = mb_decode_mimeheader($value);
}
if ($this->is_uft8($value)) {
$value = mb_decode_mimeheader($value);
}
if ($this->notDecoded($original_value, $value)) {
$value = $this->convertEncoding($original_value, $this->getEncoding($original_value));
}
}
return $value;
}
/**
* Decode a given array
* @param array $values
*
* @return array
*/
private function decodeArray($values) {
foreach($values as $key => $value) {
$values[$key] = $this->decode($value);
}
return $values;
}
/**
* Try to extract the priority from a given raw header string
*/
private function findPriority() {
if(($priority = $this->get("x_priority")) === null) return;
switch((int)"$priority"){
case IMAP::MESSAGE_PRIORITY_HIGHEST;
$priority = IMAP::MESSAGE_PRIORITY_HIGHEST;
break;
case IMAP::MESSAGE_PRIORITY_HIGH;
$priority = IMAP::MESSAGE_PRIORITY_HIGH;
break;
case IMAP::MESSAGE_PRIORITY_NORMAL;
$priority = IMAP::MESSAGE_PRIORITY_NORMAL;
break;
case IMAP::MESSAGE_PRIORITY_LOW;
$priority = IMAP::MESSAGE_PRIORITY_LOW;
break;
case IMAP::MESSAGE_PRIORITY_LOWEST;
$priority = IMAP::MESSAGE_PRIORITY_LOWEST;
break;
default:
$priority = IMAP::MESSAGE_PRIORITY_UNKNOWN;
break;
}
$this->set("priority", $priority);
}
/**
* Extract a given part as address array from a given header
* @param $values
*
* @return array
*/
private function decodeAddresses($values) {
$addresses = [];
if (extension_loaded('mailparse') && $this->config["rfc822"]) {
foreach ($values as $address) {
foreach (\mailparse_rfc822_parse_addresses($address) as $parsed_address) {
if (isset($parsed_address['address'])) {
$mail_address = explode('@', $parsed_address['address']);
if (count($mail_address) == 2) {
$addresses[] = (object)[
"personal" => isset($parsed_address['display']) ? $parsed_address['display'] : '',
"mailbox" => $mail_address[0],
"host" => $mail_address[1],
];
}
}
}
}
return $addresses;
}
foreach($values as $address) {
foreach (preg_split('/, (?=(?:[^"]*"[^"]*")*[^"]*$)/', $address) as $split_address) {
$split_address = trim(rtrim($split_address));
if (strpos($split_address, ",") == strlen($split_address) - 1) {
$split_address = substr($split_address, 0, -1);
}
if (preg_match(
'/^(?:(?P<name>.+)\s)?(?(name)<|<?)(?P<email>[^\s]+?)(?(name)>|>?)$/',
$split_address,
$matches
)) {
$name = trim(rtrim($matches["name"]));
$email = trim(rtrim($matches["email"]));
list($mailbox, $host) = array_pad(explode("@", $email), 2, null);
$addresses[] = (object)[
"personal" => $name,
"mailbox" => $mailbox,
"host" => $host,
];
}
}
}
return $addresses;
}
/**
* Extract a given part as address array from a given header
* @param object $header
*/
private function extractAddresses($header) {
foreach(['from', 'to', 'cc', 'bcc', 'reply_to', 'sender'] as $key){
if (property_exists($header, $key)) {
$this->set($key, $this->parseAddresses($header->$key));
}
}
}
/**
* Parse Addresses
* @param $list
*
* @return array
*/
private function parseAddresses($list) {
$addresses = [];
if (is_array($list) === false) {
return $addresses;
}
foreach ($list as $item) {
$address = (object) $item;
if (!property_exists($address, 'mailbox')) {
$address->mailbox = false;
}
if (!property_exists($address, 'host')) {
$address->host = false;
}
if (!property_exists($address, 'personal')) {
$address->personal = false;
} else {
$personalParts = $this->mime_header_decode($address->personal);
if(is_array($personalParts)) {
$address->personal = '';
foreach ($personalParts as $p) {
$address->personal .= $this->convertEncoding($p->text, $this->getEncoding($p));
}
}
if (strpos($address->personal, "'") === 0) {
$address->personal = str_replace("'", "", $address->personal);
}
}
$address->mail = ($address->mailbox && $address->host) ? $address->mailbox.'@'.$address->host : false;
$address->full = ($address->personal) ? $address->personal.' <'.$address->mail.'>' : $address->mail;
$addresses[] = new Address($address);
}
return $addresses;
}
/**
* Search and extract potential header extensions
*/
private function extractHeaderExtensions(){
foreach ($this->attributes as $key => $value) {
if (is_array($value)) {
$value = implode(", ", $value);
}else{
$value = (string)$value;
}
// Only parse strings and don't parse any attributes like the user-agent
if (in_array($key, ["user_agent"]) === false) {
if (($pos = strpos($value, ";")) !== false){
$original = substr($value, 0, $pos);
$this->set($key, trim(rtrim($original)), true);
// Get all potential extensions
$extensions = explode(";", substr($value, $pos + 1));
foreach($extensions as $extension) {
if (($pos = strpos($extension, "=")) !== false){
$key = substr($extension, 0, $pos);
$key = trim(rtrim(strtolower($key)));
if (isset($this->attributes[$key]) === false) {
$value = substr($extension, $pos + 1);
$value = str_replace('"', "", $value);
$value = trim(rtrim($value));
$this->set($key, $value);
}
}
}
}
}
}
}
/**
* Exception handling for invalid dates
*
* Currently known invalid formats:
* ^ Datetime ^ Problem ^ Cause
* | Mon, 20 Nov 2017 20:31:31 +0800 (GMT+8:00) | Double timezone specification | A Windows feature
* | Thu, 8 Nov 2018 08:54:58 -0200 (-02) |
* | | and invalid timezone (max 6 char) |
* | 04 Jan 2018 10:12:47 UT | Missing letter "C" | Unknown
* | Thu, 31 May 2018 18:15:00 +0800 (added by) | Non-standard details added by the | Unknown
* | | mail server |
* | Sat, 31 Aug 2013 20:08:23 +0580 | Invalid timezone | PHPMailer bug https://sourceforge.net/p/phpmailer/mailman/message/6132703/
*
* Please report any new invalid timestamps to [#45](https://github.com/Webklex/php-imap/issues)
*
* @param object $header
*
* @throws InvalidMessageDateException
*/
private function parseDate($header) {
if (property_exists($header, 'date')) {
$parsed_date = null;
$date = $header->date;
if(preg_match('/\+0580/', $date)) {
$date = str_replace('+0580', '+0530', $date);
}
$date = trim(rtrim($date));
try {
$parsed_date = Carbon::parse($date);
} catch (\Exception $e) {
switch (true) {
case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0:
case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ UT)+$/i', $date) > 0:
$date .= 'C';
break;
case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ \+[0-9]{2,4}\ \(\+[0-9]{1,2}\))+$/i', $date) > 0:
case preg_match('/([A-Z]{2,3}[\,|\ \,]\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}.*)+$/i', $date) > 0:
case preg_match('/([A-Z]{2,3}\,\ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0:
case preg_match('/([A-Z]{2,3}\, \ [0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{4}\ [0-9]{1,2}\:[0-9]{1,2}\:[0-9]{1,2}\ [\-|\+][0-9]{4}\ \(.*)\)+$/i', $date) > 0:
case preg_match('/([0-9]{1,2}\ [A-Z]{2,3}\ [0-9]{2,4}\ [0-9]{2}\:[0-9]{2}\:[0-9]{2}\ [A-Z]{2}\ \-[0-9]{2}\:[0-9]{2}\ \([A-Z]{2,3}\ \-[0-9]{2}:[0-9]{2}\))+$/i', $date) > 0:
$array = explode('(', $date);
$array = array_reverse($array);
$date = trim(array_pop($array));
break;
}
try{
$parsed_date = Carbon::parse($date);
} catch (\Exception $_e) {
throw new InvalidMessageDateException("Invalid message date. ID:".$this->get("message_id"), 1100, $e);
}
}
$this->set("date", $parsed_date);
}
}
/**
* Get all available attributes
*
* @return array
*/
public function getAttributes() {
return $this->attributes;
}
}

View File

@@ -0,0 +1,375 @@
<?php
/*
* File: IMAP.php
* Category: -
* Author: M.Goldenbaum
* Created: 14.03.19 18:22
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
/**
* Class IMAP
*
* Independent imap const holder
*/
class IMAP {
/**
* Message const
*
* @const integer TYPE_TEXT
* @const integer TYPE_MULTIPART
*
* @const integer ENC_7BIT
* @const integer ENC_8BIT
* @const integer ENC_BINARY
* @const integer ENC_BASE64
* @const integer ENC_QUOTED_PRINTABLE
* @const integer ENC_OTHER
*/
const MESSAGE_TYPE_TEXT = 0;
const MESSAGE_TYPE_MULTIPART = 1;
const MESSAGE_ENC_7BIT = 0;
const MESSAGE_ENC_8BIT = 1;
const MESSAGE_ENC_BINARY = 2;
const MESSAGE_ENC_BASE64 = 3;
const MESSAGE_ENC_QUOTED_PRINTABLE = 4;
const MESSAGE_ENC_OTHER = 5;
const MESSAGE_PRIORITY_UNKNOWN = 0;
const MESSAGE_PRIORITY_HIGHEST = 1;
const MESSAGE_PRIORITY_HIGH = 2;
const MESSAGE_PRIORITY_NORMAL = 3;
const MESSAGE_PRIORITY_LOW = 4;
const MESSAGE_PRIORITY_LOWEST = 5;
/**
* Attachment const
*
* @const integer TYPE_TEXT
* @const integer TYPE_MULTIPART
* @const integer TYPE_MESSAGE
* @const integer TYPE_APPLICATION
* @const integer TYPE_AUDIO
* @const integer TYPE_IMAGE
* @const integer TYPE_VIDEO
* @const integer TYPE_MODEL
* @const integer TYPE_OTHER
*/
const ATTACHMENT_TYPE_TEXT = 0;
const ATTACHMENT_TYPE_MULTIPART = 1;
const ATTACHMENT_TYPE_MESSAGE = 2;
const ATTACHMENT_TYPE_APPLICATION = 3;
const ATTACHMENT_TYPE_AUDIO = 4;
const ATTACHMENT_TYPE_IMAGE = 5;
const ATTACHMENT_TYPE_VIDEO = 6;
const ATTACHMENT_TYPE_MODEL = 7;
const ATTACHMENT_TYPE_OTHER = 8;
/**
* Client const
*
* @const integer CLIENT_OPENTIMEOUT
* @const integer CLIENT_READTIMEOUT
* @const integer CLIENT_WRITETIMEOUT
* @const integer CLIENT_CLOSETIMEOUT
*/
const CLIENT_OPENTIMEOUT = 1;
const CLIENT_READTIMEOUT = 2;
const CLIENT_WRITETIMEOUT = 3;
const CLIENT_CLOSETIMEOUT = 4;
/**
* Generic imap const
*
* @const integer NIL
* @const integer IMAP_OPENTIMEOUT
* @const integer IMAP_READTIMEOUT
* @const integer IMAP_WRITETIMEOUT
* @const integer IMAP_CLOSETIMEOUT
* @const integer OP_DEBUG
* @const integer OP_READONLY
* @const integer OP_ANONYMOUS
* @const integer OP_SHORTCACHE
* @const integer OP_SILENT
* @const integer OP_PROTOTYPE
* @const integer OP_HALFOPEN
* @const integer OP_EXPUNGE
* @const integer OP_SECURE
* @const integer CL_EXPUNGE
* @const integer FT_UID
* @const integer FT_PEEK
* @const integer FT_NOT
* @const integer FT_INTERNAL
* @const integer FT_PREFETCHTEXT
* @const integer ST_UID
* @const integer ST_SILENT
* @const integer ST_SET
* @const integer CP_UID
* @const integer CP_MOVE
* @const integer SE_UID
* @const integer SE_FREE
* @const integer SE_NOPREFETCH
* @const integer SO_FREE
* @const integer SO_NOSERVER
* @const integer SA_MESSAGES
* @const integer SA_RECENT
* @const integer SA_UNSEEN
* @const integer SA_UIDNEXT
* @const integer SA_UIDVALIDITY
* @const integer SA_ALL
* @const integer LATT_NOINFERIORS
* @const integer LATT_NOSELECT
* @const integer LATT_MARKED
* @const integer LATT_UNMARKED
* @const integer LATT_REFERRAL
* @const integer LATT_HASCHILDREN
* @const integer LATT_HASNOCHILDREN
* @const integer SORTDATE
* @const integer SORTARRIVAL
* @const integer SORTFROM
* @const integer SORTSUBJECT
* @const integer SORTTO
* @const integer SORTCC
* @const integer SORTSIZE
* @const integer TYPETEXT
* @const integer TYPEMULTIPART
* @const integer TYPEMESSAGE
* @const integer TYPEAPPLICATION
* @const integer TYPEAUDIO
* @const integer TYPEIMAGE
* @const integer TYPEVIDEO
* @const integer TYPEMODEL
* @const integer TYPEOTHER
* @const integer ENC7BIT
* @const integer ENC8BIT
* @const integer ENCBINARY
* @const integer ENCBASE64
* @const integer ENCQUOTEDPRINTABLE
* @const integer ENCOTHER
* @const integer IMAP_GC_ELT
* @const integer IMAP_GC_ENV
* @const integer IMAP_GC_TEXTS
*/
const NIL = 0;
const IMAP_OPENTIMEOUT = 1;
const IMAP_READTIMEOUT = 2;
const IMAP_WRITETIMEOUT = 3;
const IMAP_CLOSETIMEOUT = 4;
const OP_DEBUG = 1;
/**
* Open mailbox read-only
* @link http://php.net/manual/en/imap.constants.php
*/
const OP_READONLY = 2;
/**
* Don't use or update a .newsrc for news
* (NNTP only)
* @link http://php.net/manual/en/imap.constants.php
*/
const OP_ANONYMOUS = 4;
const OP_SHORTCACHE = 8;
const OP_SILENT = 16;
const OP_PROTOTYPE = 32;
/**
* For IMAP and NNTP
* names, open a connection but don't open a mailbox.
* @link http://php.net/manual/en/imap.constants.php
*/
const OP_HALFOPEN = 64;
const OP_EXPUNGE = 128;
const OP_SECURE = 256;
/**
* silently expunge the mailbox before closing when
* calling <b>imap_close</b>
* @link http://php.net/manual/en/imap.constants.php
*/
const CL_EXPUNGE = 32768;
/**
* The parameter is a UID
* @link http://php.net/manual/en/imap.constants.php
*/
const FT_UID = 1;
/**
* Do not set the \Seen flag if not already set
* @link http://php.net/manual/en/imap.constants.php
*/
const FT_PEEK = 2;
const FT_NOT = 4;
/**
* The return string is in internal format, will not canonicalize to CRLF.
* @link http://php.net/manual/en/imap.constants.php
*/
const FT_INTERNAL = 8;
const FT_PREFETCHTEXT = 32;
/**
* The sequence argument contains UIDs instead of sequence numbers
* @link http://php.net/manual/en/imap.constants.php
*/
const ST_UID = 1;
const ST_SILENT = 2;
const ST_MSGN = 3;
const ST_SET = 4;
/**
* the sequence numbers contain UIDS
* @link http://php.net/manual/en/imap.constants.php
*/
const CP_UID = 1;
/**
* Delete the messages from the current mailbox after copying
* with <b>imap_mail_copy</b>
* @link http://php.net/manual/en/imap.constants.php
*/
const CP_MOVE = 2;
/**
* Return UIDs instead of sequence numbers
* @link http://php.net/manual/en/imap.constants.php
*/
const SE_UID = 1;
const SE_FREE = 2;
/**
* Don't prefetch searched messages
* @link http://php.net/manual/en/imap.constants.php
*/
const SE_NOPREFETCH = 4;
const SO_FREE = 8;
const SO_NOSERVER = 16;
const SA_MESSAGES = 1;
const SA_RECENT = 2;
const SA_UNSEEN = 4;
const SA_UIDNEXT = 8;
const SA_UIDVALIDITY = 16;
const SA_ALL = 31;
/**
* This mailbox has no "children" (there are no
* mailboxes below this one).
* @link http://php.net/manual/en/imap.constants.php
*/
const LATT_NOINFERIORS = 1;
/**
* This is only a container, not a mailbox - you
* cannot open it.
* @link http://php.net/manual/en/imap.constants.php
*/
const LATT_NOSELECT = 2;
/**
* This mailbox is marked. Only used by UW-IMAPD.
* @link http://php.net/manual/en/imap.constants.php
*/
const LATT_MARKED = 4;
/**
* This mailbox is not marked. Only used by
* UW-IMAPD.
* @link http://php.net/manual/en/imap.constants.php
*/
const LATT_UNMARKED = 8;
const LATT_REFERRAL = 16;
const LATT_HASCHILDREN = 32;
const LATT_HASNOCHILDREN = 64;
/**
* Sort criteria for <b>imap_sort</b>:
* message Date
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTDATE = 0;
/**
* Sort criteria for <b>imap_sort</b>:
* arrival date
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTARRIVAL = 1;
/**
* Sort criteria for <b>imap_sort</b>:
* mailbox in first From address
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTFROM = 2;
/**
* Sort criteria for <b>imap_sort</b>:
* message subject
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTSUBJECT = 3;
/**
* Sort criteria for <b>imap_sort</b>:
* mailbox in first To address
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTTO = 4;
/**
* Sort criteria for <b>imap_sort</b>:
* mailbox in first cc address
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTCC = 5;
/**
* Sort criteria for <b>imap_sort</b>:
* size of message in octets
* @link http://php.net/manual/en/imap.constants.php
*/
const SORTSIZE = 6;
const TYPETEXT = 0;
const TYPEMULTIPART = 1;
const TYPEMESSAGE = 2;
const TYPEAPPLICATION = 3;
const TYPEAUDIO = 4;
const TYPEIMAGE = 5;
const TYPEVIDEO = 6;
const TYPEMODEL = 7;
const TYPEOTHER = 8;
const ENC7BIT = 0;
const ENC8BIT = 1;
const ENCBINARY = 2;
const ENCBASE64 = 3;
const ENCQUOTEDPRINTABLE = 4;
const ENCOTHER = 5;
/**
* Garbage collector, clear message cache elements.
* @link http://php.net/manual/en/imap.constants.php
*/
const IMAP_GC_ELT = 1;
/**
* Garbage collector, clear envelopes and bodies.
* @link http://php.net/manual/en/imap.constants.php
*/
const IMAP_GC_ENV = 2;
/**
* Garbage collector, clear texts.
* @link http://php.net/manual/en/imap.constants.php
*/
const IMAP_GC_TEXTS = 4;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,312 @@
<?php
/*
* File: Part.php
* Category: -
* Author: M.Goldenbaum
* Created: 17.09.20 20:38
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
/**
* Class Part
*
* @package Webklex\PHPIMAP
*/
class Part {
/**
* Raw part
*
* @var string $raw
*/
public $raw = "";
/**
* Part type
*
* @var int $type
*/
public $type = IMAP::MESSAGE_TYPE_TEXT;
/**
* Part content
*
* @var string $content
*/
public $content = "";
/**
* Part subtype
*
* @var string $subtype
*/
public $subtype = null;
/**
* Part charset - if available
*
* @var string $charset
*/
public $charset = "utf-8";
/**
* Part encoding method
*
* @var int $encoding
*/
public $encoding = IMAP::MESSAGE_ENC_OTHER;
/**
* Alias to check if the part is an attachment
*
* @var boolean $ifdisposition
*/
public $ifdisposition = false;
/**
* Indicates if the part is an attachment
*
* @var string $disposition
*/
public $disposition = null;
/**
* Alias to check if the part has a description
*
* @var boolean $ifdescription
*/
public $ifdescription = false;
/**
* Part description if available
*
* @var string $description
*/
public $description = null;
/**
* Part filename if available
*
* @var string $filename
*/
public $filename = null;
/**
* Part name if available
*
* @var string $name
*/
public $name = null;
/**
* Part id if available
*
* @var string $id
*/
public $id = null;
/**
* The part number of the current part
*
* @var integer $part_number
*/
public $part_number = 0;
/**
* Part length in bytes
*
* @var integer $bytes
*/
public $bytes = null;
/**
* Part content type
*
* @var string|null $content_type
*/
public $content_type = null;
/**
* @var Header $header
*/
private $header = null;
/**
* Part constructor.
* @param $raw_part
* @param Header $header
* @param integer $part_number
*
* @throws InvalidMessageDateException
*/
public function __construct($raw_part, $header = null, $part_number = 0) {
$this->raw = $raw_part;
$this->header = $header;
$this->part_number = $part_number;
$this->parse();
}
/**
* Parse the raw parts
*
* @throws InvalidMessageDateException
*/
protected function parse(){
if ($this->header === null) {
$body = $this->findHeaders();
}else{
$body = $this->raw;
}
$this->parseDisposition();
$this->parseDescription();
$this->parseEncoding();
$this->charset = $this->header->get("charset");
$this->name = $this->header->get("name");
$this->filename = $this->header->get("filename");
if(!empty($this->header->get("id"))) {
$this->id = $this->header->get("id");
} else if(!empty($this->header->get("x_attachment_id"))){
$this->id = $this->header->get("x_attachment_id");
} else if(!empty($this->header->get("content_id"))){
$this->id = strtr($this->header->get("content_id"), [
'<' => '',
'>' => ''
]);
}
$content_types = $this->header->get("content_type");
if(!empty($content_types)){
$this->subtype = $this->parseSubtype($content_types);
$content_type = $content_types;
if (is_array($content_types)) {
$content_type = $content_types[0];
}
$parts = explode(';', $content_type);
$this->content_type = trim($parts[0]);
}
$this->content = trim(rtrim($body));
$this->bytes = strlen($this->content);
}
/**
* Find all available headers and return the left over body segment
*
* @return string
* @throws InvalidMessageDateException
*/
private function findHeaders(){
$body = $this->raw;
while (($pos = strpos($body, "\r\n")) > 0) {
$body = substr($body, $pos + 2);
}
$headers = substr($this->raw, 0, strlen($body) * -1);
$body = substr($body, 0, -2);
$this->header = new Header($headers);
return (string) $body;
}
/**
* Try to parse the subtype if any is present
* @param $content_type
*
* @return string
*/
private function parseSubtype($content_type){
if (is_array($content_type)) {
foreach ($content_type as $part){
if ((strpos($part, "/")) !== false){
return $this->parseSubtype($part);
}
}
return null;
}
if (($pos = strpos($content_type, "/")) !== false){
return substr($content_type, $pos + 1);
}
return null;
}
/**
* Try to parse the disposition if any is present
*/
private function parseDisposition(){
$content_disposition = $this->header->get("content_disposition");
if($content_disposition !== null) {
$this->ifdisposition = true;
$this->disposition = (is_array($content_disposition)) ? implode(' ', $content_disposition) : $content_disposition;
}
}
/**
* Try to parse the description if any is present
*/
private function parseDescription(){
$content_description = $this->header->get("content_description");
if($content_description !== null) {
$this->ifdescription = true;
$this->description = $content_description;
}
}
/**
* Try to parse the encoding if any is present
*/
private function parseEncoding(){
$encoding = $this->header->get("content_transfer_encoding");
if($encoding !== null) {
switch (strtolower($encoding)) {
case "quoted-printable":
$this->encoding = IMAP::MESSAGE_ENC_QUOTED_PRINTABLE;
break;
case "base64":
$this->encoding = IMAP::MESSAGE_ENC_BASE64;
break;
case "7bit":
$this->encoding = IMAP::MESSAGE_ENC_7BIT;
break;
case "8bit":
$this->encoding = IMAP::MESSAGE_ENC_8BIT;
break;
case "binary":
$this->encoding = IMAP::MESSAGE_ENC_BINARY;
break;
default:
$this->encoding = IMAP::MESSAGE_ENC_OTHER;
break;
}
}
}
/**
* Check if the current part represents an attachment
*
* @return bool
*/
public function isAttachment(){
$valid_disposition = in_array(strtolower($this->disposition), ClientManager::get('options.dispositions'));
if ($this->type == IMAP::MESSAGE_TYPE_TEXT && ($this->ifdisposition == 0 || (empty($this->disposition))) && !$valid_disposition) {
if (($this->subtype == null || in_array((strtolower($this->subtype)), ["plain", "html"])) && $this->filename == null && $this->name == null) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,842 @@
<?php
/*
* File: Query.php
* Category: -
* Author: M. Goldenbaum
* Created: 21.07.18 18:54
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Query;
use Carbon\Carbon;
use Exception;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use ReflectionException;
use Webklex\PHPIMAP\Client;
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
use Webklex\PHPIMAP\Exceptions\EventNotFoundException;
use Webklex\PHPIMAP\Exceptions\GetMessagesFailedException;
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException;
use Webklex\PHPIMAP\Exceptions\MessageFlagException;
use Webklex\PHPIMAP\Exceptions\MessageHeaderFetchingException;
use Webklex\PHPIMAP\Exceptions\MessageNotFoundException;
use Webklex\PHPIMAP\Exceptions\MessageSearchValidationException;
use Webklex\PHPIMAP\Exceptions\RuntimeException;
use Webklex\PHPIMAP\IMAP;
use Webklex\PHPIMAP\Message;
use Webklex\PHPIMAP\Support\MessageCollection;
/**
* Class Query
*
* @package Webklex\PHPIMAP\Query
*/
class Query {
/** @var Collection $query */
protected $query;
/** @var string $raw_query */
protected $raw_query;
/** @var string $charset */
protected $charset;
/** @var Client $client */
protected $client;
/** @var int $limit */
protected $limit = null;
/** @var int $page */
protected $page = 1;
/** @var int $fetch_options */
protected $fetch_options = null;
/** @var int $fetch_body */
protected $fetch_body = true;
/** @var int $fetch_flags */
protected $fetch_flags = true;
/** @var int $sequence */
protected $sequence = IMAP::NIL;
/** @var string $fetch_order */
protected $fetch_order;
/** @var string $date_format */
protected $date_format;
/** @var bool $soft_fail */
protected $soft_fail = false;
/** @var array $errors */
protected $errors = [];
/**
* Query constructor.
* @param Client $client
* @param string $charset
*/
public function __construct(Client $client, $charset = 'UTF-8') {
$this->setClient($client);
$this->sequence = ClientManager::get('options.sequence', IMAP::ST_MSGN);
if (ClientManager::get('options.fetch') === IMAP::FT_PEEK) $this->leaveUnread();
if (ClientManager::get('options.fetch_order') === 'desc') {
$this->fetch_order = 'desc';
} else {
$this->fetch_order = 'asc';
}
$this->date_format = ClientManager::get('date_format', 'd M y');
$this->soft_fail = ClientManager::get('options.soft_fail', false);
$this->charset = $charset;
$this->query = new Collection();
$this->boot();
}
/**
* Instance boot method for additional functionality
*/
protected function boot() {
}
/**
* Parse a given value
* @param mixed $value
*
* @return string
*/
protected function parse_value($value) {
switch (true) {
case $value instanceof Carbon:
$value = $value->format($this->date_format);
break;
}
return (string)$value;
}
/**
* Check if a given date is a valid carbon object and if not try to convert it
* @param string|Carbon $date
*
* @return Carbon
* @throws MessageSearchValidationException
*/
protected function parse_date($date) {
if ($date instanceof Carbon) return $date;
try {
$date = Carbon::parse($date);
} catch (Exception $e) {
throw new MessageSearchValidationException();
}
return $date;
}
/**
* Get the raw IMAP search query
*
* @return string
*/
public function generate_query() {
$query = '';
$this->query->each(function($statement) use (&$query) {
if (count($statement) == 1) {
$query .= $statement[0];
} else {
if ($statement[1] === null) {
$query .= $statement[0];
} else {
$query .= $statement[0] . ' "' . $statement[1] . '"';
}
}
$query .= ' ';
});
$this->raw_query = trim($query);
return $this->raw_query;
}
/**
* Perform an imap search request
*
* @return Collection
* @throws GetMessagesFailedException
*/
protected function search() {
$this->generate_query();
try {
$available_messages = $this->client->getConnection()->search([$this->getRawQuery()], $this->sequence == IMAP::ST_UID);
return $available_messages !== false ? new Collection($available_messages) : new Collection();
} catch (RuntimeException $e) {
throw new GetMessagesFailedException("failed to fetch messages", 0, $e);
} catch (ConnectionFailedException $e) {
throw new GetMessagesFailedException("failed to fetch messages", 0, $e);
}
}
/**
* Count all available messages matching the current search criteria
*
* @return int
* @throws GetMessagesFailedException
*/
public function count() {
return $this->search()->count();
}
/**
* Fetch a given id collection
* @param Collection $available_messages
*
* @return array
* @throws ConnectionFailedException
* @throws RuntimeException
*/
protected function fetch($available_messages) {
if ($this->fetch_order === 'desc') {
$available_messages = $available_messages->reverse();
}
$uids = $available_messages->forPage($this->page, $this->limit)->toArray();
$flags = $this->client->getConnection()->flags($uids, $this->sequence == IMAP::ST_UID);
$headers = $this->client->getConnection()->headers($uids, "RFC822", $this->sequence == IMAP::ST_UID);
$contents = [];
if ($this->getFetchBody()) {
$contents = $this->client->getConnection()->content($uids, "RFC822", $this->sequence == IMAP::ST_UID);
}
return [
"uids" => $uids,
"flags" => $flags,
"headers" => $headers,
"contents" => $contents,
];
}
/**
* Make a new message from given raw components
* @param integer $uid
* @param integer $msglist
* @param string $header
* @param string $content
* @param array $flags
*
* @return Message|null
* @throws ConnectionFailedException
* @throws EventNotFoundException
* @throws GetMessagesFailedException
* @throws ReflectionException
*/
protected function make($uid, $msglist, $header, $content, $flags){
try {
return Message::make($uid, $msglist, $this->getClient(), $header, $content, $flags, $this->getFetchOptions(), $this->sequence);
}catch (MessageNotFoundException $e) {
$this->setError($uid, $e);
}catch (RuntimeException $e) {
$this->setError($uid, $e);
}catch (MessageFlagException $e) {
$this->setError($uid, $e);
}catch (InvalidMessageDateException $e) {
$this->setError($uid, $e);
}catch (MessageContentFetchingException $e) {
$this->setError($uid, $e);
}
$this->handleException($uid);
return null;
}
/**
* Get the message key for a given message
* @param string $message_key
* @param integer $msglist
* @param Message $message
*
* @return string
*/
protected function getMessageKey($message_key, $msglist, $message){
switch ($message_key) {
case 'number':
$key = $message->getMessageNo();
break;
case 'list':
$key = $msglist;
break;
case 'uid':
$key = $message->getUid();
break;
default:
$key = $message->getMessageId();
break;
}
return (string)$key;
}
/**
* Populate a given id collection and receive a fully fetched message collection
* @param Collection $available_messages
*
* @return MessageCollection
* @throws ConnectionFailedException
* @throws EventNotFoundException
* @throws GetMessagesFailedException
* @throws ReflectionException
* @throws RuntimeException
*/
protected function populate($available_messages) {
$messages = MessageCollection::make([]);
$messages->total($available_messages->count());
$message_key = ClientManager::get('options.message_key');
$raw_messages = $this->fetch($available_messages);
$msglist = 0;
foreach ($raw_messages["headers"] as $uid => $header) {
$content = isset($raw_messages["contents"][$uid]) ? $raw_messages["contents"][$uid] : "";
$flag = isset($raw_messages["flags"][$uid]) ? $raw_messages["flags"][$uid] : [];
$message = $this->make($uid, $msglist, $header, $content, $flag);
if ($message !== null) {
$key = $this->getMessageKey($message_key, $msglist, $message);
$messages->put("$key", $message);
}
$msglist++;
}
return $messages;
}
/**
* Fetch the current query and return all found messages
*
* @return MessageCollection
* @throws GetMessagesFailedException
*/
public function get() {
$available_messages = $this->search();
try {
if ($available_messages->count() > 0) {
return $this->populate($available_messages);
}
return MessageCollection::make([]);
} catch (Exception $e) {
throw new GetMessagesFailedException($e->getMessage(), 0, $e);
}
}
/**
* Fetch the current query as chunked requests
* @param callable $callback
* @param int $chunk_size
* @param int $start_chunk
*
* @throws ConnectionFailedException
* @throws EventNotFoundException
* @throws GetMessagesFailedException
* @throws ReflectionException
* @throws RuntimeException
*/
public function chunked($callback, $chunk_size = 10, $start_chunk = 1) {
$available_messages = $this->search();
if (($available_messages_count = $available_messages->count()) > 0) {
$old_limit = $this->limit;
$old_page = $this->page;
$this->limit = $chunk_size;
$this->page = $start_chunk;
do {
$messages = $this->populate($available_messages);
$callback($messages, $this->page);
$this->page++;
} while ($this->limit * $this->page <= $available_messages_count);
$this->limit = $old_limit;
$this->page = $old_page;
}
}
/**
* Paginate the current query
* @param int $per_page Results you which to receive per page
* @param int|null $page The current page you are on (e.g. 0, 1, 2, ...) use `null` to enable auto mode
* @param string $page_name The page name / uri parameter used for the generated links and the auto mode
*
* @return LengthAwarePaginator
* @throws GetMessagesFailedException
*/
public function paginate($per_page = 5, $page = null, $page_name = 'imap_page') {
if (
$page === null
&& isset($_GET[$page_name])
&& $_GET[$page_name] > 0
) {
$this->page = intval($_GET[$page_name]);
} elseif ($page > 0) {
$this->page = $page;
}
$this->limit = $per_page;
return $this->get()->paginate($per_page, $this->page, $page_name, true);
}
/**
* Get a new Message instance
* @param int $uid
* @param int|null $msglist
* @param int|null $sequence
*
* @return Message
* @throws ConnectionFailedException
* @throws RuntimeException
* @throws InvalidMessageDateException
* @throws MessageContentFetchingException
* @throws MessageHeaderFetchingException
* @throws EventNotFoundException
* @throws MessageFlagException
* @throws MessageNotFoundException
*/
public function getMessage($uid, $msglist = null, $sequence = null) {
return new Message($uid, $msglist, $this->getClient(), $this->getFetchOptions(), $this->getFetchBody(), $this->getFetchFlags(), $sequence ? $sequence : $this->sequence);
}
/**
* Get a message by its message number
* @param $msgn
* @param int|null $msglist
*
* @return Message
* @throws ConnectionFailedException
* @throws InvalidMessageDateException
* @throws MessageContentFetchingException
* @throws MessageHeaderFetchingException
* @throws RuntimeException
* @throws EventNotFoundException
* @throws MessageFlagException
* @throws MessageNotFoundException
*/
public function getMessageByMsgn($msgn, $msglist = null) {
return $this->getMessage($msgn, $msglist, IMAP::ST_MSGN);
}
/**
* Get a message by its uid
* @param $uid
*
* @return Message
* @throws ConnectionFailedException
* @throws InvalidMessageDateException
* @throws MessageContentFetchingException
* @throws MessageHeaderFetchingException
* @throws RuntimeException
* @throws EventNotFoundException
* @throws MessageFlagException
* @throws MessageNotFoundException
*/
public function getMessageByUid($uid) {
return $this->getMessage($uid, null, IMAP::ST_UID);
}
/**
* Don't mark messages as read when fetching
*
* @return $this
*/
public function leaveUnread() {
$this->setFetchOptions(IMAP::FT_PEEK);
return $this;
}
/**
* Mark all messages as read when fetching
*
* @return $this
*/
public function markAsRead() {
$this->setFetchOptions(IMAP::FT_UID);
return $this;
}
/**
* Set the sequence type
* @param int $sequence
*
* @return $this
*/
public function setSequence($sequence) {
$this->sequence = $sequence != IMAP::ST_MSGN ? IMAP::ST_UID : $sequence;
return $this;
}
/**
* @return Client
* @throws ConnectionFailedException
*/
public function getClient() {
$this->client->checkConnection();
return $this->client;
}
/**
* Set the limit and page for the current query
* @param int $limit
* @param int $page
*
* @return $this
*/
public function limit($limit, $page = 1) {
if ($page >= 1) $this->page = $page;
$this->limit = $limit;
return $this;
}
/**
* @return Collection
*/
public function getQuery() {
return $this->query;
}
/**
* @param array $query
* @return Query
*/
public function setQuery($query) {
$this->query = new Collection($query);
return $this;
}
/**
* @return string
*/
public function getRawQuery() {
return $this->raw_query;
}
/**
* @param string $raw_query
* @return Query
*/
public function setRawQuery($raw_query) {
$this->raw_query = $raw_query;
return $this;
}
/**
* @return string
*/
public function getCharset() {
return $this->charset;
}
/**
* @param string $charset
* @return Query
*/
public function setCharset($charset) {
$this->charset = $charset;
return $this;
}
/**
* @param Client $client
* @return Query
*/
public function setClient(Client $client) {
$this->client = $client;
return $this;
}
/**
* @return int
*/
public function getLimit() {
return $this->limit;
}
/**
* @param int $limit
* @return Query
*/
public function setLimit($limit) {
$this->limit = $limit <= 0 ? null : $limit;
return $this;
}
/**
* @return int
*/
public function getPage() {
return $this->page;
}
/**
* @param int $page
* @return Query
*/
public function setPage($page) {
$this->page = $page;
return $this;
}
/**
* @param boolean $fetch_options
* @return Query
*/
public function setFetchOptions($fetch_options) {
$this->fetch_options = $fetch_options;
return $this;
}
/**
* @param boolean $fetch_options
* @return Query
*/
public function fetchOptions($fetch_options) {
return $this->setFetchOptions($fetch_options);
}
/**
* @return int
*/
public function getFetchOptions() {
return $this->fetch_options;
}
/**
* @return boolean
*/
public function getFetchBody() {
return $this->fetch_body;
}
/**
* @param boolean $fetch_body
* @return Query
*/
public function setFetchBody($fetch_body) {
$this->fetch_body = $fetch_body;
return $this;
}
/**
* @param boolean $fetch_body
* @return Query
*/
public function fetchBody($fetch_body) {
return $this->setFetchBody($fetch_body);
}
/**
* @return int
*/
public function getFetchFlags() {
return $this->fetch_flags;
}
/**
* @param int $fetch_flags
* @return Query
*/
public function setFetchFlags($fetch_flags) {
$this->fetch_flags = $fetch_flags;
return $this;
}
/**
* @param string $fetch_order
* @return Query
*/
public function setFetchOrder($fetch_order) {
$fetch_order = strtolower($fetch_order);
if (in_array($fetch_order, ['asc', 'desc'])) {
$this->fetch_order = $fetch_order;
}
return $this;
}
/**
* @param string $fetch_order
* @return Query
*/
public function fetchOrder($fetch_order) {
return $this->setFetchOrder($fetch_order);
}
/**
* @return string
*/
public function getFetchOrder() {
return $this->fetch_order;
}
/**
* @return Query
*/
public function setFetchOrderAsc() {
return $this->setFetchOrder('asc');
}
/**
* @return Query
*/
public function fetchOrderAsc() {
return $this->setFetchOrderAsc();
}
/**
* @return Query
*/
public function setFetchOrderDesc() {
return $this->setFetchOrder('desc');
}
/**
* @return Query
*/
public function fetchOrderDesc() {
return $this->setFetchOrderDesc();
}
/**
* @var boolean $state
*
* @return Query
*/
public function softFail($state = true) {
return $this->setSoftFail($state);
}
/**
* @var boolean $state
*
* @return Query
*/
public function setSoftFail($state = true) {
$this->soft_fail = $state;
return $this;
}
/**
* @return boolean
*/
public function getSoftFail() {
return $this->soft_fail;
}
/**
* Handle the exception for a given uid
* @param integer $uid
*
* @throws GetMessagesFailedException
*/
protected function handleException($uid) {
if ($this->soft_fail === false && $this->hasError($uid)) {
$error = $this->getError($uid);
throw new GetMessagesFailedException($error->getMessage(), 0, $error);
}
}
/**
* Add a new error to the error holder
* @param integer $uid
* @param Exception $error
*/
protected function setError($uid, $error) {
$this->errors[$uid] = $error;
}
/**
* Check if there are any errors / exceptions present
* @var integer|null $uid
*
* @return boolean
*/
public function hasErrors($uid = null){
if ($uid !== null) {
return $this->hasError($uid);
}
return count($this->errors) > 0;
}
/**
* Check if there is an error / exception present
* @var integer $uid
*
* @return boolean
*/
public function hasError($uid){
return isset($this->errors[$uid]);
}
/**
* Get all available errors / exceptions
*
* @return array
*/
public function errors(){
return $this->getErrors();
}
/**
* Get all available errors / exceptions
*
* @return array
*/
public function getErrors(){
return $this->errors;
}
/**
* Get a specific error / exception
* @var integer $uid
*
* @return Exception|null
*/
public function error($uid){
return $this->getError($uid);
}
/**
* Get a specific error / exception
* @var integer $uid
*
* @return Exception|null
*/
public function getError($uid){
if ($this->hasError($uid)) {
return $this->errors[$uid];
}
return null;
}
}

View File

@@ -0,0 +1,551 @@
<?php
/*
* File: Query.php
* Category: -
* Author: M. Goldenbaum
* Created: 21.07.18 18:54
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Query;
use Closure;
use Illuminate\Support\Str;
use Webklex\PHPIMAP\Exceptions\InvalidWhereQueryCriteriaException;
use Webklex\PHPIMAP\Exceptions\MethodNotFoundException;
use Webklex\PHPIMAP\Exceptions\MessageSearchValidationException;
/**
* Class WhereQuery
*
* @package Webklex\PHPIMAP\Query
*
* @method WhereQuery all()
* @method WhereQuery answered()
* @method WhereQuery deleted()
* @method WhereQuery new()
* @method WhereQuery old()
* @method WhereQuery recent()
* @method WhereQuery seen()
* @method WhereQuery unanswered()
* @method WhereQuery undeleted()
* @method WhereQuery unflagged()
* @method WhereQuery unseen()
* @method WhereQuery not()
* @method WhereQuery unkeyword($value)
* @method WhereQuery to($value)
* @method WhereQuery text($value)
* @method WhereQuery subject($value)
* @method WhereQuery since($date)
* @method WhereQuery on($date)
* @method WhereQuery keyword($value)
* @method WhereQuery from($value)
* @method WhereQuery flagged()
* @method WhereQuery cc($value)
* @method WhereQuery body($value)
* @method WhereQuery before($date)
* @method WhereQuery bcc($value)
* @method WhereQuery inReplyTo($value)
* @method WhereQuery messageId($value)
*
* @mixin Query
*/
class WhereQuery extends Query {
/**
* @var array $available_criteria
*/
protected $available_criteria = [
'OR', 'AND',
'ALL', 'ANSWERED', 'BCC', 'BEFORE', 'BODY', 'CC', 'DELETED', 'FLAGGED', 'FROM', 'KEYWORD',
'NEW', 'NOT', 'OLD', 'ON', 'RECENT', 'SEEN', 'SINCE', 'SUBJECT', 'TEXT', 'TO',
'UNANSWERED', 'UNDELETED', 'UNFLAGGED', 'UNKEYWORD', 'UNSEEN', 'UID'
];
/**
* Magic method in order to allow alias usage of all "where" methods in an optional connection with "NOT"
* @param string $name
* @param array|null $arguments
*
* @return mixed
* @throws InvalidWhereQueryCriteriaException
* @throws MethodNotFoundException
*/
public function __call($name, $arguments) {
$that = $this;
$name = Str::camel($name);
if (strtolower(substr($name, 0, 3)) === 'not') {
$that = $that->whereNot();
$name = substr($name, 3);
}
if (strpos(strtolower($name), "where") === false) {
$method = 'where' . ucfirst($name);
} else {
$method = lcfirst($name);
}
if (method_exists($this, $method) === true) {
return call_user_func_array([$that, $method], $arguments);
}
throw new MethodNotFoundException("Method " . self::class . '::' . $method . '() is not supported');
}
/**
* Validate a given criteria
* @param $criteria
*
* @return string
* @throws InvalidWhereQueryCriteriaException
*/
protected function validate_criteria($criteria) {
$criteria = strtoupper($criteria);
if (substr($criteria, 0, 7) === "CUSTOM ") {
return substr($criteria, 7);
}
if (in_array($criteria, $this->available_criteria) === false) {
throw new InvalidWhereQueryCriteriaException();
}
return $criteria;
}
/**
* Register search parameters
* @param mixed $criteria
* @param null $value
*
* @return $this
* @throws InvalidWhereQueryCriteriaException
*
* Examples:
* $query->from("someone@email.tld")->seen();
* $query->whereFrom("someone@email.tld")->whereSeen();
* $query->where([["FROM" => "someone@email.tld"], ["SEEN"]]);
* $query->where(["FROM" => "someone@email.tld"])->where(["SEEN"]);
* $query->where(["FROM" => "someone@email.tld", "SEEN"]);
* $query->where("FROM", "someone@email.tld")->where("SEEN");
*/
public function where($criteria, $value = null): WhereQuery {
if (is_array($criteria)) {
foreach ($criteria as $key => $value) {
if (is_numeric($key)) {
$this->where($value);
}else{
$this->where($key, $value);
}
}
} else {
$this->push_search_criteria($criteria, $value);
}
return $this;
}
/**
* Push a given search criteria and value pair to the search query
* @param $criteria string
* @param $value mixed
*
* @throws InvalidWhereQueryCriteriaException
*/
protected function push_search_criteria(string $criteria, $value){
$criteria = $this->validate_criteria($criteria);
$value = $this->parse_value($value);
if ($value === null || $value === '') {
$this->query->push([$criteria]);
} else {
$this->query->push([$criteria, $value]);
}
}
/**
* @param Closure $closure
*
* @return $this
*/
public function orWhere(Closure $closure = null) {
$this->query->push(['OR']);
if ($closure !== null) $closure($this);
return $this;
}
/**
* @param Closure $closure
*
* @return $this
*/
public function andWhere(Closure $closure = null) {
$this->query->push(['AND']);
if ($closure !== null) $closure($this);
return $this;
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereAll() {
return $this->where('ALL');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereAnswered() {
return $this->where('ANSWERED');
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereBcc($value) {
return $this->where('BCC', $value);
}
/**
* @param mixed $value
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
* @throws MessageSearchValidationException
*/
public function whereBefore($value) {
$date = $this->parse_date($value);
return $this->where('BEFORE', $date);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereBody($value) {
return $this->where('BODY', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereCc($value) {
return $this->where('CC', $value);
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereDeleted() {
return $this->where('DELETED');
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereFlagged($value) {
return $this->where('FLAGGED', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereFrom($value) {
return $this->where('FROM', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereKeyword($value) {
return $this->where('KEYWORD', $value);
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereNew() {
return $this->where('NEW');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereNot() {
return $this->where('NOT');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereOld() {
return $this->where('OLD');
}
/**
* @param mixed $value
*
* @return WhereQuery
* @throws MessageSearchValidationException
* @throws InvalidWhereQueryCriteriaException
*/
public function whereOn($value) {
$date = $this->parse_date($value);
return $this->where('ON', $date);
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereRecent() {
return $this->where('RECENT');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereSeen() {
return $this->where('SEEN');
}
/**
* @param mixed $value
*
* @return WhereQuery
* @throws MessageSearchValidationException
* @throws InvalidWhereQueryCriteriaException
*/
public function whereSince($value) {
$date = $this->parse_date($value);
return $this->where('SINCE', $date);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereSubject($value) {
return $this->where('SUBJECT', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereText($value) {
return $this->where('TEXT', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereTo($value) {
return $this->where('TO', $value);
}
/**
* @param string $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUnkeyword($value) {
return $this->where('UNKEYWORD', $value);
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUnanswered() {
return $this->where('UNANSWERED');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUndeleted() {
return $this->where('UNDELETED');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUnflagged() {
return $this->where('UNFLAGGED');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUnseen() {
return $this->where('UNSEEN');
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereNoXSpam() {
return $this->where("CUSTOM X-Spam-Flag NO");
}
/**
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereIsXSpam() {
return $this->where("CUSTOM X-Spam-Flag YES");
}
/**
* Search for a specific header value
* @param $header
* @param $value
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereHeader($header, $value) {
return $this->where("CUSTOM HEADER $header $value");
}
/**
* Search for a specific message id
* @param $messageId
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereMessageId($messageId) {
return $this->whereHeader("Message-ID", $messageId);
}
/**
* Search for a specific message id
* @param $messageId
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereInReplyTo($messageId) {
return $this->whereHeader("In-Reply-To", $messageId);
}
/**
* @param $country_code
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereLanguage($country_code) {
return $this->where("Content-Language $country_code");
}
/**
* Get message be it UID.
*
* @param int|string $uid
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUid($uid)
{
return $this->where('UID', $uid);
}
/**
* Get messages by their UIDs.
*
* @param array<int, int> $uids
*
* @return WhereQuery
* @throws InvalidWhereQueryCriteriaException
*/
public function whereUidIn($uids)
{
$uids = implode(',', $uids);
return $this->where('UID', $uids);
}
/**
* Apply the callback if the given "value" is truthy.
* copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php
*
* @param mixed $value
* @param callable $callback
* @param callable|null $default
* @return $this|mixed
*/
public function when($value, $callback, $default = null) {
if ($value) {
return $callback($this, $value) ?: $this;
} elseif ($default) {
return $default($this, $value) ?: $this;
}
return $this;
}
/**
* Apply the callback if the given "value" is falsy.
* copied from @url https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/Traits/Conditionable.php
*
* @param mixed $value
* @param callable $callback
* @param callable|null $default
* @return $this|mixed
*/
public function unless($value, $callback, $default = null) {
if (! $value) {
return $callback($this, $value) ?: $this;
} elseif ($default) {
return $default($this, $value) ?: $this;
}
return $this;
}
}

View File

@@ -0,0 +1,174 @@
<?php
/*
* File: Structure.php
* Category: -
* Author: M.Goldenbaum
* Created: 17.09.20 20:38
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP;
use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException;
/**
* Class Structure
*
* @package Webklex\PHPIMAP
*/
class Structure {
/**
* Raw structure
*
* @var string $raw
*/
public $raw = "";
/**
* @var Header $header
*/
private $header = null;
/**
* Message type (if multipart or not)
*
* @var int $type
*/
public $type = IMAP::MESSAGE_TYPE_TEXT;
/**
* All available parts
*
* @var Part[] $parts
*/
public $parts = [];
/**
* Config holder
*
* @var array $config
*/
protected $config = [];
/**
* Structure constructor.
* @param $raw_structure
* @param Header $header
*
* @throws MessageContentFetchingException
* @throws InvalidMessageDateException
*/
public function __construct($raw_structure, Header $header) {
$this->raw = $raw_structure;
$this->header = $header;
$this->config = ClientManager::get('options');
$this->parse();
}
/**
* Parse the given raw structure
*
* @throws MessageContentFetchingException
* @throws InvalidMessageDateException
*/
protected function parse(){
$this->findContentType();
$this->parts = $this->find_parts();
}
/**
* Determine the message content type
*/
public function findContentType(){
$content_type = $this->header->get("content_type");
$content_type = (is_array($content_type)) ? implode(' ', $content_type) : $content_type;
if(stripos($content_type, 'multipart') === 0) {
$this->type = IMAP::MESSAGE_TYPE_MULTIPART;
}else{
$this->type = IMAP::MESSAGE_TYPE_TEXT;
}
}
/**
* Find all available headers and return the left over body segment
* @var string $context
* @var integer $part_number
*
* @return Part[]
* @throws InvalidMessageDateException
*/
private function parsePart($context, $part_number = 0){
$body = $context;
while (($pos = strpos($body, "\r\n")) > 0) {
$body = substr($body, $pos + 2);
}
$headers = substr($context, 0, strlen($body) * -1);
$body = substr($body, 0, -2);
$headers = new Header($headers);
if (($boundary = $headers->getBoundary()) !== null) {
return $this->detectParts($boundary, $body, $part_number);
}
return [new Part($body, $headers, $part_number)];
}
/**
* @param string $boundary
* @param string $context
* @param int $part_number
*
* @return array
* @throws InvalidMessageDateException
*/
private function detectParts($boundary, $context, $part_number = 0){
$base_parts = explode( $boundary, $context);
$final_parts = [];
foreach($base_parts as $ctx) {
$ctx = substr($ctx, 2);
if ($ctx !== "--" && $ctx != "") {
$parts = $this->parsePart($ctx, $part_number);
foreach ($parts as $part) {
$final_parts[] = $part;
$part_number = $part->part_number;
}
$part_number++;
}
}
return $final_parts;
}
/**
* Find all available parts
*
* @return array
* @throws MessageContentFetchingException
* @throws InvalidMessageDateException
*/
public function find_parts(){
if($this->type === IMAP::MESSAGE_TYPE_MULTIPART) {
if (($boundary = $this->header->getBoundary()) === null) {
throw new MessageContentFetchingException("no content found", 0);
}
return $this->detectParts($boundary, $this->raw);
}
return [new Part($this->raw, $this->header)];
}
/**
* Try to find a boundary if possible
*
* @return string|null
* @Depricated since version 2.4.4
*/
public function getBoundary(){
return $this->header->getBoundary();
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: AttachmentCollection.php
* Category: Collection
* Author: M. Goldenbaum
* Created: 16.03.18 03:13
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support;
/**
* Class AttachmentCollection
*
* @package Webklex\PHPIMAP\Support
*/
class AttachmentCollection extends PaginatedCollection {
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: FlagCollection.php
* Category: Collection
* Author: M. Goldenbaum
* Created: 21.07.18 23:10
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support;
/**
* Class FlagCollection
*
* @package Webklex\PHPIMAP\Support
*/
class FlagCollection extends PaginatedCollection {
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: FolderCollection.php
* Category: Collection
* Author: M. Goldenbaum
* Created: 18.03.18 02:21
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support;
/**
* Class FolderCollection
*
* @package Webklex\PHPIMAP\Support
*/
class FolderCollection extends PaginatedCollection {
}

View File

@@ -0,0 +1,44 @@
<?php
/*
* File: AttachmentMask.php
* Category: Mask
* Author: M.Goldenbaum
* Created: 14.03.19 20:49
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support\Masks;
use Webklex\PHPIMAP\Attachment;
/**
* Class AttachmentMask
*
* @package Webklex\PHPIMAP\Support\Masks
*/
class AttachmentMask extends Mask {
/** @var Attachment $parent */
protected $parent;
/**
* Get the attachment content base64 encoded
*
* @return string|null
*/
public function getContentBase64Encoded() {
return base64_encode($this->parent->content);
}
/**
* Get an base64 image src string
*
* @return string|null
*/
public function getImageSrc() {
return 'data:'.$this->parent->content_type.';base64,'.$this->getContentBase64Encoded();
}
}

View File

@@ -0,0 +1,137 @@
<?php
/*
* File: Mask.php
* Category: Mask
* Author: M.Goldenbaum
* Created: 14.03.19 20:49
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support\Masks;
use Illuminate\Support\Str;
use Webklex\PHPIMAP\Exceptions\MethodNotFoundException;
/**
* Class Mask
*
* @package Webklex\PHPIMAP\Support\Masks
*/
class Mask {
/**
* Available attributes
*
* @var array $attributes
*/
protected $attributes = [];
/**
* Parent instance
*
* @var object $parent
*/
protected $parent;
/**
* Mask constructor.
* @param $parent
*/
public function __construct($parent) {
$this->parent = $parent;
if(method_exists($this->parent, 'getAttributes')){
$this->attributes = array_merge($this->attributes, $this->parent->getAttributes());
}
$this->boot();
}
/**
* Boot method made to be used by any custom mask
*/
protected function boot(){}
/**
* Call dynamic attribute setter and getter methods and inherit the parent calls
* @param string $method
* @param array $arguments
*
* @return mixed
* @throws MethodNotFoundException
*/
public function __call($method, $arguments) {
if(strtolower(substr($method, 0, 3)) === 'get') {
$name = Str::snake(substr($method, 3));
if(isset($this->attributes[$name])) {
return $this->attributes[$name];
}
}elseif (strtolower(substr($method, 0, 3)) === 'set') {
$name = Str::snake(substr($method, 3));
if(isset($this->attributes[$name])) {
$this->attributes[$name] = array_pop($arguments);
return $this->attributes[$name];
}
}
if(method_exists($this->parent, $method) === true){
return call_user_func_array([$this->parent, $method], $arguments);
}
throw new MethodNotFoundException("Method ".self::class.'::'.$method.'() is not supported');
}
/**
* Magic setter
* @param $name
* @param $value
*
* @return mixed
*/
public function __set($name, $value) {
$this->attributes[$name] = $value;
return $this->attributes[$name];
}
/**
* Magic getter
* @param $name
*
* @return mixed|null
*/
public function __get($name) {
if(isset($this->attributes[$name])) {
return $this->attributes[$name];
}
return null;
}
/**
* Get the parent instance
*
* @return mixed
*/
public function getParent(){
return $this->parent;
}
/**
* Get all available attributes
*
* @return array
*/
public function getAttributes(){
return $this->attributes;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/*
* File: MessageMask.php
* Category: Mask
* Author: M.Goldenbaum
* Created: 14.03.19 20:49
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support\Masks;
use Webklex\PHPIMAP\Attachment;
use Webklex\PHPIMAP\Message;
/**
* Class MessageMask
*
* @package Webklex\PHPIMAP\Support\Masks
*/
class MessageMask extends Mask {
/** @var Message $parent */
protected $parent;
/**
* Get the message html body
*
* @return null
*/
public function getHtmlBody(){
$bodies = $this->parent->getBodies();
if (!isset($bodies['html'])) {
return null;
}
if(is_object($bodies['html']) && property_exists($bodies['html'], 'content')) {
return $bodies['html']->content;
}
return $bodies['html'];
}
/**
* Get the Message html body filtered by an optional callback
* @param callable|bool $callback
*
* @return string|null
*/
public function getCustomHTMLBody($callback = false) {
$body = $this->getHtmlBody();
if($body === null) return null;
if ($callback !== false) {
$aAttachment = $this->parent->getAttachments();
$aAttachment->each(function($oAttachment) use(&$body, $callback) {
/** @var Attachment $oAttachment */
if(is_callable($callback)) {
$body = $callback($body, $oAttachment);
}elseif(is_string($callback)) {
call_user_func($callback, [$body, $oAttachment]);
}
});
}
return $body;
}
/**
* Get the Message html body with embedded base64 images
* the resulting $body.
*
* @return string|null
*/
public function getHTMLBodyWithEmbeddedBase64Images() {
return $this->getCustomHTMLBody(function($body, $oAttachment){
/** @var Attachment $oAttachment */
if ($oAttachment->id) {
$body = str_replace('cid:'.$oAttachment->id, 'data:'.$oAttachment->getContentType().';base64, '.base64_encode($oAttachment->getContent()), $body);
}
return $body;
});
}
}

View File

@@ -0,0 +1,22 @@
<?php
/*
* File: MessageCollection.php
* Category: Collection
* Author: M. Goldenbaum
* Created: 16.03.18 03:13
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support;
/**
* Class MessageCollection
*
* @package Webklex\PHPIMAP\Support
*/
class MessageCollection extends PaginatedCollection {
}

View File

@@ -0,0 +1,82 @@
<?php
/*
* File: PaginatedCollection.php
* Category: Collection
* Author: M. Goldenbaum
* Created: 16.03.18 03:13
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Support;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Pagination\Paginator;
/**
* Class PaginatedCollection
*
* @package Webklex\PHPIMAP\Support
*/
class PaginatedCollection extends Collection {
/**
* Number of total entries
*
* @var int $total
*/
protected $total;
/**
* Paginate the current collection.
* @param int $per_page
* @param int|null $page
* @param string $page_name
* @param boolean $prepaginated
*
* @return LengthAwarePaginator
*/
public function paginate($per_page = 15, $page = null, $page_name = 'page', $prepaginated = false) {
$page = $page ?: Paginator::resolveCurrentPage($page_name);
$total = $this->total ? $this->total : $this->count();
$results = !$prepaginated && $total ? $this->forPage($page, $per_page) : $this->all();
return $this->paginator($results, $total, $per_page, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $page_name,
]);
}
/**
* Create a new length-aware paginator instance.
* @param array $items
* @param int $total
* @param int $per_page
* @param int|null $current_page
* @param array $options
*
* @return LengthAwarePaginator
*/
protected function paginator($items, $total, $per_page, $current_page, array $options) {
return new LengthAwarePaginator($items, $total, $per_page, $current_page, $options);
}
/**
* Get and set the total amount
* @param null $total
*
* @return int|null
*/
public function total($total = null) {
if($total === null) {
return $this->total;
}
return $this->total = $total;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* File: HasEvents.php
* Category: -
* Author: M.Goldenbaum
* Created: 21.09.20 22:46
* Updated: -
*
* Description:
* -
*/
namespace Webklex\PHPIMAP\Traits;
use Webklex\PHPIMAP\Events\Event;
use Webklex\PHPIMAP\Exceptions\EventNotFoundException;
/**
* Trait HasEvents
*
* @package Webklex\PHPIMAP\Traits
*/
trait HasEvents {
/**
* Event holder
*
* @var array $events
*/
protected $events = [];
/**
* Set a specific event
* @param $section
* @param $event
* @param $class
*/
public function setEvent($section, $event, $class) {
if (isset($this->events[$section])) {
$this->events[$section][$event] = $class;
}
}
/**
* Set all events
* @param $events
*/
public function setEvents($events) {
$this->events = $events;
}
/**
* Get a specific event callback
* @param $section
* @param $event
*
* @return Event
* @throws EventNotFoundException
*/
public function getEvent($section, $event) {
if (isset($this->events[$section])) {
return $this->events[$section][$event];
}
throw new EventNotFoundException();
}
/**
* Get all events
*
* @return array
*/
public function getEvents(){
return $this->events;
}
}

View File

@@ -0,0 +1,216 @@
<?php
/*
* File: imap.php
* Category: config
* Author: M. Goldenbaum
* Created: 24.09.16 22:36
* Updated: -
*
* Description:
* -
*/
return [
/*
|--------------------------------------------------------------------------
| Default date format
|--------------------------------------------------------------------------
|
| The default date format is used to convert any given Carbon::class object into a valid date string.
| These are currently known working formats: "d-M-Y", "d-M-y", "d M y"
|
*/
'date_format' => 'd-M-Y',
/*
|--------------------------------------------------------------------------
| Default account
|--------------------------------------------------------------------------
|
| The default account identifier. It will be used as default for any missing account parameters.
| If however the default account is missing a parameter the package default will be used.
| Set to 'false' [boolean] to disable this functionality.
|
*/
'default' => 'default',
/*
|--------------------------------------------------------------------------
| Available accounts
|--------------------------------------------------------------------------
|
| Please list all IMAP accounts which you are planning to use within the
| array below.
|
*/
'accounts' => [
'default' => [// account identifier
'host' => 'localhost',
'port' => 993,
'protocol' => 'imap', //might also use imap, [pop3 or nntp (untested)]
'encryption' => 'ssl', // Supported: false, 'ssl', 'tls'
'validate_cert' => true,
'username' => 'root@example.com',
'password' => '',
'authentication' => null,
'proxy' => [
'socket' => null,
'request_fulluri' => false,
'username' => null,
'password' => null,
],
"timeout" => 30
],
/*
'gmail' => [ // account identifier
'host' => 'imap.gmail.com',
'port' => 993,
'encryption' => 'ssl',
'validate_cert' => true,
'username' => 'example@gmail.com',
'password' => 'PASSWORD',
'authentication' => 'oauth',
],
'another' => [ // account identifier
'host' => '',
'port' => 993,
'encryption' => false,
'validate_cert' => true,
'username' => '',
'password' => '',
'authentication' => null,
]
*/
],
/*
|--------------------------------------------------------------------------
| Available IMAP options
|--------------------------------------------------------------------------
|
| Available php imap config parameters are listed below
| -Delimiter (optional):
| This option is only used when calling $oClient->
| You can use any supported char such as ".", "/", (...)
| -Fetch option:
| IMAP::FT_UID - Message marked as read by fetching the body message
| IMAP::FT_PEEK - Fetch the message without setting the "seen" flag
| -Fetch sequence id:
| IMAP::ST_UID - Fetch message components using the message uid
| IMAP::ST_MSGN - Fetch message components using the message number
| -Body download option
| Default TRUE
| -Flag download option
| Default TRUE
| -Soft fail
| Default FALSE - Set to TRUE if you want to ignore certain exception while fetching bulk messages
| -RFC822
| Default TRUE - Set to FALSE to prevent the usage of \imap_rfc822_parse_headers().
| See https://github.com/Webklex/php-imap/issues/115 for more information.
| -Message key identifier option
| You can choose between the following:
| 'id' - Use the MessageID as array key (default, might cause hickups with yahoo mail)
| 'number' - Use the message number as array key (isn't always unique and can cause some interesting behavior)
| 'list' - Use the message list number as array key (incrementing integer (does not always start at 0 or 1)
| 'uid' - Use the message uid as array key (isn't always unique and can cause some interesting behavior)
| -Fetch order
| 'asc' - Order all messages ascending (probably results in oldest first)
| 'desc' - Order all messages descending (probably results in newest first)
| -Disposition types potentially considered an attachment
| Default ['attachment', 'inline']
| -Common folders
| Default folder locations and paths assumed if none is provided
| -Open IMAP options:
| DISABLE_AUTHENTICATOR - Disable authentication properties.
| Use 'GSSAPI' if you encounter the following
| error: "Kerberos error: No credentials cache
| file found (try running kinit) (...)"
| or ['GSSAPI','PLAIN'] if you are using outlook mail
| -Decoder options (currently only the message subject and attachment name decoder can be set)
| 'utf-8' - Uses imap_utf8($string) to decode a string
| 'mimeheader' - Uses mb_decode_mimeheader($string) to decode a string
|
*/
'options' => [
'delimiter' => '/',
'fetch' => \Webklex\PHPIMAP\IMAP::FT_PEEK,
'sequence' => \Webklex\PHPIMAP\IMAP::ST_MSGN,
'fetch_body' => true,
'fetch_flags' => true,
'soft_fail' => false,
'rfc822' => true,
'message_key' => 'list',
'fetch_order' => 'asc',
'dispositions' => ['attachment', 'inline'],
'common_folders' => [
"root" => "INBOX",
"junk" => "INBOX/Junk",
"draft" => "INBOX/Drafts",
"sent" => "INBOX/Sent",
"trash" => "INBOX/Trash",
],
'decoder' => [
'message' => 'utf-8', // mimeheader
'attachment' => 'utf-8' // mimeheader
],
'open' => [
// 'DISABLE_AUTHENTICATOR' => 'GSSAPI'
]
],
/*
|--------------------------------------------------------------------------
| Available flags
|--------------------------------------------------------------------------
|
| List all available / supported flags. Set to null to accept all given flags.
*/
'flags' => ['recent', 'flagged', 'answered', 'deleted', 'seen', 'draft'],
/*
|--------------------------------------------------------------------------
| Available events
|--------------------------------------------------------------------------
|
*/
'events' => [
"message" => [
'new' => \Webklex\PHPIMAP\Events\MessageNewEvent::class,
'moved' => \Webklex\PHPIMAP\Events\MessageMovedEvent::class,
'copied' => \Webklex\PHPIMAP\Events\MessageCopiedEvent::class,
'deleted' => \Webklex\PHPIMAP\Events\MessageDeletedEvent::class,
'restored' => \Webklex\PHPIMAP\Events\MessageRestoredEvent::class,
],
"folder" => [
'new' => \Webklex\PHPIMAP\Events\FolderNewEvent::class,
'moved' => \Webklex\PHPIMAP\Events\FolderMovedEvent::class,
'deleted' => \Webklex\PHPIMAP\Events\FolderDeletedEvent::class,
],
"flag" => [
'new' => \Webklex\PHPIMAP\Events\FlagNewEvent::class,
'deleted' => \Webklex\PHPIMAP\Events\FlagDeletedEvent::class,
],
],
/*
|--------------------------------------------------------------------------
| Available masking options
|--------------------------------------------------------------------------
|
| By using your own custom masks you can implement your own methods for
| a better and faster access and less code to write.
|
| Checkout the two examples custom_attachment_mask and custom_message_mask
| for a quick start.
|
| The provided masks below are used as the default masks.
*/
'masks' => [
'message' => \Webklex\PHPIMAP\Support\Masks\MessageMask::class,
'attachment' => \Webklex\PHPIMAP\Support\Masks\AttachmentMask::class
]
];

View File

@@ -0,0 +1,74 @@
<?php
// autoload.php @generated by Composer
/*
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1::getLoader();
*/
spl_autoload_register(function ($class_name) {
// Enable this to detect what we need for require_once
//var_dump($class_name);
$preg_match = preg_match('/^Webklex\\\PHPIMAP\\\/', $class_name);
if (1 === $preg_match) {
$class_name = preg_replace('/\\\/', '/', $class_name);
$class_name = preg_replace('/^Webklex\\/PHPIMAP\\//', '', $class_name);
require_once __DIR__ . '/../src/' . $class_name . '.php';
}
$preg_match = preg_match('/^Illuminate\\\Support\\\/', $class_name);
if (1 === $preg_match) {
$class_name = preg_replace('/\\\/', '/', $class_name);
$class_name = preg_replace('/^Illuminate\\/Support\\//', '', $class_name);
$listofdir = array(0 => __DIR__ . '/illuminate/macroable',
1 => __DIR__ . '/illuminate/collections',
2 => __DIR__ . '/illuminate/support',
3 => __DIR__ . '/illuminate/contracts'
);
foreach($listofdir as $dir) {
if (file_exists($dir . '/' . $class_name . '.php')) {
require_once $dir . '/' . $class_name . '.php';
break;
}
}
}
$preg_match = preg_match('/^Illuminate\\\Contracts\\\/', $class_name);
if (1 === $preg_match) {
$class_name = preg_replace('/\\\/', '/', $class_name);
$class_name = preg_replace('/^Illuminate\\/Contracts\\//', '', $class_name);
$listofdir = array(
0 => __DIR__ . '/illuminate/contracts'
);
foreach($listofdir as $dir) {
if (file_exists($dir . '/' . $class_name . '.php')) {
require_once $dir . '/' . $class_name . '.php';
break;
}
}
}
$preg_match = preg_match('/^Carbon\\\/', $class_name);
if (1 === $preg_match) {
$class_name = preg_replace('/\\\/', '/', $class_name);
$class_name = preg_replace('/^Carbon\\//', '', $class_name);
$listofdir = array(
0 => __DIR__ . '/nesbot/carbon/src/Carbon'
);
foreach($listofdir as $dir) {
if (file_exists($dir . '/' . $class_name . '.php')) {
require_once $dir . '/' . $class_name . '.php';
break;
}
}
}
});

View File

@@ -0,0 +1,572 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
}

View File

@@ -0,0 +1,352 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,460 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
'PHPUnit\\Framework\\Assert' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/Assert.php',
'PHPUnit\\Framework\\AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/AssertionFailedError.php',
'PHPUnit\\Framework\\BaseTestListener' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/BaseTestListener.php',
'PHPUnit\\Framework\\Test' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/Test.php',
'PHPUnit\\Framework\\TestCase' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/TestCase.php',
'PHPUnit\\Framework\\TestListener' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/TestListener.php',
'PHPUnit\\Framework\\TestSuite' => $vendorDir . '/phpunit/phpunit/src/ForwardCompatibility/TestSuite.php',
'PHPUnit_Exception' => $vendorDir . '/phpunit/phpunit/src/Exception.php',
'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php',
'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestCase.php',
'PHPUnit_Extensions_PhptTestSuite' => $vendorDir . '/phpunit/phpunit/src/Extensions/PhptTestSuite.php',
'PHPUnit_Extensions_RepeatedTest' => $vendorDir . '/phpunit/phpunit/src/Extensions/RepeatedTest.php',
'PHPUnit_Extensions_TestDecorator' => $vendorDir . '/phpunit/phpunit/src/Extensions/TestDecorator.php',
'PHPUnit_Extensions_TicketListener' => $vendorDir . '/phpunit/phpunit/src/Extensions/TicketListener.php',
'PHPUnit_Framework_Assert' => $vendorDir . '/phpunit/phpunit/src/Framework/Assert.php',
'PHPUnit_Framework_AssertionFailedError' => $vendorDir . '/phpunit/phpunit/src/Framework/AssertionFailedError.php',
'PHPUnit_Framework_BaseTestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/BaseTestListener.php',
'PHPUnit_Framework_CodeCoverageException' => $vendorDir . '/phpunit/phpunit/src/Framework/CodeCoverageException.php',
'PHPUnit_Framework_Constraint' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint.php',
'PHPUnit_Framework_Constraint_And' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/And.php',
'PHPUnit_Framework_Constraint_ArrayHasKey' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
'PHPUnit_Framework_Constraint_ArraySubset' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
'PHPUnit_Framework_Constraint_Attribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
'PHPUnit_Framework_Constraint_Callback' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
'PHPUnit_Framework_Constraint_ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
'PHPUnit_Framework_Constraint_Composite' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
'PHPUnit_Framework_Constraint_Count' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
'PHPUnit_Framework_Constraint_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
'PHPUnit_Framework_Constraint_ExceptionCode' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
'PHPUnit_Framework_Constraint_ExceptionMessage' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegExp.php',
'PHPUnit_Framework_Constraint_FileExists' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
'PHPUnit_Framework_Constraint_GreaterThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
'PHPUnit_Framework_Constraint_IsAnything' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
'PHPUnit_Framework_Constraint_IsEmpty' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
'PHPUnit_Framework_Constraint_IsEqual' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
'PHPUnit_Framework_Constraint_IsFalse' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
'PHPUnit_Framework_Constraint_IsIdentical' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
'PHPUnit_Framework_Constraint_IsInstanceOf' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
'PHPUnit_Framework_Constraint_IsJson' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
'PHPUnit_Framework_Constraint_IsNull' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
'PHPUnit_Framework_Constraint_IsTrue' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
'PHPUnit_Framework_Constraint_IsType' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
'PHPUnit_Framework_Constraint_JsonMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
'PHPUnit_Framework_Constraint_LessThan' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
'PHPUnit_Framework_Constraint_Not' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Not.php',
'PHPUnit_Framework_Constraint_ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
'PHPUnit_Framework_Constraint_Or' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Or.php',
'PHPUnit_Framework_Constraint_PCREMatch' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/PCREMatch.php',
'PHPUnit_Framework_Constraint_SameSize' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
'PHPUnit_Framework_Constraint_StringContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
'PHPUnit_Framework_Constraint_StringEndsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
'PHPUnit_Framework_Constraint_StringMatches' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringMatches.php',
'PHPUnit_Framework_Constraint_StringStartsWith' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
'PHPUnit_Framework_Constraint_TraversableContains' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
'PHPUnit_Framework_Constraint_TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
'PHPUnit_Framework_Constraint_Xor' => $vendorDir . '/phpunit/phpunit/src/Framework/Constraint/Xor.php',
'PHPUnit_Framework_Error' => $vendorDir . '/phpunit/phpunit/src/Framework/Error.php',
'PHPUnit_Framework_Error_Deprecated' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
'PHPUnit_Framework_Error_Notice' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Notice.php',
'PHPUnit_Framework_Error_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Error/Warning.php',
'PHPUnit_Framework_Exception' => $vendorDir . '/phpunit/phpunit/src/Framework/Exception.php',
'PHPUnit_Framework_ExceptionWrapper' => $vendorDir . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
'PHPUnit_Framework_ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/src/Framework/ExpectationFailedException.php',
'PHPUnit_Framework_IncompleteTest' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
'PHPUnit_Framework_IncompleteTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
'PHPUnit_Framework_IncompleteTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/IncompleteTestError.php',
'PHPUnit_Framework_InvalidCoversTargetError' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetError.php',
'PHPUnit_Framework_InvalidCoversTargetException' => $vendorDir . '/phpunit/phpunit/src/Framework/InvalidCoversTargetException.php',
'PHPUnit_Framework_MockObject_BadMethodCallException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/BadMethodCallException.php',
'PHPUnit_Framework_MockObject_Builder_Identity' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Identity.php',
'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Builder_Match' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Match.php',
'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/MethodNameMatch.php',
'PHPUnit_Framework_MockObject_Builder_Namespace' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Namespace.php',
'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/ParametersMatch.php',
'PHPUnit_Framework_MockObject_Builder_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Stub.php',
'PHPUnit_Framework_MockObject_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/Exception.php',
'PHPUnit_Framework_MockObject_Generator' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php',
'PHPUnit_Framework_MockObject_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation.php',
'PHPUnit_Framework_MockObject_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Invocation_Object' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Object.php',
'PHPUnit_Framework_MockObject_Invocation_Static' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Static.php',
'PHPUnit_Framework_MockObject_Invokable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invokable.php',
'PHPUnit_Framework_MockObject_Matcher' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher.php',
'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyInvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyParameters.php',
'PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/ConsecutiveParameters.php',
'PHPUnit_Framework_MockObject_Matcher_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Invocation.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtIndex.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtMostCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedRecorder.php',
'PHPUnit_Framework_MockObject_Matcher_MethodName' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/MethodName.php',
'PHPUnit_Framework_MockObject_Matcher_Parameters' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Parameters.php',
'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/StatelessInvocation.php',
'PHPUnit_Framework_MockObject_MockBuilder' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockBuilder.php',
'PHPUnit_Framework_MockObject_MockObject' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockObject.php',
'PHPUnit_Framework_MockObject_RuntimeException' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/RuntimeException.php',
'PHPUnit_Framework_MockObject_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub.php',
'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
'PHPUnit_Framework_MockObject_Stub_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Exception.php',
'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/MatcherCollection.php',
'PHPUnit_Framework_MockObject_Stub_Return' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Return.php',
'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnArgument.php',
'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnCallback.php',
'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnSelf.php',
'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnValueMap.php',
'PHPUnit_Framework_MockObject_Verifiable' => $vendorDir . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Verifiable.php',
'PHPUnit_Framework_OutputError' => $vendorDir . '/phpunit/phpunit/src/Framework/OutputError.php',
'PHPUnit_Framework_RiskyTest' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTest.php',
'PHPUnit_Framework_RiskyTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/RiskyTestError.php',
'PHPUnit_Framework_SelfDescribing' => $vendorDir . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
'PHPUnit_Framework_SkippedTest' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTest.php',
'PHPUnit_Framework_SkippedTestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
'PHPUnit_Framework_SkippedTestError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestError.php',
'PHPUnit_Framework_SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/src/Framework/SkippedTestSuiteError.php',
'PHPUnit_Framework_SyntheticError' => $vendorDir . '/phpunit/phpunit/src/Framework/SyntheticError.php',
'PHPUnit_Framework_Test' => $vendorDir . '/phpunit/phpunit/src/Framework/Test.php',
'PHPUnit_Framework_TestCase' => $vendorDir . '/phpunit/phpunit/src/Framework/TestCase.php',
'PHPUnit_Framework_TestFailure' => $vendorDir . '/phpunit/phpunit/src/Framework/TestFailure.php',
'PHPUnit_Framework_TestListener' => $vendorDir . '/phpunit/phpunit/src/Framework/TestListener.php',
'PHPUnit_Framework_TestResult' => $vendorDir . '/phpunit/phpunit/src/Framework/TestResult.php',
'PHPUnit_Framework_TestSuite' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite.php',
'PHPUnit_Framework_TestSuite_DataProvider' => $vendorDir . '/phpunit/phpunit/src/Framework/TestSuite/DataProvider.php',
'PHPUnit_Framework_UnintentionallyCoveredCodeError' => $vendorDir . '/phpunit/phpunit/src/Framework/UnintentionallyCoveredCodeError.php',
'PHPUnit_Framework_Warning' => $vendorDir . '/phpunit/phpunit/src/Framework/Warning.php',
'PHPUnit_Runner_BaseTestRunner' => $vendorDir . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
'PHPUnit_Runner_Exception' => $vendorDir . '/phpunit/phpunit/src/Runner/Exception.php',
'PHPUnit_Runner_Filter_Factory' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
'PHPUnit_Runner_Filter_GroupFilterIterator' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group.php',
'PHPUnit_Runner_Filter_Group_Exclude' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Exclude.php',
'PHPUnit_Runner_Filter_Group_Include' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Group/Include.php',
'PHPUnit_Runner_Filter_Test' => $vendorDir . '/phpunit/phpunit/src/Runner/Filter/Test.php',
'PHPUnit_Runner_StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
'PHPUnit_Runner_TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
'PHPUnit_Runner_Version' => $vendorDir . '/phpunit/phpunit/src/Runner/Version.php',
'PHPUnit_TextUI_Command' => $vendorDir . '/phpunit/phpunit/src/TextUI/Command.php',
'PHPUnit_TextUI_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
'PHPUnit_TextUI_TestRunner' => $vendorDir . '/phpunit/phpunit/src/TextUI/TestRunner.php',
'PHPUnit_Util_Blacklist' => $vendorDir . '/phpunit/phpunit/src/Util/Blacklist.php',
'PHPUnit_Util_Configuration' => $vendorDir . '/phpunit/phpunit/src/Util/Configuration.php',
'PHPUnit_Util_ErrorHandler' => $vendorDir . '/phpunit/phpunit/src/Util/ErrorHandler.php',
'PHPUnit_Util_Fileloader' => $vendorDir . '/phpunit/phpunit/src/Util/Fileloader.php',
'PHPUnit_Util_Filesystem' => $vendorDir . '/phpunit/phpunit/src/Util/Filesystem.php',
'PHPUnit_Util_Filter' => $vendorDir . '/phpunit/phpunit/src/Util/Filter.php',
'PHPUnit_Util_Getopt' => $vendorDir . '/phpunit/phpunit/src/Util/Getopt.php',
'PHPUnit_Util_GlobalState' => $vendorDir . '/phpunit/phpunit/src/Util/GlobalState.php',
'PHPUnit_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/phpunit/src/Util/InvalidArgumentHelper.php',
'PHPUnit_Util_Log_JSON' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JSON.php',
'PHPUnit_Util_Log_JUnit' => $vendorDir . '/phpunit/phpunit/src/Util/Log/JUnit.php',
'PHPUnit_Util_Log_TAP' => $vendorDir . '/phpunit/phpunit/src/Util/Log/TAP.php',
'PHPUnit_Util_PHP' => $vendorDir . '/phpunit/phpunit/src/Util/PHP.php',
'PHPUnit_Util_PHP_Default' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Default.php',
'PHPUnit_Util_PHP_Windows' => $vendorDir . '/phpunit/phpunit/src/Util/PHP/Windows.php',
'PHPUnit_Util_Printer' => $vendorDir . '/phpunit/phpunit/src/Util/Printer.php',
'PHPUnit_Util_Regex' => $vendorDir . '/phpunit/phpunit/src/Util/Regex.php',
'PHPUnit_Util_String' => $vendorDir . '/phpunit/phpunit/src/Util/String.php',
'PHPUnit_Util_Test' => $vendorDir . '/phpunit/phpunit/src/Util/Test.php',
'PHPUnit_Util_TestDox_NamePrettifier' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
'PHPUnit_Util_TestDox_ResultPrinter' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
'PHPUnit_Util_TestDox_ResultPrinter_HTML' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/HTML.php',
'PHPUnit_Util_TestDox_ResultPrinter_Text' => $vendorDir . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/Text.php',
'PHPUnit_Util_TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/src/Util/TestSuiteIterator.php',
'PHPUnit_Util_Type' => $vendorDir . '/phpunit/phpunit/src/Util/Type.php',
'PHPUnit_Util_XML' => $vendorDir . '/phpunit/phpunit/src/Util/XML.php',
'PHP_CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage.php',
'PHP_CodeCoverage_Driver' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver.php',
'PHP_CodeCoverage_Driver_HHVM' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/HHVM.php',
'PHP_CodeCoverage_Driver_PHPDBG' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/PHPDBG.php',
'PHP_CodeCoverage_Driver_Xdebug' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/Xdebug.php',
'PHP_CodeCoverage_Exception' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception.php',
'PHP_CodeCoverage_Exception_UnintentionallyCoveredCode' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php',
'PHP_CodeCoverage_Filter' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Filter.php',
'PHP_CodeCoverage_Report_Clover' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Clover.php',
'PHP_CodeCoverage_Report_Crap4j' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Crap4j.php',
'PHP_CodeCoverage_Report_Factory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php',
'PHP_CodeCoverage_Report_HTML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML.php',
'PHP_CodeCoverage_Report_HTML_Renderer' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Directory.php',
'PHP_CodeCoverage_Report_HTML_Renderer_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php',
'PHP_CodeCoverage_Report_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node.php',
'PHP_CodeCoverage_Report_Node_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Directory.php',
'PHP_CodeCoverage_Report_Node_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php',
'PHP_CodeCoverage_Report_Node_Iterator' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Iterator.php',
'PHP_CodeCoverage_Report_PHP' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/PHP.php',
'PHP_CodeCoverage_Report_Text' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Text.php',
'PHP_CodeCoverage_Report_XML' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML.php',
'PHP_CodeCoverage_Report_XML_Directory' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Directory.php',
'PHP_CodeCoverage_Report_XML_File' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File.php',
'PHP_CodeCoverage_Report_XML_File_Coverage' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Coverage.php',
'PHP_CodeCoverage_Report_XML_File_Method' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Method.php',
'PHP_CodeCoverage_Report_XML_File_Report' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Report.php',
'PHP_CodeCoverage_Report_XML_File_Unit' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Unit.php',
'PHP_CodeCoverage_Report_XML_Node' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Node.php',
'PHP_CodeCoverage_Report_XML_Project' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Project.php',
'PHP_CodeCoverage_Report_XML_Tests' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Tests.php',
'PHP_CodeCoverage_Report_XML_Totals' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Totals.php',
'PHP_CodeCoverage_Util' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util.php',
'PHP_CodeCoverage_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/php-code-coverage/src/CodeCoverage/Util/InvalidArgumentHelper.php',
'PHP_Timer' => $vendorDir . '/phpunit/php-timer/src/Timer.php',
'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ASYNC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AWAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COALESCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMPILER_HALT_OFFSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELLIPSIS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENUM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EQUALS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_JOIN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_ARROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_CP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_OP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NULLSAFE_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ONUMBER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SHAPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SPACESHIP' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SUPER' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream.php',
'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/src/Token/Stream/CachingFactory.php',
'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHERE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_ATTRIBUTE' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CHILDREN' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_LABEL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_REQUIRED' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_GT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_LT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TEXT' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD_FROM' => $vendorDir . '/phpunit/php-token-stream/src/Token.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'SebastianBergmann\\Comparator\\ArrayComparator' => $vendorDir . '/sebastian/comparator/src/ArrayComparator.php',
'SebastianBergmann\\Comparator\\Comparator' => $vendorDir . '/sebastian/comparator/src/Comparator.php',
'SebastianBergmann\\Comparator\\ComparisonFailure' => $vendorDir . '/sebastian/comparator/src/ComparisonFailure.php',
'SebastianBergmann\\Comparator\\DOMNodeComparator' => $vendorDir . '/sebastian/comparator/src/DOMNodeComparator.php',
'SebastianBergmann\\Comparator\\DateTimeComparator' => $vendorDir . '/sebastian/comparator/src/DateTimeComparator.php',
'SebastianBergmann\\Comparator\\DoubleComparator' => $vendorDir . '/sebastian/comparator/src/DoubleComparator.php',
'SebastianBergmann\\Comparator\\ExceptionComparator' => $vendorDir . '/sebastian/comparator/src/ExceptionComparator.php',
'SebastianBergmann\\Comparator\\Factory' => $vendorDir . '/sebastian/comparator/src/Factory.php',
'SebastianBergmann\\Comparator\\MockObjectComparator' => $vendorDir . '/sebastian/comparator/src/MockObjectComparator.php',
'SebastianBergmann\\Comparator\\NumericComparator' => $vendorDir . '/sebastian/comparator/src/NumericComparator.php',
'SebastianBergmann\\Comparator\\ObjectComparator' => $vendorDir . '/sebastian/comparator/src/ObjectComparator.php',
'SebastianBergmann\\Comparator\\ResourceComparator' => $vendorDir . '/sebastian/comparator/src/ResourceComparator.php',
'SebastianBergmann\\Comparator\\ScalarComparator' => $vendorDir . '/sebastian/comparator/src/ScalarComparator.php',
'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => $vendorDir . '/sebastian/comparator/src/SplObjectStorageComparator.php',
'SebastianBergmann\\Comparator\\TypeComparator' => $vendorDir . '/sebastian/comparator/src/TypeComparator.php',
'SebastianBergmann\\Diff\\Chunk' => $vendorDir . '/sebastian/diff/src/Chunk.php',
'SebastianBergmann\\Diff\\Diff' => $vendorDir . '/sebastian/diff/src/Diff.php',
'SebastianBergmann\\Diff\\Differ' => $vendorDir . '/sebastian/diff/src/Differ.php',
'SebastianBergmann\\Diff\\LCS\\LongestCommonSubsequence' => $vendorDir . '/sebastian/diff/src/LCS/LongestCommonSubsequence.php',
'SebastianBergmann\\Diff\\LCS\\MemoryEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\LCS\\TimeEfficientImplementation' => $vendorDir . '/sebastian/diff/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\Line' => $vendorDir . '/sebastian/diff/src/Line.php',
'SebastianBergmann\\Diff\\Parser' => $vendorDir . '/sebastian/diff/src/Parser.php',
'SebastianBergmann\\Environment\\Console' => $vendorDir . '/sebastian/environment/src/Console.php',
'SebastianBergmann\\Environment\\Runtime' => $vendorDir . '/sebastian/environment/src/Runtime.php',
'SebastianBergmann\\Exporter\\Exporter' => $vendorDir . '/sebastian/exporter/src/Exporter.php',
'SebastianBergmann\\GlobalState\\Blacklist' => $vendorDir . '/sebastian/global-state/src/Blacklist.php',
'SebastianBergmann\\GlobalState\\CodeExporter' => $vendorDir . '/sebastian/global-state/src/CodeExporter.php',
'SebastianBergmann\\GlobalState\\Exception' => $vendorDir . '/sebastian/global-state/src/Exception.php',
'SebastianBergmann\\GlobalState\\Restorer' => $vendorDir . '/sebastian/global-state/src/Restorer.php',
'SebastianBergmann\\GlobalState\\RuntimeException' => $vendorDir . '/sebastian/global-state/src/RuntimeException.php',
'SebastianBergmann\\GlobalState\\Snapshot' => $vendorDir . '/sebastian/global-state/src/Snapshot.php',
'SebastianBergmann\\RecursionContext\\Context' => $vendorDir . '/sebastian/recursion-context/src/Context.php',
'SebastianBergmann\\RecursionContext\\Exception' => $vendorDir . '/sebastian/recursion-context/src/Exception.php',
'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => $vendorDir . '/sebastian/recursion-context/src/InvalidArgumentException.php',
'SebastianBergmann\\Version' => $vendorDir . '/sebastian/version/src/Version.php',
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Text_Template' => $vendorDir . '/phpunit/php-text-template/src/Template.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);

View File

@@ -0,0 +1,15 @@
<?php
// autoload_files.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,30 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'voku\\' => array($vendorDir . '/voku/portable-ascii/src/voku'),
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/type-resolver/src', $vendorDir . '/phpdocumentor/reflection-docblock/src'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'Webklex\\PHPIMAP\\' => array($baseDir . '/src'),
'Tests\\' => array($baseDir . '/tests'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
'Illuminate\\Support\\' => array($vendorDir . '/illuminate/macroable', $vendorDir . '/illuminate/collections', $vendorDir . '/illuminate/support'),
'Illuminate\\Pagination\\' => array($vendorDir . '/illuminate/pagination'),
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'Doctrine\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Inflector'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
);

View File

@@ -0,0 +1,57 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4da13270269c89a28e472e1f7324e6d1::getInitializer($loader));
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInit4da13270269c89a28e472e1f7324e6d1::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4da13270269c89a28e472e1f7324e6d1($fileIdentifier, $file);
}
return $loader;
}
}
/**
* @param string $fileIdentifier
* @param string $file
* @return void
*/
function composerRequire4da13270269c89a28e472e1f7324e6d1($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}

View File

@@ -0,0 +1,623 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit4da13270269c89a28e472e1f7324e6d1
{
public static $files = array (
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
);
public static $prefixLengthsPsr4 = array (
'v' =>
array (
'voku\\' => 5,
),
'p' =>
array (
'phpDocumentor\\Reflection\\' => 25,
),
'W' =>
array (
'Webmozart\\Assert\\' => 17,
'Webklex\\PHPIMAP\\' => 16,
),
'T' =>
array (
'Tests\\' => 6,
),
'S' =>
array (
'Symfony\\Polyfill\\Php80\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23,
'Symfony\\Contracts\\Translation\\' => 30,
'Symfony\\Component\\Yaml\\' => 23,
'Symfony\\Component\\Translation\\' => 30,
'Symfony\\Component\\HttpFoundation\\' => 33,
),
'P' =>
array (
'Psr\\SimpleCache\\' => 16,
'Psr\\Container\\' => 14,
'Prophecy\\' => 9,
),
'I' =>
array (
'Illuminate\\Support\\' => 19,
'Illuminate\\Pagination\\' => 22,
'Illuminate\\Contracts\\' => 21,
),
'D' =>
array (
'Doctrine\\Instantiator\\' => 22,
'Doctrine\\Inflector\\' => 19,
),
'C' =>
array (
'Carbon\\' => 7,
),
);
public static $prefixDirsPsr4 = array (
'voku\\' =>
array (
0 => __DIR__ . '/..' . '/voku/portable-ascii/src/voku',
),
'phpDocumentor\\Reflection\\' =>
array (
0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src',
1 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src',
2 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src',
),
'Webmozart\\Assert\\' =>
array (
0 => __DIR__ . '/..' . '/webmozart/assert/src',
),
'Webklex\\PHPIMAP\\' =>
array (
0 => __DIR__ . '/../..' . '/src',
),
'Tests\\' =>
array (
0 => __DIR__ . '/../..' . '/tests',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
'Symfony\\Polyfill\\Ctype\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
),
'Symfony\\Contracts\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
),
'Symfony\\Component\\Yaml\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/yaml',
),
'Symfony\\Component\\Translation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/translation',
),
'Symfony\\Component\\HttpFoundation\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/http-foundation',
),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
),
'Psr\\Container\\' =>
array (
0 => __DIR__ . '/..' . '/psr/container/src',
),
'Prophecy\\' =>
array (
0 => __DIR__ . '/..' . '/phpspec/prophecy/src/Prophecy',
),
'Illuminate\\Support\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/macroable',
1 => __DIR__ . '/..' . '/illuminate/collections',
2 => __DIR__ . '/..' . '/illuminate/support',
),
'Illuminate\\Pagination\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/pagination',
),
'Illuminate\\Contracts\\' =>
array (
0 => __DIR__ . '/..' . '/illuminate/contracts',
),
'Doctrine\\Instantiator\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator',
),
'Doctrine\\Inflector\\' =>
array (
0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Inflector',
),
'Carbon\\' =>
array (
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
),
);
public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'File_Iterator' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Iterator.php',
'File_Iterator_Facade' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Facade.php',
'File_Iterator_Factory' => __DIR__ . '/..' . '/phpunit/php-file-iterator/src/Factory.php',
'PHPUnit\\Framework\\Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/Assert.php',
'PHPUnit\\Framework\\AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/AssertionFailedError.php',
'PHPUnit\\Framework\\BaseTestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/BaseTestListener.php',
'PHPUnit\\Framework\\Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/Test.php',
'PHPUnit\\Framework\\TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/TestCase.php',
'PHPUnit\\Framework\\TestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/TestListener.php',
'PHPUnit\\Framework\\TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/ForwardCompatibility/TestSuite.php',
'PHPUnit_Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Exception.php',
'PHPUnit_Extensions_GroupTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/GroupTestSuite.php',
'PHPUnit_Extensions_PhptTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/PhptTestCase.php',
'PHPUnit_Extensions_PhptTestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/PhptTestSuite.php',
'PHPUnit_Extensions_RepeatedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/RepeatedTest.php',
'PHPUnit_Extensions_TestDecorator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/TestDecorator.php',
'PHPUnit_Extensions_TicketListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Extensions/TicketListener.php',
'PHPUnit_Framework_Assert' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Assert.php',
'PHPUnit_Framework_AssertionFailedError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/AssertionFailedError.php',
'PHPUnit_Framework_BaseTestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/BaseTestListener.php',
'PHPUnit_Framework_CodeCoverageException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/CodeCoverageException.php',
'PHPUnit_Framework_Constraint' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint.php',
'PHPUnit_Framework_Constraint_And' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/And.php',
'PHPUnit_Framework_Constraint_ArrayHasKey' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ArrayHasKey.php',
'PHPUnit_Framework_Constraint_ArraySubset' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ArraySubset.php',
'PHPUnit_Framework_Constraint_Attribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Attribute.php',
'PHPUnit_Framework_Constraint_Callback' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Callback.php',
'PHPUnit_Framework_Constraint_ClassHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ClassHasAttribute.php',
'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ClassHasStaticAttribute.php',
'PHPUnit_Framework_Constraint_Composite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Composite.php',
'PHPUnit_Framework_Constraint_Count' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Count.php',
'PHPUnit_Framework_Constraint_Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Exception.php',
'PHPUnit_Framework_Constraint_ExceptionCode' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionCode.php',
'PHPUnit_Framework_Constraint_ExceptionMessage' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessage.php',
'PHPUnit_Framework_Constraint_ExceptionMessageRegExp' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ExceptionMessageRegExp.php',
'PHPUnit_Framework_Constraint_FileExists' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/FileExists.php',
'PHPUnit_Framework_Constraint_GreaterThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/GreaterThan.php',
'PHPUnit_Framework_Constraint_IsAnything' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsAnything.php',
'PHPUnit_Framework_Constraint_IsEmpty' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsEmpty.php',
'PHPUnit_Framework_Constraint_IsEqual' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsEqual.php',
'PHPUnit_Framework_Constraint_IsFalse' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsFalse.php',
'PHPUnit_Framework_Constraint_IsIdentical' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php',
'PHPUnit_Framework_Constraint_IsInstanceOf' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsInstanceOf.php',
'PHPUnit_Framework_Constraint_IsJson' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsJson.php',
'PHPUnit_Framework_Constraint_IsNull' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsNull.php',
'PHPUnit_Framework_Constraint_IsTrue' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsTrue.php',
'PHPUnit_Framework_Constraint_IsType' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/IsType.php',
'PHPUnit_Framework_Constraint_JsonMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches.php',
'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
'PHPUnit_Framework_Constraint_LessThan' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/LessThan.php',
'PHPUnit_Framework_Constraint_Not' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Not.php',
'PHPUnit_Framework_Constraint_ObjectHasAttribute' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/ObjectHasAttribute.php',
'PHPUnit_Framework_Constraint_Or' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Or.php',
'PHPUnit_Framework_Constraint_PCREMatch' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/PCREMatch.php',
'PHPUnit_Framework_Constraint_SameSize' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/SameSize.php',
'PHPUnit_Framework_Constraint_StringContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringContains.php',
'PHPUnit_Framework_Constraint_StringEndsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringEndsWith.php',
'PHPUnit_Framework_Constraint_StringMatches' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringMatches.php',
'PHPUnit_Framework_Constraint_StringStartsWith' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/StringStartsWith.php',
'PHPUnit_Framework_Constraint_TraversableContains' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContains.php',
'PHPUnit_Framework_Constraint_TraversableContainsOnly' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/TraversableContainsOnly.php',
'PHPUnit_Framework_Constraint_Xor' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Constraint/Xor.php',
'PHPUnit_Framework_Error' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error.php',
'PHPUnit_Framework_Error_Deprecated' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Deprecated.php',
'PHPUnit_Framework_Error_Notice' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Notice.php',
'PHPUnit_Framework_Error_Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Error/Warning.php',
'PHPUnit_Framework_Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Exception.php',
'PHPUnit_Framework_ExceptionWrapper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExceptionWrapper.php',
'PHPUnit_Framework_ExpectationFailedException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/ExpectationFailedException.php',
'PHPUnit_Framework_IncompleteTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTest.php',
'PHPUnit_Framework_IncompleteTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTestCase.php',
'PHPUnit_Framework_IncompleteTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/IncompleteTestError.php',
'PHPUnit_Framework_InvalidCoversTargetError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/InvalidCoversTargetError.php',
'PHPUnit_Framework_InvalidCoversTargetException' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/InvalidCoversTargetException.php',
'PHPUnit_Framework_MockObject_BadMethodCallException' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/BadMethodCallException.php',
'PHPUnit_Framework_MockObject_Builder_Identity' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Identity.php',
'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Builder_Match' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Match.php',
'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/MethodNameMatch.php',
'PHPUnit_Framework_MockObject_Builder_Namespace' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Namespace.php',
'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/ParametersMatch.php',
'PHPUnit_Framework_MockObject_Builder_Stub' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Builder/Stub.php',
'PHPUnit_Framework_MockObject_Exception' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/Exception.php',
'PHPUnit_Framework_MockObject_Generator' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php',
'PHPUnit_Framework_MockObject_Invocation' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation.php',
'PHPUnit_Framework_MockObject_InvocationMocker' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/InvocationMocker.php',
'PHPUnit_Framework_MockObject_Invocation_Object' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Object.php',
'PHPUnit_Framework_MockObject_Invocation_Static' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invocation/Static.php',
'PHPUnit_Framework_MockObject_Invokable' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Invokable.php',
'PHPUnit_Framework_MockObject_Matcher' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher.php',
'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyInvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/AnyParameters.php',
'PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/ConsecutiveParameters.php',
'PHPUnit_Framework_MockObject_Matcher_Invocation' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Invocation.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtIndex.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastCount' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedAtMostCount' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedAtMostCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedCount.php',
'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/InvokedRecorder.php',
'PHPUnit_Framework_MockObject_Matcher_MethodName' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/MethodName.php',
'PHPUnit_Framework_MockObject_Matcher_Parameters' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/Parameters.php',
'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Matcher/StatelessInvocation.php',
'PHPUnit_Framework_MockObject_MockBuilder' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockBuilder.php',
'PHPUnit_Framework_MockObject_MockObject' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/MockObject.php',
'PHPUnit_Framework_MockObject_RuntimeException' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Exception/RuntimeException.php',
'PHPUnit_Framework_MockObject_Stub' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub.php',
'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ConsecutiveCalls.php',
'PHPUnit_Framework_MockObject_Stub_Exception' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Exception.php',
'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/MatcherCollection.php',
'PHPUnit_Framework_MockObject_Stub_Return' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/Return.php',
'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnArgument.php',
'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnCallback.php',
'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnSelf.php',
'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Stub/ReturnValueMap.php',
'PHPUnit_Framework_MockObject_Verifiable' => __DIR__ . '/..' . '/phpunit/phpunit-mock-objects/src/Framework/MockObject/Verifiable.php',
'PHPUnit_Framework_OutputError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/OutputError.php',
'PHPUnit_Framework_RiskyTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/RiskyTest.php',
'PHPUnit_Framework_RiskyTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/RiskyTestError.php',
'PHPUnit_Framework_SelfDescribing' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SelfDescribing.php',
'PHPUnit_Framework_SkippedTest' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTest.php',
'PHPUnit_Framework_SkippedTestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestCase.php',
'PHPUnit_Framework_SkippedTestError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestError.php',
'PHPUnit_Framework_SkippedTestSuiteError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SkippedTestSuiteError.php',
'PHPUnit_Framework_SyntheticError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/SyntheticError.php',
'PHPUnit_Framework_Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Test.php',
'PHPUnit_Framework_TestCase' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestCase.php',
'PHPUnit_Framework_TestFailure' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestFailure.php',
'PHPUnit_Framework_TestListener' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestListener.php',
'PHPUnit_Framework_TestResult' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestResult.php',
'PHPUnit_Framework_TestSuite' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite.php',
'PHPUnit_Framework_TestSuite_DataProvider' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/TestSuite/DataProvider.php',
'PHPUnit_Framework_UnintentionallyCoveredCodeError' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/UnintentionallyCoveredCodeError.php',
'PHPUnit_Framework_Warning' => __DIR__ . '/..' . '/phpunit/phpunit/src/Framework/Warning.php',
'PHPUnit_Runner_BaseTestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/BaseTestRunner.php',
'PHPUnit_Runner_Exception' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Exception.php',
'PHPUnit_Runner_Filter_Factory' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Factory.php',
'PHPUnit_Runner_Filter_GroupFilterIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Group.php',
'PHPUnit_Runner_Filter_Group_Exclude' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Group/Exclude.php',
'PHPUnit_Runner_Filter_Group_Include' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Group/Include.php',
'PHPUnit_Runner_Filter_Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Filter/Test.php',
'PHPUnit_Runner_StandardTestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/StandardTestSuiteLoader.php',
'PHPUnit_Runner_TestSuiteLoader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/TestSuiteLoader.php',
'PHPUnit_Runner_Version' => __DIR__ . '/..' . '/phpunit/phpunit/src/Runner/Version.php',
'PHPUnit_TextUI_Command' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/Command.php',
'PHPUnit_TextUI_ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/ResultPrinter.php',
'PHPUnit_TextUI_TestRunner' => __DIR__ . '/..' . '/phpunit/phpunit/src/TextUI/TestRunner.php',
'PHPUnit_Util_Blacklist' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Blacklist.php',
'PHPUnit_Util_Configuration' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Configuration.php',
'PHPUnit_Util_ErrorHandler' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/ErrorHandler.php',
'PHPUnit_Util_Fileloader' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Fileloader.php',
'PHPUnit_Util_Filesystem' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filesystem.php',
'PHPUnit_Util_Filter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Filter.php',
'PHPUnit_Util_Getopt' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Getopt.php',
'PHPUnit_Util_GlobalState' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/GlobalState.php',
'PHPUnit_Util_InvalidArgumentHelper' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/InvalidArgumentHelper.php',
'PHPUnit_Util_Log_JSON' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/JSON.php',
'PHPUnit_Util_Log_JUnit' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/JUnit.php',
'PHPUnit_Util_Log_TAP' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Log/TAP.php',
'PHPUnit_Util_PHP' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP.php',
'PHPUnit_Util_PHP_Default' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/Default.php',
'PHPUnit_Util_PHP_Windows' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/PHP/Windows.php',
'PHPUnit_Util_Printer' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Printer.php',
'PHPUnit_Util_Regex' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Regex.php',
'PHPUnit_Util_String' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/String.php',
'PHPUnit_Util_Test' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Test.php',
'PHPUnit_Util_TestDox_NamePrettifier' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/NamePrettifier.php',
'PHPUnit_Util_TestDox_ResultPrinter' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter.php',
'PHPUnit_Util_TestDox_ResultPrinter_HTML' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/HTML.php',
'PHPUnit_Util_TestDox_ResultPrinter_Text' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestDox/ResultPrinter/Text.php',
'PHPUnit_Util_TestSuiteIterator' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/TestSuiteIterator.php',
'PHPUnit_Util_Type' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/Type.php',
'PHPUnit_Util_XML' => __DIR__ . '/..' . '/phpunit/phpunit/src/Util/XML.php',
'PHP_CodeCoverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage.php',
'PHP_CodeCoverage_Driver' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Driver.php',
'PHP_CodeCoverage_Driver_HHVM' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/HHVM.php',
'PHP_CodeCoverage_Driver_PHPDBG' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/PHPDBG.php',
'PHP_CodeCoverage_Driver_Xdebug' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Driver/Xdebug.php',
'PHP_CodeCoverage_Exception' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Exception.php',
'PHP_CodeCoverage_Exception_UnintentionallyCoveredCode' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php',
'PHP_CodeCoverage_Filter' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Filter.php',
'PHP_CodeCoverage_Report_Clover' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Clover.php',
'PHP_CodeCoverage_Report_Crap4j' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Crap4j.php',
'PHP_CodeCoverage_Report_Factory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Factory.php',
'PHP_CodeCoverage_Report_HTML' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML.php',
'PHP_CodeCoverage_Report_HTML_Renderer' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/Directory.php',
'PHP_CodeCoverage_Report_HTML_Renderer_File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/HTML/Renderer/File.php',
'PHP_CodeCoverage_Report_Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node.php',
'PHP_CodeCoverage_Report_Node_Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Directory.php',
'PHP_CodeCoverage_Report_Node_File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/File.php',
'PHP_CodeCoverage_Report_Node_Iterator' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Node/Iterator.php',
'PHP_CodeCoverage_Report_PHP' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/PHP.php',
'PHP_CodeCoverage_Report_Text' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/Text.php',
'PHP_CodeCoverage_Report_XML' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML.php',
'PHP_CodeCoverage_Report_XML_Directory' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Directory.php',
'PHP_CodeCoverage_Report_XML_File' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File.php',
'PHP_CodeCoverage_Report_XML_File_Coverage' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Coverage.php',
'PHP_CodeCoverage_Report_XML_File_Method' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Method.php',
'PHP_CodeCoverage_Report_XML_File_Report' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Report.php',
'PHP_CodeCoverage_Report_XML_File_Unit' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/File/Unit.php',
'PHP_CodeCoverage_Report_XML_Node' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Node.php',
'PHP_CodeCoverage_Report_XML_Project' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Project.php',
'PHP_CodeCoverage_Report_XML_Tests' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Tests.php',
'PHP_CodeCoverage_Report_XML_Totals' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Report/XML/Totals.php',
'PHP_CodeCoverage_Util' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Util.php',
'PHP_CodeCoverage_Util_InvalidArgumentHelper' => __DIR__ . '/..' . '/phpunit/php-code-coverage/src/CodeCoverage/Util/InvalidArgumentHelper.php',
'PHP_Timer' => __DIR__ . '/..' . '/phpunit/php-timer/src/Timer.php',
'PHP_Token' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScope' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_TokenWithScopeAndVisibility' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ABSTRACT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AMPERSAND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AND_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ARRAY_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ASYNC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_AWAIT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BACKTICK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BAD_CHARACTER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_AND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOLEAN_OR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BOOL_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_BREAK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CALLABLE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CARET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CASE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CATCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CHARACTER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLASS_NAME_CONSTANT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLONE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_BRACKET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_CURLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_SQUARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CLOSE_TAG' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COALESCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMA' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMMENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_COMPILER_HALT_OFFSET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONCAT_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONSTANT_ENCAPSED_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CONTINUE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_CURLY_OPEN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DECLARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DEFAULT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DIV_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DNUMBER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOC_COMMENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_ARROW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_COLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_DOUBLE_QUOTES' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ECHO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELLIPSIS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ELSEIF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EMPTY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENCAPSED_AND_WHITESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDDECLARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDFOREACH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDIF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDSWITCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENDWHILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_END_HEREDOC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ENUM' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EQUALS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EVAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXCLAMATION_MARK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXIT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_EXTENDS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FINALLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FOREACH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNCTION' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_FUNC_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GLOBAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GOTO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_GT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_HALT_COMPILER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IMPLEMENTS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INCLUDE_ONCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INLINE_HTML' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTANCEOF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INSTEADOF' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INTERFACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_INT_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ISSET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_GREATER_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_IDENTICAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_NOT_IDENTICAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_IS_SMALLER_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Includes' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_JOIN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_ARROW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_CP' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LAMBDA_OP' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LINE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LIST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LNUMBER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_AND' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_OR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LOGICAL_XOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_LT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_METHOD_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MINUS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MOD_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MULT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_MUL_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NAMESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NEW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NS_SEPARATOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NULLSAFE_OBJECT_OPERATOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_NUM_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OBJECT_OPERATOR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_ONUMBER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_BRACKET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_CURLY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_SQUARE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OPEN_TAG_WITH_ECHO' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_OR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PERCENT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PIPE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PLUS_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_POW_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRINT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PRIVATE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PROTECTED' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_PUBLIC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_QUESTION_MARK' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_REQUIRE_ONCE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_RETURN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SEMICOLON' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SHAPE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SL_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SPACESHIP' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_START_HEREDOC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STATIC' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_STRING_VARNAME' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SUPER' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_SWITCH' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_Stream' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token/Stream.php',
'PHP_Token_Stream_CachingFactory' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token/Stream/CachingFactory.php',
'PHP_Token_THROW' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TILDE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRAIT_C' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TRY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_GT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_TYPELIST_LT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_UNSET_CAST' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_USE_FUNCTION' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VAR' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_VARIABLE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHERE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHILE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_WHITESPACE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_ATTRIBUTE' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CATEGORY_LABEL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_CHILDREN' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_LABEL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_REQUIRED' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_GT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TAG_LT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XHP_TEXT' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_XOR_EQUAL' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PHP_Token_YIELD_FROM' => __DIR__ . '/..' . '/phpunit/php-token-stream/src/Token.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'SebastianBergmann\\Comparator\\ArrayComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ArrayComparator.php',
'SebastianBergmann\\Comparator\\Comparator' => __DIR__ . '/..' . '/sebastian/comparator/src/Comparator.php',
'SebastianBergmann\\Comparator\\ComparisonFailure' => __DIR__ . '/..' . '/sebastian/comparator/src/ComparisonFailure.php',
'SebastianBergmann\\Comparator\\DOMNodeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DOMNodeComparator.php',
'SebastianBergmann\\Comparator\\DateTimeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DateTimeComparator.php',
'SebastianBergmann\\Comparator\\DoubleComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/DoubleComparator.php',
'SebastianBergmann\\Comparator\\ExceptionComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ExceptionComparator.php',
'SebastianBergmann\\Comparator\\Factory' => __DIR__ . '/..' . '/sebastian/comparator/src/Factory.php',
'SebastianBergmann\\Comparator\\MockObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/MockObjectComparator.php',
'SebastianBergmann\\Comparator\\NumericComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/NumericComparator.php',
'SebastianBergmann\\Comparator\\ObjectComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ObjectComparator.php',
'SebastianBergmann\\Comparator\\ResourceComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ResourceComparator.php',
'SebastianBergmann\\Comparator\\ScalarComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/ScalarComparator.php',
'SebastianBergmann\\Comparator\\SplObjectStorageComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/SplObjectStorageComparator.php',
'SebastianBergmann\\Comparator\\TypeComparator' => __DIR__ . '/..' . '/sebastian/comparator/src/TypeComparator.php',
'SebastianBergmann\\Diff\\Chunk' => __DIR__ . '/..' . '/sebastian/diff/src/Chunk.php',
'SebastianBergmann\\Diff\\Diff' => __DIR__ . '/..' . '/sebastian/diff/src/Diff.php',
'SebastianBergmann\\Diff\\Differ' => __DIR__ . '/..' . '/sebastian/diff/src/Differ.php',
'SebastianBergmann\\Diff\\LCS\\LongestCommonSubsequence' => __DIR__ . '/..' . '/sebastian/diff/src/LCS/LongestCommonSubsequence.php',
'SebastianBergmann\\Diff\\LCS\\MemoryEfficientImplementation' => __DIR__ . '/..' . '/sebastian/diff/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\LCS\\TimeEfficientImplementation' => __DIR__ . '/..' . '/sebastian/diff/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php',
'SebastianBergmann\\Diff\\Line' => __DIR__ . '/..' . '/sebastian/diff/src/Line.php',
'SebastianBergmann\\Diff\\Parser' => __DIR__ . '/..' . '/sebastian/diff/src/Parser.php',
'SebastianBergmann\\Environment\\Console' => __DIR__ . '/..' . '/sebastian/environment/src/Console.php',
'SebastianBergmann\\Environment\\Runtime' => __DIR__ . '/..' . '/sebastian/environment/src/Runtime.php',
'SebastianBergmann\\Exporter\\Exporter' => __DIR__ . '/..' . '/sebastian/exporter/src/Exporter.php',
'SebastianBergmann\\GlobalState\\Blacklist' => __DIR__ . '/..' . '/sebastian/global-state/src/Blacklist.php',
'SebastianBergmann\\GlobalState\\CodeExporter' => __DIR__ . '/..' . '/sebastian/global-state/src/CodeExporter.php',
'SebastianBergmann\\GlobalState\\Exception' => __DIR__ . '/..' . '/sebastian/global-state/src/Exception.php',
'SebastianBergmann\\GlobalState\\Restorer' => __DIR__ . '/..' . '/sebastian/global-state/src/Restorer.php',
'SebastianBergmann\\GlobalState\\RuntimeException' => __DIR__ . '/..' . '/sebastian/global-state/src/RuntimeException.php',
'SebastianBergmann\\GlobalState\\Snapshot' => __DIR__ . '/..' . '/sebastian/global-state/src/Snapshot.php',
'SebastianBergmann\\RecursionContext\\Context' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Context.php',
'SebastianBergmann\\RecursionContext\\Exception' => __DIR__ . '/..' . '/sebastian/recursion-context/src/Exception.php',
'SebastianBergmann\\RecursionContext\\InvalidArgumentException' => __DIR__ . '/..' . '/sebastian/recursion-context/src/InvalidArgumentException.php',
'SebastianBergmann\\Version' => __DIR__ . '/..' . '/sebastian/version/src/Version.php',
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
'Text_Template' => __DIR__ . '/..' . '/phpunit/php-text-template/src/Template.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit4da13270269c89a28e472e1f7324e6d1::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit4da13270269c89a28e472e1f7324e6d1::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit4da13270269c89a28e472e1f7324e6d1::$classMap;
}, null, ClassLoader::class);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,371 @@
<?php return array(
'root' => array(
'name' => 'webklex/php-imap',
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '0f467d1c4283cc035ef474db3c733653feeb570f',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'doctrine/inflector' => array(
'pretty_version' => '2.0.4',
'version' => '2.0.4.0',
'reference' => '8b7ff3e4b7de6b2c84da85637b59fd2880ecaa89',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/inflector',
'aliases' => array(),
'dev_requirement' => false,
),
'doctrine/instantiator' => array(
'pretty_version' => '1.4.1',
'version' => '1.4.1.0',
'reference' => '10dcfce151b967d20fde1b34ae6640712c3891bc',
'type' => 'library',
'install_path' => __DIR__ . '/../doctrine/instantiator',
'aliases' => array(),
'dev_requirement' => true,
),
'illuminate/collections' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/collections',
'aliases' => array(),
'dev_requirement' => false,
),
'illuminate/contracts' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'illuminate/macroable' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => 'aed81891a6e046fdee72edd497f822190f61c162',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/macroable',
'aliases' => array(),
'dev_requirement' => false,
),
'illuminate/pagination' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/pagination',
'aliases' => array(),
'dev_requirement' => false,
),
'illuminate/support' => array(
'pretty_version' => 'v8.83.23',
'version' => '8.83.23.0',
'reference' => 'c3d643e77082786ae8a51502c757e9b1a3ee254e',
'type' => 'library',
'install_path' => __DIR__ . '/../illuminate/support',
'aliases' => array(),
'dev_requirement' => false,
),
'nesbot/carbon' => array(
'pretty_version' => '2.61.0',
'version' => '2.61.0.0',
'reference' => 'bdf4f4fe3a3eac4de84dbec0738082a862c68ba6',
'type' => 'library',
'install_path' => __DIR__ . '/../nesbot/carbon',
'aliases' => array(),
'dev_requirement' => false,
),
'phpdocumentor/reflection-common' => array(
'pretty_version' => '2.2.0',
'version' => '2.2.0.0',
'reference' => '1d01c49d4ed62f25aa84a747ad35d5a16924662b',
'type' => 'library',
'install_path' => __DIR__ . '/../phpdocumentor/reflection-common',
'aliases' => array(),
'dev_requirement' => true,
),
'phpdocumentor/reflection-docblock' => array(
'pretty_version' => '5.3.0',
'version' => '5.3.0.0',
'reference' => '622548b623e81ca6d78b721c5e029f4ce664f170',
'type' => 'library',
'install_path' => __DIR__ . '/../phpdocumentor/reflection-docblock',
'aliases' => array(),
'dev_requirement' => true,
),
'phpdocumentor/type-resolver' => array(
'pretty_version' => '1.6.1',
'version' => '1.6.1.0',
'reference' => '77a32518733312af16a44300404e945338981de3',
'type' => 'library',
'install_path' => __DIR__ . '/../phpdocumentor/type-resolver',
'aliases' => array(),
'dev_requirement' => true,
),
'phpspec/prophecy' => array(
'pretty_version' => 'v1.10.3',
'version' => '1.10.3.0',
'reference' => '451c3cd1418cf640de218914901e51b064abb093',
'type' => 'library',
'install_path' => __DIR__ . '/../phpspec/prophecy',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/php-code-coverage' => array(
'pretty_version' => '2.2.4',
'version' => '2.2.4.0',
'reference' => 'eabf68b476ac7d0f73793aada060f1c1a9bf8979',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/php-code-coverage',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/php-file-iterator' => array(
'pretty_version' => '1.4.5',
'version' => '1.4.5.0',
'reference' => '730b01bc3e867237eaac355e06a36b85dd93a8b4',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/php-file-iterator',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/php-text-template' => array(
'pretty_version' => '1.2.1',
'version' => '1.2.1.0',
'reference' => '31f8b717e51d9a2afca6c9f046f5d69fc27c8686',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/php-text-template',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/php-timer' => array(
'pretty_version' => '1.0.9',
'version' => '1.0.9.0',
'reference' => '3dcf38ca72b158baf0bc245e9184d3fdffa9c46f',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/php-timer',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/php-token-stream' => array(
'pretty_version' => '1.4.12',
'version' => '1.4.12.0',
'reference' => '1ce90ba27c42e4e44e6d8458241466380b51fa16',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/php-token-stream',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/phpunit' => array(
'pretty_version' => '4.8.36',
'version' => '4.8.36.0',
'reference' => '46023de9a91eec7dfb06cc56cb4e260017298517',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/phpunit',
'aliases' => array(),
'dev_requirement' => true,
),
'phpunit/phpunit-mock-objects' => array(
'pretty_version' => '2.3.8',
'version' => '2.3.8.0',
'reference' => 'ac8e7a3db35738d56ee9a76e78a4e03d97628983',
'type' => 'library',
'install_path' => __DIR__ . '/../phpunit/phpunit-mock-objects',
'aliases' => array(),
'dev_requirement' => true,
),
'psr/container' => array(
'pretty_version' => '1.1.2',
'version' => '1.1.2.0',
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/container',
'aliases' => array(),
'dev_requirement' => false,
),
'psr/simple-cache' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/simple-cache',
'aliases' => array(),
'dev_requirement' => false,
),
'sebastian/comparator' => array(
'pretty_version' => '1.2.4',
'version' => '1.2.4.0',
'reference' => '2b7424b55f5047b47ac6e5ccb20b2aea4011d9be',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/comparator',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/diff' => array(
'pretty_version' => '1.4.3',
'version' => '1.4.3.0',
'reference' => '7f066a26a962dbe58ddea9f72a4e82874a3975a4',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/diff',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/environment' => array(
'pretty_version' => '1.3.8',
'version' => '1.3.8.0',
'reference' => 'be2c607e43ce4c89ecd60e75c6a85c126e754aea',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/environment',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/exporter' => array(
'pretty_version' => '1.2.2',
'version' => '1.2.2.0',
'reference' => '42c4c2eec485ee3e159ec9884f95b431287edde4',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/exporter',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/global-state' => array(
'pretty_version' => '1.1.1',
'version' => '1.1.1.0',
'reference' => 'bc37d50fea7d017d3d340f230811c9f1d7280af4',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/global-state',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/recursion-context' => array(
'pretty_version' => '1.0.5',
'version' => '1.0.5.0',
'reference' => 'b19cc3298482a335a95f3016d2f8a6950f0fbcd7',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/recursion-context',
'aliases' => array(),
'dev_requirement' => true,
),
'sebastian/version' => array(
'pretty_version' => '1.0.6',
'version' => '1.0.6.0',
'reference' => '58b3a85e7999757d6ad81c787a1fbf5ff6c628c6',
'type' => 'library',
'install_path' => __DIR__ . '/../sebastian/version',
'aliases' => array(),
'dev_requirement' => true,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/http-foundation' => array(
'pretty_version' => 'v5.4.11',
'version' => '5.4.11.0',
'reference' => '0a5868e0999e9d47859ba3d918548ff6943e6389',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/http-foundation',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'reference' => '6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
'aliases' => array(),
'dev_requirement' => true,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'reference' => '9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.26.0',
'version' => '1.26.0.0',
'reference' => 'cfa0ae98841b9e461207c13ab093d76b0fa7bace',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation' => array(
'pretty_version' => 'v4.4.44',
'version' => '4.4.44.0',
'reference' => 'af947fefc306cec6ea5a1f6160c7e305a71f2493',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation-contracts' => array(
'pretty_version' => 'v2.5.2',
'version' => '2.5.2.0',
'reference' => '136b19dd05cdf0709db6537d058bcab6dd6e2dbe',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/translation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/translation-implementation' => array(
'dev_requirement' => false,
'provided' => array(
0 => '1.0|2.0',
),
),
'symfony/yaml' => array(
'pretty_version' => 'v3.4.47',
'version' => '3.4.47.0',
'reference' => '88289caa3c166321883f67fe5130188ebbb47094',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(),
'dev_requirement' => true,
),
'voku/portable-ascii' => array(
'pretty_version' => '1.6.1',
'version' => '1.6.1.0',
'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a',
'type' => 'library',
'install_path' => __DIR__ . '/../voku/portable-ascii',
'aliases' => array(),
'dev_requirement' => false,
),
'webklex/php-imap' => array(
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '0f467d1c4283cc035ef474db3c733653feeb570f',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
'webmozart/assert' => array(
'pretty_version' => '1.11.0',
'version' => '1.11.0.0',
'reference' => '11cb2199493b2f8a3b53e7f19068fc6aac760991',
'type' => 'library',
'install_path' => __DIR__ . '/../webmozart/assert',
'aliases' => array(),
'dev_requirement' => true,
),
),
);

View File

@@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70400)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@@ -0,0 +1,747 @@
<?php
namespace Illuminate\Support;
use ArrayAccess;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
class Arr
{
use Macroable;
/**
* Determine whether the given value is array accessible.
*
* @param mixed $value
* @return bool
*/
public static function accessible($value)
{
return is_array($value) || $value instanceof ArrayAccess;
}
/**
* Add an element to an array using "dot" notation if it doesn't exist.
*
* @param array $array
* @param string $key
* @param mixed $value
* @return array
*/
public static function add($array, $key, $value)
{
if (is_null(static::get($array, $key))) {
static::set($array, $key, $value);
}
return $array;
}
/**
* Collapse an array of arrays into a single array.
*
* @param iterable $array
* @return array
*/
public static function collapse($array)
{
$results = [];
foreach ($array as $values) {
if ($values instanceof Collection) {
$values = $values->all();
} elseif (! is_array($values)) {
continue;
}
$results[] = $values;
}
return array_merge([], ...$results);
}
/**
* Cross join the given arrays, returning all possible permutations.
*
* @param iterable ...$arrays
* @return array
*/
public static function crossJoin(...$arrays)
{
$results = [[]];
foreach ($arrays as $index => $array) {
$append = [];
foreach ($results as $product) {
foreach ($array as $item) {
$product[$index] = $item;
$append[] = $product;
}
}
$results = $append;
}
return $results;
}
/**
* Divide an array into two arrays. One with keys and the other with values.
*
* @param array $array
* @return array
*/
public static function divide($array)
{
return [array_keys($array), array_values($array)];
}
/**
* Flatten a multi-dimensional associative array with dots.
*
* @param iterable $array
* @param string $prepend
* @return array
*/
public static function dot($array, $prepend = '')
{
$results = [];
foreach ($array as $key => $value) {
if (is_array($value) && ! empty($value)) {
$results = array_merge($results, static::dot($value, $prepend.$key.'.'));
} else {
$results[$prepend.$key] = $value;
}
}
return $results;
}
/**
* Convert a flatten "dot" notation array into an expanded array.
*
* @param iterable $array
* @return array
*/
public static function undot($array)
{
$results = [];
foreach ($array as $key => $value) {
static::set($results, $key, $value);
}
return $results;
}
/**
* Get all of the given array except for a specified array of keys.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function except($array, $keys)
{
static::forget($array, $keys);
return $array;
}
/**
* Determine if the given key exists in the provided array.
*
* @param \ArrayAccess|array $array
* @param string|int $key
* @return bool
*/
public static function exists($array, $key)
{
if ($array instanceof Enumerable) {
return $array->has($key);
}
if ($array instanceof ArrayAccess) {
return $array->offsetExists($key);
}
return array_key_exists($key, $array);
}
/**
* Return the first element in an array passing a given truth test.
*
* @param iterable $array
* @param callable|null $callback
* @param mixed $default
* @return mixed
*/
public static function first($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
if (empty($array)) {
return value($default);
}
foreach ($array as $item) {
return $item;
}
}
foreach ($array as $key => $value) {
if ($callback($value, $key)) {
return $value;
}
}
return value($default);
}
/**
* Return the last element in an array passing a given truth test.
*
* @param array $array
* @param callable|null $callback
* @param mixed $default
* @return mixed
*/
public static function last($array, callable $callback = null, $default = null)
{
if (is_null($callback)) {
return empty($array) ? value($default) : end($array);
}
return static::first(array_reverse($array, true), $callback, $default);
}
/**
* Flatten a multi-dimensional array into a single level.
*
* @param iterable $array
* @param int $depth
* @return array
*/
public static function flatten($array, $depth = INF)
{
$result = [];
foreach ($array as $item) {
$item = $item instanceof Collection ? $item->all() : $item;
if (! is_array($item)) {
$result[] = $item;
} else {
$values = $depth === 1
? array_values($item)
: static::flatten($item, $depth - 1);
foreach ($values as $value) {
$result[] = $value;
}
}
}
return $result;
}
/**
* Remove one or many array items from a given array using "dot" notation.
*
* @param array $array
* @param array|string $keys
* @return void
*/
public static function forget(&$array, $keys)
{
$original = &$array;
$keys = (array) $keys;
if (count($keys) === 0) {
return;
}
foreach ($keys as $key) {
// if the exact key exists in the top-level, remove it
if (static::exists($array, $key)) {
unset($array[$key]);
continue;
}
$parts = explode('.', $key);
// clean up before each pass
$array = &$original;
while (count($parts) > 1) {
$part = array_shift($parts);
if (isset($array[$part]) && is_array($array[$part])) {
$array = &$array[$part];
} else {
continue 2;
}
}
unset($array[array_shift($parts)]);
}
}
/**
* Get an item from an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string|int|null $key
* @param mixed $default
* @return mixed
*/
public static function get($array, $key, $default = null)
{
if (! static::accessible($array)) {
return value($default);
}
if (is_null($key)) {
return $array;
}
if (static::exists($array, $key)) {
return $array[$key];
}
if (strpos($key, '.') === false) {
return $array[$key] ?? value($default);
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($array) && static::exists($array, $segment)) {
$array = $array[$segment];
} else {
return value($default);
}
}
return $array;
}
/**
* Check if an item or items exist in an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string|array $keys
* @return bool
*/
public static function has($array, $keys)
{
$keys = (array) $keys;
if (! $array || $keys === []) {
return false;
}
foreach ($keys as $key) {
$subKeyArray = $array;
if (static::exists($array, $key)) {
continue;
}
foreach (explode('.', $key) as $segment) {
if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
$subKeyArray = $subKeyArray[$segment];
} else {
return false;
}
}
}
return true;
}
/**
* Determine if any of the keys exist in an array using "dot" notation.
*
* @param \ArrayAccess|array $array
* @param string|array $keys
* @return bool
*/
public static function hasAny($array, $keys)
{
if (is_null($keys)) {
return false;
}
$keys = (array) $keys;
if (! $array) {
return false;
}
if ($keys === []) {
return false;
}
foreach ($keys as $key) {
if (static::has($array, $key)) {
return true;
}
}
return false;
}
/**
* Determines if an array is associative.
*
* An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
*
* @param array $array
* @return bool
*/
public static function isAssoc(array $array)
{
$keys = array_keys($array);
return array_keys($keys) !== $keys;
}
/**
* Determines if an array is a list.
*
* An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
*
* @param array $array
* @return bool
*/
public static function isList($array)
{
return ! self::isAssoc($array);
}
/**
* Get a subset of the items from the given array.
*
* @param array $array
* @param array|string $keys
* @return array
*/
public static function only($array, $keys)
{
return array_intersect_key($array, array_flip((array) $keys));
}
/**
* Pluck an array of values from an array.
*
* @param iterable $array
* @param string|array|int|null $value
* @param string|array|null $key
* @return array
*/
public static function pluck($array, $value, $key = null)
{
$results = [];
[$value, $key] = static::explodePluckParameters($value, $key);
foreach ($array as $item) {
$itemValue = data_get($item, $value);
// If the key is "null", we will just append the value to the array and keep
// looping. Otherwise we will key the array using the value of the key we
// received from the developer. Then we'll return the final array form.
if (is_null($key)) {
$results[] = $itemValue;
} else {
$itemKey = data_get($item, $key);
if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
$itemKey = (string) $itemKey;
}
$results[$itemKey] = $itemValue;
}
}
return $results;
}
/**
* Explode the "value" and "key" arguments passed to "pluck".
*
* @param string|array $value
* @param string|array|null $key
* @return array
*/
protected static function explodePluckParameters($value, $key)
{
$value = is_string($value) ? explode('.', $value) : $value;
$key = is_null($key) || is_array($key) ? $key : explode('.', $key);
return [$value, $key];
}
/**
* Push an item onto the beginning of an array.
*
* @param array $array
* @param mixed $value
* @param mixed $key
* @return array
*/
public static function prepend($array, $value, $key = null)
{
if (func_num_args() == 2) {
array_unshift($array, $value);
} else {
$array = [$key => $value] + $array;
}
return $array;
}
/**
* Get a value from the array, and remove it.
*
* @param array $array
* @param string|int $key
* @param mixed $default
* @return mixed
*/
public static function pull(&$array, $key, $default = null)
{
$value = static::get($array, $key, $default);
static::forget($array, $key);
return $value;
}
/**
* Convert the array into a query string.
*
* @param array $array
* @return string
*/
public static function query($array)
{
return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
}
/**
* Get one or a specified number of random values from an array.
*
* @param array $array
* @param int|null $number
* @param bool|false $preserveKeys
* @return mixed
*
* @throws \InvalidArgumentException
*/
public static function random($array, $number = null, $preserveKeys = false)
{
$requested = is_null($number) ? 1 : $number;
$count = count($array);
if ($requested > $count) {
throw new InvalidArgumentException(
"You requested {$requested} items, but there are only {$count} items available."
);
}
if (is_null($number)) {
return $array[array_rand($array)];
}
if ((int) $number === 0) {
return [];
}
$keys = array_rand($array, $number);
$results = [];
if ($preserveKeys) {
foreach ((array) $keys as $key) {
$results[$key] = $array[$key];
}
} else {
foreach ((array) $keys as $key) {
$results[] = $array[$key];
}
}
return $results;
}
/**
* Set an array item to a given value using "dot" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* @param array $array
* @param string|null $key
* @param mixed $value
* @return array
*/
public static function set(&$array, $key, $value)
{
if (is_null($key)) {
return $array = $value;
}
$keys = explode('.', $key);
foreach ($keys as $i => $key) {
if (count($keys) === 1) {
break;
}
unset($keys[$i]);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if (! isset($array[$key]) || ! is_array($array[$key])) {
$array[$key] = [];
}
$array = &$array[$key];
}
$array[array_shift($keys)] = $value;
return $array;
}
/**
* Shuffle the given array and return the result.
*
* @param array $array
* @param int|null $seed
* @return array
*/
public static function shuffle($array, $seed = null)
{
if (is_null($seed)) {
shuffle($array);
} else {
mt_srand($seed);
shuffle($array);
mt_srand();
}
return $array;
}
/**
* Sort the array using the given callback or "dot" notation.
*
* @param array $array
* @param callable|array|string|null $callback
* @return array
*/
public static function sort($array, $callback = null)
{
return Collection::make($array)->sortBy($callback)->all();
}
/**
* Recursively sort an array by keys and values.
*
* @param array $array
* @param int $options
* @param bool $descending
* @return array
*/
public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)
{
foreach ($array as &$value) {
if (is_array($value)) {
$value = static::sortRecursive($value, $options, $descending);
}
}
if (static::isAssoc($array)) {
$descending
? krsort($array, $options)
: ksort($array, $options);
} else {
$descending
? rsort($array, $options)
: sort($array, $options);
}
return $array;
}
/**
* Conditionally compile classes from an array into a CSS class list.
*
* @param array $array
* @return string
*/
public static function toCssClasses($array)
{
$classList = static::wrap($array);
$classes = [];
foreach ($classList as $class => $constraint) {
if (is_numeric($class)) {
$classes[] = $constraint;
} elseif ($constraint) {
$classes[] = $class;
}
}
return implode(' ', $classes);
}
/**
* Filter the array using the given callback.
*
* @param array $array
* @param callable $callback
* @return array
*/
public static function where($array, callable $callback)
{
return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
}
/**
* Filter items where the value is not null.
*
* @param array $array
* @return array
*/
public static function whereNotNull($array)
{
return static::where($array, function ($value) {
return ! is_null($value);
});
}
/**
* If the given value is not an array and not null, wrap it in one.
*
* @param mixed $value
* @return array
*/
public static function wrap($value)
{
if (is_null($value)) {
return [];
}
return is_array($value) ? $value : [$value];
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
<?php
namespace Illuminate\Support;
/**
* @mixin \Illuminate\Support\Enumerable
*/
class HigherOrderCollectionProxy
{
/**
* The collection being operated on.
*
* @var \Illuminate\Support\Enumerable
*/
protected $collection;
/**
* The method being proxied.
*
* @var string
*/
protected $method;
/**
* Create a new proxy instance.
*
* @param \Illuminate\Support\Enumerable $collection
* @param string $method
* @return void
*/
public function __construct(Enumerable $collection, $method)
{
$this->method = $method;
$this->collection = $collection;
}
/**
* Proxy accessing an attribute onto the collection items.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this->collection->{$this->method}(function ($value) use ($key) {
return is_array($value) ? $value[$key] : $value->{$key};
});
}
/**
* Proxy a method call onto the collection items.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->collection->{$this->method}(function ($value) use ($method, $parameters) {
return $value->{$method}(...$parameters);
});
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Illuminate\Support;
/**
* @mixin \Illuminate\Support\Enumerable
*/
class HigherOrderWhenProxy
{
/**
* The collection being operated on.
*
* @var \Illuminate\Support\Enumerable
*/
protected $collection;
/**
* The condition for proxying.
*
* @var bool
*/
protected $condition;
/**
* Create a new proxy instance.
*
* @param \Illuminate\Support\Enumerable $collection
* @param bool $condition
* @return void
*/
public function __construct(Enumerable $collection, $condition)
{
$this->condition = $condition;
$this->collection = $collection;
}
/**
* Proxy accessing an attribute onto the collection.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this->condition
? $this->collection->{$key}
: $this->collection;
}
/**
* Proxy a method call onto the collection.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return $this->condition
? $this->collection->{$method}(...$parameters)
: $this->collection;
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Illuminate\Support;
use RuntimeException;
class ItemNotFoundException extends RuntimeException
{
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Taylor Otwell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
<?php
namespace Illuminate\Support;
use RuntimeException;
class MultipleItemsFoundException extends RuntimeException
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
{
"name": "illuminate/collections",
"description": "The Illuminate Collections package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": "^7.3|^8.0",
"illuminate/contracts": "^8.0",
"illuminate/macroable": "^8.0"
},
"autoload": {
"psr-4": {
"Illuminate\\Support\\": ""
},
"files": [
"helpers.php"
]
},
"extra": {
"branch-alias": {
"dev-master": "8.x-dev"
}
},
"suggest": {
"symfony/var-dumper": "Required to use the dump method (^5.4)."
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}

View File

@@ -0,0 +1,186 @@
<?php
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
if (! function_exists('collect')) {
/**
* Create a collection from the given value.
*
* @param mixed $value
* @return \Illuminate\Support\Collection
*/
function collect($value = null)
{
return new Collection($value);
}
}
if (! function_exists('data_fill')) {
/**
* Fill in data where it's missing.
*
* @param mixed $target
* @param string|array $key
* @param mixed $value
* @return mixed
*/
function data_fill(&$target, $key, $value)
{
return data_set($target, $key, $value, false);
}
}
if (! function_exists('data_get')) {
/**
* Get an item from an array or object using "dot" notation.
*
* @param mixed $target
* @param string|array|int|null $key
* @param mixed $default
* @return mixed
*/
function data_get($target, $key, $default = null)
{
if (is_null($key)) {
return $target;
}
$key = is_array($key) ? $key : explode('.', $key);
foreach ($key as $i => $segment) {
unset($key[$i]);
if (is_null($segment)) {
return $target;
}
if ($segment === '*') {
if ($target instanceof Collection) {
$target = $target->all();
} elseif (! is_array($target)) {
return value($default);
}
$result = [];
foreach ($target as $item) {
$result[] = data_get($item, $key);
}
return in_array('*', $key) ? Arr::collapse($result) : $result;
}
if (Arr::accessible($target) && Arr::exists($target, $segment)) {
$target = $target[$segment];
} elseif (is_object($target) && isset($target->{$segment})) {
$target = $target->{$segment};
} else {
return value($default);
}
}
return $target;
}
}
if (! function_exists('data_set')) {
/**
* Set an item on an array or object using dot notation.
*
* @param mixed $target
* @param string|array $key
* @param mixed $value
* @param bool $overwrite
* @return mixed
*/
function data_set(&$target, $key, $value, $overwrite = true)
{
$segments = is_array($key) ? $key : explode('.', $key);
if (($segment = array_shift($segments)) === '*') {
if (! Arr::accessible($target)) {
$target = [];
}
if ($segments) {
foreach ($target as &$inner) {
data_set($inner, $segments, $value, $overwrite);
}
} elseif ($overwrite) {
foreach ($target as &$inner) {
$inner = $value;
}
}
} elseif (Arr::accessible($target)) {
if ($segments) {
if (! Arr::exists($target, $segment)) {
$target[$segment] = [];
}
data_set($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite || ! Arr::exists($target, $segment)) {
$target[$segment] = $value;
}
} elseif (is_object($target)) {
if ($segments) {
if (! isset($target->{$segment})) {
$target->{$segment} = [];
}
data_set($target->{$segment}, $segments, $value, $overwrite);
} elseif ($overwrite || ! isset($target->{$segment})) {
$target->{$segment} = $value;
}
} else {
$target = [];
if ($segments) {
data_set($target[$segment], $segments, $value, $overwrite);
} elseif ($overwrite) {
$target[$segment] = $value;
}
}
return $target;
}
}
if (! function_exists('head')) {
/**
* Get the first element of an array. Useful for method chaining.
*
* @param array $array
* @return mixed
*/
function head($array)
{
return reset($array);
}
}
if (! function_exists('last')) {
/**
* Get the last element from an array.
*
* @param array $array
* @return mixed
*/
function last($array)
{
return end($array);
}
}
if (! function_exists('value')) {
/**
* Return the default value of the given value.
*
* @param mixed $value
* @return mixed
*/
function value($value, ...$args)
{
return $value instanceof Closure ? $value(...$args) : $value;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Illuminate\Contracts\Auth\Access;
interface Authorizable
{
/**
* Determine if the entity has a given ability.
*
* @param iterable|string $abilities
* @param array|mixed $arguments
* @return bool
*/
public function can($abilities, $arguments = []);
}

View File

@@ -0,0 +1,150 @@
<?php
namespace Illuminate\Contracts\Auth\Access;
interface Gate
{
/**
* Determine if a given ability has been defined.
*
* @param string $ability
* @return bool
*/
public function has($ability);
/**
* Define a new ability.
*
* @param string $ability
* @param callable|string $callback
* @return $this
*/
public function define($ability, $callback);
/**
* Define abilities for a resource.
*
* @param string $name
* @param string $class
* @param array|null $abilities
* @return $this
*/
public function resource($name, $class, array $abilities = null);
/**
* Define a policy class for a given class type.
*
* @param string $class
* @param string $policy
* @return $this
*/
public function policy($class, $policy);
/**
* Register a callback to run before all Gate checks.
*
* @param callable $callback
* @return $this
*/
public function before(callable $callback);
/**
* Register a callback to run after all Gate checks.
*
* @param callable $callback
* @return $this
*/
public function after(callable $callback);
/**
* Determine if the given ability should be granted for the current user.
*
* @param string $ability
* @param array|mixed $arguments
* @return bool
*/
public function allows($ability, $arguments = []);
/**
* Determine if the given ability should be denied for the current user.
*
* @param string $ability
* @param array|mixed $arguments
* @return bool
*/
public function denies($ability, $arguments = []);
/**
* Determine if all of the given abilities should be granted for the current user.
*
* @param iterable|string $abilities
* @param array|mixed $arguments
* @return bool
*/
public function check($abilities, $arguments = []);
/**
* Determine if any one of the given abilities should be granted for the current user.
*
* @param iterable|string $abilities
* @param array|mixed $arguments
* @return bool
*/
public function any($abilities, $arguments = []);
/**
* Determine if the given ability should be granted for the current user.
*
* @param string $ability
* @param array|mixed $arguments
* @return \Illuminate\Auth\Access\Response
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function authorize($ability, $arguments = []);
/**
* Inspect the user for the given ability.
*
* @param string $ability
* @param array|mixed $arguments
* @return \Illuminate\Auth\Access\Response
*/
public function inspect($ability, $arguments = []);
/**
* Get the raw result from the authorization callback.
*
* @param string $ability
* @param array|mixed $arguments
* @return mixed
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function raw($ability, $arguments = []);
/**
* Get a policy instance for a given class.
*
* @param object|string $class
* @return mixed
*
* @throws \InvalidArgumentException
*/
public function getPolicyFor($class);
/**
* Get a guard instance for the given user.
*
* @param \Illuminate\Contracts\Auth\Authenticatable|mixed $user
* @return static
*/
public function forUser($user);
/**
* Get all of the defined abilities.
*
* @return array
*/
public function abilities();
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Illuminate\Contracts\Auth;
interface Authenticatable
{
/**
* Get the name of the unique identifier for the user.
*
* @return string
*/
public function getAuthIdentifierName();
/**
* Get the unique identifier for the user.
*
* @return mixed
*/
public function getAuthIdentifier();
/**
* Get the password for the user.
*
* @return string
*/
public function getAuthPassword();
/**
* Get the token value for the "remember me" session.
*
* @return string
*/
public function getRememberToken();
/**
* Set the token value for the "remember me" session.
*
* @param string $value
* @return void
*/
public function setRememberToken($value);
/**
* Get the column name for the "remember me" token.
*
* @return string
*/
public function getRememberTokenName();
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Illuminate\Contracts\Auth;
interface CanResetPassword
{
/**
* Get the e-mail address where password reset links are sent.
*
* @return string
*/
public function getEmailForPasswordReset();
/**
* Send the password reset notification.
*
* @param string $token
* @return void
*/
public function sendPasswordResetNotification($token);
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Illuminate\Contracts\Auth;
interface Factory
{
/**
* Get a guard instance by name.
*
* @param string|null $name
* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
*/
public function guard($name = null);
/**
* Set the default guard the factory should serve.
*
* @param string $name
* @return void
*/
public function shouldUse($name);
}

Some files were not shown because too many files have changed in this diff Show More