Brian Wolff has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/394092 )
Change subject: Support loading hook information from extension.json ...................................................................... Support loading hook information from extension.json As of yet, nothing is done with hook info. Change-Id: I978302f5a6f18ab2070af4e296cdcd20faaa4a07 --- M README M src/MediaWikiSecurityCheckPlugin.php A tests/integration/json/Parser.php A tests/integration/json/expectedResults.txt A tests/integration/json/extension.json A tests/integration/json/test.php M tests/runtests.sh 7 files changed, 89 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/tools/phan/SecurityCheckPlugin refs/changes/92/394092/1 diff --git a/README b/README index 42bf034..128b2fd 100644 --- a/README +++ b/README @@ -9,3 +9,8 @@ project or a MediaWiki/MediaWiki extension respectively. This is only tested with Phan 0.8.0 + +== Environment variables == +The following environment variables affect the plugin: +* SECURITY_CHECK_EXT_PATH - Path to extension.json when in MediaWiki mode. If not set assumes the project root directory. +* SECCHECK_DEBUG - File to output extra debug information (If running from shell, /dev/stderr is convenient) diff --git a/src/MediaWikiSecurityCheckPlugin.php b/src/MediaWikiSecurityCheckPlugin.php index bc66349..7bcee97 100644 --- a/src/MediaWikiSecurityCheckPlugin.php +++ b/src/MediaWikiSecurityCheckPlugin.php @@ -7,9 +7,12 @@ require_once __DIR__ . "/MWPreVisitor.php"; use Phan\CodeBase; +use Phan\Config; use Phan\Language\Context; use Phan\Language\FQSEN\FullyQualifiedFunctionLikeName; use Phan\Language\FQSEN\FullyQualifiedClassName; +use Phan\Language\FQSEN\FullyQualifiedFunctionName as FQSENFunc; +use Phan\Language\FQSEN\FullyQualifiedMethodName as FQSENMethod; use ast\Node; class MediaWikiSecurityCheckPlugin extends SecurityCheckPlugin { @@ -284,12 +287,56 @@ } /** + * Register hooks from extension.json + * + * Assumes extension.json is in project root directory + * unless SECURITY_CHECK_EXT_PATH is set + */ + protected function loadExtensionJson() { + static $done; + if ( $done ) { + return; + } + $done = true; + $envPath = getenv( 'SECURITY_CHECK_EXT_PATH' ); + if ( $envPath ) { + $jsonPath = $envPath . '/' . 'extension.json'; + } else { + $jsonPath = Config::projectPath( 'extension.json' ); + } + if ( file_exists( $jsonPath ) ) { + $json = json_decode( file_get_contents( $jsonPath ), true ); + if ( !is_array( $json ) ) { + return; + } + if ( isset( $json['Hooks'] ) && is_array( $json['Hooks'] ) ) { + foreach ( $json['Hooks'] as $hookName => $cbList ) { + foreach ( (array)$cbList as $cb ) { + // All callbacks here are simple + // "someFunction" or "Class::SomeMethod" + if ( strpos( $cb, '::' ) === false ) { + $callback = FQSENFunc::fromFullyQualifiedString( + $cb + ); + } else { + $callback = FQSENMethod::fromFullyQualifiedString( + $cb + ); + } + $this->registerHook( $hookName, $callback ); + } + } + } + } + } + /** * Get a list of subscribers for hook * * @param string $hookName Hook in question. Hooks starting with ! are special. * @return FullyQualifiedFunctionLikeName[] */ public function getHookSubscribers( string $hookName ) : array { + $this->loadExtensionJson(); if ( isset( $this->hookSubscribers[$hookName] ) ) { return $this->hookSubscribers[$hookName]; } @@ -305,6 +352,7 @@ * @return string The hook it is implementing */ public function isSpecialHookSubscriber( FullyQualifiedFunctionLikeName $fqsen ) { + $this->loadExtensionJson(); $specialHooks = [ '!ParserFunctionHook', '!ParserHook' diff --git a/tests/integration/json/Parser.php b/tests/integration/json/Parser.php new file mode 100644 index 0000000..5fc9186 --- /dev/null +++ b/tests/integration/json/Parser.php @@ -0,0 +1,3 @@ +<?php +class Parser { +} diff --git a/tests/integration/json/expectedResults.txt b/tests/integration/json/expectedResults.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/integration/json/expectedResults.txt diff --git a/tests/integration/json/extension.json b/tests/integration/json/extension.json new file mode 100644 index 0000000..22cf7ca --- /dev/null +++ b/tests/integration/json/extension.json @@ -0,0 +1,14 @@ +{ + "name": "testJsonFile", + "author": [ + "Brian Wolff" + ], + "Hooks": { + "ParserFirstCallInit": [ + "wfRegister" + ], + "MediaWikiPerformAction": [ + "SomeClass::onMediaWikiPerformAction" + ] + } +} diff --git a/tests/integration/json/test.php b/tests/integration/json/test.php new file mode 100644 index 0000000..7f98b9d --- /dev/null +++ b/tests/integration/json/test.php @@ -0,0 +1,16 @@ +<?php + +function register( Parser $parser ) { +} + +class SomeClass { + public static function onMediaWikiPerformAction( + $output, + $page, + $title, + $user, + $request, + $mw + ) { + } +} diff --git a/tests/runtests.sh b/tests/runtests.sh index 110f442..eea31ea 100755 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -6,7 +6,7 @@ # -v will add debug output. testname will run only that test # -cd `dirname $0`/ +cd `dirname "$0"`/ tmpFile=`mktemp testtmp.XXXXXXXX` trap "rm $tmpFile" exit totalTests=0 @@ -24,6 +24,8 @@ for i in $testList do echo "Running test $i" + SECURITY_CHECK_EXT_PATH=`dirname "$0"`"/integration/$i/" + export SECURITY_CHECK_EXT_PATH totalTests=$((totalTests+1)) $php ../vendor/etsy/phan/phan \ --project-root-directory "." \ -- To view, visit https://gerrit.wikimedia.org/r/394092 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I978302f5a6f18ab2070af4e296cdcd20faaa4a07 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/tools/phan/SecurityCheckPlugin Gerrit-Branch: master Gerrit-Owner: Brian Wolff <bawolff...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits