From: jenkins-bot Date: Tue, 19 Dec 2017 12:21:59 +0000 (+0000) Subject: Merge "Require indentation of CASE statements in PHP code" X-Git-Tag: 1.31.0-rc.0~1168 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=3d95da4952619f9f773298c4461ccfc646fb18a9;hp=-c Merge "Require indentation of CASE statements in PHP code" --- 3d95da4952619f9f773298c4461ccfc646fb18a9 diff --combined includes/page/WikiPage.php index 7498ca52b0,ac9cd84403..c37566bdf6 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@@ -23,7 -23,6 +23,7 @@@ use MediaWiki\Edit\PreparedEdit; use \MediaWiki\Logger\LoggerFactory; use \MediaWiki\MediaWikiServices; +use Wikimedia\Assert\Assert; use Wikimedia\Rdbms\FakeResultWrapper; use Wikimedia\Rdbms\IDatabase; use Wikimedia\Rdbms\DBError; @@@ -195,15 -194,15 +195,15 @@@ class WikiPage implements Page, IDBAcce */ private static function convertSelectType( $type ) { switch ( $type ) { - case 'fromdb': - return self::READ_NORMAL; - case 'fromdbmaster': - return self::READ_LATEST; - case 'forupdate': - return self::READ_LOCKING; - default: - // It may already be an integer or whatever else - return $type; + case 'fromdb': + return self::READ_NORMAL; + case 'fromdbmaster': + return self::READ_LATEST; + case 'forupdate': + return self::READ_LOCKING; + default: + // It may already be an integer or whatever else + return $type; } } @@@ -672,7 -671,7 +672,7 @@@ $revision = Revision::newFromPageId( $this->getId(), $latest, $flags ); } else { $dbr = wfGetDB( DB_REPLICA ); - $revision = Revision::newKnownCurrent( $dbr, $this->getId(), $latest ); + $revision = Revision::newKnownCurrent( $dbr, $this->getTitle(), $latest ); } if ( $revision ) { // sanity @@@ -1265,11 -1264,8 +1265,11 @@@ $conditions['page_latest'] = $lastRevision; } + $revId = $revision->getId(); + Assert::parameter( $revId > 0, '$revision->getId()', 'must be > 0' ); + $row = [ /* SET */ - 'page_latest' => $revision->getId(), + 'page_latest' => $revId, 'page_touched' => $dbw->timestamp( $revision->getTimestamp() ), 'page_is_new' => ( $lastRevision === 0 ) ? 1 : 0, 'page_is_redirect' => $rt !== null ? 1 : 0, diff --combined includes/parser/Parser.php index 8986ddd995,f9f9410124..10a338ed01 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@@ -406,6 -406,13 +406,6 @@@ class Parser $text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null ) { - /** - * First pass--just handle sections, pass the rest off - * to internalParse() which does all the real work. - */ - - global $wgShowHostnames; - if ( $clearState ) { // We use U+007F DELETE to construct strip markers, so we have to make // sure that this character does not occur in the input text. @@@ -467,7 -474,7 +467,7 @@@ } } - # Done parsing! Compute runtime adaptive expiry if set + # Compute runtime adaptive expiry if set $this->mOutput->finalizeAdaptiveCacheExpiry(); # Warn if too many heavyweight parser functions were used @@@ -478,9 -485,110 +478,9 @@@ ); } - # Information on include size limits, for the benefit of users who try to skirt them + # Information on limits, for the benefit of users who try to skirt them if ( $this->mOptions->getEnableLimitReport() ) { - $max = $this->mOptions->getMaxIncludeSize(); - - $cpuTime = $this->mOutput->getTimeSinceStart( 'cpu' ); - if ( $cpuTime !== null ) { - $this->mOutput->setLimitReportData( 'limitreport-cputime', - sprintf( "%.3f", $cpuTime ) - ); - } - - $wallTime = $this->mOutput->getTimeSinceStart( 'wall' ); - $this->mOutput->setLimitReportData( 'limitreport-walltime', - sprintf( "%.3f", $wallTime ) - ); - - $this->mOutput->setLimitReportData( 'limitreport-ppvisitednodes', - [ $this->mPPNodeCount, $this->mOptions->getMaxPPNodeCount() ] - ); - $this->mOutput->setLimitReportData( 'limitreport-ppgeneratednodes', - [ $this->mGeneratedPPNodeCount, $this->mOptions->getMaxGeneratedPPNodeCount() ] - ); - $this->mOutput->setLimitReportData( 'limitreport-postexpandincludesize', - [ $this->mIncludeSizes['post-expand'], $max ] - ); - $this->mOutput->setLimitReportData( 'limitreport-templateargumentsize', - [ $this->mIncludeSizes['arg'], $max ] - ); - $this->mOutput->setLimitReportData( 'limitreport-expansiondepth', - [ $this->mHighestExpansionDepth, $this->mOptions->getMaxPPExpandDepth() ] - ); - $this->mOutput->setLimitReportData( 'limitreport-expensivefunctioncount', - [ $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit() ] - ); - Hooks::run( 'ParserLimitReportPrepare', [ $this, $this->mOutput ] ); - - $limitReport = "NewPP limit report\n"; - if ( $wgShowHostnames ) { - $limitReport .= 'Parsed by ' . wfHostname() . "\n"; - } - $limitReport .= 'Cached time: ' . $this->mOutput->getCacheTime() . "\n"; - $limitReport .= 'Cache expiry: ' . $this->mOutput->getCacheExpiry() . "\n"; - $limitReport .= 'Dynamic content: ' . - ( $this->mOutput->hasDynamicContent() ? 'true' : 'false' ) . - "\n"; - - foreach ( $this->mOutput->getLimitReportData() as $key => $value ) { - if ( Hooks::run( 'ParserLimitReportFormat', - [ $key, &$value, &$limitReport, false, false ] - ) ) { - $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false ); - $valueMsg = wfMessage( [ "$key-value-text", "$key-value" ] ) - ->inLanguage( 'en' )->useDatabase( false ); - if ( !$valueMsg->exists() ) { - $valueMsg = new RawMessage( '$1' ); - } - if ( !$keyMsg->isDisabled() && !$valueMsg->isDisabled() ) { - $valueMsg->params( $value ); - $limitReport .= "{$keyMsg->text()}: {$valueMsg->text()}\n"; - } - } - } - // Since we're not really outputting HTML, decode the entities and - // then re-encode the things that need hiding inside HTML comments. - $limitReport = htmlspecialchars_decode( $limitReport ); - // Run deprecated hook - Hooks::run( 'ParserLimitReport', [ $this, &$limitReport ], '1.22' ); - - // Sanitize for comment. Note '‐' in the replacement is U+2010, - // which looks much like the problematic '-'. - $limitReport = str_replace( [ '-', '&' ], [ '‐', '&' ], $limitReport ); - $text .= "\n\n"; - - // Add on template profiling data in human/machine readable way - $dataByFunc = $this->mProfiler->getFunctionStats(); - uasort( $dataByFunc, function ( $a, $b ) { - return $a['real'] < $b['real']; // descending order - } ); - $profileReport = []; - foreach ( array_slice( $dataByFunc, 0, 10 ) as $item ) { - $profileReport[] = sprintf( "%6.2f%% %8.3f %6d %s", - $item['%real'], $item['real'], $item['calls'], - htmlspecialchars( $item['name'] ) ); - } - $text .= "\n"; - - $this->mOutput->setLimitReportData( 'limitreport-timingprofile', $profileReport ); - - // Add other cache related metadata - if ( $wgShowHostnames ) { - $this->mOutput->setLimitReportData( 'cachereport-origin', wfHostname() ); - } - $this->mOutput->setLimitReportData( 'cachereport-timestamp', - $this->mOutput->getCacheTime() ); - $this->mOutput->setLimitReportData( 'cachereport-ttl', - $this->mOutput->getCacheExpiry() ); - $this->mOutput->setLimitReportData( 'cachereport-transientcontent', - $this->mOutput->hasDynamicContent() ); - - if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) { - wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' . - $this->mTitle->getPrefixedDBkey() ); - } + $text .= $this->makeLimitReport(); } # Wrap non-interface parser output in a
so it can be targeted @@@ -503,120 -611,6 +503,120 @@@ return $this->mOutput; } + /** + * Set the limit report data in the current ParserOutput, and return the + * limit report HTML comment. + * + * @return string + */ + protected function makeLimitReport() { + global $wgShowHostnames; + + $maxIncludeSize = $this->mOptions->getMaxIncludeSize(); + + $cpuTime = $this->mOutput->getTimeSinceStart( 'cpu' ); + if ( $cpuTime !== null ) { + $this->mOutput->setLimitReportData( 'limitreport-cputime', + sprintf( "%.3f", $cpuTime ) + ); + } + + $wallTime = $this->mOutput->getTimeSinceStart( 'wall' ); + $this->mOutput->setLimitReportData( 'limitreport-walltime', + sprintf( "%.3f", $wallTime ) + ); + + $this->mOutput->setLimitReportData( 'limitreport-ppvisitednodes', + [ $this->mPPNodeCount, $this->mOptions->getMaxPPNodeCount() ] + ); + $this->mOutput->setLimitReportData( 'limitreport-ppgeneratednodes', + [ $this->mGeneratedPPNodeCount, $this->mOptions->getMaxGeneratedPPNodeCount() ] + ); + $this->mOutput->setLimitReportData( 'limitreport-postexpandincludesize', + [ $this->mIncludeSizes['post-expand'], $maxIncludeSize ] + ); + $this->mOutput->setLimitReportData( 'limitreport-templateargumentsize', + [ $this->mIncludeSizes['arg'], $maxIncludeSize ] + ); + $this->mOutput->setLimitReportData( 'limitreport-expansiondepth', + [ $this->mHighestExpansionDepth, $this->mOptions->getMaxPPExpandDepth() ] + ); + $this->mOutput->setLimitReportData( 'limitreport-expensivefunctioncount', + [ $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit() ] + ); + Hooks::run( 'ParserLimitReportPrepare', [ $this, $this->mOutput ] ); + + $limitReport = "NewPP limit report\n"; + if ( $wgShowHostnames ) { + $limitReport .= 'Parsed by ' . wfHostname() . "\n"; + } + $limitReport .= 'Cached time: ' . $this->mOutput->getCacheTime() . "\n"; + $limitReport .= 'Cache expiry: ' . $this->mOutput->getCacheExpiry() . "\n"; + $limitReport .= 'Dynamic content: ' . + ( $this->mOutput->hasDynamicContent() ? 'true' : 'false' ) . + "\n"; + + foreach ( $this->mOutput->getLimitReportData() as $key => $value ) { + if ( Hooks::run( 'ParserLimitReportFormat', + [ $key, &$value, &$limitReport, false, false ] + ) ) { + $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false ); + $valueMsg = wfMessage( [ "$key-value-text", "$key-value" ] ) + ->inLanguage( 'en' )->useDatabase( false ); + if ( !$valueMsg->exists() ) { + $valueMsg = new RawMessage( '$1' ); + } + if ( !$keyMsg->isDisabled() && !$valueMsg->isDisabled() ) { + $valueMsg->params( $value ); + $limitReport .= "{$keyMsg->text()}: {$valueMsg->text()}\n"; + } + } + } + // Since we're not really outputting HTML, decode the entities and + // then re-encode the things that need hiding inside HTML comments. + $limitReport = htmlspecialchars_decode( $limitReport ); + // Run deprecated hook + Hooks::run( 'ParserLimitReport', [ $this, &$limitReport ], '1.22' ); + + // Sanitize for comment. Note '‐' in the replacement is U+2010, + // which looks much like the problematic '-'. + $limitReport = str_replace( [ '-', '&' ], [ '‐', '&' ], $limitReport ); + $text = "\n\n"; + + // Add on template profiling data in human/machine readable way + $dataByFunc = $this->mProfiler->getFunctionStats(); + uasort( $dataByFunc, function ( $a, $b ) { + return $a['real'] < $b['real']; // descending order + } ); + $profileReport = []; + foreach ( array_slice( $dataByFunc, 0, 10 ) as $item ) { + $profileReport[] = sprintf( "%6.2f%% %8.3f %6d %s", + $item['%real'], $item['real'], $item['calls'], + htmlspecialchars( $item['name'] ) ); + } + $text .= "\n"; + + $this->mOutput->setLimitReportData( 'limitreport-timingprofile', $profileReport ); + + // Add other cache related metadata + if ( $wgShowHostnames ) { + $this->mOutput->setLimitReportData( 'cachereport-origin', wfHostname() ); + } + $this->mOutput->setLimitReportData( 'cachereport-timestamp', + $this->mOutput->getCacheTime() ); + $this->mOutput->setLimitReportData( 'cachereport-ttl', + $this->mOutput->getCacheExpiry() ); + $this->mOutput->setLimitReportData( 'cachereport-transientcontent', + $this->mOutput->hasDynamicContent() ); + + if ( $this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10 ) { + wfDebugLog( 'generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' . + $this->mTitle->getPrefixedDBkey() ); + } + return $text; + } + /** * Half-parse wikitext to half-parsed HTML. This recursive parser entry point * can be called from an extension tag hook. @@@ -3498,7 -3492,13 +3498,7 @@@ * @return Revision|bool False if missing */ public static function statelessFetchRevision( Title $title, $parser = false ) { - $pageId = $title->getArticleID(); - $revId = $title->getLatestRevID(); - - $rev = Revision::newKnownCurrent( wfGetDB( DB_REPLICA ), $pageId, $revId ); - if ( $rev ) { - $rev->setTitle( $title ); - } + $rev = Revision::newKnownCurrent( wfGetDB( DB_REPLICA ), $title ); return $rev; } @@@ -4207,7 -4207,7 +4207,7 @@@ # Decode HTML entities $safeHeadline = Sanitizer::decodeCharReferences( $safeHeadline ); - $safeHeadline = $this->normalizeSectionName( $safeHeadline ); + $safeHeadline = self::normalizeSectionName( $safeHeadline ); $fallbackHeadline = Sanitizer::escapeIdForAttribute( $safeHeadline, Sanitizer::ID_FALLBACK ); $linkAnchor = Sanitizer::escapeIdForLink( $safeHeadline ); @@@ -5022,40 -5022,40 +5022,40 @@@ $paramName = $paramMap[$magicName]; switch ( $paramName ) { - case 'gallery-internal-alt': - $alt = $this->stripAltText( $match, false ); - break; - case 'gallery-internal-link': - $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) ); - $chars = self::EXT_LINK_URL_CLASS; - $addr = self::EXT_LINK_ADDR; - $prots = $this->mUrlProtocols; - // check to see if link matches an absolute url, if not then it must be a wiki link. - if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) { - // Result of LanguageConverter::markNoConversion - // invoked on an external link. - $linkValue = substr( $linkValue, 4, -2 ); - } - if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) { - $link = $linkValue; - $this->mOutput->addExternalLink( $link ); - } else { - $localLinkTitle = Title::newFromText( $linkValue ); - if ( $localLinkTitle !== null ) { - $this->mOutput->addLink( $localLinkTitle ); - $link = $localLinkTitle->getLinkURL(); + case 'gallery-internal-alt': + $alt = $this->stripAltText( $match, false ); + break; + case 'gallery-internal-link': + $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) ); + $chars = self::EXT_LINK_URL_CLASS; + $addr = self::EXT_LINK_ADDR; + $prots = $this->mUrlProtocols; + // check to see if link matches an absolute url, if not then it must be a wiki link. + if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) { + // Result of LanguageConverter::markNoConversion + // invoked on an external link. + $linkValue = substr( $linkValue, 4, -2 ); + } + if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) { + $link = $linkValue; + $this->mOutput->addExternalLink( $link ); + } else { + $localLinkTitle = Title::newFromText( $linkValue ); + if ( $localLinkTitle !== null ) { + $this->mOutput->addLink( $localLinkTitle ); + $link = $localLinkTitle->getLinkURL(); + } + } + break; + default: + // Must be a handler specific parameter. + if ( $handler->validateParam( $paramName, $match ) ) { + $handlerOptions[$paramName] = $match; + } else { + // Guess not, consider it as caption. + wfDebug( "$parameterMatch failed parameter validation\n" ); + $label = '|' . $parameterMatch; } - } - break; - default: - // Must be a handler specific parameter. - if ( $handler->validateParam( $paramName, $match ) ) { - $handlerOptions[$paramName] = $match; - } else { - // Guess not, consider it as caption. - wfDebug( "$parameterMatch failed parameter validation\n" ); - $label = '|' . $parameterMatch; - } } } else { @@@ -5217,52 -5217,52 +5217,52 @@@ } else { # Validate internal parameters switch ( $paramName ) { - case 'manualthumb': - case 'alt': - case 'class': - # @todo FIXME: Possibly check validity here for - # manualthumb? downstream behavior seems odd with - # missing manual thumbs. - $validated = true; - $value = $this->stripAltText( $value, $holders ); - break; - case 'link': - $chars = self::EXT_LINK_URL_CLASS; - $addr = self::EXT_LINK_ADDR; - $prots = $this->mUrlProtocols; - if ( $value === '' ) { - $paramName = 'no-link'; - $value = true; + case 'manualthumb': + case 'alt': + case 'class': + # @todo FIXME: Possibly check validity here for + # manualthumb? downstream behavior seems odd with + # missing manual thumbs. $validated = true; - } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) { - if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) { - $paramName = 'link-url'; - $this->mOutput->addExternalLink( $value ); - if ( $this->mOptions->getExternalLinkTarget() ) { - $params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget(); - } - $validated = true; - } - } else { - $linkTitle = Title::newFromText( $value ); - if ( $linkTitle ) { - $paramName = 'link-title'; - $value = $linkTitle; - $this->mOutput->addLink( $linkTitle ); + $value = $this->stripAltText( $value, $holders ); + break; + case 'link': + $chars = self::EXT_LINK_URL_CLASS; + $addr = self::EXT_LINK_ADDR; + $prots = $this->mUrlProtocols; + if ( $value === '' ) { + $paramName = 'no-link'; + $value = true; $validated = true; + } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) { + if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) { + $paramName = 'link-url'; + $this->mOutput->addExternalLink( $value ); + if ( $this->mOptions->getExternalLinkTarget() ) { + $params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget(); + } + $validated = true; + } + } else { + $linkTitle = Title::newFromText( $value ); + if ( $linkTitle ) { + $paramName = 'link-title'; + $value = $linkTitle; + $this->mOutput->addLink( $linkTitle ); + $validated = true; + } } - } - break; - case 'frameless': - case 'framed': - case 'thumbnail': - // use first appearing option, discard others. - $validated = !$seenformat; - $seenformat = true; - break; - default: - # Most other things appear to be empty or numeric... - $validated = ( $value === false || is_numeric( trim( $value ) ) ); + break; + case 'frameless': + case 'framed': + case 'thumbnail': + // use first appearing option, discard others. + $validated = !$seenformat; + $seenformat = true; + break; + default: + # Most other things appear to be empty or numeric... + $validated = ( $value === false || is_numeric( trim( $value ) ) ); } } @@@ -5756,42 -5756,23 +5756,42 @@@ return $this->mDefaultSort; } + private static function getSectionNameFromStrippedText( $text ) { + $text = Sanitizer::normalizeSectionNameWhitespace( $text ); + $text = Sanitizer::decodeCharReferences( $text ); + $text = self::normalizeSectionName( $text ); + return $text; + } + + private static function makeAnchor( $sectionName ) { + return '#' . Sanitizer::escapeIdForLink( $sectionName ); + } + + private static function makeLegacyAnchor( $sectionName ) { + global $wgFragmentMode; + if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) { + // ForAttribute() and ForLink() are the same for legacy encoding + $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK ); + } else { + $id = Sanitizer::escapeIdForLink( $text ); + } + + return "#$id"; + } + /** * Try to guess the section anchor name based on a wikitext fragment * presumably extracted from a heading, for example "Header" from * "== Header ==". * * @param string $text - * - * @return string + * @return string Anchor (starting with '#') */ public function guessSectionNameFromWikiText( $text ) { # Strip out wikitext links(they break the anchor) $text = $this->stripSectionName( $text ); - $text = Sanitizer::normalizeSectionNameWhitespace( $text ); - $text = Sanitizer::decodeCharReferences( $text ); - $text = $this->normalizeSectionName( $text ); - - return '#' . Sanitizer::escapeIdForLink( $text ); + $sectionName = self::getSectionNameFromStrippedText( $text ); + return self::makeAnchor( $sectionName ); } /** @@@ -5801,23 -5782,25 +5801,23 @@@ * than UTF-8, resulting in breakage. * * @param string $text The section name - * @return string An anchor + * @return string Anchor (starting with '#') */ public function guessLegacySectionNameFromWikiText( $text ) { - global $wgFragmentMode; - # Strip out wikitext links(they break the anchor) $text = $this->stripSectionName( $text ); - $text = Sanitizer::normalizeSectionNameWhitespace( $text ); - $text = Sanitizer::decodeCharReferences( $text ); - $text = $this->normalizeSectionName( $text ); - - if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) { - // ForAttribute() and ForLink() are the same for legacy encoding - $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK ); - } else { - $id = Sanitizer::escapeIdForLink( $text ); - } + $sectionName = self::getSectionNameFromStrippedText( $text ); + return self::makeLegacyAnchor( $sectionName ); + } - return "#$id"; + /** + * Like guessSectionNameFromWikiText(), but takes already-stripped text as input. + * @param string $text Section name (plain text) + * @return string Anchor (starting with '#') + */ + public static function guessSectionNameFromStrippedText( $text ) { + $sectionName = self::getSectionNameFromStrippedText( $text ); + return self::makeAnchor( $sectionName ); } /** @@@ -5826,7 -5809,7 +5826,7 @@@ * @param string $text * @return string */ - private function normalizeSectionName( $text ) { + private static function normalizeSectionName( $text ) { # T90902: ensure the same normalization is applied for IDs as to links $titleParser = MediaWikiServices::getInstance()->getTitleParser(); try { diff --combined includes/utils/AutoloadGenerator.php index 1415ea32b4,14c432c0bb..d12531b304 --- a/includes/utils/AutoloadGenerator.php +++ b/includes/utils/AutoloadGenerator.php @@@ -42,13 -42,6 +42,13 @@@ class AutoloadGenerator */ protected $overrides = []; + /** + * Directories that should be excluded + * + * @var string[] + */ + protected $excludePaths = []; + /** * @param string $basepath Root path of the project being scanned for classes * @param array|string $flags @@@ -67,34 -60,6 +67,34 @@@ } } + /** + * Directories that should be excluded + * + * @since 1.31 + * @param string[] $paths + */ + public function setExcludePaths( array $paths ) { + foreach ( $paths as $path ) { + $this->excludePaths[] = self::normalizePathSeparator( $path ); + } + } + + /** + * Whether the file should be excluded + * + * @param string $path File path + * @return bool + */ + private function shouldExclude( $path ) { + foreach ( $this->excludePaths as $dir ) { + if ( strpos( $path, $dir ) === 0 ) { + return true; + } + } + + return false; + } + /** * Force a class to be autoloaded from a specific path, regardless of where * or if it was detected. @@@ -129,9 -94,6 +129,9 @@@ if ( substr( $inputPath, 0, $len ) !== $this->basepath ) { throw new \Exception( "Path is not within basepath: $inputPath" ); } + if ( $this->shouldExclude( $inputPath ) ) { + return; + } $result = $this->collector->getClasses( file_get_contents( $inputPath ) ); @@@ -392,18 -354,18 +392,18 @@@ class ClassCollector // Note: When changing class name discovery logic, // AutoLoaderTest.php may also need to be updated. switch ( $token[0] ) { - case T_NAMESPACE: - case T_CLASS: - case T_INTERFACE: - case T_TRAIT: - case T_DOUBLE_COLON: - $this->startToken = $token; - break; - case T_STRING: - if ( $token[1] === 'class_alias' ) { + case T_NAMESPACE: + case T_CLASS: + case T_INTERFACE: + case T_TRAIT: + case T_DOUBLE_COLON: $this->startToken = $token; - $this->alias = []; - } + break; + case T_STRING: + if ( $token[1] === 'class_alias' ) { + $this->startToken = $token; + $this->alias = []; + } } } @@@ -414,78 -376,78 +414,78 @@@ */ protected function tryEndExpect( $token ) { switch ( $this->startToken[0] ) { - case T_DOUBLE_COLON: - // Skip over T_CLASS after T_DOUBLE_COLON because this is something like - // "self::static" which accesses the class name. It doens't define a new class. - $this->startToken = null; - break; - case T_NAMESPACE: - if ( $token === ';' || $token === '{' ) { - $this->namespace = $this->implodeTokens() . '\\'; - } else { - $this->tokens[] = $token; - } - break; - - case T_STRING: - if ( $this->alias !== null ) { - // Flow 1 - Two string literals: - // - T_STRING class_alias - // - '(' - // - T_CONSTANT_ENCAPSED_STRING 'TargetClass' - // - ',' - // - T_WHITESPACE - // - T_CONSTANT_ENCAPSED_STRING 'AliasName' - // - ')' - // Flow 2 - Use of ::class syntax for first parameter - // - T_STRING class_alias - // - '(' - // - T_STRING TargetClass - // - T_DOUBLE_COLON :: - // - T_CLASS class - // - ',' - // - T_WHITESPACE - // - T_CONSTANT_ENCAPSED_STRING 'AliasName' - // - ')' - if ( $token === '(' ) { - // Start of a function call to class_alias() - $this->alias = [ 'target' => false, 'name' => false ]; - } elseif ( $token === ',' ) { - // Record that we're past the first parameter - if ( $this->alias['target'] === false ) { - $this->alias['target'] = true; - } - } elseif ( is_array( $token ) && $token[0] === T_CONSTANT_ENCAPSED_STRING ) { - if ( $this->alias['target'] === true ) { - // We already saw a first argument, this must be the second. - // Strip quotes from the string literal. - $this->alias['name'] = substr( $token[1], 1, -1 ); + case T_DOUBLE_COLON: + // Skip over T_CLASS after T_DOUBLE_COLON because this is something like + // "self::static" which accesses the class name. It doens't define a new class. + $this->startToken = null; + break; + case T_NAMESPACE: + if ( $token === ';' || $token === '{' ) { + $this->namespace = $this->implodeTokens() . '\\'; + } else { + $this->tokens[] = $token; + } + break; + + case T_STRING: + if ( $this->alias !== null ) { + // Flow 1 - Two string literals: + // - T_STRING class_alias + // - '(' + // - T_CONSTANT_ENCAPSED_STRING 'TargetClass' + // - ',' + // - T_WHITESPACE + // - T_CONSTANT_ENCAPSED_STRING 'AliasName' + // - ')' + // Flow 2 - Use of ::class syntax for first parameter + // - T_STRING class_alias + // - '(' + // - T_STRING TargetClass + // - T_DOUBLE_COLON :: + // - T_CLASS class + // - ',' + // - T_WHITESPACE + // - T_CONSTANT_ENCAPSED_STRING 'AliasName' + // - ')' + if ( $token === '(' ) { + // Start of a function call to class_alias() + $this->alias = [ 'target' => false, 'name' => false ]; + } elseif ( $token === ',' ) { + // Record that we're past the first parameter + if ( $this->alias['target'] === false ) { + $this->alias['target'] = true; + } + } elseif ( is_array( $token ) && $token[0] === T_CONSTANT_ENCAPSED_STRING ) { + if ( $this->alias['target'] === true ) { + // We already saw a first argument, this must be the second. + // Strip quotes from the string literal. + $this->alias['name'] = substr( $token[1], 1, -1 ); + } + } elseif ( $token === ')' ) { + // End of function call + $this->classes[] = $this->alias['name']; + $this->alias = null; + $this->startToken = null; + } elseif ( !is_array( $token ) || ( + $token[0] !== T_STRING && + $token[0] !== T_DOUBLE_COLON && + $token[0] !== T_CLASS && + $token[0] !== T_WHITESPACE + ) ) { + // Ignore this call to class_alias() - compat/Timestamp.php + $this->alias = null; + $this->startToken = null; } - } elseif ( $token === ')' ) { - // End of function call - $this->classes[] = $this->alias['name']; - $this->alias = null; - $this->startToken = null; - } elseif ( !is_array( $token ) || ( - $token[0] !== T_STRING && - $token[0] !== T_DOUBLE_COLON && - $token[0] !== T_CLASS && - $token[0] !== T_WHITESPACE - ) ) { - // Ignore this call to class_alias() - compat/Timestamp.php - $this->alias = null; - $this->startToken = null; } - } - break; - - case T_CLASS: - case T_INTERFACE: - case T_TRAIT: - $this->tokens[] = $token; - if ( is_array( $token ) && $token[0] === T_STRING ) { - $this->classes[] = $this->namespace . $this->implodeTokens(); - } + break; + + case T_CLASS: + case T_INTERFACE: + case T_TRAIT: + $this->tokens[] = $token; + if ( is_array( $token ) && $token[0] === T_STRING ) { + $this->classes[] = $this->namespace . $this->implodeTokens(); + } } }