uawdijnntqw1x1x1
IP : 216.73.216.136
Hostname : dhandapanilive
Kernel : Linux dhandapanilive 5.15.0-139-generic #149~20.04.1-Ubuntu SMP Wed Apr 16 08:29:56 UTC 2025 x86_64
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
OS : Linux
PATH:
/
var
/
www
/
html
/
dhandapani
/
a8fc6
/
..
/
bin
/
..
/
9da53
/
phpcpd.tar
/
/
src/Log/Text.php000077700000004531151323632730007530 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Log; use SebastianBergmann\PHPCPD\CodeCloneMap; use Symfony\Component\Console\Output\OutputInterface; final class Text { /** * Prints a result set from Detector::copyPasteDetection(). */ public function printResult(OutputInterface $output, CodeCloneMap $clones): void { $verbose = $output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL; if (\count($clones) > 0) { $output->write( \sprintf( 'Found %d clones with %d duplicated lines in %d files:' . \PHP_EOL . \PHP_EOL, \count($clones), $clones->getNumberOfDuplicatedLines(), $clones->getNumberOfFilesWithClones() ) ); } foreach ($clones as $clone) { $firstOccurrence = true; foreach ($clone->getFiles() as $file) { $output->writeln( \sprintf( ' %s%s:%d-%d%s', $firstOccurrence ? '- ' : ' ', $file->getName(), $file->getStartLine(), $file->getStartLine() + $clone->getSize(), $firstOccurrence ? ' (' . $clone->getSize() . ' lines)' : '' ) ); $firstOccurrence = false; } if ($verbose) { $output->write(\PHP_EOL . $clone->getLines(' ')); } $output->writeln(''); } if ($clones->isEmpty()) { $output->write("No clones found.\n\n"); return; } $output->write( \sprintf( "%s duplicated lines out of %d total lines of code.\n" . "Average size of duplication is %d lines, largest clone has %d of lines\n\n", $clones->getPercentage(), $clones->getNumLines(), $clones->getAverageSize(), $clones->getLargestSize() ) ); } } src/Log/PMD.php000077700000003045151323632730007223 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Log; use SebastianBergmann\PHPCPD\CodeCloneMap; final class PMD extends AbstractXmlLogger { /** * Processes a list of clones. */ public function processClones(CodeCloneMap $clones): void { $cpd = $this->document->createElement('pmd-cpd'); $this->document->appendChild($cpd); foreach ($clones as $clone) { $duplication = $cpd->appendChild( $this->document->createElement('duplication') ); $duplication->setAttribute('lines', (string) $clone->getSize()); $duplication->setAttribute('tokens', (string) $clone->getTokens()); foreach ($clone->getFiles() as $codeCloneFile) { $file = $duplication->appendChild( $this->document->createElement('file') ); $file->setAttribute('path', $codeCloneFile->getName()); $file->setAttribute('line', (string) $codeCloneFile->getStartLine()); } $duplication->appendChild( $this->document->createElement( 'codefragment', $this->escapeForXml($clone->getLines()) ) ); } $this->flush(); } } src/Log/.htaccess000077700000000177151323632730007673 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>src/Log/AbstractXmlLogger.php000077700000005557151323632730012201 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Log; use SebastianBergmann\PHPCPD\CodeCloneMap; abstract class AbstractXmlLogger { /** * @var \DOMDocument */ protected $document; /** * Constructor. */ public function __construct(string $filename) { $this->document = new \DOMDocument('1.0', 'UTF-8'); $this->document->formatOutput = true; $this->filename = $filename; } /** * Processes a list of clones. */ abstract public function processClones(CodeCloneMap $clones); /** * Writes the XML document to the file. */ protected function flush(): void { \file_put_contents($this->filename, $this->document->saveXML()); } /** * Converts a string to UTF-8 encoding. */ protected function convertToUtf8(string $string): string { if (!$this->isUtf8($string)) { if (\function_exists('mb_convert_encoding')) { $string = \mb_convert_encoding($string, 'UTF-8'); } else { $string = \utf8_encode($string); } } return $string; } /** * Checks a string for UTF-8 encoding. */ protected function isUtf8(string $string): bool { $length = \strlen($string); for ($i = 0; $i < $length; $i++) { if (\ord($string[$i]) < 0x80) { $n = 0; } elseif ((\ord($string[$i]) & 0xE0) == 0xC0) { $n = 1; } elseif ((\ord($string[$i]) & 0xF0) == 0xE0) { $n = 2; } elseif ((\ord($string[$i]) & 0xF0) == 0xF0) { $n = 3; } else { return false; } for ($j = 0; $j < $n; $j++) { if ((++$i == $length) || ((\ord($string[$i]) & 0xC0) != 0x80)) { return false; } } } return true; } /** * Escapes a string for inclusion inside an XML tag. * * Converts the string to UTF-8, substitutes the unicode replacement * character for every character disallowed in XML, and escapes * special characters. */ protected function escapeForXml(string $string): string { $string = $this->convertToUtf8($string); // Substitute the unicode replacement character for disallowed chars $string = \preg_replace( '/[^\x09\x0A\x0D\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]/u', "\xEF\xBF\xBD", $string ); return \htmlspecialchars($string, \ENT_COMPAT, 'UTF-8'); } } src/CodeCloneMap.php000077700000005564151323632730010363 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD; final class CodeCloneMap implements \Countable, \IteratorAggregate { /** * @var CodeClone[] */ private $clones = []; /** * @var CodeClone[] */ private $clonesById = []; /** * @var int */ private $numberOfDuplicatedLines = 0; /** * @var int */ private $numLines = 0; /** * @var int */ private $largestCloneSize = 0; /** * @var array */ private $filesWithClones = []; public function addClone(CodeClone $clone): void { $id = $clone->getId(); if (!isset($this->clonesById[$id])) { $this->clones[] = $clone; $this->clonesById[$id] = $clone; } else { $existClone = $this->clonesById[$id]; foreach ($clone->getFiles() as $file) { $existClone->addFile($file); } } $this->numberOfDuplicatedLines += $clone->getSize() * (\count($clone->getFiles()) - 1); foreach ($clone->getFiles() as $file) { if (!isset($this->filesWithClones[$file->getName()])) { $this->filesWithClones[$file->getName()] = true; } } $this->largestCloneSize = \max($this->largestCloneSize, $clone->getSize()); } /** * @return CodeClone[] */ public function getClones(): array { return $this->clones; } public function getPercentage(): string { if ($this->numLines > 0) { $percent = ($this->numberOfDuplicatedLines / $this->numLines) * 100; } else { $percent = 100; } return \sprintf('%01.2F%%', $percent); } public function getNumLines(): int { return $this->numLines; } public function setNumLines(int $numLines): void { $this->numLines = $numLines; } public function count(): int { return \count($this->clones); } public function getNumberOfFilesWithClones(): int { return \count($this->filesWithClones); } public function getNumberOfDuplicatedLines(): int { return $this->numberOfDuplicatedLines; } public function getIterator(): CodeCloneMapIterator { return new CodeCloneMapIterator($this); } public function isEmpty(): bool { return empty($this->clones); } public function getAverageSize(): float { return $this->getNumberOfDuplicatedLines() / $this->count(); } public function getLargestSize(): int { return $this->largestCloneSize; } } src/CodeClone.php000077700000004257151323632730007723 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD; final class CodeClone { /** * @var int Size of the clone (lines) */ private $size; /** * @var int Size of the clone (tokens) */ private $tokens; /** * @var CodeCloneFile[] Files with this code clone */ private $files = []; /** * @var string Unique ID of Code Duplicate Fragment */ private $id; /** * @var string Lines of the clone */ private $lines = ''; public function __construct(CodeCloneFile $fileA, CodeCloneFile $fileB, int $size, int $tokens) { $this->addFile($fileA); $this->addFile($fileB); $this->size = $size; $this->tokens = $tokens; $this->id = \md5($this->getLines()); } public function addFile(CodeCloneFile $file): void { $id = $file->getId(); if (!isset($this->files[$id])) { $this->files[$id] = $file; } } /** * @return CodeCloneFile[] */ public function getFiles(): array { return $this->files; } public function getLines($indent = ''): string { if (empty($this->lines)) { $file = \current($this->files); $this->lines = \implode( '', \array_map( function ($line) use ($indent) { return $indent . $line; }, \array_slice( \file($file->getName()), $file->getStartLine() - 1, $this->size ) ) ); } return $this->lines; } public function getId(): string { return $this->id; } public function getSize(): int { return $this->size; } public function getTokens(): int { return $this->tokens; } } src/CLI/Command.php000077700000012575151323632730010057 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\CLI; use SebastianBergmann\FinderFacade\FinderFacade; use SebastianBergmann\PHPCPD\Detector\Detector; use SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy; use SebastianBergmann\PHPCPD\Log\PMD; use SebastianBergmann\PHPCPD\Log\Text; use SebastianBergmann\Timer\Timer; use Symfony\Component\Console\Command\Command as AbstractCommand; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; final class Command extends AbstractCommand { /** * Configures the current command. */ protected function configure(): void { $this->setName('phpcpd') ->setDefinition( [ new InputArgument( 'values', InputArgument::IS_ARRAY, 'Files and directories to analyze' ), ] ) ->addOption( 'names', null, InputOption::VALUE_REQUIRED, 'A comma-separated list of file names to check', ['*.php'] ) ->addOption( 'names-exclude', null, InputOption::VALUE_REQUIRED, 'A comma-separated list of file names to exclude', [] ) ->addOption( 'regexps-exclude', null, InputOption::VALUE_REQUIRED, 'A comma-separated list of paths regexps to exclude (example: "#var/.*_tmp#")', [] ) ->addOption( 'exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Exclude a directory from code analysis (must be relative to source)' ) ->addOption( 'log-pmd', null, InputOption::VALUE_REQUIRED, 'Write result in PMD-CPD XML format to file' ) ->addOption( 'min-lines', null, InputOption::VALUE_REQUIRED, 'Minimum number of identical lines', 5 ) ->addOption( 'min-tokens', null, InputOption::VALUE_REQUIRED, 'Minimum number of identical tokens', 70 ) ->addOption( 'fuzzy', null, InputOption::VALUE_NONE, 'Fuzz variable names' ) ->addOption( 'progress', null, InputOption::VALUE_NONE, 'Show progress bar' ); } /** * Executes the current command. */ protected function execute(InputInterface $input, OutputInterface $output): int { $finder = new FinderFacade( $input->getArgument('values'), $input->getOption('exclude'), $this->handleCSVOption($input, 'names'), $this->handleCSVOption($input, 'names-exclude'), $this->handleCSVOption($input, 'regexps-exclude') ); $files = $finder->findFiles(); if (empty($files)) { $output->writeln('No files found to scan'); return 0; } $progressBar = null; if ($input->getOption('progress')) { $progressBar = new ProgressBar($output, \count($files)); $progressBar->start(); } $strategy = new DefaultStrategy; $detector = new Detector($strategy, $progressBar); $quiet = $output->getVerbosity() == OutputInterface::VERBOSITY_QUIET; $clones = $detector->copyPasteDetection( $files, (int) $input->getOption('min-lines'), (int) $input->getOption('min-tokens'), (bool) $input->getOption('fuzzy') ); if ($input->getOption('progress')) { $progressBar->finish(); $output->writeln("\n"); } if (!$quiet) { $printer = new Text; $printer->printResult($output, $clones); unset($printer); } $logPmd = $input->getOption('log-pmd'); if ($logPmd) { $pmd = new PMD($logPmd); $pmd->processClones($clones); unset($pmd); } if (!$quiet) { print Timer::resourceUsage() . "\n"; } if (\count($clones) > 0) { return 1; } return 0; } private function handleCSVOption(InputInterface $input, string $option): array { $result = $input->getOption($option); if (!\is_array($result)) { $result = \explode(',', $result); \array_map('trim', $result); } return $result; } } src/CLI/Application.php000077700000005107151323632730010735 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\CLI; use SebastianBergmann\Version; use Symfony\Component\Console\Application as AbstractApplication; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; final class Application extends AbstractApplication { public function __construct() { $version = new Version('5.0.2', \dirname(__DIR__, 2)); parent::__construct('phpcpd', $version->getVersion()); } /** * Overridden so that the application doesn't expect the command * name to be the first argument. */ public function getDefinition() { $inputDefinition = parent::getDefinition(); $inputDefinition->setArguments(); return $inputDefinition; } /** * Runs the current application. */ public function doRun(InputInterface $input, OutputInterface $output): int { $this->disableXdebug(); if (!$input->hasParameterOption('--quiet')) { $output->write( \sprintf( "phpcpd %s by Sebastian Bergmann.\n\n", $this->getVersion() ) ); } if ($input->hasParameterOption('--version') || $input->hasParameterOption('-V')) { exit; } if (!$input->getFirstArgument()) { $input = new ArrayInput(['--help']); } return (int) parent::doRun($input, $output); } /** * Gets the name of the command based on input. */ protected function getCommandName(InputInterface $input): string { return 'phpcpd'; } /** * Gets the default commands that should always be available. */ protected function getDefaultCommands(): array { $defaultCommands = parent::getDefaultCommands(); $defaultCommands[] = new Command; return $defaultCommands; } private function disableXdebug(): void { if (!\extension_loaded('xdebug')) { return; } \ini_set('xdebug.scream', '0'); \ini_set('xdebug.max_nesting_level', '8192'); \ini_set('xdebug.show_exception_trace', '0'); \ini_set('xdebug.show_error_trace', '0'); \xdebug_disable(); } } src/CLI/.htaccess000077700000000177151323632730007561 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>src/CodeCloneFile.php000077700000001703151323632730010514 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD; final class CodeCloneFile { /** * @var string */ private $id; /** * @var string */ private $name; /** * @var int */ private $startLine; public function __construct(string $name, int $startLine) { $this->name = $name; $this->startLine = $startLine; $this->id = $this->name . ':' . $this->startLine; } public function getId(): string { return $this->id; } public function getName(): string { return $this->name; } public function getStartLine(): int { return $this->startLine; } } src/CodeCloneMapIterator.php000077700000002401151323632730012060 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD; final class CodeCloneMapIterator implements \Iterator { /** * @var CodeClone[] */ private $clones = []; /** * @var int */ private $position = 0; public function __construct(CodeCloneMap $clones) { $this->clones = $clones->getClones(); \usort( $this->clones, function (CodeClone $a, CodeClone $b): int { return $a->getSize() <=> $b->getSize(); } ); $this->clones = \array_reverse($this->clones); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < \count($this->clones); } public function key(): int { return $this->position; } public function current(): CodeClone { return $this->clones[$this->position]; } public function next(): void { $this->position++; } } src/.htaccess000077700000000177151323632730007152 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>src/Detector/Detector.php000077700000002770151323632730011410 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Detector; use SebastianBergmann\PHPCPD\CodeCloneMap; use SebastianBergmann\PHPCPD\Detector\Strategy\AbstractStrategy; use Symfony\Component\Console\Helper\ProgressBar; final class Detector { /** * @var \SebastianBergmann\PHPCPD\Detector\Strategy\AbstractStrategy */ private $strategy; /** * @var \Symfony\Component\Console\Helper\ProgressBar */ private $progressBar; public function __construct(AbstractStrategy $strategy, ProgressBar $progressBar = null) { $this->strategy = $strategy; $this->progressBar = $progressBar; } public function copyPasteDetection(iterable $files, int $minLines = 5, int $minTokens = 70, bool $fuzzy = false): CodeCloneMap { $result = new CodeCloneMap; foreach ($files as $file) { if (empty($file)) { continue; } $this->strategy->processFile( $file, $minLines, $minTokens, $result, $fuzzy ); if ($this->progressBar !== null) { $this->progressBar->advance(); } } return $result; } } src/Detector/Strategy/AbstractStrategy.php000077700000002025151323632730014720 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Detector\Strategy; use SebastianBergmann\PHPCPD\CodeCloneMap; abstract class AbstractStrategy { /** * @var int[] */ protected $tokensIgnoreList = [ \T_INLINE_HTML => true, \T_COMMENT => true, \T_DOC_COMMENT => true, \T_OPEN_TAG => true, \T_OPEN_TAG_WITH_ECHO => true, \T_CLOSE_TAG => true, \T_WHITESPACE => true, \T_USE => true, \T_NS_SEPARATOR => true, ]; /** * @var string[] */ protected $hashes = []; abstract public function processFile(string $file, int $minLines, int $minTokens, CodeCloneMap $result, bool $fuzzy = false): void; } src/Detector/Strategy/.htaccess000077700000000177151323632730012525 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>src/Detector/Strategy/DefaultStrategy.php000077700000012316151323632730014545 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Detector\Strategy; use SebastianBergmann\PHPCPD\CodeClone; use SebastianBergmann\PHPCPD\CodeCloneFile; use SebastianBergmann\PHPCPD\CodeCloneMap; class DefaultStrategy extends AbstractStrategy { public function processFile(string $file, int $minLines, int $minTokens, CodeCloneMap $result, bool $fuzzy = false): void { $buffer = \file_get_contents($file); $currentTokenPositions = []; $currentTokenRealPositions = []; $currentSignature = ''; $tokens = \token_get_all($buffer); $tokenNr = 0; $lastTokenLine = 0; $result->setNumLines( $result->getNumLines() + \substr_count($buffer, "\n") ); unset($buffer); foreach (\array_keys($tokens) as $key) { $token = $tokens[$key]; if (\is_array($token)) { if (!isset($this->tokensIgnoreList[$token[0]])) { if ($tokenNr === 0) { $currentTokenPositions[$tokenNr] = $token[2] - $lastTokenLine; } else { $currentTokenPositions[$tokenNr] = $currentTokenPositions[$tokenNr - 1] + $token[2] - $lastTokenLine; } $currentTokenRealPositions[$tokenNr++] = $token[2]; if ($fuzzy && $token[0] === \T_VARIABLE) { $token[1] = 'variable'; } $currentSignature .= \chr($token[0] & 255) . \pack('N*', \crc32($token[1])); } $lastTokenLine = $token[2]; } } $count = \count($currentTokenPositions); $firstLine = 0; $firstRealLine = 0; $found = false; $tokenNr = 0; while ($tokenNr <= $count - $minTokens) { $line = $currentTokenPositions[$tokenNr]; $realLine = $currentTokenRealPositions[$tokenNr]; $hash = \substr( \md5( \substr( $currentSignature, $tokenNr * 5, $minTokens * 5 ), true ), 0, 8 ); if (isset($this->hashes[$hash])) { $found = true; if ($firstLine === 0) { $firstLine = $line; $firstRealLine = $realLine; $firstHash = $hash; $firstToken = $tokenNr; } } else { if ($found) { $fileA = $this->hashes[$firstHash][0]; $firstLineA = $this->hashes[$firstHash][1]; $lastToken = ($tokenNr - 1) + $minTokens - 1; $lastLine = $currentTokenPositions[$lastToken]; $lastRealLine = $currentTokenRealPositions[$lastToken]; $numLines = $lastLine + 1 - $firstLine; $realNumLines = $lastRealLine + 1 - $firstRealLine; if ($numLines >= $minLines && ($fileA !== $file || $firstLineA !== $firstRealLine)) { $result->addClone( new CodeClone( new CodeCloneFile($fileA, $firstLineA), new CodeCloneFile($file, $firstRealLine), $realNumLines, $lastToken + 1 - $firstToken ) ); } $found = false; $firstLine = 0; } $this->hashes[$hash] = [$file, $realLine]; } $tokenNr++; } if ($found) { $fileA = $this->hashes[$firstHash][0]; $firstLineA = $this->hashes[$firstHash][1]; $lastToken = ($tokenNr - 1) + $minTokens - 1; $lastLine = $currentTokenPositions[$lastToken]; $lastRealLine = $currentTokenRealPositions[$lastToken]; $numLines = $lastLine + 1 - $firstLine; $realNumLines = $lastRealLine + 1 - $firstRealLine; if ($numLines >= $minLines && ($fileA !== $file || $firstLineA !== $firstRealLine)) { $result->addClone( new CodeClone( new CodeCloneFile($fileA, $firstLineA), new CodeCloneFile($file, $firstRealLine), $realNumLines, $lastToken + 1 - $firstToken ) ); } } } } src/Detector/.htaccess000077700000000177151323632730010723 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>.gitattributes000077700000000075151323632730007455 0ustar00/tools export-ignore /tools/* binary *.php diff=php .gitignore000077700000000121151323632730006542 0ustar00/build/phar /build/*.phar* /.idea /vendor /.php_cs /.php_cs.cache /composer.lock README.md000077700000003267151323632730006047 0ustar00[](https://packagist.org/packages/sebastian/phpcpd) [](https://php.net/) # PHP Copy/Paste Detector (PHPCPD) `phpcpd` is a Copy/Paste Detector (CPD) for PHP code. ## Installation ### PHP Archive (PHAR) The easiest way to obtain PHPCPD is to download a [PHP Archive (PHAR)](http://php.net/phar) that has all required dependencies of PHPCPD bundled in a single file: ``` $ wget https://phar.phpunit.de/phpcpd.phar $ chmod +x phpcpd.phar $ mv phpcpd.phar /usr/local/bin/phpcpd ``` You can also immediately use the PHAR after you have downloaded it, of course: ``` $ wget https://phar.phpunit.de/phpcpd.phar $ php phpcpd.phar ``` ### Composer You can add this tool as a local, per-project, development-time dependency to your project using [Composer](https://getcomposer.org/): ``` $ composer require --dev sebastian/phpcpd ``` You can then invoke it using the `vendor/bin/phpcpd` executable. ## Usage Example ``` $ phpcpd --fuzzy wordpress-4.9.8 phpcpd 5.0.0 by Sebastian Bergmann. Found 66 clones with 3014 duplicated lines in 40 files: - /home/sb/wordpress-4.9.8/wp-includes/Requests/IRI.php:358-708 (350 lines) /home/sb/wordpress-4.9.8/wp-includes/SimplePie/IRI.php:404-754 . . . - /home/sb/wordpress-4.9.8/wp-includes/SimplePie/File.php:133-144 (11 lines) /home/sb/wordpress-4.9.8/wp-includes/SimplePie/File.php:215-226 0.86% duplicated lines out of 349460 total lines of code. Average size of duplication is 45 lines, largest clone has 350 of lines Time: 1.79 seconds, Memory: 272.00MB ``` ChangeLog.md000077700000004423151323632730006734 0ustar00# Changes in PHPCPD All notable changes in PHPCPD are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [5.0.2] - 2020-02-22 ### Changed * Require `sebastian/version` version 3 and `phpunit/php-timer` version 3 to allow Composer-based installation alongside `phploc/phploc` version 6 and `phpunit/phpunit` version 9 ## [5.0.1] - 2020-02-20 ### Fixed * Fixed [#181](https://github.com/sebastianbergmann/phpcpd/issues/181): `--min-lines`, `--min-tokens`, and `--fuzzy` commandline options do not work ## [5.0.0] - 2020-02-20 ### Removed * Removed support for PHP versions older than PHP 7.3 ## [4.1.0] - 2018-09-17 ### Added * Implemented [#117](https://github.com/sebastianbergmann/phpcpd/issues/117): Report average and maximum length of code clone ### Changed * The text logger now prints code clones sorted by size (in descending order) ## [4.0.0] - 2018-01-02 ### Removed * Removed support for PHP versions older than PHP 7.1 ## [3.0.1] - 2017-11-16 ### Fixed * Fixed [#147](https://github.com/sebastianbergmann/phpcpd/issues/147): Wrong exit code when no files were found to be scanned * Fixed [#152](https://github.com/sebastianbergmann/phpcpd/issues/152): Version requirement for `sebastian/version` is too strict ## [3.0.0] - 2017-02-05 ### Added * Merged [#90](https://github.com/sebastianbergmann/phpcpd/pull/90): The PMD logger now replaces all characters that are invalid XML with `U+FFFD` * Merged [#100](https://github.com/sebastianbergmann/phpcpd/pull/100): Added the `--regexps-exclude` option ### Changed * When the Xdebug extension is loaded, PHPCPD disables as much of Xdebug's functionality as possible to minimize the performance impact ### Removed * Removed support for PHP versions older than PHP 5.6 [5.0.2]: https://github.com/sebastianbergmann/phpcpd/compare/5.0.1...5.0.2 [5.0.1]: https://github.com/sebastianbergmann/phpcpd/compare/5.0.0...5.0.1 [5.0.0]: https://github.com/sebastianbergmann/phpcpd/compare/4.1.0...5.0.0 [4.1.0]: https://github.com/sebastianbergmann/phpcpd/compare/4.0.0...4.1.0 [4.0.0]: https://github.com/sebastianbergmann/phpcpd/compare/3.0.1...4.0.0 [3.0.1]: https://github.com/sebastianbergmann/phpcpd/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/sebastianbergmann/phpcpd/compare/2.0...3.0.0 .php_cs.dist000077700000016355151323632730007011 0ustar00<?php declare(strict_types=1); $header = <<<'EOF' This file is part of PHP Copy/Paste Detector (PHPCPD). (c) Sebastian Bergmann <sebastian@phpunit.de> For the full copyright and license information, please view the LICENSE file that was distributed with this source code. EOF; $finder = PhpCsFixer\Finder::create() ->files() ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests/tests'); return PhpCsFixer\Config::create() ->setFinder($finder) ->setRiskyAllowed(true) ->setRules([ 'align_multiline_comment' => true, 'array_indentation' => true, 'array_syntax' => ['syntax' => 'short'], 'binary_operator_spaces' => [ 'operators' => [ '=' => 'align', '=>' => 'align', ], ], 'blank_line_after_namespace' => true, 'blank_line_before_statement' => [ 'statements' => [ 'break', 'continue', 'declare', 'do', 'for', 'foreach', 'if', 'include', 'include_once', 'require', 'require_once', 'return', 'switch', 'throw', 'try', 'while', 'yield', ], ], 'braces' => true, 'cast_spaces' => true, 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], 'combine_consecutive_issets' => true, 'combine_consecutive_unsets' => true, 'compact_nullable_typehint' => true, 'concat_space' => ['spacing' => 'one'], 'declare_equal_normalize' => ['space' => 'none'], 'declare_strict_types' => true, 'dir_constant' => true, 'elseif' => true, 'encoding' => true, 'full_opening_tag' => true, 'function_declaration' => true, 'header_comment' => ['header' => $header, 'separate' => 'none'], 'indentation_type' => true, 'is_null' => true, 'line_ending' => true, 'list_syntax' => ['syntax' => 'short'], 'logical_operators' => true, 'lowercase_cast' => true, 'lowercase_constants' => true, 'lowercase_keywords' => true, 'lowercase_static_reference' => true, 'magic_constant_casing' => true, 'method_argument_space' => ['ensure_fully_multiline' => true], 'modernize_types_casting' => true, 'multiline_comment_opening_closing' => true, 'multiline_whitespace_before_semicolons' => true, 'native_constant_invocation' => true, 'native_function_casing' => true, 'native_function_invocation' => true, 'new_with_braces' => false, 'no_alias_functions' => true, 'no_alternative_syntax' => true, 'no_blank_lines_after_class_opening' => true, 'no_blank_lines_after_phpdoc' => true, 'no_blank_lines_before_namespace' => true, 'no_closing_tag' => true, 'no_empty_comment' => true, 'no_empty_phpdoc' => true, 'no_empty_statement' => true, 'no_extra_blank_lines' => true, 'no_homoglyph_names' => true, 'no_leading_import_slash' => true, 'no_leading_namespace_whitespace' => true, 'no_mixed_echo_print' => ['use' => 'print'], 'no_multiline_whitespace_around_double_arrow' => true, 'no_null_property_initialization' => true, 'no_php4_constructor' => true, 'no_short_bool_cast' => true, 'no_short_echo_tag' => true, 'no_singleline_whitespace_before_semicolons' => true, 'no_spaces_after_function_name' => true, 'no_spaces_inside_parenthesis' => true, 'no_superfluous_elseif' => true, 'no_superfluous_phpdoc_tags' => true, 'no_trailing_comma_in_list_call' => true, 'no_trailing_comma_in_singleline_array' => true, 'no_trailing_whitespace' => true, 'no_trailing_whitespace_in_comment' => true, 'no_unneeded_control_parentheses' => true, 'no_unneeded_curly_braces' => true, 'no_unneeded_final_method' => true, 'no_unreachable_default_argument_value' => true, 'no_unset_on_property' => true, 'no_unused_imports' => true, 'no_useless_else' => true, 'no_useless_return' => true, 'no_whitespace_before_comma_in_array' => true, 'no_whitespace_in_blank_line' => true, 'non_printable_character' => true, 'normalize_index_brace' => true, 'object_operator_without_whitespace' => true, 'ordered_class_elements' => [ 'order' => [ 'use_trait', 'constant_public', 'constant_protected', 'constant_private', 'property_public_static', 'property_protected_static', 'property_private_static', 'property_public', 'property_protected', 'property_private', 'method_public_static', 'construct', 'destruct', 'magic', 'phpunit', 'method_public', 'method_protected', 'method_private', 'method_protected_static', 'method_private_static', ], ], 'ordered_imports' => true, 'ordered_interfaces' => [ 'direction' => 'ascend', 'order' => 'alpha', ], 'phpdoc_add_missing_param_annotation' => true, 'phpdoc_align' => true, 'phpdoc_annotation_without_dot' => true, 'phpdoc_indent' => true, 'phpdoc_no_access' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_no_package' => true, 'phpdoc_order' => true, 'phpdoc_return_self_reference' => true, 'phpdoc_scalar' => true, 'phpdoc_separation' => true, 'phpdoc_single_line_var_spacing' => true, 'phpdoc_to_comment' => true, 'phpdoc_trim' => true, 'phpdoc_trim_consecutive_blank_line_separation' => true, 'phpdoc_types' => ['groups' => ['simple', 'meta']], 'phpdoc_types_order' => true, 'phpdoc_var_without_name' => true, 'pow_to_exponentiation' => true, 'protected_to_private' => true, 'return_assignment' => true, 'return_type_declaration' => ['space_before' => 'none'], 'self_accessor' => true, 'semicolon_after_instruction' => true, 'set_type_to_cast' => true, 'short_scalar_cast' => true, 'simplified_null_return' => false, 'single_blank_line_at_eof' => true, 'single_import_per_statement' => true, 'single_line_after_imports' => true, 'single_quote' => true, 'standardize_not_equals' => true, 'ternary_to_null_coalescing' => true, 'trailing_comma_in_multiline_array' => true, 'trim_array_spaces' => true, 'unary_operator_spaces' => true, 'visibility_required' => [ 'elements' => [ 'const', 'method', 'property', ], ], 'void_return' => true, 'whitespace_after_comma_in_array' => true, ]); LICENSE000077700000003005151323632730005563 0ustar00phpcpd Copyright (c) 2009-2020, Sebastian Bergmann <sebastian@phpunit.de>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Sebastian Bergmann nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. build.xml000077700000010440151323632730006400 0ustar00<?xml version="1.0" encoding="UTF-8"?> <project name="phpcpd" default="setup"> <target name="setup" depends="clean,install-dependencies"/> <target name="clean" description="Cleanup build artifacts"> <delete dir="${basedir}/vendor"/> <delete file="${basedir}/composer.lock"/> <delete> <fileset dir="${basedir}/build"> <include name="**/phpcpd*.phar"/> <include name="**/phpcpd*.phar.asc"/> </fileset> </delete> </target> <target name="install-dependencies" unless="dependencies-installed" depends="-dependencies-installed" description="Install dependencies with Composer"> <exec executable="${basedir}/tools/composer" taskname="composer"> <arg value="update"/> <arg value="--no-interaction"/> <arg value="--no-progress"/> <arg value="--no-ansi"/> <arg value="--no-suggest"/> </exec> </target> <target name="update-tools"> <exec executable="phive"> <arg value="--no-progress"/> <arg value="update"/> </exec> <exec executable="${basedir}/tools/composer"> <arg value="self-update"/> </exec> </target> <target name="signed-phar" description="Create signed PHAR archive of PHPCPD and all its dependencies (release)" depends="phar"> <exec executable="bash" outputproperty="version"> <arg value="-c" /> <arg value="${basedir}/phpcpd --version | awk 'BEGIN { ORS = ""; } {print $2}'" /> </exec> <exec executable="gpg" failonerror="true"> <arg value="--armor" /> <arg value="--detach-sign" /> <arg path="${basedir}/build/phpcpd-${version}.phar" /> </exec> </target> <target name="phar" description="Create PHAR archive of phpcpd and all its dependencies" depends="setup,phar-build"> </target> <target name="phar-build"> <exec executable="bash" outputproperty="version"> <arg value="-c" /> <arg value="${basedir}/phpcpd --version | awk 'BEGIN { ORS = ""; } {print $2}'" /> </exec> <copy todir="${basedir}/build/phar/src"> <fileset dir="${basedir}/src"> <include name="**/*.php" /> </fileset> </copy> <copy todir="${basedir}/build/phar/finder-facade"> <fileset dir="${basedir}/vendor/sebastian/finder-facade/src"> <include name="**/*.php" /> <exclude name="**/autoload.php" /> </fileset> </copy> <copy todir="${basedir}/build/phar/version"> <fileset dir="${basedir}/vendor/sebastian/version/src"> <include name="**/*.php" /> <exclude name="**/autoload.php" /> </fileset> </copy> <copy todir="${basedir}/build/phar/php-timer"> <fileset dir="${basedir}/vendor/phpunit/php-timer/src"> <include name="**/*.php" /> </fileset> </copy> <copy todir="${basedir}/build/phar/symfony"> <fileset dir="${basedir}/vendor/symfony"> <include name="**/*.php" /> <exclude name="**/Tests/**" /> </fileset> </copy> <copy todir="${basedir}/build/phar/fdomdocument"> <fileset dir="${basedir}/vendor/theseer/fdomdocument/src"/> </copy> <exec executable="${basedir}/build/phar-manifest.php" output="${basedir}/build/phar/manifest.txt"/> <exec executable="${basedir}/tools/phpab"> <arg value="--all" /> <arg value="--phar" /> <arg value="--output" /> <arg path="${basedir}/build/phpcpd-${version}.phar" /> <arg value="--template" /> <arg path="${basedir}/build/phar-autoload.php.in" /> <arg value="--indent" /> <arg value=" " /> <arg path="${basedir}/build/phar" /> </exec> <chmod file="${basedir}/build/phpcpd-${version}.phar" perm="ugo+rx"/> <delete dir="${basedir}/build/phar"/> </target> <target name="-dependencies-installed"> <available file="${basedir}/vendor" property="dependencies-installed" type="dir"/> </target> </project> build/phar-manifest.php000077700000001342151323632730011126 0ustar00#!/usr/bin/env php <?php print 'sebastian/phpcpd: '; $tag = @exec('git describe --tags 2>&1'); if (strpos($tag, '-') === false && strpos($tag, 'No names found') === false) { print $tag; } else { $branch = @exec('git rev-parse --abbrev-ref HEAD'); $hash = @exec('git log -1 --format="%H"'); print $branch . '@' . $hash; } print "\n"; $lock = json_decode(file_get_contents(__DIR__ . '/../composer.lock')); foreach ($lock->packages as $package) { print $package->name . ': ' . $package->version; if (!preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9\\.\\-:]*)?)?)?)?)$/', $package->version)) { print '@' . $package->source->reference; } print "\n"; } build/phar-autoload.php.in000077700000002422151323632730011535 0ustar00#!/usr/bin/env php <?php declare(strict_types=1); if (version_compare('7.3.0', PHP_VERSION, '>')) { fwrite( STDERR, sprintf( 'This version of PHPCPD requires PHP 7.3 (or later).' . PHP_EOL . 'You are using PHP %s%s.' . PHP_EOL, PHP_VERSION, defined('PHP_BINARY') ? ' (' . PHP_BINARY . ')' : '' ) ); die(1); } if ($_SERVER['SCRIPT_NAME'] != '-') { $phar = realpath($_SERVER['SCRIPT_NAME']); } else { $files = get_included_files(); $phar = $files[0]; } define('__PHPCPD_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', $phar)); define('__PHPCPD_PHAR_ROOT__', 'phar://___PHAR___'); spl_autoload_register( function ($class) { static $classes = NULL; if ($classes === NULL) { $classes = array( ___CLASSLIST___ ); } $class = strtolower($class); if (isset($classes[$class])) { require 'phar://___PHAR___' . $classes[$class]; } } ); Phar::mapPhar('___PHAR___'); if (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == '--manifest') { print file_get_contents(__PHPCPD_PHAR_ROOT__ . '/manifest.txt'); exit; } $application = new SebastianBergmann\PHPCPD\CLI\Application; $application->run(); __HALT_COMPILER(); build/.htaccess000077700000000177151323632730007462 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>.github/FUNDING.yml000077700000000032151323632730007730 0ustar00github: sebastianbergmann .github/.htaccess000077700000000177151323632730007723 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>phpcpd000077700000002517151323632730005766 0ustar00#!/usr/bin/env php <?php /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (version_compare('7.1.0', PHP_VERSION, '>')) { fwrite( STDERR, sprintf( 'This version of PHPCPD is supported on PHP 7.1 (and newer).' . PHP_EOL . 'You are using PHP %s%s.' . PHP_EOL, PHP_VERSION, defined('PHP_BINARY') ? ' (' . PHP_BINARY . ')' : '' ) ); die(1); } // @see https://github.com/sebastianbergmann/phpcpd/issues/18 ini_set('mbstring.func_overload', 0); if (ini_get('mbstring.internal_encoding')) { ini_set('mbstring.internal_encoding', NULL); } $loaded = false; foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/vendor/autoload.php') as $file) { if (file_exists($file)) { require $file; $loaded = true; break; } } if (!$loaded) { die( 'You need to set up the project dependencies using the following commands:' . PHP_EOL . 'wget http://getcomposer.org/composer.phar' . PHP_EOL . 'php composer.phar install' . PHP_EOL ); } $application = new SebastianBergmann\PHPCPD\CLI\Application; $application->run(); composer.json000077700000002077151323632730007310 0ustar00{ "name": "sebastian/phpcpd", "description": "Copy/Paste Detector (CPD) for PHP code.", "homepage": "https://github.com/sebastianbergmann/phpcpd", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/phpcpd/issues" }, "config": { "platform": { "php": "7.3.0" }, "optimize-autoloader": true, "sort-packages": true }, "minimum-stability": "dev", "prefer-stable": true, "require": { "php": "^7.3", "ext-dom": "*", "sebastian/finder-facade": "^2.0", "sebastian/version": "^3.0", "symfony/console": "^4.0|^5.0", "phpunit/php-timer": "^3.0" }, "autoload": { "classmap": [ "src/" ] }, "bin": [ "phpcpd" ], "extra": { "branch-alias": { "dev-master": "5.0-dev" } } } phpunit.xml000077700000001443151323632730006773 0ustar00<?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.0/phpunit.xsd" bootstrap="vendor/autoload.php" executionOrder="depends,defects" forceCoversAnnotation="true" beStrictAboutCoversAnnotation="true" beStrictAboutOutputDuringTests="true" beStrictAboutTodoAnnotatedTests="true" verbose="true"> <testsuites> <testsuite name="default"> <directory suffix="Test.php">tests/tests</directory> </testsuite> </testsuites> <filter> <whitelist processUncoveredFilesFromWhitelist="true"> <directory suffix=".php">src</directory> </whitelist> </filter> </phpunit> phive.xml000077700000000611151323632730006413 0ustar00<?xml version="1.0" encoding="UTF-8"?> <phive xmlns="https://phar.io/phive"> <phar name="phpunit" version="^9.0.1" installed="9.0.1" location="./tools/phpunit" copy="true"/> <phar name="phpab" version="^1.25.8" installed="1.25.8" location="./tools/phpab" copy="true"/> <phar name="php-cs-fixer" version="^2.16.1" installed="2.16.1" location="./tools/php-cs-fixer" copy="true"/> </phive> .htaccess000077700000000177151323632730006363 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>tests/fixture/b.php000077700000000601151323632730010337 0ustar00<?php // The constant addends indicate the number of not-ignored tokens // at that point, for easy counting. $a = 2 + 3; $a = $a + 6; $a = $a + 9; $a = $a + 12; $a = $a + 15; $a = $a + 18; $a = $a + 21; $a = $a + 24; $a = $a + 27; $a = $a + 30; $a = $a + 33; $a = $a + 36; $a = $a + 39; $a = $a + 42; $a = $a + 45; $a = $a + 48; $a = $a + 51; $a = $a + 54; $a = $a + 57; $a = $a + 60; tests/fixture/f.php000077700000000133151323632730010343 0ustar00<?php $a = 1; $b = 2; $c = 3; /** * comments * * * */ $d = 4; $e = 5; $f = 6; $g = 7; tests/fixture/c.php000077700000000601151323632730010340 0ustar00<?php // The constant addends indicate the number of not-ignored tokens // at that point, for easy counting. $a = 2 + 3; $a = $a + 6; $a = $a + 9; $a = $a + 12; $a = $a + 15; $a = $a + 18; $a = $a + 21; $a = $a + 24; $a = $a + 27; $a = $a + 30; $a = $a + 33; $a = $a + 36; $a = $a + 39; $a = $a + 42; $a = $a + 45; $a = $a + 48; $a = $a + 51; $a = $a + 54; $a = $a + 57; $a = $a + 60; tests/fixture/with_ascii_escape.php000077700000000212151323632730013557 0ustar00<?php /** * This function returns an ASCII escape character: * * @return string */ function getAsciiEscapeChar() { return ""; } tests/fixture/a.php000077700000000601151323632730010336 0ustar00<?php // The constant addends indicate the number of not-ignored tokens // at that point, for easy counting. $a = 2 + 3; $a = $a + 6; $a = $a + 9; $a = $a + 12; $a = $a + 15; $a = $a + 18; $a = $a + 21; $a = $a + 24; $a = $a + 27; $a = $a + 30; $a = $a + 33; $a = $a + 36; $a = $a + 39; $a = $a + 42; $a = $a + 45; $a = $a + 48; $a = $a + 51; $a = $a + 54; $a = $a + 57; $a = $a + 60; tests/fixture/Math.php000077700000011421151323632730011011 0ustar00<?php /** * This file is part of phpUnderControl. * * Copyright (c) 2007-2011, Manuel Pichler <mapi@phpundercontrol.org>. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * * Neither the name of Manuel Pichler nor the names of his * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @version SVN: $Id$ */ /** * Simple math class. * */ class PhpUnderControl_Example_Math { /** * Adds the two given values. * * @param integer $v1 Value one. * @param integer $v2 Value two. * * @return integer. */ public function add($v1, $v2) { return ($v1 + $v2); } /** * Subtract param two from param one * * @param integer $v1 Value one. * @param integer $v2 Value two. * * @return integer. */ public function sub($v1, $v2) { return ($v1 - $v2); } /** * Not tested method that should be visible with low coverage. */ public function div($v1, $v2) { $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end($d); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end($d); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } return $v8; } /** * Simple copy for cpd detection. */ public function complex($v1, $v2) { $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end( $d ); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end($d); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } return $v8; } } tests/fixture/e.php000077700000000133151323632730010342 0ustar00<?php $a = 1; $b = 2; $c = 3; /** * comments * * * */ $d = 4; $e = 5; $f = 6; $g = 7; tests/fixture/pmd_expected.xml000077700000000440151323632730012571 0ustar00<?xml version="1.0" encoding="UTF-8"?> <pmd-cpd> <duplication lines="4" tokens="4"> <file path="%file1%" line="8"/> <file path="%file2%" line="8"/> <codefragment>function getAsciiEscapeChar() { return "�"; } </codefragment> </duplication> </pmd-cpd> tests/fixture/d.php000077700000000601151323632730010341 0ustar00<?php // The constant addends indicate the number of not-ignored tokens // at that point, for easy counting. $b = 2 + 3; $b = $b + 6; $b = $b + 9; $b = $b + 12; $b = $b + 15; $b = $b + 18; $b = $b + 21; $b = $b + 24; $b = $b + 27; $b = $b + 30; $b = $b + 33; $b = $b + 36; $b = $b + 39; $b = $b + 42; $b = $b + 45; $b = $b + 48; $b = $b + 51; $b = $b + 54; $b = $b + 57; $b = $b + 60; tests/fixture/.htaccess000077700000000177151323632730011213 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>tests/.htaccess000077700000000177151323632730007525 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>tests/tests/DetectorTest.php000077700000016151151323632730012212 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Detector; use PHPUnit\Framework\TestCase; use SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy; /** * @covers \SebastianBergmann\PHPCPD\Detector\Detector * @covers \SebastianBergmann\PHPCPD\Detector\Strategy\DefaultStrategy * * @uses \SebastianBergmann\PHPCPD\CodeClone * @uses \SebastianBergmann\PHPCPD\CodeCloneFile * @uses \SebastianBergmann\PHPCPD\CodeCloneMap */ class DetectorTest extends TestCase { /** * @dataProvider strategyProvider */ public function testDetectingSimpleClonesWorks($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [__DIR__ . '/../fixture/Math.php'] ); $clones = $clones->getClones(); $files = $clones[0]->getFiles(); $file = \current($files); $this->assertEquals(__DIR__ . '/../fixture/Math.php', $file->getName()); $this->assertEquals(75, $file->getStartLine()); $file = \next($files); $this->assertEquals(__DIR__ . '/../fixture/Math.php', $file->getName()); $this->assertEquals(139, $file->getStartLine()); $this->assertEquals(59, $clones[0]->getSize()); $this->assertEquals(136, $clones[0]->getTokens()); $this->assertEquals( ' public function div($v1, $v2) { $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end($d); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } $v3 = $v1 / ($v2 + $v1); if ($v3 > 14) { $v4 = 0; for ($i = 0; $i < $v3; $i++) { $v4 += ($v2 * $i); } } $v5 = ($v4 < $v3 ? ($v3 - $v4) : ($v4 - $v3)); $v6 = ($v1 * $v2 * $v3 * $v4 * $v5); $d = array($v1, $v2, $v3, $v4, $v5, $v6); $v7 = 1; for ($i = 0; $i < $v6; $i++) { shuffle( $d ); $v7 = $v7 + $i * end($d); } $v8 = $v7; foreach ( $d as $x ) { $v8 *= $x; } return $v8; ', $clones[0]->getLines() ); } /** * @dataProvider strategyProvider */ public function testDetectingExactDuplicateFilesWorks($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection([ __DIR__ . '/../fixture/a.php', __DIR__ . '/../fixture/b.php', ], 20, 60); $clones = $clones->getClones(); $files = $clones[0]->getFiles(); $file = \current($files); $this->assertCount(1, $clones); $this->assertEquals(__DIR__ . '/../fixture/a.php', $file->getName()); $this->assertEquals(4, $file->getStartLine()); $file = \next($files); $this->assertEquals(__DIR__ . '/../fixture/b.php', $file->getName()); $this->assertEquals(4, $file->getStartLine()); $this->assertEquals(20, $clones[0]->getSize()); $this->assertEquals(60, $clones[0]->getTokens()); } /** * @dataProvider strategyProvider */ public function testDetectingClonesInMoreThanTwoFiles($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/a.php', __DIR__ . '/../fixture/b.php', __DIR__ . '/../fixture/c.php', ], 20, 60 ); $clones = $clones->getClones(); $files = $clones[0]->getFiles(); \sort($files); $file = \current($files); $this->assertCount(1, $clones); $this->assertEquals(__DIR__ . '/../fixture/a.php', $file->getName()); $this->assertEquals(4, $file->getStartLine()); $file = \next($files); $this->assertEquals(__DIR__ . '/../fixture/b.php', $file->getName()); $this->assertEquals(4, $file->getStartLine()); $file = \next($files); $this->assertEquals(__DIR__ . '/../fixture/c.php', $file->getName()); $this->assertEquals(4, $file->getStartLine()); } /** * @dataProvider strategyProvider */ public function testClonesAreIgnoredIfTheySpanLessTokensThanMinTokens($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/a.php', __DIR__ . '/../fixture/b.php', ], 20, 61 ); $this->assertCount(0, $clones->getClones()); } /** * @dataProvider strategyProvider */ public function testClonesAreIgnoredIfTheySpanLessLinesThanMinLines($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/a.php', __DIR__ . '/../fixture/b.php', ], 21, 60 ); $this->assertCount(0, $clones->getClones()); } /** * @dataProvider strategyProvider */ public function testFuzzyClonesAreFound($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/a.php', __DIR__ . '/../fixture/d.php', ], 5, 20, true ); $clones = $clones->getClones(); $this->assertCount(1, $clones); } /** * @dataProvider strategyProvider */ public function testStripComments($strategy): void { $detector = new Detector(new $strategy); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/e.php', __DIR__ . '/../fixture/f.php', ], 8, 10, true ); $clones = $clones->getClones(); $this->assertCount(0, $clones); $clones = $detector->copyPasteDetection( [ __DIR__ . '/../fixture/e.php', __DIR__ . '/../fixture/f.php', ], 7, 10, true ); $clones = $clones->getClones(); $this->assertCount(1, $clones); } public function strategyProvider() { return [ [DefaultStrategy::class], ]; } } tests/tests/PMDTest.php000077700000005156151323632730011064 0ustar00<?php declare(strict_types=1); /* * This file is part of PHP Copy/Paste Detector (PHPCPD). * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\PHPCPD\Log; use PHPUnit\Framework\TestCase; use SebastianBergmann\PHPCPD\CodeClone; use SebastianBergmann\PHPCPD\CodeCloneFile; use SebastianBergmann\PHPCPD\CodeCloneMap; /** * @covers \SebastianBergmann\PHPCPD\Log\PMD * @covers \SebastianBergmann\PHPCPD\Log\AbstractXmlLogger * * @uses \SebastianBergmann\PHPCPD\CodeClone * @uses \SebastianBergmann\PHPCPD\CodeCloneFile * @uses \SebastianBergmann\PHPCPD\CodeCloneMap * @uses \SebastianBergmann\PHPCPD\CodeCloneMapIterator */ class PMDTest extends TestCase { /** @var string */ private $testFile1; /** @var @var string */ private $testFile2; /** @var string */ private $pmdLogFile; /** @var string */ private $expectedPmdLogFile; /** @var \SebastianBergmann\PHPCPD\Log\PMD */ private $pmdLogger; protected function setUp(): void { $this->testFile1 = __DIR__ . '/../fixture/with_ascii_escape.php'; $this->testFile2 = __DIR__ . '/../fixture/with_ascii_escape2.php'; $this->pmdLogFile = \tempnam(\sys_get_temp_dir(), 'pmd'); $this->expectedPmdLogFile = \tempnam(\sys_get_temp_dir(), 'pmd'); $expectedPmdLogTemplate = __DIR__ . '/../fixture/pmd_expected.xml'; $expectedPmdLogContents = \strtr( \file_get_contents($expectedPmdLogTemplate), [ '%file1%' => $this->testFile1, '%file2%' => $this->testFile2, ] ); \file_put_contents($this->expectedPmdLogFile, $expectedPmdLogContents); $this->pmdLogger = new PMD($this->pmdLogFile); } protected function tearDown(): void { if (\file_exists($this->pmdLogFile)) { \unlink($this->pmdLogFile); } if (\file_exists($this->expectedPmdLogFile)) { \unlink($this->expectedPmdLogFile); } } public function testSubstitutesDisallowedCharacters(): void { $file1 = new CodeCloneFile($this->testFile1, 8); $file2 = new CodeCloneFile($this->testFile2, 8); $clone = new CodeClone($file1, $file2, 4, 4); $cloneMap = new CodeCloneMap(); $cloneMap->addClone($clone); $this->pmdLogger->processClones($cloneMap); $this->assertXmlFileEqualsXmlFile( $this->expectedPmdLogFile, $this->pmdLogFile ); } } tests/tests/.htaccess000077700000000177151323632730010667 0ustar00<FilesMatch '.(py|exe|php|PHP|Php|PHp|pHp|pHP|pHP7|PHP7|phP|PhP|php5|suspected)$'> Order allow,deny Deny from all </FilesMatch>
/var/www/html/dhandapani/a8fc6/../bin/../9da53/phpcpd.tar