-
Posts
115 -
Joined
-
Last visited
-
Days Won
2
Everything posted by gRegor
-
I think I have this working, but part of it feels hacky. In the form config, I set the destinationPath to the final location (no intermediate temp directory): $destinationPath = $this->config->paths($this) . '.uploads/'; $destinationPath = $this->config->paths($this) . '.uploads/'; Calling processInput() will handle the upload and move the file to that destination using the original filename. That process also sets up a Pagefiles object as the value of the InputfieldFile. This is where it gets kinda hacky: That Pagefiles object defaults to the current admin page that the form is uploading via, so it sets the paths to that page ID instead of the destination path. Despite this, that is not where the uploaded file is. Example dump of the object (key parts): ProcessWire\InputfieldFile Object ( [className] => InputfieldFile [attributes] => Array ( ... [value] => ProcessWire\Pagefiles Object ( [count] => 1 [url] => /site/assets/files/####/ [path] => /full/path/to/site/assets/files/####/ [items] => Array ( [uploaded-filename.csv] => Array ( [url] => /site/assets/files/####/uploaded-filename.csv [filename] => /full/path/to/site/assets/files/####/uploaded-filename.csv ... [filedata] => Array ( [uploadName] => Uploaded-Filename.csv ) ) ) ) [type] => file ) ... ) Finally, I can get the basename of that uploaded file, build the correct path to the file with `destinationPath`, and use $files->rename() to rename it to the desired scheme: $form->processInput($this->input->post); // should add a check for $form->getErrors() here $field = $form->get('scores_upload'); $original_filename = $field->value->first()->basename(); $result = $this->files->rename( $field->destinationPath . $original_filename, $target_filename );
-
Hm, well a bit of progress: I realized that InputfieldFile has its own usage of WireUpload already (source). I was originally thinking that it uploaded the file only to a tmp directory, then I had to manually use WireUpload to move it to the long-term location. The InputfieldFile method will largely work, but unfortunately it doesn't let me call `setTargetFilename()` on the WireUpload, so I might not be able to enforce the naming scheme I was using. I'm still really curious why this stopped working after the upgrade. So far, comparing versions, InputfieldFile seems to work pretty similarly.
-
I've looked through quite a few threads and the source code, but unfortunately have not found exactly what I was looking for. I recently upgraded to PW 3.0.246 on PHP 8.2 and I'm wondering if there's some breaking changes I need to adjust for: I have an admin module using InputfieldFile (noAjax) that prompts for a CSV file and uses WireUpload to handle it by creating a unique name and moving the file to a longer-term location. This worked pretty smoothly on PW 3.0.165 (I think it was around that version), but seems to be failing now with "Unable to move uploaded file". Code snippets below. This is inside a Process module called ProcessMemberScorecard. These aren't large files and all the directories exist and should have correct permissions: // start out by creating a WireTempDir based on the class name $destination = $this->files->tempDir($this->className)->get(); // then an InputFieldWrapper is created and field configs with importArray() $wrapper->importArray( [ [ 'type' => 'file', 'name' => 'scores_upload', 'label' => 'Scores File', 'description' => 'Select a CSV file to upload', 'icon' => 'upload', 'extensions' => 'csv', 'destinationPath' => $destination, 'maxFiles' => 1, 'maxFilesize' => 10 * 1024 * 1024, 'noAjax' => true, 'descrptionRows' => 0, ], // more field configs... ] ); Then on POST request, the form is processed and a WireUpload is run: if ($this->input->requestMethod('POST')) { $form->processInput($this->input->post); $ul = new WireUpload('scores_upload'); $ul->setValidExtensions(['csv']); $ul->setMaxFiles(1); $ul->setOverwrite(true); // this appears to correctly set the full system path for /site/modules/ProcessMemberScorecard/.uploads/ and that folder exists and has a lot of previously uploaded files from this module $ul->setDestinationPath($this->config->paths($this) . '.uploads/'); // set up final filename for destination $dt = new DateTime(); $tmpname = bin2hex(random_bytes(8)); $ul->setTargetFilename( sprintf('%s-%s.csv', $dt->format('Y-m-d'), $tmpname ) ); $results = $ul->execute(); if (count($results) == 0) { foreach ($ul->getErrors() as $error) { $this->log->save('scorecard', $error); $this->error($error); } return $form->render(); } // get final filename from $results[0] and do additional processing } I'm still getting errors like "Unable to move uploaded file to: /site/modules/ProcessMemberScorecard/.uploads/2025-03-04-a4604381bbe12d34.csv" I have tried changing the permissions on that `.uploads` directory in the module to 0777 (bad!), but still getting the same error. Is there something in newer versions of WireUpload that prevent moving files into folders with a leading dot? I couldn't find anything like that in the source code, but just trying to think though all the possibilities. Thanks for any help!
-
Version 0.2.3 of the ProcessWire IndieAuth Module is released: Fixed a bug when adding profile information to a token response Install now attempts to add the introspection-endpoint Improved admin: list of granted access tokens Add an option to no longer advertise the backwards-compatible link-rels. These remain on by default; future release may change to off by default. More in the changelog
-
Version 0.2.2 of the ProcessWire IndieAuth Module is released: Admin tools to support the Client Credentials flow and manually adding a token when testing Added an Introspection endpoint Updated client information discovery. It now prefers the JSON document and falls back to parsing microformats2. Scoped dependencies so this can more easily run on the same site with ProcessWire Webmentions without conflicts More in the changelog
-
Related: a helpful lib I've been using for URL normalization and parsing is https://sabre.io/uri/
-
4.25.18 appears to still have the issue. It's in these lines: $info = parse_url($_SERVER['REQUEST_URI']); $parts = explode('/', $info['path']); I added some debugging and a proof of concept workaround (surely not correct) for the missing path: $info = parse_url($_SERVER['REQUEST_URI']); if (array_key_exists('path', $info)) { $path = $info['path']; } else { $path = '/'; } $parts = explode('/', $path); I think the more correct thing to do is ensure a full, valid URL is passed into parse_url() to ensure the path gets parsed correctly. I can file a github issue if that helps.
-
@adrian Oh interesting, I had just updated it before posting, but I see there's actually 4.25.18. PW might have had .17 cached as the newest version. I'll update again.
-
I'm experiencing this in production, not with Laravel. It appears to happen when the path has an empty segment, e.g. https://gregorlove.com//xmlrpc.php?rsd This isn't a valid URL on my site, I know it's just someone scanning for vulnerabilities, but I saw this error in the Tracy logs: Warning: Undefined array key "path" in /site/assets/cache/FileCompiler/site/modules/TracyDebugger/TracyDebugger.module.php on line 2865 Deprecated: explode(): Passing null to parameter #2 ($string) of type string is deprecated in /site/assets/cache/FileCompiler/site/modules/TracyDebugger/TracyDebugger.module.php on line 2865 ProcessWire: 3.0.210 PHP: 8.1.27 TracyDebugger: 4.25.17 Update: The issue appears to be that `REQUEST_URI` in this instance is `//xmlrpc.php?rsd`. Running parse_url() on that does not return a path segment because it parses `xmlrpc.php` as the host and `?rsd` as the query. The following explode() line expects that path. I think there needs to be some more sanitization before using the result of that parse_url().
-
I've been loving BT's The Secret Language of Trees
-
Hey all, I've looked at some other threads and github issues, but didn't find what I was looking for: https://processwire.com/talk/topic/21616-file-upload-inside-custom-module/ https://processwire.com/talk/topic/619-what-does-it-mean-destinationpath-is-empty-or-does-not-exist-upload_file/ https://github.com/processwire/processwire-issues/issues/885 I'm on PW version 3.0.165. I have a module using InputfieldFile to upload a CSV, then move it to a unique filename within a subdirectory in the module. Then it processes the CSV into a db table. That's actually all working smoothly, except I still get error messages on upload "destinationPath is empty or does not exist [field label]" and "Missing required value [field name]" Below is the relevant code. A couple notes: 1. I have both `required` and `requiredAttr` set because I wanted to avoid them clicking submit without selecting a file (it's happened, haha). I've tried turning those off and it fixes the second error "Missing required value" but not the first one about destinationPath 2. I can't seem to debug the $destination created by tempDir(), because I think it is removed when the request ends, but I presume it must be working OK because the CSV file ends up in the `/.uploads/` directory I specify, and is processed into a database table. 3. `/site/assets/cache/` directory is chmod 0777 and owned by "nobody" (yes, I know, I need to tighten this down :) Thanks for any assistance! Worst case I guess I can tell them to ignore the red message since it is actually working. <?php $destination = $this->files->tempDir($this)->get(); // debugging shows $destination = /site/assets/cache/WireTempDir/.ProcessMemberScorecard/0/ $form = $this->modules->get('InputfieldForm'); $form->attr('action', $this->page->url . 'upload-scores'); $form->attr('enctype', 'multipart/form-data'); $wrapper = new InputfieldWrapper(); $wrapper->importArray( [ [ 'type' => 'file', 'name' => 'scores_upload', 'label' => 'Scores File', 'description' => 'Select a CSV file to upload', 'required' => true, 'requiredAttr' => true, 'icon' => 'upload', 'extensions' => 'csv', 'destinationPath' => $destination, 'maxFiles' => 1, 'maxFilesize' => 10 * 1024 * 1024, 'noAjax' => true, 'descrptionRows' => 0, ], // additional checkbox fields, not relevant ] ); $form->append($wrapper); if ($this->input->requestMethod('POST')) { $form->processInput($this->input->post); $ul = new WireUpload('scores_upload'); $ul->setValidExtensions(['csv']); $ul->setMaxFiles(1); $ul->setOverwrite(true); $ul->setDestinationPath($this->config->paths($this) . '.uploads/'); $dt = new DateTime(); $tmpname = bin2hex(random_bytes(8)); $ul->setTargetFilename( sprintf('%s-%s.csv', $dt->format('Y-m-d'), $tmpname ) ); $results = $ul->execute(); if ($errors = $ul->getErrors()) { foreach ($errors as $error) { $this->error($error); } return $form->render(); } if (!$results) { // older, probably not needed since both required and requiredAttr are set $this->error('Please select a CSV file to upload'); return $form->render(); } // handle processing at this point, // then redirect to the next step where user confirms // the final result } .
-
- inputfieldfile
- destinationpath
-
(and 2 more)
Tagged with:
-
Well the table entries are simple enough, so I'm going to just try removing them. I'll report back if my site implodes, but I suspect it will be fine. ?
- 1 reply
-
- 1
-
-
I posted in the release thread, but that thread is several months old so I'm reposting here to get more eyes on it: After upgrading to 3.0.210 and running Modules > Refresh, it warned: I don't think I've had InputfieldTinyMCE installed before unless it was from an early 2.x version (site's been on PW since ~2014). It's definitely not the new InputfieldTinyMCE. I don't recognize JqueryFancybox. I checked in db table `modules` and there are entries for InputfieldTinyMCE and JqueryFancybox, no date in the created column (0000-00-00 00:00:00), so I'm guessing these are quite old? I know the site hasn't had those folders in /modules over the last several years at least. Is it safe to just remove those entries from the modules table?
-
Just upgraded from 3.0.165 and the process went very smoothly as always. Only odd thing is a notice when I run Modules > Refresh: I don't think I've had InputfieldTinyMCE installed before unless it was from an early 2.x version (site's been on PW since ~2014). I don't recognize JqueryFancybox. Doesn't seem to be causing any problems, but is there something else I need to update? Edit: I checked in db table `modules` and do have entries for InputfieldTinyMCE and JqueryFancybox, no date in the created column (0000-00-00 00:00:00), so I'm guessing these are quite old? I know the site hasn't had those folders in /modules over the last several years at least. Is it safe to just remove those entries from the modules table?
-
Not ProcessWire-specific. $this-> is the way to access properties and methods within the object, as part of Object Oriented Programming. More: https://www.php.net/manual/en/language.oop5.properties.php
-
Bump. This is now in the modules directory! ? The first post has been updated with current details.
-
I heard back from Ryan via email:
-
Ah, I hadn't considered it might be the repo name being different than the class. I might try that first. If flattening is required, I do wonder how to best organize modules like Webmention, which is actually a set of two Process classes, an InputField class, and FieldType class.
-
Is there anything in /site/assets/logs/errors.txt (or exceptions.txt)? I will usually turn on error_reporting and display_errors in index.php or ready.php: error_reporting(E_ALL); ini_set('display_errors', '1');
-
Should custom forms be built with the ProcessWire Form API?
gRegor replied to Jonathan Lahijani's topic in General Support
I build a lot of custom registration forms on ProcessWire sites and prefer to write the HTML directly, with some ProcessWire goodies added on. This seems quickest for authoring forms that match the site and doesn't require jQuery/jQueryUI. I prefer to make forms work even when JS is disabled, if possible. For CSRF, I manually generate a single-use token and put in the hidden form fields. I have a custom class that lets me set up a set of fields, their types, and validation rules. Parts of that leverage PW's $sanitizer and sanitized values end up in $input->whitelist() for easy processing and for populating form field values. -
Answered Below Short version: the git repository must have the .module.php file (and .info.php or .config.php files if used) in the top directory. It is OK to put any other files in sub-directories. ProcessWire will create the /modules/ModuleName directory during install and put all files in there, so there's no need to have folder ModuleName in your repository. --- Original post: I am trying to submit https://github.com/gRegorLove/ProcessWire-IndieAuth I get these errors on the first step: The module has the static getModuleInfo() function. My folder structure does put the files in a directory of the same name (ProcessIndieAuth), but I've not had issues with submitting modules like that in the past (Webmention -- granted, it's been several year ago now). Must I "flatten" the files by not having them in the sub-directory? I tried searching the forums and the documentation but couldn't find a definitive answer.
-
Late reply here, but I have some PHPunit tests in my IndieAuth module: https://github.com/gRegorLove/ProcessWire-IndieAuth/tree/main/ProcessIndieAuth/tests bootstrap.php: loads the Composer dependencies and ProcessWire via its index.php ClientIdTest.php: I think this file is older and needs to be updated, but it still gives an idea how I load the module and test methods within it. ServerTest.php: newer file which shows testing additional classes in the module. In this instance, this is like any generic PHPunit testing since that class is static methods and isn't calling ProcessWire methods.
-
Just pushed a bug fix: During install it now adds the role "indieauth". Assign this role to any users that should be able to authenticate / authorize IndieAuth clients. The README has been updated accordingly.
-
Now in the module directory: https://processwire.com/modules/process-indie-auth/ IndieAuth lets you sign in to applications using your domain name and grant access to read/write to your site. This module adds IndieAuth support to your ProcessWire site, enabling two main things: Authentication: When you visit a site like indielogin.com and enter your domain name, you will be taken to your ProcessWire admin area to sign in and approve the request. If you approve the request, you will be returned to the site and logged in as your domain name. Authorization: When you visit an application like Quill, it needs to also get your permission to post to your site. You will be taken to your ProcessWire admin area to sign in and approve the request/scopes that the app is requesting (create, update, delete, etc.). If you approve the request, you will be returned to the app, logged in as your domain name, and the app will have an access token for your site. Features Browse the applications you have granted access tokens to. See when each one was granted, last used, and will expire. Revoke any application’s access tokens Set the default expiration period for new access tokens. The initial default is 14 days. Automatically remove expired tokens During authorization, confirm and change the scopes granted to the application. For example, an app may request “create” and “delete” scopes, but you can grant only “create.” During authorization, you can also choose to grant an access token with no expiration Installation Navigate to Modules > New. In the Module Class Name field, enter ProcessIndieAuth Copy the template files from the module’s directory /extras/templates into your site’s /site/templates directory. Verify that the plugin installed pages: IndieAuth Metadata Endpoint Authorization Endpoint Token Endpoint Token Revocation Endpoint IndieAuth page under the admin’s Access menu Look up the user(s) that you want to allow to use IndieAuth and assign them the “indieauth” role Update your home page template to add the link elements inside the <head> element: <?=$modules->get('ProcessIndieAuth')->getLinkElements();?> This should result in three <link> elements in the source HTML: <head> <link rel="indieauth-metadata" href="/indieauth-metadata-endpoint/"> <link rel="authorization_endpoint" href="/authorization-endpoint/"> <link rel="token_endpoint" href="/token-endpoint/"> </head> Sign In To test signing in with IndieAuth, visit indielogin.com and enter your domain name. Follow the prompts to authenticate and you should end up back on indielogin.com with a success message. Sign In and Authorize To authorize an application with IndieAuth, your site will first need a module that uses access tokens. I have a Micropub for ProcessWire module in development that does that. Micropub is a standard that lets you publish to your site using third-party clients. If you’d like to try it out, follow the instructions on GitHub to install it. After installing, visit Quill and enter your domain name. Follow the prompts and note the additional fields for “scope” and “expiration,” since you are authorizing an application to interact with your site. After successfully authorizing, try to post a short note from Quill. Quill should redirect you to the new post if it was successful. For a list of other Micropub clients you can try, see https://indieweb.org/Micropub/Clients. Admin and Options In the admin, you can see which applications you have granted access tokens to. You can see when each token was issued, last accessed, and its expiration. You can also manually revoke a token at any time. Navigate to: Access > IndieAuth. There are a couple options in the admin at: Modules > Configure > ProcessIndieAuth: Default access token lifetime (in seconds): This defaults to 14 days and is what appears in the authorization screenshot above. Automatically remove access tokens after expiration (enabled by default): When enabled, the site checks approximately every six hours and removes expired access tokens. Regardless of whether this option is enabled, the module will reject any application attempting to use an expired access token. Since access tokens cannot (currently) have their expiration extended, I recommend keeping this option enabled so the admin list stays tidy and current. Finally, this module writes some admin logs. Access those at: Setup > Logs > indieauth More About IndieAuth If you’re interested in more details about IndieAuth, I recommend the article “OAuth for the Open Web” by Aaron Parecki (or the video presentation). If you are interested in implementing IndieAuth in your project, see the IndieAuth specification. Originally published at: https://gregorlove.com/2022/07/indieauth-for-processwire-released/ Previously: 2021-10-07: This post was originally about alpha testing the plugin before I submitted it to the modules directory.