Jump to content

Robin S

Members
  • Posts

    4,999
  • Joined

  • Days Won

    331

Everything posted by Robin S

  1. @Christophe, I can't follow what you're doing so if you have a question specifically about Custom Inputfield Dependencies rather than the core show-if features then please rephrase it and include some screenshots. For now what I can say is: Custom Inputfield Dependencies uses the $pages->find() selector syntax as described in the PW docs. This is a different syntax than the core show-if selectors, so you can't just copy/paste selectors from one to the other. Syntax like "parent.id=1314 || id=1250" and "parent.id=1314 | id=1250" is not valid for $pages->find(). If you want to match one field/value combination OR a different field/value combination then you need to use OR-group syntax: https://processwire.com/docs/selectors/#or-groups And InputfieldSelector (the inputfield used by Custom Inputfield Dependencies for "Show only if page is matched by custom find") doesn't support OR-groups so you would have to use a selector string in "Show only if page is matched by selector". (parent.id=1314), (id=1250)
  2. @soyerH, calling deleteAll() on a single image field is also working for me, so something unusual is going on for you. A couple of ideas... 1. Is the page a "normal" page or is it a User page that involves the alternate template/parent for users feature? Your page path and field name made me wonder this. If it is an alternate user parent/template and you can identify the steps to reproduce the problem please create a GitHub issue for it. 2. Does it work if you set the field value to null instead of calling deleteAll()?
  3. You can use Ryan's ProcessDatabaseBackups module to do this. Export: Import: Without ProcessDatabaseBackups you could use PhpMyAdmin or Adminer to do something similar. If your Hanna codes reference external files (I prefer to use files for my Hanna codes so I can edit them in my IDE) then you would need to copy those to the other site too.
  4. @Christophe, glad you find it useful. Technically you don't need Custom Inputfield Dependencies if you want to show/hide a field according to the parent page ID. The PW core includes a "Parent" field in Page Edit on the "Settings" tab. This field is named "parent_id" so you can do something like this:
  5. @Christophe a module that will help with this:
  6. A module to work around a few shortcomings of Fieldset and FieldsetPage fields. Not submitted to the modules directory because I'm hopeful that most if not all of this will be handled in the core eventually. https://github.com/processwire/processwire-issues/issues/1953 https://github.com/processwire/processwire-requests/issues/533 https://github.com/processwire/processwire-requests/issues/534 Fieldset Helper Adds some visibility features to fields of type FieldtypeFieldsetOpen and FieldsetPage, and adds a helper method to get the child fields of a FieldtypeFieldsetOpen field. Visibility The module adds support for the following visibility settings to FieldtypeFieldsetOpen and FieldsetPage fields: Open when populated + Closed when blank Open when populated + Closed when blank + Load only when opened (AJAX) * Open when populated + Closed when blank + Locked (not editable) Open when blank + Closed when populated "Blank" in the context of a fieldset means that all the child fields within the fieldset are blank. * The AJAX part of this option doesn't currently work for FieldsetPage. Get the child fields of a fieldset If you've ever wanted to get the child fields that are within a fieldset you will have noticed that the ProcessWire API doesn't provide a direct way of doing this. Although they appear indented in Edit Template, the child fields are actually all on the same "level" as the other fields in the template. The module adds a FieldtypeFieldsetOpen::getFieldsetFields() method that you can use to get the child fields of a fieldset for a given page. Example: $field = $fields->get('my_fieldset'); $template = $templates->get('my_template'); $fieldset_fields = $field->type->getFieldsetFields($field, $template); First argument: the fieldset Field, i.e. a Field whose type is an instance of FieldtypeFieldsetOpen (this includes FieldtypeFieldsetTabOpen). Second argument: the Template that the fieldset field is part of. Return value: a FieldsArray of child fields. If there is a nested fieldset inside the fieldset then the child fields of the nested fieldset are not included in the return value, but of course you can use the method again to get the child fields of that fieldset. https://github.com/Toutouwai/FieldsetHelper
  7. @ttttim, as a test you could try $page->getUnformatted('field_name') and see if that is also empty. That will tell you if the issue relates to the formatValue() method or not. It's just a guess, but the saved value might be failing the test at FieldtypeDynamicOptions::sanitizeValue(). This checks the saved value against the allowed values as defined in your hook to FieldtypeDynamicOptions::getSelectableOptions(). If you temporarily change that method so that it doesn't do any sanitizing... public function sanitizeValue(Page $page, Field $field, $value) { return $value; } ...and find that you are then able to get the field value via AppApi then it means that something about AppApi is causing your hook to not return the expected selectable options. Like, maybe $page and $field are not what you would expect them to be inside the hook. You should be able to use Tracy to debug what is going on inside your hook when AppApi is involved.
  8. I've never heard of anyone using nested Hanna tags before and I don't think TextformatterHannaCode itself supports it. I tried it just now without HannaCodeDialog installed and TextformatterHannaCode didn't successfully replace the nested tags. It's too fringe for me to want to spend time on for HannaCodeDialog but seeing as your nested tags don't have any user-editable attributes you can probably use some alternative token replacement for those like wirePopulateStringTags()/WireTextTools::populatePlaceholders(). Or maybe you could play around with manually setting the dialog field value in a HannaCodeDialog::buildForm() hook. Not sure if that would work or not.
  9. @Alpina, the OP is asking how to output the field values of a page in the order that the fields are positioned in the page's template. To get the fields in order you can use $page->fields, and you can then iterate over those fields to get the field values from $page via the name of each field. As developer you generally have control over both the template within the PW admin and the template file that outputs markup. So if you have a template with fields "title", "body" and "gallery" then I think the normal way to control the order of these fields is by structuring the markup you want within the template file and then getting each field value individually by name. <h1><?= $page->title ?></h1> <div class="text"> <?= $page->body ?> </div> <div class="gallery"> <?php foreach($page->images as $image): ?> <img src="<?= $image->url ?>" alt="<?= $image->description ?>"> <?php endforeach; ?> </div> If later there is a decision to place the gallery before the body text then you change the order of the markup in the template file. You might also change the order of the fields within the template in the PW admin so that it reflects the order that fields are output in the frontend, but that's a separate decision and moving the fields in the PW admin doesn't actually define the order of output. Alternatively you could have no fixed order of output within the template file and use the order of the template fields as defined in the PW admin. <?php foreach($page->fields as $field): ?> <?php $value = $page->get($field->name); ?> <?php if($field->name === 'title'): ?> <h1><?= $value ?></h1> <?php elseif($field->name === 'body'): ?> <div class="text"> <?= $value ?> </div> <?php elseif($field->name === 'images'): ?> <div class="gallery"> <?php foreach($value as $image): ?> <img src="<?= $image->url ?>" alt="<?= $image->description ?>"> <?php endforeach; ?> </div> <?php endif; ?> <?php endforeach; ?> I just think this is a less practical approach and makes the template file harder to understand.
  10. foreach($page->fields as $field) { $value = $page->get($field->name); // Now output the value or process it as needed for output... } Seems rather impractical to me though, as you would no doubt need to do a lot of if() tests to output the right markup based on the field type and what wrapping markup is needed, etc. Much simpler to get your specific field values individually in your template file and control the order of markup there.
  11. Use the main menu to go to Modules > Configure > FieldtypeFile In the "Allowed Fieldtype modules for custom fields" field, tick the checkbox for URLLanguage. It says it may not be 100% compatible with custom fields but it seems to work fine for me.
  12. This gets the inputfield name, not the field name. The inputfield name will have a suffix when it appears inside a repeater, so checking it against a particular field name is not a reliable way to identify the field. The settings for a Page Reference field gives you an example hook for when you want to use the "Custom PHP code" option. The example shows that the best way to identify the field is via the hasField property. So for your hook: $wire->addHookAfter('InputfieldPage::getSelectablePages', function (HookEvent $event) { $page = $event->arguments('page'); if($event->object->hasField == 'refStep') { // Your hook code here... } });
  13. @adrian you probably saw already that there's a flag you can add to the rewrite rule in htaccess to allow the encoded question mark: https://httpd.apache.org/docs/current/rewrite/flags.html#flag_unsafe_allow_3f But who wants to reopen a fixed security hole? It seems like this Apache change will affect a lot of websites as the built-in URL encoding functions in JS and PHP don't make any special exception for the question mark character, and it's surely not that rare to pass an encoded URL as a GET parameter. So it seems like the options are to specifically replace the encoded question mark with ? after getting the return value from a URL encoding function, or to use a completely different encoding like Base64 if all or part of a URL needs to be used in a GET parameter. Edit: I've created a topic in the ProDevTools support forum to draw Ryan's attention to this discussion. Oh, you already PMd him so that probably wasn't necessary.
  14. Weird that you saw it on the old version, because like you say it's probably related to the changes in Apache 2.4.60 https://httpd.apache.org/security/vulnerabilities_24.html https://www.cve.org/CVERecord?id=CVE-2024-38474
  15. I haven't experienced the issue (I get normal 200 responses for User Activity requests) but it sounds like some sort of pre-emptive security blocking. If you're running WireRequestBlocker see my topic here because the default rules are quite broad. Or maybe your host has introduced some security software without notifying you? I had an irritating situation like this with Cloudways recently (thankfully resolved now).
  16. I'd like to second this. It would be great if the new/improved admin theme was built with maximum customisability in mind. One use case is so that we can more easily offer a "mostly-frontend" user an admin experience that's radically different to what a superuser or site administrator gets in the uncustomised admin. Another admin customisation issue I've struck recently is when you want to customise markup for InputfieldWrapper. There's InputfieldWrapper::setMarkup() but this is marked as internal and isn't that practical to use because InputfieldWrapper::markup is static. That means any custom markup you set there persists for all InputfieldWrappers that are subsequently rendered, when what I want to do is customise markup for a specific instance of InputfieldWrapper. Edit: pull request When the admin theme is revisited it would be great to ask of each component that's rendered, "Is there an opportunity to make this rendering customisable?"
  17. Inspired by @horst's helpful post above, here is some code for preventing guests from accessing original images that leverages more of the PW API... In .htaccess, just after "RewriteEngine On" # When original images are requested, rewrite for PHP user verification # If a matching file exists RewriteCond %{REQUEST_FILENAME} -f # And the file is within the /site/assets/files/ directory RewriteCond %{REQUEST_FILENAME} (^|/)site/assets/files/(.*?)/ # And the file extension is for an image type that we want to restrict access to RewriteCond %{REQUEST_FILENAME} \.(jpg|jpeg|gif|png)$ [NC] # And the filename portion of the path contains less than two dots (i.e. is not an image variation) RewriteCond %{REQUEST_FILENAME} !^(.+\/)?[^\/]+\.[^\/]+\.[^\/]+$ [NC] # Then rewrite to a hooked URL for user verification RewriteRule ^(.*)$ index.php?it=/original-image/ [L,QSA] In /site/ready.php // A URL hook for verifying that the user is allowed to view original images $wire->addHook('/original-image/', function($event) { $path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $ext = pathinfo($path, PATHINFO_EXTENSION); $filename = $event->wire()->config->paths->root . ltrim($path, '/'); $allowed_exts = ['jpg', 'jpeg', 'png', 'gif']; // Optional: get the Pageimage and the Page it belongs to // if this affects whether the user is allowed to view the file // $pm = $event->wire()->pages(1)->filesManager; // $pageimage = $pm->getFile($filename); // $page = $pageimage->page; // Send the file if the user is allowed to view it if( // The file extension must be one of the allowed extensions in_array($ext, $allowed_exts) && // The user must be logged in $event->wire()->user->isLoggedin() && // The file must exist is_file($filename) ) { $event->wire()->files->send($filename); } // Otherwise, return a 403 Forbidden response header('HTTP/1.0 403 Forbidden'); die('403 Forbidden'); });
  18. Logs JSON Viewer Formats JSON data in ProcessLogger for improved readability. Because log files can only contain strings, it's a common practice to use json_encode() to convert an array to a string when you want to save the data to a log file. But the resulting JSON is not as readable as it could be when viewing the log in ProcessLogger. The Logs JSON Viewer module uses the json-viewer library to improve the readability of JSON data in ProcessLogger and add some useful features. Before: After: Configuration You can set the config options for json-viewer in a textarea field. See the json-viewer readme for information about the options. There is also an option to set the width of the column that contains the JSON data. This setting exists because otherwise the column jumps around in an inconsistent and distracting way when changing from log to log or between paginations. Features You can switch the view of the JSON data between formatted and unformatted using the toggle button at the bottom of the data. The viewer has a number of useful features such as: Progressively expand or collapse levels in the data. View the count of child items and the data type of each item. Search for a string within the data. Copy all or part of the data to the clipboard (requires the HTTPS protocol). https://github.com/Toutouwai/LogsJsonViewer https://processwire.com/modules/logs-json-viewer/
  19. Thanks, and I just noticed the HelloWorld panel too. Very helpful ? That's a good solution, thanks. I missed that there is now a JSON viewing feature. That's what my upcoming module does too. Still worth releasing I think because it has some extra features and config options.
  20. Thanks. Good call, I didn't think about that panel. You don't want to be making changes and additions to Tracy Debugger for the sake of other modules. The appeal of CustomLogs might be quite niche so I'll wait for a bit, but I could perhaps look at including a panel for Tracy within the CustomLogs module. I think I remember reading somewhere that you've allowed for third-party panels - can you refresh my memory on this? And could there be a way to hook into the ProcessWire Logs panel rendering (if there isn't already)? I have another log-related module to release and I could potentially add a feature so that it applies to the Logs panel too.
  21. Custom Logs When you use the core $log->save() method you can only save a single string of text. When you view the log in the core ProcessLogger the columns and their header labels are predetermined. The Custom Logs module is different in that it lets you write and view log files with the number of columns and the column header labels you specify in the module configuration. Configuration In the "Custom logs" textarea field, enter custom logs, one per line, in the format... name: column label, column label, column label ...with as many comma-separated column labels as needed. The log name must be a word consisting of only [-._a-z0-9] and no extension. If you prefix a URL column label with {url} then the value in the column will be rendered as a link in the log viewer. The date/time will automatically be added as the first column so you do not need to specify it here. Writing to a custom log Use the CustomLogs::save($name, $data, $options) method to save data to a custom log file. $cl = $modules->get('CustomLogs'); $cl->save('my-log', $my_data); Arguments $name Name of log to save to (word consisting of only [-._a-z0-9] and no extension). $data An array of strings to save to the log. The number and order of items in the array should match the columns that are configured for the log. $options (optional) Options for FileLog::save(). Normally you won't need to use this argument. Example of use Custom log definition in the module configuration: visits: {url}URL, IP Address, User Agent, {url}Referrer Saving data to the log: $cl = $modules->get('CustomLogs'); $data = [ $_SERVER['REQUEST_URI'] ?? '', $_SERVER['REMOTE_ADDR'] ?? '', $_SERVER['HTTP_USER_AGENT'] ?? '', $_SERVER['HTTP_REFERER'] ?? '', ]; $cl->save('visits', $data); Viewing the resulting log in Setup > Logs > visits: https://github.com/Toutouwai/CustomLogs https://processwire.com/modules/custom-logs/
  22. @joe_g, you could use a similar approach to that used by the Repeater Images module. Demo... Repeater Matrix field config: Hook in /site/ready.php: $wire->addHookBefore('Pages::saveReady', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); if($page->template == 'demo_matrix_upload') { // File extension to Repeater Matrix type and subfield mapping $matrix_types = [ 'jpg' => [ 'type' => 'jpg', 'subfield' => 'image', ], 'mp4' => [ 'type' => 'mp4', 'subfield' => 'file', ], ]; // For each file in the "Upload files to Matrix" field foreach($page->upload_files_to_matrix as $pagefile) { // Skip file if it does not have an allowed file extension // It also makes sense to configure the upload field to only allow // the extensions you have matrix types for if(!isset($matrix_types[$pagefile->ext])) continue; // Add a Repeater Matrix item of the matching type for the file $item = $page->matrix_files->getNewItem(); $item->setMatrixType($matrix_types[$pagefile->ext]['type']); // Save the item so it is ready to accept files $item->save(); // Add the file $item->{$matrix_types[$pagefile->ext]['subfield']}->add($pagefile->filename); // Save the item again $item->save(); } // Remove all the uploaded files from the upload field $page->upload_files_to_matrix->removeAll(); } }); Result:
  23. I don't have a good sense of what you're doing in your code, but AFAIK Process module permissions should only be applicable to viewing the page of the Process module. I would have thought you would be able to do something like this... $m = $modules->get('MyModule'); echo $m->myMethod($foo, $bar); ...regardless of if the current user is guest or not. But great that you've found a solution.
  24. I suggest using URL hooks for any requests coming from the front-end. It wouldn't be ideal to have front-end requests going to a Process module page in any case because that would decrease site security by publicly revealing the admin login URL.
  25. Awesome module @ryan! Could the module include an option to style custom children differently to genuine children? Or maybe add a special class to custom children items so we can target them in custom admin CSS. And for advanced cases, a hookable method so custom children items could be identified and potentially modified when rendered in Page List.
×
×
  • Create New...