I am working on a 2D string with \n new line at the end.
The maze is 1000 x 1000 but I downscales this to 10 x 5 for the sake of readability.
0 means empty space.
S means starting point.
T means target point.
I created a function called cal_path to calculate the path between S and T. However the
result is not correct. I've hard-coded an estimate answer. Any advice/help would be much appreciated.
<?php
$maze='S000000000
0000000000
0000000000
00000000T0
0000000000';
$maze_y=explode(PHP_EOL,$maze);//convert line to array
function show_maze($maze_y){
for ($y=0;$y<count($maze_y);$y++){
for ($x=0;$x<=strlen($maze_y[$y]);$x++){
echo $maze_y[$y][$x];
}
echo "\n";
}
}
function cal_path($maze_y){
// I hardcoded it right now, I am stuck here
return array(
array(1,1),
array(1,2),
array(1,3),
array(2,4),
array(2,5),
array(2,6),
array(3,7),
array(3,8),
);
}
show_maze($maze_y); //original maze
$path=cal_path($maze_y);
foreach ($path as $point){
$maze_y[$point[0]][$point[1]]='P';
}
show_maze($maze_y);
Output:
S000000000
0000000000
0000000000
00000000T0
0000000000
Estimate Output:
S000000000
0PPP000000
0000PPP000
0000000PP0
0000000000
Here's my attempt, but it fails to find a shortest path.
<?php
$maze = '0000000000
0000S00000
0000000000
00000000T0
0000000000';
$maze_y = explode(PHP_EOL, $maze); //convert line to array
function show_maze($maze_y)
{
for ($y = 0; $y < count($maze_y); $y++) {
for ($x = 0; $x < strlen($maze_y[$y]); $x++) {
echo $maze_y[$y][$x];
}
echo "\n";
}
}
function cal_path($maze_y)
{
$found_start = -1;
$found_end = -1;
$row = 0;
foreach ($maze_y as $current) {
for ($x = 0; $x <= strlen($current); $x++) {
if ($found_start == -1) {
$found_start = (strpos($current, 'S') === false) ? '-1' : strpos($current, 'S');
if ($found_start != -1) {
$found_start_y = $row;
}
}
if ($found_end == -1) {
$found_end = (strpos($current, 'T') === false) ? '-1' : strpos($current, 'T');
if ($found_end != -1) {
$found_end_y = $row;
}
}
}
$row++;
}
echo 'start' . $found_start . ' - ' . $found_start_y;
echo "\n";
echo 'end' . $found_end . ' - ' . $found_end_y;
echo "\n";
$step_size_y = $found_end_y - $found_start_y;
$step_size_x = $found_end - $found_start;
echo "step size X $step_size_x Y $step_size_y";
echo "\n";
$start_pointer = array($found_start, $found_start_y);
$maxtry = 100;
$cal_result = array();
while ($maxtry > 0 && ($start_pointer[0] != $found_end || $start_pointer[1] != $found_end_y)) {
$maxtry--;
if ($step_size_x > 1 && $start_pointer[0] != $found_end) {
$start_pointer[0]++;
} else if ($step_size_x < 1 && $start_pointer[0] != $found_end) {
$start_pointer[0]--;
}
if ($step_size_y > 1 && $start_pointer[1] != $found_end_y) {
$start_pointer[1]++;
} else if ($step_size_y < 1 && $start_pointer[1] != $found_end_y) {
$start_pointer[1]--;
}
array_push($cal_result, array($start_pointer[1] , $start_pointer[0] ));
echo 'Path: ' . $start_pointer[0] . ' - ' . $start_pointer[1] . "\n";
}
return $cal_result;
}
show_maze($maze_y); //original maze
$path = cal_path($maze_y);
foreach ($path as $point) {
$maze_y[$point[0]][$point[1]] = 'P';
}
show_maze($maze_y);
You can use the following as a starting point.
It's a simple implementation of the pseudocode at: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Using_a_priority_queue
<?php
require_once 'src/MinQueue.php';
require_once 'src/Dijkstra.php';
require_once 'src/Maze.php';
$maze = Maze::fromString(file_get_contents('maze.txt')); // < a simple text file
$start = $maze->find('S');
$goal = $maze->find('T');
$helper = new Dijkstra(
// return neighbors
function ($a) use ($maze) {
return $maze->getNeighbors($a, ['W']);
},
// calculate the distance
function ($a, $b) use ($maze) {
return $maze->getDistance($a, $b);
}
);
$tStart = microtime(true);
$path = $helper->findPath($start, $goal);
$tEnd = microtime(true);
// export the maze with the path marked with '.'
$mazeStrWithPath = $maze->toString(function ($tile) use ($path) {
return in_array($tile, $path, true) && !in_array($tile->value, ['S', 'T'])
? '.'
: $tile->value
;
});
printf("%s\nin: %.5fs\n\n", $mazeStrWithPath, $tEnd - $tStart);
example output:
_____________________________________________________W_________________
_____________________________________________________W_________________
_____________________________________________________W_________________
_________________W___________________________________W_________________
_________________W___________________________________W_____________T___
_________________W___________________________________W____________.____
_________________W___________________________________W___________._____
_________________W___________________________________W__________.______
_________________W___________________________________W_________._______
_________________W____________________.........______W________.________
_________________W___________________.WWWWWWWWW._____W_______._________
_________________W__________________._W_____...______W______.__________
_________________W_________________.__W____.WWWWWWWWWW_____.___________
_________________W________________.___W_____...............____________
_________________W_____________...____W________________________________
_________________W____________.WWWWWWWW________________________________
_________________W_____________.______W________________________________
_________W_______W______________._____W________________________________
_________W_______W______________._____W________________________________
_________W_______WWWWWWWWWWWWWWW._____W________________________________
_________W_____________________.______W________________________________
_________W____________________._______W________________________________
_________W___________________.________W________________________________
__S...___W__________________._________W________________________________
______.__W_________________.__________W________________________________
_______._W________________.___________W________________________________
________.W_______________.____________W________________________________
_________................_____________W________________________________
Using the following classes:
MinQueue
<?php
declare(strict_types=1);
class MinQueue implements \Countable
{
/**
* #var \SplPriorityQueue
*/
private $queue;
/**
* #var \SplObjectStorage
*/
private $register;
/**
* MinQueue constructor.
*/
public function __construct()
{
$this->queue = new class extends \SplPriorityQueue
{
/** #inheritdoc */
public function compare($p, $q)
{
return $q <=> $p;
}
};
$this->register = new \SplObjectStorage();
}
/**
* #param object $value
* #param mixed $priority
*/
public function insert($value, $priority)
{
$this->queue->insert($value, $priority);
$this->register->attach($value);
}
/**
* #return object
*/
public function extract()
{
$value = $this->queue->extract();
$this->register->detach($value);
return $value;
}
/**
* #inheritdoc
*/
public function contains($value)
{
return $this->register->contains($value);
}
/**
* #inheritdoc
*/
public function count()
{
return count($this->queue);
}
}
Dijkstra
<?php
declare(strict_types=1);
class Dijkstra
{
/**
* #var callable
*/
private $neighbors;
/**
* #var callable
*/
private $length;
/**
* Dijkstra constructor.
*
* #param callable $neighbors
* #param callable $length
*/
public function __construct(callable $neighbors, callable $length)
{
$this->neighbors = $neighbors;
$this->length = $length;
}
/**
* see: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Using_a_priority_queue
*
* #param object $src
* #param object $dst
*
* #return array
*/
public function findPath($src, $dst): array
{
// setup
$queue = new MinQueue();
$distance = new \SplObjectStorage();
$path = new \SplObjectStorage();
// init
$queue->insert($src, 0);
$distance[$src] = 0;
while (count($queue) > 0) {
$u = $queue->extract();
if ($u === $dst) {
return $this->buildPath($dst, $path);
}
foreach (call_user_func($this->neighbors, $u) as $v) {
$alt = $distance[$u] + call_user_func($this->length, $u, $v);
$best = isset($distance[$v]) ? $distance[$v] : INF;
if ($alt < $best) {
$distance[$v] = $alt;
$path[$v] = $u;
if (!$queue->contains($v)) {
$queue->insert($v, $alt);
}
}
}
}
throw new \LogicException('No path found.');
}
/**
* #param object $dst
* #param \SplObjectStorage $path
*
* #return array
*/
private function buildPath($dst, \SplObjectStorage $path): array
{
$result = [$dst];
while (isset($path[$dst]) && null !== $path[$dst]) {
$src = $path[$dst];
$result[] = $src;
$dst = $src;
}
return array_reverse($result);
}
}
Maze
<?php
declare(strict_types=1);
class Maze
{
/**
* #var array
*/
private $tiles = [];
/**
* Maze constructor.
*
* #param array $tiles
*/
private function __construct(array $tiles = [])
{
$this->tiles = $tiles;
}
/**
* #param string $maze
* #param string $rowDelimiter
*
* #return Maze
*/
public static function fromString(string $maze, string $rowDelimiter = "\n"): Maze
{
$tiles = [];
foreach (explode($rowDelimiter, $maze) as $r => $row) {
$rowTiles = [];
foreach (str_split(trim($row)) as $c => $value) {
$rowTiles[] = (object)[
'row' => $r,
'col' => $c,
'value' => $value
];
}
$tiles[] = $rowTiles;
}
return new self($tiles);
}
/**
* #param callable $renderer
* #param string $rowDelimiter
*
* #return string
*/
public function toString(callable $renderer = null, string $rowDelimiter = "\n"): string
{
$renderer = $renderer ?: function ($tile) { return $tile->value; };
$result = [];
foreach ($this->tiles as $r => $row) {
if (!isset($result[$r])) {
$result[$r] = [];
}
foreach ($row as $c => $tile) {
$result[$r][$c] = $renderer($tile);
}
}
return implode($rowDelimiter, array_map('implode', $result));
}
/**
* #param string $value
*
* #return object
*/
public function find(string $value)
{
foreach ($this->tiles as $row) {
foreach ($row as $tile) {
if ($tile->value === $value) {
return $tile;
}
}
}
return null;
}
/**
* #param object $tile
* #param array $filter
*
* #return array
*/
public function getNeighbors($tile, array $filter = []): array
{
$neighbors = [];
foreach ([
[-1, -1], [-1, 0], [-1, 1],
[ 0, -1], [ 0, 1],
[ 1, -1], [ 1, 0], [ 1, 1],
] as $transformation) {
$r = $tile->row + $transformation[0];
$c = $tile->col + $transformation[1];
if (isset($this->tiles[$r][$c]) && !in_array($this->tiles[$r][$c]->value, $filter, true)) {
$neighbors[] = $this->tiles[$r][$c];
}
}
return $neighbors;
}
/**
* #param object $a
* #param object $b
*
* #return float
*/
public function getDistance($a, $b): float
{
$p = $b->row - $a->row;
$q = $b->col - $a->col;
return sqrt($p * $p + $q * $q);
}
}
Download: https://github.com/Yoshix/so-49896590
I am trying to override the Topmenu block in Magento 2 so that I can change the HTML structure of my sub menus but I can't seem to get past this problem.
What I have done
I have created a module called Ecommerce\Topmenu.
Files
app/code/Ecommerce/Topmenu
-- etc/
--- di.xml
--- module.xml
-- Plugin/
--- Topmenu.php
-- registration.php
Topmenu.php
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Ecommerce\Topmenu\Plugin;
use \Magento\Framework\DataObject\IdentityInterface;
use \Magento\Framework\View\Element\Template;
use \Magento\Framework\Data\TreeFactory;
use \Magento\Framework\Data\Tree\Node;
use \Magento\Framework\Data\Tree\NodeFactory;
/**
* Html page top menu block
*/
class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
/**
* Get top menu html
*
* #param string $outermostClass
* #param string $childrenWrapClass
* #param int $limit
* #return string
*/
public function getHtml($outermostClass = '', $childrenWrapClass = '', $limit = 0)
{
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_before',
['menu' => $this->_menu, 'block' => $this]
);
$this->_menu->setOutermostClass($outermostClass);
$this->_menu->setChildrenWrapClass($childrenWrapClass);
$html = $this->_getHtml($this->_menu, $childrenWrapClass, $limit);
$transportObject = new \Magento\Framework\DataObject(['html' => $html]);
$this->_eventManager->dispatch(
'page_block_html_topmenu_gethtml_after',
['menu' => $this->_menu, 'transportObject' => $transportObject]
);
$html = $transportObject->getHtml();
return $html;
}
/**
* Count All Subnavigation Items
*
* #param \Magento\Backend\Model\Menu $items
* #return int
*/
protected function _countItems($items)
{
$total = $items->count();
foreach ($items as $item) {
/** #var $item \Magento\Backend\Model\Menu\Item */
if ($item->hasChildren()) {
$total += $this->_countItems($item->getChildren());
}
}
return $total;
}
/**
* Building Array with Column Brake Stops
*
* #param \Magento\Backend\Model\Menu $items
* #param int $limit
* #return array|void
*
* #todo: Add Depth Level limit, and better logic for columns
*/
protected function _columnBrake($items, $limit)
{
$total = $this->_countItems($items);
if ($total <= $limit) {
return;
}
$result[] = ['total' => $total, 'max' => (int)ceil($total / ceil($total / $limit))];
$count = 0;
$firstCol = true;
foreach ($items as $item) {
$place = $this->_countItems($item->getChildren()) + 1;
$count += $place;
if ($place >= $limit) {
$colbrake = !$firstCol;
$count = 0;
} elseif ($count >= $limit) {
$colbrake = !$firstCol;
$count = $place;
} else {
$colbrake = false;
}
$result[] = ['place' => $place, 'colbrake' => $colbrake];
$firstCol = false;
}
return $result;
}
/**
* Add sub menu HTML code for current menu item
*
* #param \Magento\Framework\Data\Tree\Node $child
* #param string $childLevel
* #param string $childrenWrapClass
* #param int $limit
* #return string HTML code
*/
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
{
$html = '';
if (!$child->hasChildren()) {
return $html;
}
$colStops = null;
if ($childLevel == 0 && $limit) {
$colStops = $this->_columnBrake($child->getChildren(), $limit);
}
$html .= '<ul class="level' . $childLevel . ' megaSub">';
$html .= $this->_getHtml($child, $childrenWrapClass, $limit, $colStops);
$html .= '</ul>';
return $html;
}
/**
* Recursively generates top menu html from data that is specified in $menuTree
*
* #param \Magento\Framework\Data\Tree\Node $menuTree
* #param string $childrenWrapClass
* #param int $limit
* #param array $colBrakes
* #return string
*
* #SuppressWarnings(PHPMD.CyclomaticComplexity)
* #SuppressWarnings(PHPMD.NPathComplexity)
*/
protected function _getHtml(
\Magento\Framework\Data\Tree\Node $menuTree,
$childrenWrapClass,
$limit,
$colBrakes = []
) {
$html = '';
$children = $menuTree->getChildren();
$parentLevel = $menuTree->getLevel();
$childLevel = $parentLevel === null ? 0 : $parentLevel + 1;
$counter = 1;
$itemPosition = 1;
$childrenCount = $children->count();
$parentPositionClass = $menuTree->getPositionClass();
$itemPositionClassPrefix = $parentPositionClass ? $parentPositionClass . '-' : 'nav-';
foreach ($children as $child) {
$child->setLevel($childLevel);
$child->setIsFirst($counter == 1);
$child->setIsLast($counter == $childrenCount);
$child->setPositionClass($itemPositionClassPrefix . $counter);
$outermostClassCode = '';
$outermostClass = $menuTree->getOutermostClass();
if ($childLevel == 0 && $outermostClass) {
$outermostClassCode = ' class="' . $outermostClass . '" ';
$child->setClass($outermostClass);
}
if (count($colBrakes) && $colBrakes[$counter]['colbrake']) {
// $html .= '</ul></li><li class="column"><ul>';
}
if($counter > 1 && $childLevel == 1){
continue;
}
$html .= '<li ' . $this->_getRenderedMenuItemAttributes($child) . '>';
$html .= '<a href="' . $child->getUrl() . '" ' . $outermostClassCode . '><span>' . $this->escapeHtml(
$child->getName()
) . '</span></a>' . $this->_addSubMenu(
$child,
$childLevel,
$childrenWrapClass,
$limit
) . '</li>';
$itemPosition++;
$counter++;
}
if (count($colBrakes) && $limit) {
$html = '<li class="column"><ul>' . $html . '</ul></li>';
}
return $html;
}
/**
* Generates string with all attributes that should be present in menu item element
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return string
*/
protected function _getRenderedMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
$html = '';
$attributes = $this->_getMenuItemAttributes($item);
foreach ($attributes as $attributeName => $attributeValue) {
$html .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"';
}
return $html;
}
/**
* Returns array of menu item's attributes
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return array
*/
protected function _getMenuItemAttributes(\Magento\Framework\Data\Tree\Node $item)
{
$menuItemClasses = $this->_getMenuItemClasses($item);
return ['class' => implode(' ', $menuItemClasses)];
}
/**
* Returns array of menu item's classes
*
* #param \Magento\Framework\Data\Tree\Node $item
* #return array
*/
protected function _getMenuItemClasses(\Magento\Framework\Data\Tree\Node $item)
{
$classes = [];
$classes[] = 'level' . $item->getLevel();
$classes[] = $item->getPositionClass();
if ($item->getIsFirst()) {
$classes[] = 'first';
}
if ($item->getIsActive()) {
$classes[] = 'active';
} elseif ($item->getHasActive()) {
$classes[] = 'has-active';
}
if ($item->getIsLast()) {
$classes[] = 'last';
}
if ($item->getClass()) {
$classes[] = $item->getClass();
}
if ($item->hasChildren()) {
$classes[] = 'parent';
}
return $classes;
}
/**
* Add identity
*
* #param array $identity
* #return void
*/
public function addIdentity($identity)
{
if (!in_array($identity, $this->identities)) {
$this->identities[] = $identity;
}
}
/**
* Get identities
*
* #return array
*/
public function getIdentities()
{
return $this->identities;
}
/**
* Get cache key informative items
*
* #return array
*/
public function getCacheKeyInfo()
{
$keyInfo = parent::getCacheKeyInfo();
$keyInfo[] = $this->getUrl('*/*/*', ['_current' => true, '_query' => '']);
return $keyInfo;
}
/**
* Get tags array for saving cache
*
* #return array
*/
protected function getCacheTags()
{
return array_merge(parent::getCacheTags(), $this->getIdentities());
}
/**
* Get menu object.
*
* #return Node
*/
public function getMenu()
{
return $this->_menu;
}
}
** Expected behavour **
My module should override the Magento Topmenu module whilst inheriting it allowing me to change the output markup
The problem
After running setup:upgrade and recompiling, I am just presented with the following error:
Fatal error: Call to a member function setOutermostClass() on null in /var/www/myecom.co.uk/app/code/Ecommerce/Topmenu/Plugin/Topmenu.php on line 36
It's like my code is not correctly extending the Topmenu block.
Any ideas?
For fix this my solution is insert construct as below:
public function __construct(Template\Context $context, NodeFactory $nodeFactory, TreeFactory $treeFactory, array $data = [])
{
parent::__construct($context, $nodeFactory, $treeFactory, $data);
$this->nodeFactory = $nodeFactory;
$this->treeFactory = $treeFactory;
}
This problem is a result of a recent Magento update which explains why I was having this problem using code that had previously worked for me on earlier Magento versions.
Final Solution
The final solution to fix this after Magento's update is to replace $this->_menu with $this->getMenu()
Now the working version of my custom module extends the Magento top menu class and just overrides the _getHtml function to change the markup as required.
I have found a php inventory http://inventory-management.org/ easy but was written in PHP4? and I run now on PHP5. I have found some errors that I have already managed to fix but they are keep coming up so I would like to see if I can managed to run at the end. (As it is really simple script only has 5-7 php files).
Could someone help me please how to fix this error?
Fatal error: Cannot redeclare fputcsv() in C:\xampp\htdocs\Inventory\lib\common.php on line 935
which is:
function fputcsv ($fp, $array, $deliminator=",") {
return fputs($fp, putcsv($array,$delimitator));
}#end fputcsv()
here is the full code:
<?php
/*
*/
/**
* description returns an array with filename base name and the extension
*
* #param filemane format
*
* #return array
*
* #access public
*/
function FileExt($filename) {
//checking if the file have an extension
if (!strstr($filename, "."))
return array("0"=>$filename,"1"=>"");
//peoceed to normal detection
$filename = strrev($filename);
$extpos = strpos($filename , ".");
$file = strrev(substr($filename , $extpos + 1));
$ext = strrev(substr($filename , 0 , $extpos));
return array("0"=>$file,"1"=>$ext);
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function UploadFile($source, $destination , $name ="") {
$name = $name ? $name : basename($source);
$name = FileExt($name);
$name[2]= $name[0];
$counter = 0 ;
while (file_exists( $destination . $name[0] . "." . $name[1] )) {
$name[0] = $name[2] . $counter;
$counter ++;
}
copy($source , $destination . $name[0] . "." . $name[1] );
#chmod($destination . $name[0] . "." . $name[1] , 0777);
}
function UploadFileFromWeb($source, $destination , $name) {
$name = FileExt($name);
$name[2]= $name[0];
$counter = 0 ;
while (file_exists( $destination . $name[0] . "." . $name[1] )) {
$name[0] = $name[2] . $counter;
$counter ++;
}
SaveFileContents($destination . $name[0] . "." . $name[1] , $source);
#chmod($destination . $name[0] . "." . $name[1] , 0777);
}
/**
* returns the contents of a file in a string
*
* #param string $file_name name of file to be loaded
*
* #return string
*
* #acces public
*/
function GetFileContents($file_name) {
// if (!file_exists($file_name)) {
// return null;
// }
//echo "<br>:" . $file_name;
$file = fopen($file_name,"r");
//checking if the file was succesfuly opened
if (!$file)
return null;
if (strstr($file_name,"://"))
while (!feof($file))
$result .= fread($file,1024);
else
$result = #fread($file,filesize($file_name));
fclose($file);
return $result;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function SaveFileContents($file_name,$content) {
// echo $file_name;
$file = fopen($file_name,"w");
fwrite($file,$content);
fclose($file);
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function Debug($what,$pre = 1,$die = 0) {
if (PB_DEBUG_EXT == 1) {
if ($pre == 1)
echo "<pre style=\"background-color:white;\">";
print_r($what);
if ($pre == 1)
echo "</pre>";
if ($die == 1)
die;
}
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function SendMail($to,$from,$subject,$message,$to_name,$from_name) {
if ($to_name)
$to = "$to_name <$to>";
$headers = "MIME-Version: 1.0\n";
$headers .= "Content-type: text; charset=iso-8859-1\n";
if ($from_name) {
$headers .= "From: $from_name <$from>\n";
$headers .= "Reply-To: $from_name <$from>\n";
}
else {
$headers .= "From: $from\n";
$headers .= "Reply-To: $from\n";
}
$headers .= "X-Mailer: PHP/" . phpversion();
return mail($to, $subject, $message,$headers);
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function FillVars($var,$fields,$with) {
$fields = explode (",",$fields);
foreach ($fields as $field)
if (!$var[$field])
!$var[$field] = $with;
return $var;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function CleanupString($string,$strip_tags = TRUE) {
$string = addslashes(trim($string));
if ($strip_tags)
$string = strip_tags($string);
return $string;
}
define("RX_EMAIL","^[a-z0-9]+([_\\.-][a-z0-9]+)*#([a-z0-9]+([\.-][a-z0-9]+)*)+\\.[a-z]{2,}$");
define("RX_CHARS","[a-z\ ]");
define("RX_DIGITS","[0-9]");
define("RX_ALPHA","[^a-z0-9_]");
define("RX_ZIP","[0-9\-]");
define("RX_PHONE","[0-9\-\+\(\)]");
/**
* description
*
* #param
*
* #return
*
* #access
*/
function CheckString($string,$min,$max,$regexp = "",$rx_result = FALSE) {
if (get_magic_quotes_gpc() == 0)
$string = CleanupString($string);
if (strlen($string) < $min)
return 1;
elseif (($max != 0) && (strlen($string) > $max))
return 2;
elseif ($regexp != "")
if ($rx_result == eregi($regexp,$string))
return 3;
return 0;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/// FIRST_NAME:S:3:60,LAST_NAME:S...
function ValidateVars($source,$vars) {
$vars = explode(",",$vars);
foreach ($vars as $var) {
list($name,$type,$min,$max) = explode(":",$var);
switch ($type) {
case "S":
$type = RX_CHARS;
$rx_result = FALSE;
break;
case "I":
$type = RX_DIGITS;
$rx_result = TRUE;
break;
case "E":
$type = RX_EMAIL;
$rx_result = FALSE;
break;
case "P":
$type = RX_PHONE;
$rx_result = TRUE;
break;
case "Z":
$type = RX_ZIP;
$rx_result = FALSE;
break;
case "A":
$type = "";
break;
case "F":
//experimental crap
$type = RX_ALPHA;
$rx_result = TRUE;
//$source[strtolower($name)] = str_replace(" ", "" , $source[strtolower($name)] );
break;
}
//var_dump($result);
if (($result = CheckString($source[strtolower($name)],$min,$max,$type,$rx_result)) != 0)
$errors[] = $name;
}
return is_array($errors) ? $errors : 0;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function ResizeImage($source,$destination,$size) {
if (PB_IMAGE_MAGICK == 1)
system( PB_IMAGE_MAGICK_PATH . "convert $source -resize {$size}x{$size} $destination");
else
copy($source,$destination);
}
/**
* uses microtime() to return the current unix time w/ microseconds
*
* #return float the current unix time in the form of seconds.microseconds
*
* #access public
*/
function GetMicroTime() {
list($usec,$sec) = explode(" ",microtime());
return (float) $usec + (float) $sec;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function GetArrayPart($input,$from,$count) {
$return = array();
$max = count($input);
for ($i = $from; $i < $from + $count; $i++ )
if ($i<$max)
$return[] = $input[$i];
return $return;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function ReplaceAllImagesPath($htmldata,$image_path) {
$htmldata = stripslashes($htmldata);
// replacing IE formating style
$htmldata = str_replace("<IMG","<img",$htmldata);
// esmth, i dont know why i'm doing
preg_match_all("'<img.*?>'si",$htmldata,$images);
//<?//ing edit plus
foreach ($images[0] as $image)
$htmldata = str_replace($image,ReplaceImagePath($image,$image_path),$htmldata);
return $htmldata;//implode("\n",$html_out);
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function ReplaceImagePath($image,$replace) {
// removing tags
$image = stripslashes($image);
$image = str_replace("<","",$image);
$image = str_replace(">","",$image);
// exploging image in proprietes
$image_arr = explode(" ",$image);
for ($i = 0;$i < count($image_arr) ;$i++ ) {
if (stristr($image_arr[$i],"src")) {
// lets it :]
$image_arr[$i] = explode("=",$image_arr[$i]);
// modifing the image path
// i doing this
// replacing ',"
$image_arr[$i][1] = str_replace("'","",$image_arr[$i][1]);
$image_arr[$i][1] = str_replace("\"","",$image_arr[$i][1]);
//getting only image name
$image_arr[$i][1] = strrev(substr(strrev($image_arr[$i][1]),0,strpos(strrev($image_arr[$i][1]),"/")));
// building the image back
$image_arr[$i][1] = "\"" . $replace . $image_arr[$i][1] . "\"";
$image_arr[$i] = implode ("=",$image_arr[$i]);
}
}
// adding tags
return "<" . implode(" ",$image_arr) . ">";
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function DowloadAllImages($images,$path) {
foreach ($images as $image)
#SaveFileContents($path ."/".ExtractFileNameFromPath($image),#implode("",#file($image)));
}
function GetAllImagesPath($htmldata) {
$htmldata = stripslashes($htmldata);
// replacing IE formating style
$htmldata = str_replace("<IMG","<img",$htmldata);
// esmth, i dont know why i'm doing
preg_match_all("'<img.*?>'si",$htmldata,$images);
//<?//ing edit plus
foreach ($images[0] as $image)
$images_path[] = GetImageName($image);
return $images_path;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function GetImagePath($image) {
// removing tags
$image = stripslashes($image);
$image = str_replace("<","",$image);
$image = str_replace(">","",$image);
// exploging image in proprietes
$image_arr = explode(" ",$image);
for ($i = 0;$i < count($image_arr) ;$i++ ) {
if (stristr($image_arr[$i],"src")) {
// lets it :]
$image_arr[$i] = explode("=",$image_arr[$i]);
// modifing the image path
// i doing this
// replacing ',"
$image_arr[$i][1] = str_replace("'","",$image_arr[$i][1]);
$image_arr[$i][1] = str_replace("\"","",$image_arr[$i][1]);
return strrev(substr(strrev($image_arr[$i][1]),0,strpos(strrev($image_arr[$i][1]),"/")));;
}
}
// adding tags
return "";
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function GetImageName($image) {
// removing tags
$image = stripslashes($image);
$image = str_replace("<","",$image);
$image = str_replace(">","",$image);
// exploging image in proprietes
$image_arr = explode(" ",$image);
for ($i = 0;$i < count($image_arr) ;$i++ ) {
if (stristr($image_arr[$i],"src")) {
// lets it :]
$image_arr[$i] = explode("=",$image_arr[$i]);
// modifing the image path
// i doing this
// replacing ',"
$image_arr[$i][1] = str_replace("'","",$image_arr[$i][1]);
$image_arr[$i][1] = str_replace("\"","",$image_arr[$i][1]);
return $image_arr[$i][1];
}
}
// adding tags
return "";
}
/**
* reinventing the wheel [badly]
*
* #param somthin
*
* #return erroneous
*
* #access denied
*/
function ExtractFileNameFromPath($file) {
//return strrev(substr(strrev($file),0,strpos(strrev($file),"/")));
// sau ai putea face asha. umpic mai smart ca mai sus dar tot stupid
// daca le dai path fara slashes i.e. un filename prima returneaza "" asta taie primu char
//return substr($file,strrpos($file,"/") + 1,strlen($file) - strrpos($file,"/"));
// corect ar fi cred asha [observa smart usage`u de strRpos]
//return substr($file,strrpos($file,"/") + (strstr($file,"/") ? 1 : 0),strlen($file) - strrpos($file,"/"));
// sau putem folosi tactica `nute mai caca pe tine and rtm' shi facem asha
return basename($file);
// har har :]]
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function RemoveArraySlashes($array) {
if ($array)
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = RemoveArraySlashes($item);
else
$array[$key] = stripslashes($item);
return $array;
}
function AddArraySlashes($array) {
if ($array)
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = AddArraySlashes($item);
else
$array[$key] = addslashes($item);
return $array;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function Ahtmlentities($array) {
if (is_array($array))
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = ahtmlentities($item);
else
$array[$key] = htmlentities(stripslashes($item),ENT_COMPAT);
else
return htmlentities(stripslashes($array),ENT_COMPAT);
return $array;
}
function AStripSlasshes($array) {
if (is_array($array))
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = AStripSlasshes($item);
else
$array[$key] = stripslashes($item);
else
return stripslashes($array);
return $array;
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function Ahtml_entity_decode($array) {
if ($array)
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = ahtml_entity_decode($item);
else
$array[$key] = html_entity_decode($item,ENT_COMPAT);
return $array;
}
function array2xml ($name, $value, $indent = 1)
{
$indentstring = "\t";
for ($i = 0; $i < $indent; $i++)
{
$indentstring .= $indentstring;
}
if (!is_array($value))
{
$xml = $indentstring.'<'.$name.'>'.$value.'</'.$name.'>'."\n";
}
else
{
if($indent === 1)
{
$isindex = False;
}
else
{
$isindex = True;
while (list ($idxkey, $idxval) = each ($value))
{
if ($idxkey !== (int)$idxkey)
{
$isindex = False;
}
}
}
reset($value);
while (list ($key, $val) = each ($value))
{
if($indent === 1)
{
$keyname = $name;
$nextkey = $key;
}
elseif($isindex)
{
$keyname = $name;
$nextkey = $name;
}
else
{
$keyname = $key;
$nextkey = $key;
}
if (is_array($val))
{
$xml .= $indentstring.'<'.$keyname.'>'."\n";
$xml .= array2xml ($nextkey, $val, $indent+1);
$xml .= $indentstring.'</'.$keyname.'>'."\n";
}
else
{
$xml .= array2xml ($nextkey, $val, $indent);
}
}
}
return $xml;
}
function GetPhpContent($file) {
if (file_exists($file) ) {
$data = GetFileContents($file);
//replacing special chars in content
$data = str_replace("<?php","",$data);
$data = str_replace("?>","",$data);
return $data;
}
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function KeyArray($array,$recurse = 0 , $count = 1) {
if (is_array($array)) {
foreach ($array as $key => $val) {
$array[$key]["key"] = $count ++;
if ($recurse) {
foreach ($array[$key] as $k => $val)
if (is_array($val)) {
KeyArray($array[$key][$k] , $recurse , $count);
}
}
}
}
return $count + 1;
}
function RandomWord( $passwordLength ) {
$password = "";
for ($index = 1; $index <= $passwordLength; $index++) {
// Pick random number between 1 and 62
$randomNumber = rand(1, 62);
// Select random character based on mapping.
if ($randomNumber < 11)
$password .= Chr($randomNumber + 48 - 1); // [ 1,10] => [0,9]
else if ($randomNumber < 37)
$password .= Chr($randomNumber + 65 - 10); // [11,36] => [A,Z]
else
$password .= Chr($randomNumber + 97 - 36); // [37,62] => [a,z]
}
return $password;
}
function DeleteFolder($file) {
if (file_exists($file)) {
chmod($file,0777);
if (is_dir($file)) {
$handle = opendir($file);
while($filename = readdir($handle)) {
if ($filename != "." && $filename != "..") {
DeleteFolder($file."/".$filename);
}
}
closedir($handle);
rmdir($file);
} else {
unlink($file);
}
}
}
function GenerateRecordID($array) {
$max = 0;
if (is_array($array)) {
foreach ($array as $key => $val)
$max = ($key > $max ? $key : $max);
return $max + 1;
}
else return 1;
}
/*****************************************************
Links cripting for admin
DO NOT TOUCH UNLKESS YOU KNOW WHAT YOU ARE DOING
*****************************************************/
/**
* description
*
* #param
*
* #return
*
* #access
*/
function CryptLink($link) {
if (defined("PB_CRYPT_LINKS") && (PB_CRYPT_LINKS == 1)) {
if (stristr($link,"javascript:")) {
/* if (stristr($link,"window.location=")) {
$pos = strpos($link , "window.location=");
$js = substr($link , 0 , $pos + 17 );
$final = substr($link , $pos + 17 );
$final = substr($final, 0, strlen($final) - 1 );
//well done ... crypt the link now
$url = #explode("?" , $final);
if (!is_array($url))
$url[0] = $final;
$tmp = str_replace( $url[0] . "?" , "" , $final);
$uri = urlencode(urlencode(base64_encode(str_rot13($tmp))));
$link = $js . $url[0] . "?" . $uri . md5($uri) . "'";
}
*/
} else {
$url = #explode("?" , $link);
if (!is_array($url))
$url[0] = $link;
$tmp = str_replace( $url[0] . "?" , "" , $link);
$uri = urlencode(urlencode(base64_encode(str_rot13($tmp))));
$link = $url[0] . "?" . $uri . md5($uri);
}
}
return $link;
}
/************************************************************************/
/* SOME PREINITIALISATION CRAP*/
if (defined("PB_CRYPT_LINKS") && (PB_CRYPT_LINKS == 1) ) {
$key = key($_GET);
if (is_array($_GET) && (count($_GET) == 1) && ($_GET[$key] == "")) {
$tmp = $_SERVER["QUERY_STRING"];
//do the md5 check
$md5 = substr($tmp , -32);
$tmp = substr($tmp , 0 , strlen($tmp) - 32);
if ($md5 != md5($tmp)) {
//header("index.php?action=badrequest");
//exit;
die("Please dont change the links!");
}
$tmp = str_rot13(base64_decode(urldecode(urldecode($tmp))));
$tmp_array = #explode("&" , $tmp);
$tmp_array = is_array($tmp_array) ? $tmp_array : array($tmp);
if (is_array($tmp_array)) {
foreach ($tmp_array as $key => $val) {
$tmp2 = explode("=" , $val);
$out[$tmp2[0]] = $tmp2[1];
}
} else {
$tmp2 = explode("=" , $tmp);
$out[$tmp2[0]] = $tmp2[1];
}
$_GET = $out;
}
}
/***********************************************************************/
function ArrayReplace($what , $with , $array ) {
if ($array)
foreach ($array as $key => $item)
if (is_array($item))
$array[$key] = ArrayReplace($what , $with , $item);
else
$array[$key] = str_replace($what , $with , $item);
return $array;
}
function stri_replace( $find, $replace, $string )
{
$parts = explode( strtolower($find), strtolower($string) );
$pos = 0;
foreach( $parts as $key=>$part ){
$parts[ $key ] = substr($string, $pos, strlen($part));
$pos += strlen($part) + strlen($find);
}
return( join( $replace, $parts ) );
}
/**
* description
*
* #param
*
* #return
*
* #access
*/
function GMTDate($format , $date) {
global $_GMT;
return date($format , $date - $_GMT);
}
function putcsv ($array, $deliminator=",") {
$line = "";
foreach($array as $val) {
# remove any windows new lines,
# as they interfere with the parsing at the other end
$val = str_replace("\r\n", "\n", $val);
# if a deliminator char, a double quote char or a newline
# are in the field, add quotes
if(ereg("[$deliminator\"\n\r]", $val)) {
$val = '"'.str_replace('"', '""', $val).'"';
}#end if
$line .= $val.$deliminator;
}#end foreach
# strip the last deliminator
$line = substr($line, 0, (strlen($deliminator) * -1));
# add the newline
$line .= "\n";
# we don't care if the file pointer is invalid,
# let fputs take care of it
return $line;
}#end fputcsv()
function fputcsv ($fp, $array, $deliminator=",") {
return fputs($fp, putcsv($array,$delimitator));
}#end fputcsv()
/**
* description
*
* #param
*
* #return
*
* #access
*/
function is_subaction($sub,$action) {
return (bool)($_GET["sub"] == $sub) && ($_GET["action"] == $action);
}
?>
many thanks in advance
fputcsv() is a built in PHP function. This means you cannot name your own function the same thing.
If you need this code to work with PHP4, just check to see if the function exists first, then if not, create your own.
if (!function_exists('fputcsv')) {
// Your definition here
}
I am sending a mail using PHP Mail Function
I just need to find the status of the mail whether it is delivered or Bounced
is there any possible way to solve this Problem
You can use return-path header with specific e-mail address - for example bounce#domain.com
After that all bounced (undelivered) e-mails would be returned to inbox for bounce#domain.com
You can connect to this pop3 inbox via PHP and read all messages.
Parse every messages and find (may be via regex) error code and reason...
I use this code:
$bounce = new BounceMail();
$bounce->setDebug(false);
//create connection
$bounce->createConnection('server', 110, 'user', 'password');
//parse messages
$bounce->parseMessages();
//save parsed messages to database
$messages = $bounce->getParsedMessages();
foreach ($messages as $message_id => $message) {
/* variable $message looks like:
$message = array(
'email_address' => 'email',
'bounce_type' => 'bounce type',
'smtp_server' => 'smtp_server',
'smtp_error' => 'smtp_error',
);
*/
//save returned email to database here
}
and BounceMail class:
<?php
/*
* Depends on 'Net/POP3.php';
*/
/**
* Class BounceMail
*/
class BounceMail extends Net_POP3
{
/**
* #var array
*/
private $messages = array();
/**
* #var array
*/
private $parsed_messages = array();
/**
* #var array
*/
private $partially_parsed_messages = array();
/**
* #var array
*/
private $allowed_email_domains = array();
/**
* #var array
*/
private $allowed_email_addresses = array();
/**
* #param $host
* #param $port
* #param $username
* #param $password
* #return bool
* #throws ErrorException
*/
public function createConnection($host, $port, $username, $password)
{
if (!$this->connect($host, $port)) {
Throw new ErrorException("Error connecting to POP3 socket.");
}
if (true !== ($login = $this->login($username, $password, true))) {
Throw new ErrorException("Login failed:" . $login->getMessage());
}
if (false === ($messages = $this->getListing())) {
Throw new ErrorException("Error getting POP3 box listing.");
} else {
$this->messages = $messages;
}
return true;
}
/**
* #return bool
*/
public function parseMessages()
{
$this->newDebugMessage('PARSING ' . count($this->messages) . ' MESSAGES');
$fully_parsed = 0;
foreach ($this->messages as $message) {
$parsed_message = $this->parseMessage($message);
$email_address = $this->getEmailAddress($parsed_message);
$smtp_error = $this->getSMTPError($parsed_message);
$smtp_server = $this->getSMTPServer($parsed_message);
$bounce_type = $this->getBounceType($smtp_error);
if ($this->checkAllowedContent($parsed_message)) {
$this->newParsedMessage($message['msg_id'], $email_address, $smtp_server, $smtp_error, $bounce_type);
if (!empty($email_address) && !empty($smtp_error) && !empty($smtp_server) && !empty($bounce_type)) {
$fully_parsed++;
} elseif (!empty($email_address) && (empty($smtp_error) || empty($smtp_server) || empty($bounce_type))) {
$this->newPartiallyParsedMessage($email_address, $parsed_message, array($smtp_error, $smtp_server, $bounce_type));
}
}
}
$this->newDebugMessage('SUCCESSFULLY PARSED ' . count($this->parsed_messages) . ' MESSAGES');
$this->newDebugMessage('EVERYTHING FOUND IN ' . $fully_parsed . ' MESSAGES');
return true;
}
/**
* #return array
*/
public function getParsedMessages()
{
return $this->parsed_messages;
}
/**
* #param bool $as_text
* #return array|string
*/
public function getPartiallyParsedMessages($as_text = true)
{
if ($as_text) {
$text = '';
foreach ($this->partially_parsed_messages as $message) {
foreach ($message as $data) {
$text .= $data . "\r\n";
}
$text .= "\r\n---------------\r\n\r\n";
}
return $text;
} else {
return $this->partially_parsed_messages;
}
}
/**
* #param array $domains
*/
public function setAllowedEmailDomains(array $domains)
{
$this->allowed_email_domains = $domains;
}
/**
* #param array $addresses
*/
public function setAllowedEmailAddresses(array $addresses)
{
$this->allowed_email_addresses = $addresses;
}
/**
* #param $message
* #return bool|string
*/
public function newDebugMessage($message)
{
if ($this->_debug) {
$trace = debug_backtrace();
$debug_message = !empty($trace) && isset($trace[1]["function"]) ? $trace[1]["function"] . ' | ' : '';
$debug_message .= !empty($trace) && isset($trace[1]["method"]) ? $trace[1]["method"] . ' | ' : '';
$debug_message .= $message . "\r\n";
echo $debug_message;
return $debug_message;
}
return false;
}
/**
* #param $parsed_message
* #return bool
*/
private function checkAllowedContent($parsed_message)
{
foreach ($parsed_message as $content) {
if (!$this->parseAllowedContent($content)) {
return false;
}
}
return true;
}
/**
* #param $content
* #return bool
*/
private function parseAllowedContent($content)
{
$patterns = array(
'SENDER POLICY FRAMEWORK' => '/(5.7.1\s*Sender\s*Policy\s*Framework)/im',
'TOO MANY HOPS' => '/too\s*many\s*hops/im',
'BLOCKED' => '/554\s*Blocked\s*by\s*Reputation\s*Enabled\s*Defense/im'
);
foreach ($patterns as $name => $pattern) {
$matches = array();
preg_match($pattern, $content, $matches);
if (isset($matches[1]) && !empty($matches[1])) {
$this->newDebugMessage('DISALLOWED CONTENT FOUND (' . $name . ')');
return false;
}
}
return true;
}
/**
* #param $message_id
* #param $email_address
* #param $smtp_server
* #param $smtp_error
* #param $bounce_type
* #return array|bool
*/
private function newParsedMessage($message_id, $email_address, $smtp_server, $smtp_error, $bounce_type)
{
if (!empty($message_id) && !empty($email_address)) {
return $this->parsed_messages[$message_id] = array('email_address' => $email_address, 'smtp_server' => $smtp_server, 'smtp_error' => $smtp_error, 'bounce_type' => $bounce_type);
}
return false;
}
/**
* #param $email_address
* #param array $parsed_message
* #param array $vars
* #return array|bool
*/
private function newPartiallyParsedMessage($email_address, array $parsed_message, array $vars = array())
{
$full_content = '';
foreach ($parsed_message as $content) {
$full_content .= $content . "\r\n";
}
if (!empty($email_address) && !empty($full_content)) {
if (!empty($vars)) {
foreach ($vars as $var) {
$full_content .= "\r\n" . $var . ' | ';
}
}
return $this->partially_parsed_messages[] = array($email_address, $full_content);
} else {
return false;
}
}
/**
* #param $message
* #return array|bool
*/
private function parseMessage($message)
{
if (empty($message)) {
$this->newDebugMessage('Empty message');
return false;
}
if (!$content = $this->getMsg($message['msg_id'])) {
$this->newDebugMessage('Error reading content of message :' . $message['msg_id'] . '/' . $message['uidl']);
}
//todo add attachments
if (!empty($content)) {
return array('content' => $content);
}
return false;
}
/**
* #param $parsed_message
* #return bool
*/
private function getEmailAddress($parsed_message)
{
if (empty($parsed_message)) {
$this->newDebugMessage('Empty parsed message');
return false;
}
$found_emails = array();
foreach ($parsed_message as $content) {
$found_emails = array_unique(array_merge($found_emails, $this->parseEmailAddress($content)));
}
if (count($found_emails) > 1) {
$this->newDebugMessage('More than one e-mail address found: ' . join('; ', $found_emails));
return false;
}
if (count($found_emails) == 1) {
$this->newDebugMessage('Found e-mail address: ' . $found_emails[0]);
return $found_emails[0];
}
$this->newDebugMessage('No e-mail address found');
return false;
}
/**
* #param $content
* #return array
*/
private function parseEmailAddress($content)
{
$email_patterns = array('/[^-]To:\s?<?([a-zA-Z0-9_.-]+#[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+)>?/i',);
$found_emails = array();
foreach ($email_patterns as $pattern) {
$matches = array();
preg_match_all($pattern, $content, $matches);
if (!empty($matches) && isset($matches[1])) {
$recipient_emails = $matches[1];
$recipient_emails = array_filter($recipient_emails, array($this, 'filter_allowed_domains'));
$recipient_emails = array_filter($recipient_emails, array($this, 'filter_allowed_addresses'));
if (!empty($recipient_emails)) {
$found_emails = array_unique(array_merge($found_emails, $recipient_emails));
}
}
}
return $found_emails;
}
/**
* #param $email
* #return bool
*/
private function filter_allowed_domains($email)
{
return !in_array(substr(strrchr($email, "#"), 1), $this->allowed_email_domains);
}
/**
* #param $email
* #return bool
*/
private function filter_allowed_addresses($email)
{
return !in_array($email, $this->allowed_email_addresses);
}
/**
* #param $smtp_error
* #return bool|int
*/
private function getBounceType($smtp_error)
{
if (empty($smtp_error)) {
$this->newDebugMessage('Empty smtp error');
return false;
}
$status = substr($smtp_error, 0, 1);
switch ($status) {
case 4:
return 1; //temporary
break;
case 5:
return 2; //permanent
break;
}
return false;
}
/**
* #param $parsed_message
* #return bool
*/
private function getSMTPServer($parsed_message)
{
if (empty($parsed_message)) {
$this->newDebugMessage('Empty parsed message');
return false;
}
$found = array();
foreach ($parsed_message as $content) {
$found = array_unique(array_merge($found, $this->parseSMTPServer($content)));
}
if (count($found) > 0) {
$server = substr(join('; ', $found), 0, 254);
$this->newDebugMessage('Found SMTP server: ' . $server);
return $server;
}
$this->newDebugMessage('No SMTP server found');
return false;
}
/**
* #param $content
* #return array
*/
private function parseSMTPServer($content)
{
$patterns = array('/remote-mta:\s?dns;\s?([^\s]*)/i', '/reporting-mta:\s?dns;\s?([^\s]*)/i', '/received-from-mta:\s?dns;\s?([^\s]*)/i');
$found_statuses = array();
foreach ($patterns as $pattern) {
$matches = array();
preg_match_all($pattern, $content, $matches);
if (!empty($matches) && isset($matches[1])) {
$found_statuses = array_unique(array_merge($found_statuses, $matches[1]));
}
}
return $found_statuses;
}
/**
* #param $parsed_message
* #return bool
*/
private function getSMTPError($parsed_message)
{
if (empty($parsed_message)) {
$this->newDebugMessage('Empty parsed message');
return false;
}
$found = array();
foreach ($parsed_message as $content) {
$found = array_unique(array_merge($found, $this->parseSMTPError($content)));
}
if (count($found) > 0) {
$error = substr(join('; ', $found), 0, 19);
$this->newDebugMessage('Found SMTP Error: ' . $error);
return $error;
}
$this->newDebugMessage('No SMTP Error found');
return false;
}
/**
* #param $content
* #return array
*/
private function parseSMTPError($content)
{
//replace errors with codes
$content = str_replace('User mailbox exceeds allowed size', ' 452 4.1.1 ', $content);
$content = str_replace('user is over quota', ' 452 4.1.1 ', $content);
//find error
$patterns = array(
'/status:\s?#?(\d\.\d\.\d)/i',
'/[\d]{3}\s#?(\d\.\d\.\d)/',
'/\(#(\d\.\d\.\d)\)/',
'/Remote SMTP Server Returned:\s?#?([\d]{3})/i',
);
$found_statuses = array();
foreach ($patterns as $pattern) {
$matches = array();
preg_match_all($pattern, $content, $matches);
if (!empty($matches) && isset($matches[1])) {
$found_statuses = array_unique(array_merge($found_statuses, $matches[1]));
}
}
return $found_statuses;
}
}
you should add more regulars into parseSMTPError