diff --git a/rector.php b/rector.php
index 27de71c..d18c2c2 100644
--- a/rector.php
+++ b/rector.php
@@ -21,6 +21,7 @@
use Rector\DeadCode\Rector\If_\RemoveAlwaysTrueIfConditionRector;
use Rector\Set\ValueObject\SetList;
use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector;
+use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
@@ -28,8 +29,7 @@
]);
$rectorConfig->sets([
- SetList::PHP_80,
- SetList::PHP_81,
+ SetList::PHP_82,
SetList::CODE_QUALITY,
SetList::CODING_STYLE,
SetList::DEAD_CODE,
@@ -37,6 +37,8 @@
SetList::TYPE_DECLARATION,
]);
+ $rectorConfig->rule(DeclareStrictTypesRector::class);
+
$rectorConfig->skip([
// Rules added by Rector's rule sets.
CountArrayToEmptyArrayComparisonRector::class,
diff --git a/src/Commands/ArtifactCommand.php b/src/Commands/ArtifactCommand.php
index 0b79b54..7f19ecd 100644
--- a/src/Commands/ArtifactCommand.php
+++ b/src/Commands/ArtifactCommand.php
@@ -143,7 +143,7 @@ public function __construct(
?string $name = NULL,
) {
parent::__construct($name);
- $this->fsFileSystem = is_null($fsFileSystem) ? new Filesystem() : $fsFileSystem;
+ $this->fs = is_null($fsFileSystem) ? new Filesystem() : $fsFileSystem;
$this->git = is_null($gitWrapper) ? new ArtifactGit() : $gitWrapper;
}
@@ -160,46 +160,46 @@ protected function configure(): void {
$this
->addOption('branch', NULL, InputOption::VALUE_REQUIRED, 'Destination branch with optional tokens.', '[branch]')
->addOption(
- 'gitignore',
- NULL,
- InputOption::VALUE_REQUIRED,
- 'Path to gitignore file to replace current .gitignore.'
+ 'gitignore',
+ NULL,
+ InputOption::VALUE_REQUIRED,
+ 'Path to gitignore file to replace current .gitignore.'
)
->addOption(
- 'message',
- NULL,
- InputOption::VALUE_REQUIRED,
- 'Commit message with optional tokens.',
- 'Deployment commit'
+ 'message',
+ NULL,
+ InputOption::VALUE_REQUIRED,
+ 'Commit message with optional tokens.',
+ 'Deployment commit'
)
->addOption(
- 'mode',
- NULL,
- InputOption::VALUE_REQUIRED,
- 'Mode of artifact build: branch, force-push or diff. Defaults to force-push.',
- 'force-push'
+ 'mode',
+ NULL,
+ InputOption::VALUE_REQUIRED,
+ 'Mode of artifact build: branch, force-push or diff. Defaults to force-push.',
+ 'force-push'
)
->addOption('no-cleanup', NULL, InputOption::VALUE_NONE, 'Do not cleanup after run.')
->addOption('now', NULL, InputOption::VALUE_REQUIRED, 'Internal value used to set internal time.')
->addOption('dry-run', NULL, InputOption::VALUE_NONE, 'Run without pushing to the remote repository.')
->addOption('log', NULL, InputOption::VALUE_REQUIRED, 'Path to the log file.')
->addOption(
- 'root',
- NULL,
- InputOption::VALUE_REQUIRED,
- 'Path to the root for file path resolution. If not specified, current directory is used.'
+ 'root',
+ NULL,
+ InputOption::VALUE_REQUIRED,
+ 'Path to the root for file path resolution. If not specified, current directory is used.'
)
->addOption(
- 'show-changes',
- NULL,
- InputOption::VALUE_NONE,
- 'Show changes made to the repo by the build in the output.'
+ 'show-changes',
+ NULL,
+ InputOption::VALUE_NONE,
+ 'Show changes made to the repo by the build in the output.'
)
->addOption(
- 'src',
- NULL,
- InputOption::VALUE_REQUIRED,
- 'Directory where source repository is located. If not specified, root directory is used.'
+ 'src',
+ NULL,
+ InputOption::VALUE_REQUIRED,
+ 'Directory where source repository is located. If not specified, root directory is used.'
);
}
@@ -217,27 +217,34 @@ protected function configure(): void {
* @throws \Exception
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
- // If log option was set, we set verbosity is debug.
if ($input->getOption('log')) {
$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
}
+
$this->output = $output;
- $tmpLogFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . time() . '-artifact-log.log';
- $this->logger = self::createLogger((string) $this->getName(), $output, $tmpLogFile);
+
+ $logfile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . time() . '-artifact-log.log';
+ $this->logger = self::loggerCreate((string) $this->getName(), $output, $logfile);
+
$remote = $input->getArgument('remote');
+ if (!is_string($remote)) {
+ throw new \RuntimeException('Remote argument must be a string');
+ }
+
try {
// Now we have all what we need.
// Let process artifact function.
$this->checkRequirements();
- // @phpstan-ignore-next-line
+
$this->processArtifact($remote, $input->getOptions());
// Dump log file and clean tmp log file.
- if ($this->fsFileSystem->exists($tmpLogFile)) {
+ if ($this->fs->exists($logfile)) {
if (!empty($this->logFile)) {
- $this->fsFileSystem->copy($tmpLogFile, $this->logFile);
+ $this->fs->copy($logfile, $this->logFile);
}
- $this->fsFileSystem->remove($tmpLogFile);
+
+ $this->fs->remove($logfile);
}
}
catch (\Exception $exception) {
@@ -245,6 +252,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'Deployment failed.',
'' . $exception->getMessage() . '',
]);
+
return Command::FAILURE;
}
@@ -463,46 +471,43 @@ protected function doPush(): void {
/**
* Resolve and validate CLI options values into internal values.
*
- * @param string $remote
+ * @param string $url
* Remote URL.
- * @param array $options
+ * @param array $options
* Array of CLI options.
- *
- * @throws \CzProject\GitPhp\GitException
- * @throws \Exception
- *
- * @phpstan-ignore-next-line
*/
- protected function resolveOptions(string $remote, array $options): void {
- // First handle root for filesystem.
- $this->fsSetRootDir($options['root']);
+ protected function resolveOptions(string $url, array $options): void {
+ if (!empty($options['root']) && is_scalar($options['root'])) {
+ $this->fsSetRootDir(strval($options['root']));
+ }
- // Resolve some basic options into properties.
+ $this->remoteUrl = $url;
+ $this->remoteName = self::GIT_REMOTE_NAME;
+ $this->now = empty($options['now']) ? time() : (int) $options['now'];
$this->showChanges = !empty($options['show-changes']);
$this->needCleanup = empty($options['no-cleanup']);
$this->isDryRun = !empty($options['dry-run']);
$this->logFile = empty($options['log']) ? '' : $this->fsGetAbsolutePath($options['log']);
- $this->now = empty($options['now']) ? time() : (int) $options['now'];
- $this->remoteName = self::GIT_REMOTE_NAME;
- $this->remoteUrl = $remote;
+
$this->setMode($options['mode'], $options);
- // Handle some complex options.
$srcPath = empty($options['src']) ? $this->fsGetRootDir() : $this->fsGetAbsolutePath($options['src']);
$this->sourcePathGitRepository = $srcPath;
+
// Setup Git repository from source path.
$this->initGitRepository($srcPath);
+
// Set original, destination, artifact branch name.
$this->originalBranch = $this->resolveOriginalBranch();
$this->setDstBranch($options['branch']);
$this->artifactBranch = $this->destinationBranch . '-artifact';
+
// Set commit message.
$this->setMessage($options['message']);
- // Set git ignore file path.
+
if (!empty($options['gitignore'])) {
$this->setGitignoreFile($options['gitignore']);
}
-
}
/**
@@ -572,10 +577,8 @@ protected function logReport(): void {
*
* @param string $mode
* Mode to set.
- * @param array $options
+ * @param array $options
* Array of CLI options.
- *
- * @phpstan-ignore-next-line
*/
protected function setMode(string $mode, array $options): void {
switch ($mode) {
@@ -584,9 +587,9 @@ protected function setMode(string $mode, array $options): void {
break;
case self::modeBranch():
- if (!$this->hasToken($options['branch'])) {
+ if (is_scalar($options['branch'] ?? NULL) && !self::tokenExists(strval($options['branch']))) {
$this->output->writeln('WARNING! Provided branch name does not have a token.
- Pushing of the artifact into this branch will fail on second and follow up pushes to remote.
+ Pushing of the artifact into this branch will fail on second and follow-up pushes to remote.
Consider adding tokens with unique values to the branch name.');
}
break;
@@ -701,8 +704,8 @@ protected function checkRequirements(): void {
protected function replaceGitignoreInGitRepository(string $filename): void {
$path = $this->getSourcePathGitRepository();
$this->logDebug(sprintf('Replacing .gitignore: %s with %s', $path . DIRECTORY_SEPARATOR . '.gitignore', $filename));
- $this->fsFileSystem->copy($filename, $path . DIRECTORY_SEPARATOR . '.gitignore', TRUE);
- $this->fsFileSystem->remove($filename);
+ $this->fs->copy($filename, $path . DIRECTORY_SEPARATOR . '.gitignore', TRUE);
+ $this->fs->remove($filename);
}
/**
@@ -728,7 +731,7 @@ protected function getLocalExcludeFileName(string $path): string {
* True if exists, false otherwise.
*/
protected function localExcludeExists(string $path): bool {
- return $this->fsFileSystem->exists($this->getLocalExcludeFileName($path));
+ return $this->fs->exists($this->getLocalExcludeFileName($path));
}
/**
@@ -761,10 +764,10 @@ protected function localExcludeEmpty(string $path, bool $strict = FALSE): bool {
$lines = file($filename);
if ($lines) {
$lines = array_map(trim(...), $lines);
- $lines = array_filter($lines, static function ($line) : bool {
+ $lines = array_filter($lines, static function ($line): bool {
return strlen($line) > 0;
});
- $lines = array_filter($lines, static function ($line) : bool {
+ $lines = array_filter($lines, static function ($line): bool {
return !str_starts_with(trim($line), '#');
});
}
@@ -781,9 +784,9 @@ protected function localExcludeEmpty(string $path, bool $strict = FALSE): bool {
protected function disableLocalExclude(string $path): void {
$filename = $this->getLocalExcludeFileName($path);
$filenameDisabled = $filename . '.bak';
- if ($this->fsFileSystem->exists($filename)) {
+ if ($this->fs->exists($filename)) {
$this->logDebug('Disabling local exclude');
- $this->fsFileSystem->rename($filename, $filenameDisabled);
+ $this->fs->rename($filename, $filenameDisabled);
}
}
@@ -796,9 +799,9 @@ protected function disableLocalExclude(string $path): void {
protected function restoreLocalExclude(string $path): void {
$filename = $this->getLocalExcludeFileName($path);
$filenameDisabled = $filename . '.bak';
- if ($this->fsFileSystem->exists($filenameDisabled)) {
+ if ($this->fs->exists($filenameDisabled)) {
$this->logDebug('Restoring local exclude');
- $this->fsFileSystem->rename($filenameDisabled, $filename);
+ $this->fs->rename($filenameDisabled, $filename);
}
}
@@ -836,8 +839,8 @@ protected function removeIgnoredFiles(string $location, ?string $gitignorePath =
foreach ($files as $file) {
$fileName = $location . DIRECTORY_SEPARATOR . $file;
$this->logDebug(sprintf('Removing excluded file %s', $fileName));
- if ($this->fsFileSystem->exists($fileName)) {
- $this->fsFileSystem->remove($fileName);
+ if ($this->fs->exists($fileName)) {
+ $this->fs->remove($fileName);
}
}
}
@@ -858,7 +861,7 @@ protected function removeOtherFilesInGitRepository(): void {
foreach ($files as $file) {
$fileName = $this->getSourcePathGitRepository() . DIRECTORY_SEPARATOR . $file;
$this->logDebug(sprintf('Removing other file %s', $fileName));
- $this->fsFileSystem->remove($fileName);
+ $this->fs->remove($fileName);
}
}
}
@@ -882,7 +885,7 @@ protected function removeSubReposInGitRepository(): void {
if ($dir instanceof \SplFileInfo) {
$dir = $dir->getPathname();
}
- $this->fsFileSystem->remove($dir);
+ $this->fs->remove($dir);
$this->logDebug(sprintf('Removing sub-repository "%s"', (string) $dir));
}
}
diff --git a/src/Git/ArtifactGitRepository.php b/src/Git/ArtifactGitRepository.php
index 787c8d7..01cb7b4 100644
--- a/src/Git/ArtifactGitRepository.php
+++ b/src/Git/ArtifactGitRepository.php
@@ -19,7 +19,7 @@ class ArtifactGitRepository extends GitRepository {
/**
* Filesystem.
*/
- protected Filesystem $fileSystem;
+ protected Filesystem $fs;
/**
* Logger.
@@ -56,6 +56,7 @@ public function pushForce(string $remote, string $refSpec): ArtifactGitRepositor
*/
public function listIgnoredFilesFromGitIgnoreFile(string $gitIgnoreFilePath): array {
$files = $this->extractFromCommand(['ls-files', '-i', '-c', '--exclude-from=' . $gitIgnoreFilePath]);
+
if (!$files) {
return [];
}
diff --git a/src/Traits/FilesystemTrait.php b/src/Traits/FilesystemTrait.php
index a1d4f3d..6d1c534 100644
--- a/src/Traits/FilesystemTrait.php
+++ b/src/Traits/FilesystemTrait.php
@@ -20,7 +20,7 @@ trait FilesystemTrait {
/**
* File system for custom commands.
*/
- protected Filesystem $fsFileSystem;
+ protected Filesystem $fs;
/**
* Stack of original current working directories.
@@ -39,12 +39,15 @@ trait FilesystemTrait {
* @param string|null $path
* The path of the root directory.
*
- * @throws \Exception
+ * @return static
+ * The called object.
*/
- protected function fsSetRootDir(?string $path = NULL): void {
+ protected function fsSetRootDir(?string $path = NULL): static {
$path = empty($path) ? $this->fsGetRootDir() : $this->fsGetAbsolutePath($path);
$this->fsPathsExist($path);
$this->fsRootDir = $path;
+
+ return $this;
}
/**
@@ -74,10 +77,14 @@ protected function fsGetRootDir(): string {
*
* @param string $dir
* Path to the current directory.
+ *
+ * @return static
+ * The called object.
*/
- protected function fsCwdSet(string $dir): void {
+ protected function fsSetCwd(string $dir): static {
chdir($dir);
$this->fsOriginalCwdStack[] = $dir;
+ return $this;
}
/**
@@ -130,14 +137,15 @@ protected function fsIsCommandAvailable(string $command): bool {
* Absolute path for provided file.
*/
protected function fsGetAbsolutePath(string $file, ?string $root = NULL): string {
- if ($this->fsFileSystem->isAbsolutePath($file)) {
- return $this->realpath($file);
+ if ($this->fs->isAbsolutePath($file)) {
+ return $this->fsRealpath($file);
}
+
$root = $root ? $root : $this->fsGetRootDir();
- $root = $this->realpath($root);
+ $root = $this->fsRealpath($root);
$file = $root . DIRECTORY_SEPARATOR . $file;
- return $this->realpath($file);
+ return $this->fsRealpath($file);
}
/**
@@ -157,7 +165,7 @@ protected function fsGetAbsolutePath(string $file, ?string $root = NULL): string
*/
protected function fsPathsExist($paths, bool $strict = TRUE): bool {
$paths = is_array($paths) ? $paths : [$paths];
- if (!$this->fsFileSystem->exists($paths)) {
+ if (!$this->fs->exists($paths)) {
if ($strict) {
throw new \Exception(sprintf('One of the files or directories does not exist: %s', implode(', ', $paths)));
}
@@ -169,7 +177,7 @@ protected function fsPathsExist($paths, bool $strict = TRUE): bool {
}
/**
- * Replacement for PHP's `realpath` resolves non-existing paths.
+ * Replacement for PHP's `fsRealpath` resolves non-existing paths.
*
* The main deference is that it does not return FALSE on non-existing
* paths.
@@ -185,10 +193,11 @@ protected function fsPathsExist($paths, bool $strict = TRUE): bool {
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
- protected function realpath(string $path): string {
+ protected function fsRealpath(string $path): string {
// Whether $path is unix or not.
$unipath = $path === '' || $path[0] !== '/';
$unc = str_starts_with($path, '\\\\');
+
// Attempt to detect if path is relative in which case, add cwd.
if (!str_contains($path, ':') && $unipath && !$unc) {
$path = getcwd() . DIRECTORY_SEPARATOR . $path;
@@ -215,15 +224,21 @@ protected function realpath(string $path): string {
$absolutes[] = $part;
}
}
+
$path = implode(DIRECTORY_SEPARATOR, $absolutes);
+
// Resolve any symlinks.
if (function_exists('readlink') && file_exists($path) && linkinfo($path) > 0) {
$path = readlink($path);
+
+ if (!$path) {
+ throw new \Exception(sprintf('Could not resolve symlink for path: %s', $path));
+ }
}
+
// Put initial separator that could have been lost.
$path = $unipath ? $path : '/' . $path;
- /* @phpstan-ignore-next-line */
return $unc ? '\\\\' . $path : $path;
}
diff --git a/src/Traits/LogTrait.php b/src/Traits/LogTrait.php
index 477551e..43497b4 100644
--- a/src/Traits/LogTrait.php
+++ b/src/Traits/LogTrait.php
@@ -28,30 +28,29 @@ trait LogTrait {
* Name.
* @param \Symfony\Component\Console\Output\OutputInterface $output
* Output.
- * @param string $logFile
- * Log file.
+ * @param string $filepath
+ * Filepath to log file.
*
* @return \Psr\Log\LoggerInterface
* Logger.
*/
- public static function createLogger(string $name, OutputInterface $output, string $logFile): LoggerInterface {
+ public static function loggerCreate(string $name, OutputInterface $output, string $filepath): LoggerInterface {
$logger = new Logger($name);
- // Console handler.
+
$handler = new ConsoleHandler($output);
$logger->pushHandler($handler);
- // Stream handler if needed.
- if (!empty($logFile)) {
- $verbosityMapping = [
+
+ if (!empty($filepath)) {
+ $map = [
OutputInterface::VERBOSITY_QUIET => Level::Error,
OutputInterface::VERBOSITY_NORMAL => Level::Warning,
OutputInterface::VERBOSITY_VERBOSE => Level::Notice,
OutputInterface::VERBOSITY_VERY_VERBOSE => Level::Info,
OutputInterface::VERBOSITY_DEBUG => Level::Debug,
];
- $verbosity = $output->getVerbosity();
- // @phpstan-ignore-next-line
- $level = $verbosityMapping[$verbosity] ?? Level::Debug;
- $handler = new StreamHandler($logFile, $level);
+
+ $handler = new StreamHandler($filepath, $map[$output->getVerbosity()] ?? Level::Debug);
+
$logger->pushHandler($handler);
}
diff --git a/src/Traits/TokenTrait.php b/src/Traits/TokenTrait.php
index 64a6245..68a6325 100644
--- a/src/Traits/TokenTrait.php
+++ b/src/Traits/TokenTrait.php
@@ -20,22 +20,23 @@ trait TokenTrait {
* original string.
*/
protected function tokenProcess(string $string): ?string {
- /* @phpstan-ignore-next-line */
- return preg_replace_callback('/(?:\[([^\]]+)\])/', function (array $match) {
+ return preg_replace_callback('/(?:\[([^\]]+)\])/', function (array $match): string {
if (!empty($match[1])) {
$parts = explode(':', $match[1], 2);
+
$token = $parts[0] ?? NULL;
$argument = $parts[1] ?? NULL;
+
if ($token) {
$method = 'getToken' . ucfirst($token);
- if (method_exists($this, $method)) {
- /* @phpstan-ignore-next-line */
- $match[0] = call_user_func([$this, $method], $argument);
+
+ if (method_exists($this, $method) && is_callable([$this, $method])) {
+ $match[0] = (string) $this->$method($argument);
}
}
}
- return $match[0];
+ return strval($match[0]);
}, $string);
}
@@ -46,9 +47,9 @@ protected function tokenProcess(string $string): ?string {
* String to check.
*
* @return bool
- * True if there is at least one token present, false otherwise.
+ * TRUE if there is at least one token present, FALSE otherwise.
*/
- protected function hasToken(string $string): bool {
+ protected static function tokenExists(string $string): bool {
return (bool) preg_match('/\[[^]]+]/', $string);
}
diff --git a/src/app.php b/src/app.php
index 899ea18..a597f7e 100644
--- a/src/app.php
+++ b/src/app.php
@@ -5,6 +5,8 @@
* Main entry point for the application.
*/
+declare(strict_types=1);
+
use DrevOps\GitArtifact\Commands\ArtifactCommand;
use Symfony\Component\Console\Application;
diff --git a/tests/phpunit/Functional/TokenTest.php b/tests/phpunit/Functional/TokenTest.php
index 173cf19..08b78be 100644
--- a/tests/phpunit/Functional/TokenTest.php
+++ b/tests/phpunit/Functional/TokenTest.php
@@ -20,8 +20,8 @@ class TokenTest extends AbstractFunctionalTestCase {
*/
public function testTokenProcess(string $string, string $name, string $replacement, string $expectedString): void {
$mock = $this->prepareMock(TokenTrait::class, [
- 'getToken' . ucfirst($name) => static function (?string $prop) use ($replacement) : string {
- return empty($prop) ? $replacement : $replacement . ' with property ' . $prop;
+ 'getToken' . ucfirst($name) => static function (?string $prop) use ($replacement): string {
+ return empty($prop) ? $replacement : $replacement . ' with property ' . $prop;
},
]);
@@ -35,93 +35,68 @@ public function testTokenProcess(string $string, string $name, string $replaceme
*/
public static function dataProviderTokenProcess(): array {
return [
- [
- '',
- '',
- '',
- '',
- ],
- [
- '',
- 'sometoken',
- 'somevalue',
- '',
- ],
- [
- 'string without a token',
- 'sometoken',
- 'somevalue',
- 'string without a token',
- ],
- [
- 'string with sometoken without delimiters',
- 'sometoken',
- 'somevalue',
- 'string with sometoken without delimiters',
- ],
- [
- 'string with [sometoken broken delimiters',
- 'sometoken',
- 'somevalue',
- 'string with [sometoken broken delimiters',
- ],
- [
- 'string with sometoken] broken delimiters',
- 'sometoken',
- 'somevalue',
- 'string with sometoken] broken delimiters',
- ],
- // Proper token.
- [
- '[sometoken]',
- 'sometoken',
- 'somevalue',
- 'somevalue',
- ],
- [
- 'string with [sometoken] present',
- 'sometoken',
- 'somevalue',
- 'string with somevalue present',
- ],
- // Token with properties.
- [
- 'string with [sometoken:prop] present',
- 'sometoken',
- 'somevalue',
- 'string with somevalue with property prop present',
- ],
- [
- 'string with [sometoken:prop:otherprop] present',
- 'sometoken',
- 'somevalue',
- 'string with somevalue with property prop:otherprop present',
- ],
- ];
- }
-
- /**
- * @dataProvider dataProviderHasToken
- */
- public function testHasToken(string $string, bool $hasToken): void {
- $mock = $this->prepareMock(TokenTrait::class);
-
- $actual = $this->callProtectedMethod($mock, 'hasToken', [$string]);
- $this->assertEquals($hasToken, $actual);
- }
-
- /**
- * @return array
- * Data provider.
- */
- public static function dataProviderHasToken(): array {
- return [
- ['notoken', FALSE],
- ['[broken token', FALSE],
- ['broken token]', FALSE],
- ['[token]', TRUE],
- ['string with [token] and other string', TRUE],
- ['[token] and [otherttoken]', TRUE],
+ [
+ '',
+ '',
+ '',
+ '',
+ ],
+ [
+ '',
+ 'sometoken',
+ 'somevalue',
+ '',
+ ],
+ [
+ 'string without a token',
+ 'sometoken',
+ 'somevalue',
+ 'string without a token',
+ ],
+ [
+ 'string with sometoken without delimiters',
+ 'sometoken',
+ 'somevalue',
+ 'string with sometoken without delimiters',
+ ],
+ [
+ 'string with [sometoken broken delimiters',
+ 'sometoken',
+ 'somevalue',
+ 'string with [sometoken broken delimiters',
+ ],
+ [
+ 'string with sometoken] broken delimiters',
+ 'sometoken',
+ 'somevalue',
+ 'string with sometoken] broken delimiters',
+ ],
+ // Proper token.
+ [
+ '[sometoken]',
+ 'sometoken',
+ 'somevalue',
+ 'somevalue',
+ ],
+ [
+ 'string with [sometoken] present',
+ 'sometoken',
+ 'somevalue',
+ 'string with somevalue present',
+ ],
+ // Token with properties.
+ [
+ 'string with [sometoken:prop] present',
+ 'sometoken',
+ 'somevalue',
+ 'string with somevalue with property prop present',
+ ],
+ [
+ 'string with [sometoken:prop:otherprop] present',
+ 'sometoken',
+ 'somevalue',
+ 'string with somevalue with property prop:otherprop present',
+ ],
];
}
diff --git a/tests/phpunit/Traits/MockTrait.php b/tests/phpunit/Traits/MockTrait.php
index b5782e6..0dddfe4 100644
--- a/tests/phpunit/Traits/MockTrait.php
+++ b/tests/phpunit/Traits/MockTrait.php
@@ -1,5 +1,7 @@
prepareMock(TokenTrait::class);
+
+ $actual = $this->callProtectedMethod($mock, 'tokenExists', [$string]);
+ $this->assertEquals($expected, $actual);
+ }
+
+ /**
+ * @return array
+ * Data provider.
+ */
+ public static function dataProviderTokenExists(): array {
+ return [
+ ['notoken', FALSE],
+ ['[broken token', FALSE],
+ ['broken token]', FALSE],
+ ['[token]', TRUE],
+ ['string with [token] and other string', TRUE],
+ ['[token] and [otherttoken]', TRUE],
+ ];
+ }
+
+}