Jump to content

Robin S

Members
  • Posts

    5,013
  • Joined

  • Days Won

    335

Everything posted by Robin S

  1. I'm surprised a textarea field value can be null rather than an empty string. Maybe something to do with multi-language. I'm casting $text to string in v0.1.3 so hopefully fixed. Thanks for the report.
  2. Good idea, I've done that in v0.1.2
  3. @adrian, I've added most of your requests in v0.1.1. But not the colour-coding because the results don't fall into universal good or bad categories - it depends on the intended audience, e.g. you would expect a high grade level on a website for an academic journal.
  4. Text Readability A module that uses the PHP Text Statistics class to evaluate the readability of English text in textarea fields according to various tests. The available readability tests are: Flesch Kincaid Reading Ease Flesch Kincaid Grade Level Gunning Fog Index SMOG Index Automated Reability Index Spache Readability Score Dale Chall Readability Score Coleman Liau Index The results of the enabled tests are displayed at the bottom of textarea fields – either when the "book" header icon is clicked, or at all times, depending on the option selected in the module configuration. An interpretive tooltip appears when you hover any of the result values. Requires ProcessWire >= 3.0.246 and PHP >= 7.2.0 Why is readability important? Readable.com says: And: The Wikipedia article on readability has useful information too. Module configuration Select which readability tests you want to enable. For each test there is an "about" link to information about the test. Select whether the results of the enabled readability tests should be shown only when the header action icon is clicked (default), or if the results should always be shown. For multi-language sites, select which ProcessWire language represents English (as the tests are only intended for English text). Advanced If you want to disable the readability test results for a particular textarea field you can hook TextReadability::allowReadabilityResults. Example: $wire->addHookAfter('TextReadability::allowReadabilityResults', function(HookEvent $event) { $field = $event->arguments(0); $page = $event->arguments(1); // Disable readability results for the "body" field on the "home" page if($field->name === 'body' && $page->template == 'home') $event->return = false; }); https://github.com/Toutouwai/TextReadability https://processwire.com/modules/text-readability/
  5. Have you looked at this module? https://processwire.com/modules/wire-mail-gmail/
  6. Which approach to take depends on where you want the added markup to appear, relative to things like description and notes. Demo: $wire->addHookBefore('InputfieldText::render', function(HookEvent $event) { /** @var InputfieldText $inputfield */ $inputfield = $event->object; if($inputfield->name !== 'text_1') return; $inputfield->prependMarkup('<div>prependMarkup</div>'); $inputfield->appendMarkup('<div>appendMarkup</div>'); }); $wire->addHookAfter('InputfieldText::render', function(HookEvent $event) { /** @var InputfieldText $inputfield */ $inputfield = $event->object; if($inputfield->name !== 'text_1') return; $event->return = '<div>before render</div>' . $event->return . '<div>after render</div>'; }); Related request: https://github.com/processwire/processwire-requests/issues/536
  7. @Morphosis, the value of a populated "single" Page Reference field... ...is a Page object. So it's redundant to get the ID of the Page Reference field value and then get the Page object from the ID, because you already have the Page object. So you probably want something like this: // If the Page Reference field is populated (i.e. its value is not a NullPage having an ID of zero) // and there are some images uploaded to the selected page if($page->gallery_cta_source->id && $page->gallery_cta_source->gallery_images->count) { // Then output the images foreach($page->gallery_cta_source->gallery_images as $image) { // ... } }
  8. Assuming that the field would be changed in Page Edit rather than as result of some other API code, you can validate the user input in a hook to InputfieldText::processInput. Example: $wire->addHookBefore('InputfieldText::processInput', function(HookEvent $event) { $inputfield = $event->object; $input = $event->arguments(0); $field = $inputfield->hasField; $page = $inputfield->hasPage; // For a particular field name and template name if($field && $field->name === 'text_1' && $page && $page->template == 'events') { $old_value = $page->getUnformatted('text_1'); // Return early if the old value is empty if(!$old_value) return; $new_value = $input[$inputfield->name]; // If the first three characters have changed if(substr($new_value, 0, 3) !== substr($old_value, 0, 3)) { // Show an error message $inputfield->error('You are not allowed to change the first three characters of the "Text 1" field.'); // Replace the hooked method so the new value won't be saved to the field $event->replace = true; } } });
  9. No, because this module is a helper for the admin interface. Doing bulk operations on a set of pages is what the PW API is for. The key method you would use for this is Pageimages::add(). The basic idea assuming two different pages are involved: // Get the first page in whatever way you like $p_1 = $pages(1234); // Turn off output formatting $p_1->of(false); // Get the image from the image_1 field // The first() method is used because the value of an image field // is always a Pageimages object when output formatting is off $image = $p_1->image_1->first(); // Get the second page in whatever way you like $p_2 = $pages(1235); // Turn off output formatting because you are about to change a field value $p_2->of(false); // Add the image to the image_2 field on the second page // This is an example of Pageimages::add() $p_2->image_2->add($image); // Save the change to the second page $p_2->save('image_2'); // Now perhaps you want to remove the image from the first page? $p_1->image_1->remove($image); $p_1->save('image_1'); If you are copying between two fields on the same page you'll have to work around this issue: https://github.com/processwire/processwire-issues/issues/1863 In FileMover I deal with this by calling Pagefile::install(): https://github.com/Toutouwai/FileMover/blob/0020e365557730e59bad87286548e69f562be0d8/FileMover.module.php#L165-L166 The filename will then be automatically incremented. The incremented filename is something you'll want to consider if anything is linking directly to the image as the link will be broken once you remove the original image. Of course you'll want to test everything carefully in a safe environment before you do any bulk operation on a live site. If it all sounds too difficult or risky, then consider if it's even necessary. Why not just keep two different image fields instead of consolidating them into one?
  10. I'm not sure what the technical reason is for the 404 not being handled from ready.php, but as a workaround you could set a custom property on the $page object to indicate that a 404 should be thrown and then throw the 404 later, e.g. from a template file or from _main.php. // Your conditional in ready.php if($foo === 'bar') $page->throw404 = true; // In template file or _main.php if($page->throw404) wire404();
  11. I'm not aware of anything changing that would make this module redundant, but it will be easy for you to check and find out. When using the Image & File Dependencies module, if your image field is named "image" you would use the selector string: _image>0
  12. @dragan, this module works by hooking into Pageimage::size(), so it's only going to create an AVIF version of images that have been through some Pageimage sizing method.
  13. The docs for the feature say: So if the URL being loaded is the URL for an actual page (regardless of whether it has a template file or not) then no URL Segment is going to apply. And if the URL resolves to a "car" page then the template file that's rendered won't actually be "car-maker.php" where your URL Segment code exists. If there's a car template file then it will be "car.php" that's rendered, and if there's no car template file then it will be whatever template file applies to your "404 Not Found" page.
  14. @Fuzzy, you might something useful in these posts:
  15. Thanks. No, because the icons are in a column labelled "Actions", with each icon representing an action you can take rather than a status that the PageTable item has. Plus the module has had its conventions for 8 years now and it would be pretty confusing for existing users if the icons suddenly reversed their meanings.
  16. You might be interested in these modules too: https://processwire.com/modules/page-edit-per-user/ https://processwire.com/modules/page-edit-per-role/
  17. It seems to work if you allow edit access on the parent template in the normal way via the PW admin... ...and then disallow editing on the parent template in a hook to Page::editable() $wire->addHookAfter('Page::editable', function(HookEvent $event) { /** @var Page $page */ $page = $event->object; $user = $event->wire()->user; // Return early if PW has already determined that the user is not allowed to edit if(!$event->return) return; // Don't allow users with the "editor" role to edit pages with the "colours" template if($page->template == 'colours' && $user->hasRole('editor')) $event->return = false; });
  18. You can use a hook in /site/ready.php to set the page that images will be selected from, if you want it to be different than the default. The hook will work for both CKEditor and TinyMCE. $wire->addHookBefore('ProcessController::execute', function(HookEvent $event) { $input = $event->wire()->input; $page = $event->wire()->page; $pages = $event->wire()->pages; // Return early if the process is not ProcessPageEditImageSelect if(!$page || $page->process != 'ProcessPageEditImageSelect') return; // The ID of the page that is open in Page Edit $edit_page_id = (int) $input->get('edit_page_id'); // The ID of the page that images will be selected from by default // Often this is the same as $edit_page_id, but it can be different in the case of Repeater items, etc. $images_page_id = (int) $input->get('id'); // Check that the $edit_page_id is populated, otherwise the user will not // be able to manually choose a different page to select images from if(!$edit_page_id) return; // Optionally do some test using $edit_page_id and/or $images_page_id $edit_page = $pages->get($edit_page_id); if($edit_page->template != 'basic_page') return; // Set a different ID for the page that images will be selected from // e.g. select images from the home page $input->get->id = 1; });
  19. I'm not sure if it's a solution to your issue, but I have this hook in every site (see the referenced issues for background): // Instead of rebuilding image variations, remove them and they'll be rebuilt when next requested // Fix for: https://github.com/processwire/processwire-issues/issues/1301 // Also see: https://github.com/processwire/processwire-issues/issues/1277 $wire->addHookBefore('Pageimage::rebuildVariations', function(HookEvent $event) { /** @var Pageimage $pageimage */ $pageimage = $event->object; $event->replace = true; $pageimage->removeVariations(); // Return expected output to avoid errors $event->return = [ 'rebuilt' => [], 'skipped' => [], 'reasons' => [], 'errors' => [], ]; }); It's only safe to do this if you do not allow image variations to be directly inserted into RTE fields. More info in this comment: https://github.com/processwire/processwire-issues/issues/1301#issuecomment-893957331
  20. $pages->findRaw() will be helpful here. It's hugely faster than $pages->find() and easier to work with than SQL queries. You could do a couple of searches and connect the resulting data by repeater page ID. Example: // Ensure PagePaths module is installed so that URL is available to findRaw() $shop_data = $pages->findRaw("template=shop", ['title', 'url', 'locations'], ['nulls' => true, 'flat' => true]); // Here you could also get other fields from the repeater pages as needed $location_data = $pages->findRaw("template=repeater_locations, check_access=0", ['location'], ['nulls' => true, 'flat' => true]); $shops = []; // Loop over the shop data and get the lat/lng for each location, matching by repeater page ID foreach($shop_data as $id => $item) { $data = [ 'title' => $item['title'], 'url' => $item['url'], 'locations' => [], ]; $location_ids = explode(',', $item['locations.data']); foreach($location_ids as $location_id) { if(!isset($location_data[$location_id])) continue; $data['locations'][] = [ 'lat' => $location_data[$location_id]['location.lat'], 'lng' => $location_data[$location_id]['location.lng'], ]; } $shops[$id] = $data; } db($shops);
  21. @Macrura, I'm not sure if your issue is the same as the caching issue that @adrian recently reported in the GitHub repo, but I've found a way to do some cache-busting in v0.5.2 so please try upgrading and see if that solves it. If not, could you please open a GitHub issue and we can continue the conversation there?
  22. @Macrura, great, thanks.
  23. Hi @Macrura, I can't reproduce that here. Could you please help with debugging by doing a couple of Tracy dumps after this line? bd($hanna_tags, "hanna_tags"); bd($tag_name, "tag_name"); For the Tracy bar to appear in the dialog you'll need to allow it in the module config, and maybe make the dialog a bit bigger than the default so it's easier to see the dump results.
  24. Maybe this is safe, but it looks very risky to me. The ID here is coming from the URL, which is a type of user input. You would want to be 100% certain someone can't insert the default superuser ID 41 into the URL and then get logged in without a password and gain full access to the admin.
×
×
  • Create New...