Skip to content

file_exists() returns false for symlinks with missing targets #346

@dshoreman

Description

@dshoreman

Background

If a symlink is passed and its target does not exist, PHP's file_exists function will return false regardless of whether the symlink itself exists at the given path or not.

The Issue

Currently we short-circuit when PHP claims the "file" doesn't exist:

public function delete(string $path): array
{
$remove = is_dir($path) ? 'rmdir' : 'unlink';
$error = ['code' => 500, 'msg' => 'Failed removing' . $path];
if (!file_exists($path)) {
return ['error' => null];
}
if (!is_writable($path)) {
return ['error' => ['code' => 403, 'msg' => 'No permission to write path']];
}
return ['error' => $remove($path) ? null : $error];
}

...meaning if we attempt to delete a symlink and its target has already been removed, it's not possible to remove the symlink without first pointing it to a file that exists (or creating the file it references).


We'll need another test (see below), but it may be necessary to check is_link() first so that special treatment can be given.

Theoretical Test

/** @test */
public function can_delete_symlink_when_target_is_missing(): void
{
    $link = 'test-skel/some-symlink';
    $target = 'test-skel/non-existent-path';

    createSymlink($link, $target);
    deleteWithFileManager($link);
    assertDoesNotExist($link);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions