processwire / processwire-issues

ProcessWire issue reports.
45 stars 2 forks source link

Relative path issue in wireIncludeFile #511

Open adrianbj opened 6 years ago

adrianbj commented 6 years ago

Short description of the issue

Methods in the WireFileTools class, like include use relative paths so if you use wireIncludeFile() or $files->include() from a module the file is not included because the path is something like: ./templates/fileToInclude.php

Expected behavior

It should work no matter where it's called from.

Actual behavior

You get an error triggered by https://github.com/processwire/processwire/blob/a9ec5a640ac0442d3980d2cd33770626aafc91a2/wire/core/WireFileTools.php#L730

Optional: Suggestion for a possible fix

Convert path to filename to be absolute.

Setup/Environment

Toutouwai commented 6 years ago

I use $files->render() via the wireRenderFile() function in a module and it works okay. There is the defaultPath option available.

I don't see a defaultPath option for $files->include() - maybe this option should be added, or perhaps you are able to include files from any of the allowedPaths (which includes the /site/modules/ directory by default) already?

adrianbj commented 6 years ago

Thanks for chiming in @Toutouwai

Maybe I should have been a little more explicit - I am actually hoping that Zeka from the PW forums will chime in (not sure his Github handle) because he found this with the Tracy console panel.

If you put something like this: wireIncludeFile('templates/fileToInclude'); in ready.php, the Console panel gets the file doesn't exist error because it renders a template, but obviously from the Tracy module's path, rather than from site/templates. I think he also had issues when using that from a module. In reality I think there might be several scenarios where this could show up, but I think adding $config->paths->root to the front of all rendered files would fix it. Maybe I am missing something though as I haven't investigated thoroughly.

Lazerproof commented 6 years ago

@adrianbj Thank you for opening this issue.

When I put this line in ready.php wireIncludeFile('templates/helpers/translations'); file is successfully included, but it somehow influence how Console panel from TracyDeggur works. It begins to output whole render of the page instead of the result of code execution.

In my case, I didn't get the exception from this line https://github.com/processwire/processwire/blob/a9ec5a640ac0442d3980d2cd33770626aafc91a2/wire/core/WireFileTools.php#L730 when open the site but got when using the Console panel.

How to reproduce it:

  1. Install Tracy Debugger
  2. Use wireIncludeFile to include some file from ready.php
  3. Try to use Tracy`s Console panel.

I've tested this behavior on two different installations of the latest PW.

adrianbj commented 6 years ago

Thanks for contributing @Lazerproof - I also don't see any error when viewing the site, but I also don't think this is specific to Tracy. In that example where a wireIncludeFile is added to ready.php, from what I can tell any module that results in ready.php being loaded will trigger that "file does not exist" error because the path to the included file will be relative to the root of the module, rathe than /site/

Hopefully between us we've now managed to explain this a little better :)

ryancramerdesign commented 6 years ago

I'm not sure I understand the issue report. File functions (whether PHP's or PW's) operate from the current working directory, not from the directory that the caller's file lives in (which it would have no way of knowing). During execution, ProcessWire sets the current working directory to the dir of whatever file is being rendered, i.e. /site/templates/. So any file function that you call (whether one from PHP or PW or anything else), a relative path is going to be relative to that directory. Unless you have set the current working directory chdir() on your own, don't call file functions with relative paths. If you want something relative to the file of where you make the call, then use __DIR__ . '/myfile.php' so that it translates to the intended full path. Also, $files->render()is a little different in that it lets you specify the starting point for relative paths (defaultPath), with the default being /site/templates/. But if you are using these functions (or any PHP file functions) somewhere other than template files, prepend a __DIR__ to your relative path so that you are not passing a relative path to a function without knowing the current working directory. PW can't do this for you because __DIR__ and __FILE__ always reflect the dir/file of the file they are placed in.

adrianbj commented 6 years ago

@ryancramerdesign - maybe this is an unusual situation, but Tracy's Console panel uses: new TemplateFile() to render the output of whatever code is run. Because this starts PW it also calls any wireIncludeFile() calls in ready.php. While the relative path works normally, it doesn't work when triggered by new TemplateFile().

Probably the easiest way for you to see what is going on is to follow @Lazerproof 's instructions above. I didn't mention Tracy in my OP because I think it's very possible this could occur in other future modules as well. The dev adding a wireIncludeFile shouldn't have to consider the path to the root when using wireIncludeFile(). Is there any logical way you can simply prepend $config->paths->site so that it works as expected everywhere, or will that break the logic that others might currently be relying on? Or do you have any other suggestions for a way that modules (like Tracy) can make a call to new TemplateFile() without breaking their functionality?

Thanks.

netcarver commented 5 years ago

@ryancramerdesign Do you have enough information to proceed?

adrianbj commented 5 years ago

@ryancramerdesign - you state that this is not a bug, but could you please confirm that you tested as per @Lazerproof 's instructions above? I still think this could easily be solved by prepending $config->paths->site to the path. What do you think?