Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1429350
RequireExistsPlugin.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
RequireExistsPlugin.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
Phan\Plugin\Internal
;
use
ast
;
use
ast\Node
;
use
Phan\AST\ASTReverter
;
use
Phan\AST\ContextNode
;
use
Phan\AST\UnionTypeVisitor
;
use
Phan\Config
;
use
Phan\Issue
;
use
Phan\Language\Type\StringType
;
use
Phan\Library\Paths
;
use
Phan\PluginV3
;
use
Phan\PluginV3\PluginAwarePostAnalysisVisitor
;
use
Phan\PluginV3\PostAnalyzeNodeCapability
;
use
function
file_exists
;
use
function
is_file
;
/**
* Analyzes require/include/require_once/include_once statements to check if the file exists
*/
class
RequireExistsPlugin
extends
PluginV3
implements
PostAnalyzeNodeCapability
{
public
static
function
getPostAnalyzeNodeVisitorClassName
():
string
{
return
RequireExistsVisitor
::
class
;
}
}
/**
* Visits require/include/require_once/include_once statements to check if the file exists
*/
class
RequireExistsVisitor
extends
PluginAwarePostAnalysisVisitor
{
/**
* @override
*/
public
function
visitIncludeOrEval
(
Node
$node
):
void
{
if
(
$node
->
flags
===
ast\flags\EXEC_EVAL
)
{
$this
->
analyzeEval
(
$node
);
return
;
}
$expr
=
$node
->
children
[
'expr'
];
if
(
$expr
instanceof
Node
)
{
$path
=
(
new
ContextNode
(
$this
->
code_base
,
$this
->
context
,
$expr
))->
getEquivalentPHPScalarValue
();
}
else
{
$path
=
$expr
;
}
if
(!
\is_string
(
$path
))
{
$type
=
UnionTypeVisitor
::
unionTypeFromNode
(
$this
->
code_base
,
$this
->
context
,
$expr
);
if
(!
$type
->
canCastToUnionType
(
StringType
::
instance
(
false
)->
asPHPDocUnionType
(),
$this
->
code_base
))
{
$this
->
emitIssue
(
Issue
::
TypeInvalidRequire
,
$expr
->
lineno
??
$node
->
lineno
,
$type
);
}
return
;
}
$this
->
checkPathExistsInContext
(
$node
,
$path
);
}
private
function
analyzeEval
(
Node
$node
):
void
{
$expr
=
$node
->
children
[
'expr'
];
$type
=
UnionTypeVisitor
::
unionTypeFromNode
(
$this
->
code_base
,
$this
->
context
,
$expr
);
if
(!
$type
->
canCastToUnionType
(
StringType
::
instance
(
false
)->
asPHPDocUnionType
(),
$this
->
code_base
))
{
$this
->
emitIssue
(
Issue
::
TypeInvalidEval
,
$expr
->
lineno
??
$node
->
lineno
,
$type
);
}
}
/**
* Check if the path provided to include()/require_once()/etc is valid.
*/
private
function
checkPathExistsInContext
(
Node
$node
,
string
$relative_path
):
void
{
$absolute_path
=
$this
->
getAbsolutePath
(
$node
,
$relative_path
);
if
(!
file_exists
(
$absolute_path
))
{
$this
->
emitIssue
(
Issue
::
MissingRequireFile
,
$node
->
children
[
'expr'
]->
lineno
??
$node
->
lineno
,
Paths
::
escapePathForIssue
(
$relative_path
)
);
return
;
}
if
(!
is_file
(
$absolute_path
))
{
$this
->
emitIssue
(
Issue
::
InvalidRequireFile
,
$node
->
children
[
'expr'
]->
lineno
??
$node
->
lineno
,
Paths
::
escapePathForIssue
(
$relative_path
)
);
return
;
}
}
private
function
getAbsolutePath
(
Node
$node
,
string
$relative_path
):
string
{
if
(
Paths
::
isAbsolutePath
(
$relative_path
))
{
return
$relative_path
;
}
if
(
Config
::
getValue
(
'warn_about_relative_include_statement'
))
{
$this
->
emitIssue
(
Issue
::
RelativePathUsed
,
$node
->
children
[
'exec'
]->
lineno
??
$node
->
lineno
,
ASTReverter
::
EXEC_NODE_FLAG_NAMES
[
$node
->
flags
]
??
'unknown'
,
Paths
::
escapePathForIssue
(
$relative_path
)
);
}
$first_absolute_path
=
null
;
foreach
(
Config
::
getValue
(
'include_paths'
)
?:
[
'.'
]
as
$include_path
)
{
if
(!
Paths
::
isAbsolutePath
(
$include_path
))
{
$include_path
=
Paths
::
toAbsolutePath
(
\dirname
(
Config
::
projectPath
(
$this
->
context
->
getFile
())),
$include_path
);
}
$absolute_path
=
Paths
::
toAbsolutePath
(
$include_path
,
$relative_path
);
if
(
file_exists
(
$absolute_path
))
{
return
$absolute_path
;
}
$first_absolute_path
=
$first_absolute_path
??
$absolute_path
;
}
// If we searched every directory in include_paths, but none existed,
// then give up and return the first (missing) resolved path.
return
$first_absolute_path
??
'(unknown)'
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 17:27 (10 h, 13 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2a/ff/c25fae55dfbb9b8b67023836d3b8
Default Alt Text
RequireExistsPlugin.php (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment