RewriteCond %{REQUEST_FILENAME} !-d
Ensures the request does not map to a valid directory.
RewriteCond %{REQUEST_FILENAME} !-f
Ensures the request does not map to a valid file
RewriteCond %{REQUEST_FILENAME}.php -f
Ensures that if you add .php to the requested location, it does map to a valid file.
RewriteRule .* $0.php [L]
If all the above conditions are true, then this matches the entire URL (the .*) and rewrites it to include the .php suffix.
The parentheses create a group which can be referenced in the substitution. In this instance they are not needed because you want to refer to the entire match which is already handled by $0 which is an automatic reference to the matching input string as a whole. If you wanted to match only a subset of the input string, then you'd use parentheses and $1, $2, etc.