Skip to content

Conversation

@h-marumoto
Copy link
Contributor

@h-marumoto h-marumoto commented Jan 7, 2026

This PR fixes #1144

This issue likely refers to errors generated by static analysis.
I have addressed those issues.

Issue 1:

line 1347 : if (!$_compile->isDot()) {
Undefined method 'isDot'.

Investigation

While investigating this warning, I discovered that:

  1. isDot() is not available on the loop variable
    RecursiveIteratorIterator returns SplFileInfo objects in foreach loops
    SplFileInfo does not have an isDot() method
    isDot() only exists on DirectoryIterator and RecursiveDirectoryIterator classes
  2. The isDot() check was unnecessary
    All entries starting with . are already filtered out earlier:
    Since isDot() only matches . and .. (both start with .), they are already excluded
    The isDot() check is unreachable code
if (substr(basename($_file->getPathname()), 0, 1) === '.') {
    continue;
}

Fix

Removed the unnecessary isDot() checks from:

  • src/Smarty.php (line 1347)
  • src/Cacheresource/File.php (line 224)
  • tests/PHPUnit_Smarty.php (line 294)

Impact

No functional changes.
The removed checks were redundant and never executed.

Issue 2:

line 1389 : apc_delete_file($_filepath);
Undefined function 'Smarty\apc_delete_file'.

The old APC (Alternative PHP Cache) extension was deprecated in PHP 5.5 and is not available in PHP 7.0+.
Since Smarty now requires PHP 7.2+ (as defined in composer.json), all APC-related code has become dead code that will never execute.

Fix:

  • Removed dead code in Smarty.php and src/Cacheresource/File.php
  • Removed APC cache resource implementation and tests:
    • tests/UnitTests/__shared/cacheresources/cacheresource.apc.php
    • tests/UnitTests/CacheResourceTests/_shared/PHPunitplugins/cacheresource.apctest.php
    • tests/UnitTests/CacheResourceTests/Apc/CacheResourceCustomApcTest.php

Impact:

No functional impact.
The removed code was never executed on supported PHP versions (7.2+).

I would appreciate it if you could review this.
Thank you!

@h-marumoto h-marumoto closed this Jan 7, 2026
@h-marumoto h-marumoto reopened this Jan 7, 2026
@wisskid
Copy link
Member

wisskid commented Jan 7, 2026

good finds! And if the isDot method isn't available, wouldn't the entire isDir if-branch surrounding it be useless as well?

@h-marumoto
Copy link
Contributor Author

Thanks for the comment!
However, I think the isDir() check is still necessary.

The issue was only with the isDot() check, which was redundant (. and .. are already filtered out by the preceding check, e.g.)
The isDot() check was likely included to exclude . and .. from deletion, but they are already excluded by the preceding checks.
The isDir() check itself is still needed to distinguish between directories and files for proper handling (e.g., rmdir vs file deletion logic).

If my understanding is incorrect, please let me know!
Thank you!

@wisskid
Copy link
Member

wisskid commented Jan 7, 2026

Consider the following code segment:

		$_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
		foreach ($_compile as $_file) {
			if (substr(basename($_file->getPathname()), 0, 1) === '.') {
				continue;
			}
			$_filepath = (string)$_file;
			if ($_file->isDir()) {
				if (!$_compile->isDot()) {
					// delete folder if empty
					@rmdir($_file->getPathname());
				}
			} else {
				// delete only php files

Since isDot does not exists as a method on RecursiveIteratorIterator, the line if (!$_compile->isDot()) { cannot have been interpreted, thus if ($_file->isDir()) { probably always returns false.

Moreover, it has done sone for over 10 years, because these lines are in the codebase since (at least) 2015.

@h-marumoto
Copy link
Contributor Author

I apologize my understanding was incorrect.

However, I believe the current fix is likely the correct approach for the following reasons:
As pointed out in the issue, the error

line 1347 : if (!$_compile->isDot()) {
Undefined method 'isDot'.

was appearing in static analysis tools like VSCode, but the code actually runs without issues in practice.

I initially thought $_compile referred to a SplFileInfo object within the loop, but it actually refers to a RecursiveIteratorIterator object, which in this context represents the RecursiveDirectoryIterator object being processed.
However, static analysis tools cannot understand this, which is why they flagged it as a non-existent method.
This means that while the following approach might have been sufficient to simply fix the static analysis error, it turns out that the isDot() check was redundant to begin with:

		$_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
		foreach ($_compile as $_file) {
			if (substr(basename($_file->getPathname()), 0, 1) === '.') {
				continue;
			}
			$_filepath = (string)$_file;
			if ($_file->isDir()) {
				/** @var RecursiveDirectoryIterator $dirIterator */
				$dir = $_compile->getSubIterator();
				if (!$dir->isDot()) {
					// delete folder if empty
					@rmdir($_file->getPathname());
				}
			} else {
				// delete only php files

I would prefer to keep the isDir() conditional branch, as removing it could result in unnecessary directories remaining in the target deletion directory.

@wisskid
Copy link
Member

wisskid commented Jan 8, 2026

I just tested what you wrote ("the code actually runs without issues in practice") and wow, you are right. So RecursiveIteratorIterator passes any undefined method call on to the wrapped object? That means your changes are indeed correct. I will merge them!

@wisskid wisskid merged commit 6709d00 into smarty-php:master Jan 8, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Errors in Smarty.php version 5.5

2 participants