Repository: roots/acorn (php)

Issue:
Feature Request: Add `relativePath` or `themePath` to `Asset`
### Terms

- [X] I have read the [guidelines for Contributing to Roots Projects](https://github.com/roots/.github/blob/master/CONTRIBUTING.md)
- [X] This request is not a duplicate of an existing issue
- [X] This is not a personal support request that should be posted on the [Roots Discourse](https://discourse.roots.io/) community

### Summary

`Asset` currently has a `path()` function that returns the full, absolute path to the asset.
Sometimes the path relative to the theme directory is also needed, as for [`add_editor_style`](https://developer.wordpress.org/reference/functions/add_editor_style/).
Currently, additional code/library is needed to get the path relative to theme directory from the absolute path returned by the `path()` function.
It would be nice if also a function is added that returns the path to asset relative to the (Sage) theme directory.

### Motivation

#### Why are we doing this?
Sometimes the path relative to the theme directory is also needed.

#### What use cases does it support?
[`add_editor_style`](https://developer.wordpress.org/reference/functions/add_editor_style/) requires either an URI (that currently cause an [issue post-processing CSS in Gutenberg editor to rewrite URLs relative to stylehsheet](https://core.trac.wordpress.org/ticket/55728#ticket)) or a path to a local file relative to the theme directory (that doesn't cause this issue).

#### What is the expected outcome?
Elimination of additional code/library for making the absolute asset path (from `path()`) relative to the theme directory path, 
so it can be used by functions like `add_editor_style`.

#### Potential conflicts / foreseeable issues
One more API function in `acorn`, paths and their handling shouldn't change in the foreseeable future, so once the code (and tests) for a theme-directory-relative path function is in place, no changes should be expected any time soon.
As this functionality would be requires in any theme that adds the frontend styles in the expected way (using `add_editor_style`), this should justify adding such an additional function.

### Additional Context

https://discourse.roots.io/t/absolute-domain-relative-path-for-asset-urls-in-css/23121/4

Pull request description:
✨ add `Asset::relativePath()`
Closes #227 

```php
$relative_path = asset('app.css')->relativePath(get_theme_file_path());
```

Patch:
diff --git a/src/Roots/Acorn/Assets/Asset/Asset.php b/src/Roots/Acorn/Assets/Asset/Asset.php
index 418e607..4efd90e 100644
--- a/src/Roots/Acorn/Assets/Asset/Asset.php
+++ b/src/Roots/Acorn/Assets/Asset/Asset.php
@@ -4,6 +4,7 @@ namespace Roots\Acorn\Assets\Asset;
 
 use SplFileInfo;
 use Roots\Acorn\Assets\Contracts\Asset as AssetContract;
+use Roots\Acorn\Filesystem\Filesystem;
 
 class Asset implements AssetContract
 {
@@ -82,6 +83,19 @@ class Asset implements AssetContract
         return file_get_contents($this->path());
     }
 
+    /**
+     * Get the relative path to the asset.
+     *
+     * @param string $base_path Base path to use for relative path.
+     * @return string
+     */
+    public function relativePath(string $base_path): string
+    {
+        $base_path = rtrim($base_path, '/\\') . '/';
+
+        return (new Filesystem())->getRelativePath($base_path, $this->path());
+    }
+
     /**
      * Base64-encoded contents
      *
diff --git a/src/Roots/Acorn/Assets/AssetsServiceProvider.php b/src/Roots/Acorn/Assets/AssetsServiceProvider.php
index 2f72401..eebcb26 100644
--- a/src/Roots/Acorn/Assets/AssetsServiceProvider.php
+++ b/src/Roots/Acorn/Assets/AssetsServiceProvider.php
@@ -2,8 +2,8 @@
 
 namespace Roots\Acorn\Assets;
 
+use Illuminate\Support\ServiceProvider;
 use Roots\Acorn\Assets\View\BladeDirective;
-use Roots\Acorn\ServiceProvider;
 
 class AssetsServiceProvider extends ServiceProvider
 {


Test patch:
diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php
index 860a5b0..48b65a5 100644
--- a/tests/Assets/AssetTest.php
+++ b/tests/Assets/AssetTest.php
@@ -73,3 +73,7 @@ it('can require_once a php asset', function () {
 it('can fail to load a php asset', function () {
     (new PhpAsset(temp('does/not/exist.php'), 'https://kjo.kjo/'))->load();
 })->throws(FileNotFoundException::class);
+
+it('can get a relative path', function () {
+    assertMatchesSnapshot($this->assets->asset('apray.ext')->relativePath($this->fixture('asset_types')));
+});
diff --git a/tests/__snapshots__/AssetTest__it_can_get_a_relative_path__1.txt b/tests/__snapshots__/AssetTest__it_can_get_a_relative_path__1.txt
new file mode 100644
index 0000000..5ffc2ec
--- /dev/null
+++ b/tests/__snapshots__/AssetTest__it_can_get_a_relative_path__1.txt
@@ -0,0 +1,1 @@
+public/assets/apray.cache-busted.ext
\ No newline at end of file