Giter Club home page Giter Club logo

path-util's Introduction

File Path Utility

Build Status Build status Scrutinizer Code Quality Latest Stable Version Total Downloads Dependency Status

Latest release: 2.3.0

PHP >= 5.3.3

This package provides robust, cross-platform utility functions for normalizing, comparing and modifying file paths and URLs.

Deprecation

This package has been merged into the Symfony Filesystem Component 5.4. It is not maintained anymore.

Installation

The utility can be installed with Composer:

$ composer require webmozart/path-util

Usage

Use the Path class to handle file paths:

use Webmozart\PathUtil\Path;

echo Path::canonicalize('/var/www/vhost/webmozart/../config.ini');
// => /var/www/vhost/config.ini

echo Path::canonicalize('C:\Programs\Webmozart\..\config.ini');
// => C:/Programs/config.ini

echo Path::canonicalize('~/config.ini');
// => /home/webmozart/config.ini

echo Path::makeAbsolute('config/config.yml', '/var/www/project');
// => /var/www/project/config/config.yml

echo Path::makeRelative('/var/www/project/config/config.yml', '/var/www/project/uploads');
// => ../config/config.yml

$paths = array(
    '/var/www/vhosts/project/httpdocs/config/config.yml',
    '/var/www/vhosts/project/httpdocs/images/banana.gif',
    '/var/www/vhosts/project/httpdocs/uploads/../images/nicer-banana.gif',
);

Path::getLongestCommonBasePath($paths);
// => /var/www/vhosts/project/httpdocs

Path::getFilename('/views/index.html.twig');
// => index.html.twig

Path::getFilenameWithoutExtension('/views/index.html.twig');
// => index.html

Path::getFilenameWithoutExtension('/views/index.html.twig', 'html.twig');
Path::getFilenameWithoutExtension('/views/index.html.twig', '.html.twig');
// => index

Path::getExtension('/views/index.html.twig');
// => twig

Path::hasExtension('/views/index.html.twig');
// => true

Path::hasExtension('/views/index.html.twig', 'twig');
// => true

Path::hasExtension('/images/profile.jpg', array('jpg', 'png', 'gif'));
// => true

Path::changeExtension('/images/profile.jpeg', 'jpg');
// => /images/profile.jpg

Path::join('phar://C:/Documents', 'projects/my-project.phar', 'composer.json');
// => phar://C:/Documents/projects/my-project.phar/composer.json

Path::getHomeDirectory();
// => /home/webmozart

Use the Url class to handle URLs:

use Webmozart\PathUtil\Url;

echo Url::makeRelative('http://example.com/css/style.css', 'http://example.com/puli');
// => ../css/style.css

echo Url::makeRelative('http://cdn.example.com/css/style.css', 'http://example.com/puli');
// => http://cdn.example.com/css/style.css

Learn more in the Documentation and the API Docs.

Authors

Documentation

Read the Documentation if you want to learn more about the contained functions.

Contribute

Contributions are always welcome!

Support

If you are having problems, send a mail to [email protected] or shout out to @webmozart on Twitter.

License

All contents of this package are licensed under the MIT license.

path-util's People

Contributors

davidbadura avatar h4cc avatar harikt avatar hason avatar king2500 avatar senseexception avatar tgalopin avatar webmozart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

path-util's Issues

PHP 8 compat

The Problem

The package cannot be installed on PHP 8 from master, producing the following error:

Error: Your lock file does not contain a compatible set of packages. Please run composer update.

  Problem 1
    - webmozart/path-util is locked to version dev-master and an update of this package was not requested.
    - webmozart/path-util dev-master requires php ^5.3.3|^7.0 -> your php version (8.0.2) does not satisfy that requirement.
  Problem 2
    - webmozart/path-util dev-master requires php ^5.3.3|^7.0 -> your php version (8.0.2) does not satisfy that requirement.
    - webmozart/path-util 2.3.x-dev is an alias of webmozart/path-util dev-master and thus requires it to be installed too.
    - webmozart/path-util is locked to version 2.3.x-dev and an update of this package was not requested.

  Problem 1
    - webmozart/path-util is locked to version dev-master and an update of this package was not requested.
    - webmozart/path-util dev-master requires php ^5.3.3|^7.0 -> your php version (8.0.2) does not satisfy that requirement.
  Problem 2
    - webmozart/path-util dev-master requires php ^5.3.3|^7.0 -> your php version (8.0.2) does not satisfy that requirement.
    - webmozart/path-util 2.3.x-dev is an alias of webmozart/path-util dev-master and thus requires it to be installed too.
    - webmozart/path-util is locked to version 2.3.x-dev and an update of this package was not requested.

Error: Process completed with exit code 2.

Possible Cause

2.3 declares compatibility from PHP 5.3.3 to infinity, implicitly allowing PHP 8.
master removes this compatibility by declaring ^5.3.3|^7.0.

Suggested Solution

Explicitly declare compatibility with PHP 8, e.g. ^5.3.3|^7.0|^8.0.

Remarks

While the point of the solution to explicitly add PHP 8.0 to the list of supported versions stands, I am not entirely sure that it is possible to resolve dependencies to any list of constraints that will support both PHP 5.3 and PHP 8.

Therefore, the solution may be also the followig:

  1. Add a new branch 2.3.x, and keep the current constraint ^5.3.3|^7.0 there.
  2. Rewind master to 2.3.0, because dev-master is supposed to represent the latest stable version. This is important, because otherwise lower stability in dependants breaks everything.
  3. Add a new branch e.g. 2.4.x, and declare ^7.0|^8.0 there (or a higher version, like 7.1 or 7.2 even, because unless you composer update on CI, there is no single PHPUnit version that can support the whole range of declared PHP versions).

Tilde replacement is incorrect

The "tilde to HOME" replacement seems incorrect:

if ('~' === $path[0]) {

If you are user_a and you type ~user_b, this would be replaced by the shell to mean /home/user_b. The current code will replace this to /home/user_auser_b instead.

Is this package still maintained?

I see last commits 6 years ago and last release was on Dec 2015. Also, lots of PRs are unreviewed as well. So I was wondering if anybody is still maintaining the project?

Incorrect documentation

Comment for method Path::makeAbsolute is incorrect.

Path::makeAbsolute("C:/style.css", "/webmozart/puli/css");

actually returns C:/style.css rather than throwing an exception (as documentation says), possibly functionality changed with version 2.5?

Question: why Windows paths use the slash instead of the backslash?

It's a bit strange, at least for me, that Windows paths are normalized using the slash as directory separator. I simply wanted to know why this decision was made.

It's clearly easier to handle only one directory separator, whatever is the current platform... but the reality is that most Windows users expect paths to be normalized using the backslash as directory separator.

echo Path::join('C:\\foo', 'bar.txt'); // or: Path::join('C:/foo', 'bar.txt')
// Prints : "C:/foo/bar.txt" on Windows, instead of the expected "C:\\foo\\bar.txt".

This is a (minor) issue: if I want to use these paths in a Shell command (for example, by calling the exec or shell_exec functions), I must replace the slash occurrences by a backslash to avoid Shell errors (e.g. raised by cmd.exe).

Path::isLocal for stream wrappers like phar://

Theoretical question:

I think ...

Path::isLocal('phar://C:/Documents/projects/my-project.phar/composer.json');

... returns false.

Does that make sense?

The basic question here is:
How is "local" defined? Are stream wrappers to local files considered local or not?

@webmozart what do you think?

Remove 'final' keyword

Would you be open to removing the 'final' keyword so that the class can be easily extended?

I was looking at extending this in one of my utility libraries where I could canonicalize and return the first 3 directories in the path while having access to all the other Path methods. As an aside, maybe adding a first class method that performs this in a canonical way. This is helpful when you have a cross sectional tree setup with different projects where you need to autoload the right '.../vendor/autoload.php', from wherever you are in tree.

e.g.:
/devel/projects/A/www/vendor
/devel/projects/B/www/vendor

so if I write a quick test jig in: /devel/projects/B/www/entities/test.php

I can quickly require_once the correct:

require_once(Path::join(Path::first(__DIR__, 4), Path::canonicalize('vendor/autoload.php')));

I could inject it, but I'd have to write bounce helpers for all static methods I was going to use.

Personally, I don't believe any general purpose library should use final, because the point of a library is the ability to extend them to add enhanced functionality or change certain behaviors if need be to solve/integrate a task at hand. My general rule is that only class/objects, that are to be fully concrete should use the 'final' keyword, or where a class has certain security implications that it needs to be locked down to prevent behavioral modifications. I'm open to contrary viewpoints though.

Thank you for your consideration.

PHP 7.3 compatibility issues - "Since PHP 7.0, functions inspecting arguments, like func_get_args(), no longer report the original value as passed to a parameter, but will instead provide the current value."

Steps to reproduce
phpcs -p -s -v --standard=PHPCompatibility vendor/webmozart/ --runtime-set testVersion 7.3 --report-full=PHP_7_3_Compatibility_vendor_webmozart.log --extensions=php,module,inc -d memory_limit=512M

Generated report from phpcs & found one warning below -

FILE: /vendor/webmozart/path-util/src/Path.php

 852 | WARNING | Since PHP 7.0, functions inspecting arguments, like func_get_args(), no longer report the original value as passed to a parameter, but will instead provide the current value. The parameter "$paths" was used, and possibly
     |         | changed (by reference), on line 851. (PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection)

Improve performance of path mapping.

$ find res | wc -l
4874 
$ time puli path map /app res
noglob puli path map /app res  291.27s user 0.29s system 99% cpu 4:51.61 total

Mapping a res directory containing a public directory with a bower_components directory containing 21 javascript libraries takes ~5 minutes currently. I profiled the script and found that

        $parts = array_filter(explode('/', $path), 'strlen');

in Path::canonicalize() was taking around 30% of the time. Changing this to:

        $parts = [];
        foreach( explode('/', $path) as $k=>$v ){
            if( $v !== '' ){
                $parts[$k] = $v;
            }
        }

Reduces the time to filter the array to around a third of the time taken by array_filter();
Additionally

$basePath = self::canonicalize($basePath);

in Path::isBasePath() is called repeatedly with the same base path. Adding in a private member to cache results from this line further reduces runtime. The total runtime after these two changes is roughly half that currently (~2:30 runtime vs ~4:50).

        if( ! isset( self::$canonicalized[$basePath] ) ){
            $basePath = self::canonicalize($basePath);
            self::$canonicalized[$basePath] = $basePath;
        }else{
            $basePath = self::$canonicalized[$basePath];
        }

(Also defining Path::$canonicalized of course).

A risk here is that there's currently no limit on the size of the caching array. An arbitrary limit to the number of entries probably wouldn't affect performance too much however.

I've tried the changes on a checkout of path-util and the testsuite passes.

If you think the changes look reasonable I can set up a pull request.

Edit: I pasted the wrong version of the replacement snippet for array_filter().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.