Skip to content

Commit 749f99c

Browse files
authored
Create Php.php
1 parent 23b0a29 commit 749f99c

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

src/lib/lint/Php.php

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
namespace frdl\Lint;
4+
5+
class Php
6+
{
7+
protected $cacheDir = null;
8+
9+
public function __construct($cacheDir = null)
10+
{
11+
$this->cacheDir = $cacheDir;
12+
}
13+
14+
public function setCacheDir($cacheDir = null)
15+
{
16+
$this->cacheDir = $cacheDir;
17+
return $this;
18+
}
19+
20+
public function getCacheDir()
21+
{
22+
if((null!==$this->cacheDir && !empty($this->cacheDir)) && is_dir($this->cacheDir)){
23+
return $this->cacheDir;
24+
}
25+
26+
if(!isset($_ENV['FRDL_HPS_CACHE_DIR']))$_ENV['FRDL_HPS_CACHE_DIR']=getenv('FRDL_HPS_CACHE_DIR');
27+
28+
$this->cacheDir =
29+
( isset($_ENV['FRDL_HPS_CACHE_DIR']) && !empty($_ENV['FRDL_HPS_CACHE_DIR']))
30+
? $_ENV['FRDL_HPS_CACHE_DIR']
31+
: \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . \get_current_user(). \DIRECTORY_SEPARATOR . 'cache' . \DIRECTORY_SEPARATOR ;
32+
33+
$this->cacheDir = rtrim($this->cacheDir, '\\/'). \DIRECTORY_SEPARATOR.'lint';
34+
35+
if(!is_dir($this->cacheDir)){
36+
mkdir($this->cacheDir, 0755, true);
37+
}
38+
39+
40+
return $this->cacheDir;
41+
}
42+
43+
public function lintString($source)
44+
{
45+
$cachedir = $this->getCacheDir();
46+
if(!is_writable($cachedir)){
47+
mkdir($cachedir, 0755, true);
48+
}
49+
$tmpfname = tempnam($cachedir, 'frdl_lint_php');
50+
if(empty($tmpfname))return false;
51+
file_put_contents($tmpfname, $source);
52+
$valid = $this->checkSyntax($tmpfname, false);
53+
unlink($tmpfname);
54+
return $valid;
55+
}
56+
57+
public function lintFile($fileName, $checkIncludes = true)
58+
{
59+
return call_user_func_array([$this, 'checkSyntax'], [$fileName, $checkIncludes]);
60+
}
61+
62+
public static function lintStringStatic($source)
63+
{
64+
$o = new self;
65+
$tmpfname = tempnam($o->getCacheDir(), 'frdl_lint_php');
66+
file_put_contents($tmpfname, $source);
67+
$valid = $o->checkSyntax($tmpfname, false);
68+
unlink($tmpfname);
69+
return $valid;
70+
}
71+
72+
public static function lintFileStatic($fileName, $checkIncludes = true)
73+
{
74+
$o = new self;
75+
$o->setCacheDir($o->getCacheDir());
76+
return call_user_func_array([$o, 'checkSyntax'], [$fileName, $checkIncludes]);
77+
}
78+
79+
public static function __callStatic($name, $arguments)
80+
{
81+
$o = new self;
82+
return call_user_func_array([$o, $name], $arguments);
83+
}
84+
85+
public function checkSyntax($fileName, $checkIncludes = false)
86+
{
87+
if(!file_exists($fileName))
88+
throw new \Exception("Cannot read file ".$fileName);
89+
90+
// Sort out the formatting of the filename
91+
$fileName = realpath($fileName);
92+
93+
// Get the shell output from the syntax check command
94+
$output = shell_exec(sprintf('%s -l "%s"', (new \webfan\hps\patch\PhpBinFinder())->find(), $fileName));
95+
96+
// Try to find the parse error text and chop it off
97+
$syntaxError = preg_replace("/Errors parsing.*$/", "", $output, -1, $count);
98+
99+
// If the error text above was matched, throw an exception containing the syntax error
100+
if($count > 0)
101+
//throw new \Exception(trim($syntaxError));
102+
return 'Errors parsing '.print_r([$output, $count],true);
103+
104+
// If we are going to check the files includes
105+
if($checkIncludes)
106+
{
107+
foreach($this->getIncludes($fileName) as $include)
108+
{
109+
// Check the syntax for each include
110+
$tCheck = $this->checkSyntax($include, $checkIncludes);
111+
if(true!==$tCheck){
112+
return $tCheck;
113+
}
114+
}
115+
}
116+
117+
return true;
118+
}
119+
120+
public function getIncludes($fileName)
121+
{
122+
$includes = array();
123+
// Get the directory name of the file so we can prepend it to relative paths
124+
$dir = dirname($fileName);
125+
126+
// Split the contents of $fileName about requires and includes
127+
// We need to slice off the first element since that is the text up to the first include/require
128+
$requireSplit = array_slice(preg_split('/require|include/i', file_get_contents($fileName)), 1);
129+
130+
// For each match
131+
foreach($requireSplit as $string)
132+
{
133+
// Substring up to the end of the first line, i.e. the line that the require is on
134+
$string = substr($string, 0, strpos($string, ";"));
135+
136+
// If the line contains a reference to a variable, then we cannot analyse it
137+
// so skip this iteration
138+
if(strpos($string, "$") !== false)
139+
continue;
140+
141+
// Split the string about single and double quotes
142+
$quoteSplit = preg_split('/[\'"]/', $string);
143+
144+
// The value of the include is the second element of the array
145+
// Putting this in an if statement enforces the presence of '' or "" somewhere in the include
146+
// includes with any kind of run-time variable in have been excluded earlier
147+
// this just leaves includes with constants in, which we can't do much about
148+
if($include = $quoteSplit[1])
149+
{
150+
// If the path is not absolute, add the dir and separator
151+
// Then call realpath to chop out extra separators
152+
if(strpos($include, ':') === FALSE)
153+
$include = realpath($dir.\DIRECTORY_SEPARATOR.$include);
154+
155+
array_push($includes, $include);
156+
}
157+
}
158+
159+
return $includes;
160+
}
161+
}

0 commit comments

Comments
 (0)