Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.x Add ImageHelper filters to customize paths #2725

Merged
merged 17 commits into from
Jan 26, 2024

Conversation

mcaskill
Copy link
Contributor

@mcaskill mcaskill commented Mar 21, 2023

Related:

Issue

As reported in aforementioned issue and pull request, the ImageHelper::theme_url_to_dir() method is unable to resolve a URL/path in a non-standard theme directory structure.

This is the case if your "stylesheet" directory is located in a subdirectory of your theme my-theme/theme as was initially proposed in Timber's v2 starter-theme and employed by various theme boilerplates.

Solution

The solution, as proposed by @gchtr, is to add filters in ImageHelper to allow one to customize the logic of converting a URL to a path.

For example, we could add a timber/theme_url_to_dir filter that allows you to filter the result of Timber\ImageHelper::theme_url_to_dir().

I've added four filters:

  • ImageHelper::analyze_url()
    • timber/image_helper/pre_analyze_url to short-circuit the method's default URL analysis logic.
    • timber/image_helper/analyze_url to mutate the default analyzed URL components.
  • ImageHelper::theme_url_to_dir()
    • timber/image_helper/pre_theme_url_to_dir to short-circuit the method's default path resolution logic.
    • timber/image_helper/theme_url_to_dir to mutate the default resolved path.

I've added filters to analyze_url() since it's the one that calls theme_url_to_dir() and also contains opinionated logic for analyzing the URL.

Maybe the short-circuit filters could still call their non-pre filters, this would involve wrapping the default logic in a "did pre-filter return null".

Here's how its being used in a client project:

public function register_filters() : void {
	add_filter( 'timber/image_helper/pre_theme_url_to_dir', [ $this, 'filter_timber_image_helper_pre_theme_url_to_dir' ], 10, 2 );
}

public function filter_timber_image_helper_pre_theme_url_to_dir( ?string $path, string $src ): ?string {
	if ( is_null( $path ) && str_starts_with( $src, $this->theme_uri ) ) {
		$path = str_replace( $this->theme_uri, '', strtok( $src, '?' ) );
		$path = $this->theme_path . '/' . ltrim( $path, '/' );
	}

	return $path;
}

Impact

Adding an extra hooks could affect performance but it should be minor.

Usage Changes

The current logic of those methods does not change, filters are added to allow one to handle them early or mutate the default resulting values.

Considerations

See discussions from #2458

Testing

  • Modified install-wp-tests.sh to ensure TMPDIR is canonical.
  • Fixed tests of TestTimberImageHelperInternals::testAnalyzeURLTheme().
  • Added tests for filters in ImageHelper::analyze_url().
  • Added tests for filters in ImageHelper::theme_url_to_dir().

Added:
- Filter "timber/image_helper/pre_analyze_url" to short-circuit the method's default URL analysis logic.
- Filter "timber/image_helper/analyze_url" to mutate the analyzed URL components.
Added:
- Filter "timber/image_helper/pre_theme_url_to_dir" to short-circuit the method's default path resolution logic.
- Filter "timber/image_helper/theme_url_to_dir" to mutate the resolved path.
@mcaskill mcaskill changed the title 2.x add image helper filters 2.x Add ImageHelper filters to customize paths Mar 21, 2023
@mcaskill mcaskill changed the base branch from master to 2.x March 21, 2023 17:45
@coveralls
Copy link

coveralls commented Mar 21, 2023

Coverage Status

coverage: 88.744% (+0.2%) from 88.522% when pulling e09279e on mcaskill:2.x-add-image-helper-filters into f56f062 on timber:2.x.

Moved original URL parsing from `analyze_url()` to new method `_analyze_url()`.

Changed logic of filters; "timber/image_helper/pre_analyze_url" controls whether the original logic is called, to ensure the "timber/image_helper/analyze_url" filter is always applied.
Moved original URL conversion from `theme_url_to_dir()` to new method `_theme_url_to_dir()`.

Changed logic of filters; "timber/image_helper/pre_theme_url_to_dir" controls whether the original logic is called, to ensure the "timber/image_helper/theme_url_to_dir" filter is always applied.
@mcaskill mcaskill force-pushed the 2.x-add-image-helper-filters branch 2 times, most recently from 3ae1ffd to 237930d Compare March 21, 2023 20:38
If any symbolic links in `TMPDIR` are not resolved, usage of `realpath()` risks paths being broken such as by `ImageHelper::analyze_url()` calling `URLHelper::remove_url_component()` to remove `WP_CONTENT_DIR`.

Given a WordPress installation at:

```sh
/var/folders/XX/XXXXXXXXXX/X/wordpress/
```

And the following URL:

```sh
http://example.org/wp-content/themes/timber-test-theme/assets/images/cardinals.jpg
```

The `ImageHelper::theme_url_to_dir()` method would return the following absolute path (which internally calls `realpath()`):

```sh
/private/var/folders/XX/XXXXXXXXXX/X/wordpress/wp-content/themes/timber-test-theme/assets/images/cardinals.jpg
```

The `ImageHelper::analyze_url()` method would return the following components:

```php
[
  'url'       => 'http://example.org/wp-content/themes/timber-test-theme/assets/images/cardinals.jpg',
  'absolute'  => true,
  'base'      => 2,
  'subdir'    => '/private/themes/timber-test-theme/assets/images',
  'filename'  => 'cardinals',
  'extension' => 'jpg',
  'basename'  => 'cardinals.jpg',
]
```

As illustrated by `subdir`, the absolute path is broken by `URLHelper::remove_url_component()` striping the symbolically linked path from the canonical path.
Changed:
- Added `set_up()` and `tear_down()` from `TestExternalImage` to prepare test environment for content directory test.
- Fixed tests of `testAnalyzeURLTheme()` based on `TestExternalImage`.

These fixes will help with adding tests for `ImageHelper::theme_url_to_dir()`.
@mcaskill mcaskill force-pushed the 2.x-add-image-helper-filters branch from 237930d to 713a2b9 Compare March 22, 2023 00:13
Changed:
- Added `set_up()` and `tear_down()` to match `TestTimberImageHelperInternals` (from `TestExternalImage`) to prepare test environment for content directory test.
@mcaskill mcaskill marked this pull request as ready for review March 22, 2023 00:28
@gchtr gchtr added 2.0 Ready for Review Ready for a contrib to take a look at and review/merge labels May 12, 2023
@gchtr gchtr mentioned this pull request May 17, 2023
30 tasks
@Levdbas Levdbas self-requested a review May 21, 2023 05:09
@gchtr gchtr removed the 2.0 label May 29, 2023
@gchtr
Copy link
Member

gchtr commented May 29, 2023

Adding filters is definitely the way to go. Because this isn’t a breaking change and we want to focus on getting 2.0 ready, I switched this to 2.x Future.

* 2.x: (95 commits)
  Update statements to Weak implicit
  Check expected values as suggested by @nlemoine
  fix: phpstan issues & use fully qualified imports
  Refactor file models: update phpdoc
  Refactor file models: remove file property
  Refactor file models
  Fix coding style issue
  Update method descriptions
  Update return types and documentation
  Fix is_external() to work with domains only
  Fix test
  Improve URLHelper is_local method
  Improve docblocks of URLHelper methods is_local and is_external
  Replace strstr in URLHelper is_external method
  Fix shortened return in URLHelper is_local method
  remove error_log and prefix functions
  add check to image create functions
  Run coding standard checks only with highest or stable dependencies
  Add CS fixes to ignored revs
  Fix some CS issues
  ...
@Moustachos
Copy link

@gchtr any update on this one now that 2.x is stable? :)

Thanks!

@Levdbas Levdbas added 2.0 and removed 2.x Future labels Dec 13, 2023
@Levdbas Levdbas added this to the 2.0.1 milestone Dec 14, 2023
@Levdbas
Copy link
Member

Levdbas commented Dec 15, 2023

Hi @Moustachos , we have this in mind for a first minor release for Timber 2. Release date is TBD.

@Moustachos
Copy link

Thanks @Levdbas 👍

Copy link
Member

@gchtr gchtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this on, @mcaskill. And sorry for the longer wait.

I really appreciate that you took the time to carefully craft the DocBlocks for the filters with proper descriptions 🙌.

I just have on issue with the underscore prefixes in the private function names. Otherwise, this looks good to me and I think we can merge this for the next minor release.

src/ImageHelper.php Outdated Show resolved Hide resolved
src/ImageHelper.php Outdated Show resolved Hide resolved
src/ImageHelper.php Outdated Show resolved Hide resolved
Changed:
- Renamed `_analyze_url` to `get_url_components`.
- Renamed `_theme_url_to_dir` to `get_dir_from_theme_url`.
@gchtr
Copy link
Member

gchtr commented Jan 25, 2024

This looks good from my side 👍.

@nlemoine Can you have a quick look and merge this, if it looks alright to you, too?

Copy link
Member

@nlemoine nlemoine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still feels a bit odd to handle such things but doesn't hurt 👍

@Levdbas Levdbas merged commit ebc54fc into timber:2.x Jan 26, 2024
8 of 28 checks passed
@mcaskill mcaskill deleted the 2.x-add-image-helper-filters branch January 26, 2024 23:15
@Levdbas Levdbas modified the milestones: 2.0.1, 2.1.0 Feb 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.0 Ready for Review Ready for a contrib to take a look at and review/merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants