Jump to content

Robin S

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Robin S

  1. @CrazyEnimal, please insert your code inside a code block in forum posts. You can use SQL in ProcessWire when it suits you. That's what the $database API variable is for. Here is one way you could get a listing of manufacturers with the number of occurrences within a selection of cars. // Get the IDs of the cars $car_ids = $pages->findIDs("parent=$parent, template=page_car, dealer=$dealer_id"); // Get table for manufacturer Page Reference field $table = $fields->get('manufacturer')->getTable(); // Get manufacturers that are selected in the car pages $query = $database->query("SELECT data FROM $table WHERE pages_id IN (" . implode(',', $car_ids) . ")"); $manufacturer_ids = $query->fetchAll(\PDO::FETCH_COLUMN); // Count how many times each manufacturer occurs in the results $manufacturer_occurrences = array_count_values($manufacturer_ids); // Sort the results in order of occurrences, highest to lowest arsort($manufacturer_occurrences); // Get the manufacturer pages $manufacturers = $pages->getById(array_keys($manufacturer_occurrences)); // Output a list of manufacturer titles and the number of occurrences foreach($manufacturers as $manufacturer) { echo "<p>{$manufacturer->title} ({$manufacturer_occurrences[$manufacturers->id]})</p>"; }
  2. Assuming the categories are assigned to locations by a Page Reference field named "categories": $locations = $pages->find("template=location"); foreach($locations as $location) { foreach($location->categories as $category) { echo "<marker title='$location->title' category='$category->title'/>"; } }
  3. In PW you cannot have multiple sibling pages with exactly the same name. That's why the pages are automatically renamed - otherwise you would see an error message.
  4. Maybe it's a matter of rethinking this in light of what the real objective is. I'm guessing that when the notify_user checkbox is checked and the page is saved, something happens - some sort of action that notifies a user. You're saying that you want to force the notify_user checkbox to be in a checked state if the categories field is changed, presumably to force the action to happen. So why not just do the action if the categories field has changed? $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); // If the notify_user checkbox is checked or the categories field value has changed... if($page->notify_user || $page->isChanged('categories')) { // Do the notify user action... } });
  5. Since this thread was started a hasPage property has been added to Inputfield instances in PW. So you can do this: $wire->addHookBefore('Inputfield::render', function(HookEvent $event) { /* @var Inputfield $inputfield */ $inputfield = $event->object; $page = $inputfield->hasPage; if($page) { // Use $page bd($page->name, 'page name'); } });
  6. The new FormBuilder features look very nice, thanks! Lots of questions spring to mind... 1. When using Form A within a Form B, is it possible to override any of the field settings of Form A in the context of Form B? Say, if I was using Form A inside several other forms but I needed one of the fields to be required only within Form B. 2. Is it possible to have show-if and required-if dependencies on fields within Form A that depend on the values of fields within Form B? 3. In a paginated form, are the form values submitted to the server each time Next / Back is clicked? So is each page validated independently and the user cannot move forward until the current page validates, or is all the validation done on the final submit? 4. If each page is submitted/validated independently, can a site admin see partial form submissions in Entries that are abandoned before the final submit button is clicked? 5. Or if the form is only submitted/validated after all pages are completed, how are field errors displayed if they occur on multiple different pages in the form? 6. Is it planned to have an overview navigation of the pagination using the page headings, so a user can jump directly to any previous page in form and can see how far they have progressed through the total form? 7. Do the different pages "know" about the values entered into other pages in the form, so show-if and required-if can depend on values in other pages? Probably I just need to wait until the new version is released. 🙂
  7. This means that there is no property "page" on $event->argument(0). The first and only argument to InputfieldPage::getSelectablePages() is: @param Page $page The Page being edited This is the page that's open in Page Edit, regardless of whether the Page Reference field is inside a Repeater or not. So probably you don't need to use getForPage() in your situation.
  8. FormBuilder has just such a setting: Although strangely if I change this setting it doesn't stick and always returns to "Auto-detect" - might be a bug. For controlling the WireMail mailer used by other modules perhaps the recently released Mail Router module could be a solution. Although the module that is sending the mail can't be detected directly, for some circumstances you could perhaps use a prefix in the subject line (e.g. "Form submission: ...") that could determine which WireMail mailer is used.
  9. I forgot to mention that you must enable URL segments on the uppy template. I've updated my previous post to include this step. Although I'm not sure why you would get a 403 because of that - rather you should get a 404.
  10. Here's a basic example of how you could save files to a PW page via a front-end page using tus-php and Uppy. 1. Install tus-php via Composer. 2. Create a PW template that will provide the tus-php server endpoint - in this example the template is named "uppy". In the template Files tab, disable any automatically appended template file. In the template URLs tab, allow URL segments. If using Tracy Debugger, disable the debug bar in the front-end for this template because we don't want any output from Tracy being included in the response. The contents of the uppy.php template file: <?php namespace ProcessWire; // Create PW temp directory $td = $files->tempDir('uppy'); $td_path = (string) $td; // Create TusPhp server $server = new \TusPhp\Tus\Server(); // Set path to endpoint - no trailing slash here $server->setApiPath('/uppy'); // Set upload directory $server->setUploadDir($td_path); // Listener function for when an upload is completed $server->event()->addListener('tus-server.upload.complete', function(\TusPhp\Events\TusEvent $event) { // Get path of uploaded file $file_path = $event->getFile()->getFilePath(); // Add uploaded file to "files" field on Home page $p = wire('pages')->get(1); $p->of(false); $p->files->add($file_path); $p->save('files'); }); // Send response $response = $server->serve(); $response->send(); // Exit from current PHP process // Could probably use PW halt here as an alternative // return $this->halt(); exit(0); 3. Create a page using the template - in this example the page is at url http://1testing.oo/uppy/ 4. Add the Uppy assets, JS and markup to the template of the front-end page that you will upload files from. Markup Regions are used in this example. <pw-region id="scripts"> <script src="https://transloadit.edgly.net/releases/uppy/v1.4.0/uppy.min.js"></script> <script> const uppy = Uppy.Core({debug: true, autoProceed: false}) .use(Uppy.Dashboard, {target: '#uppy-box', inline: true}) .use(Uppy.Tus, {endpoint: 'http://1testing.oo/uppy/', limit:10}); </script> </pw-region><!--#scripts--> <pw-region id="stylesheets"> <link href="https://transloadit.edgly.net/releases/uppy/v1.4.0/uppy.min.css" rel="stylesheet"> </pw-region><!--#stylesheets--> <div id="body"> <div id="uppy-box"></div> </div><!--#body--> 5. Upload files via the front-end and see that they are added to the "files" field on the Home page.
  11. I always use the "Server directory" option because I'm using the profiles locally and so there's no point in an extra zipping/unzipping stage. So could be a bug with the ZIP export option.
  12. This part is optional - it's exists in case you want your server endpoint to be something pretty like http://yourdomain.com/files/ But if it's causing you a problem you can leave out the tus-php .htaccess and set your endpoint to http://yourdomain.com/server.php or whatever with no rewrite needed.
  13. You can simplify that a bit to this... $classname = $event->arguments[0]; if($classname !== $this->className) return; // Only continue if settings of this module are being saved.
  14. Ryan's ProcessExportProfile module includes ready.php in the exported files. Based on your other comment, I think there may have been an error during the export process because I frequently install profiles exported by this module without any problems.
  15. This is why I think we need a field aliases feature. I have a working module that allows the use of field aliases anywhere in template files and in /site/ready.php and /site/init.php, but issues with the File Compiler need to be fixed before the module can be released.
  16. As the name would suggest, it's triggered when the input values in the Page Edit form are processed. 🙂 There aren't really any circumstances when page data will not be saved when the Page Edit form is submitted, apart from a fatal PHP error due to some mistake in your code. The situations where a page save might be attempted but not actually occur are outlined in this code, but these are only likely to happen when a page is being saved via the API. Are you thinking of warnings caused by empty required fields? Because page data is still saved in that case. But if you don't want an email to be sent if there are empty required fields you can check to see if there are any form errors: // Return early if there are any form errors if(count($form->getErrors()) return;
  17. ProcessPageEdit::processInput() calls itself recursively for every instance of an InputfieldWrapper found within the form, incrementing $level for each nesting. But because we know we have added the notify checkbox field at the top level there's no point in looking for it within any nested InputfieldWrapper.
  18. A couple of hooks for /site/ready.php: $wire->addHookAfter('ProcessPageEdit::buildFormContent', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->return; // Maybe return early if page does not use a particular template /* @var ProcessPageEdit $ppe */ $ppe = $event->object; /* @var Page $page */ $page = $ppe->getPage(); if($page->template != 'basic_page') return; // Add checkbox field /* @var InputfieldCheckbox $f */ $f = $event->wire('modules')->InputfieldCheckbox; $f->name = 'notify'; $f->label = 'Notify users about changes'; $form->add($f); }); $wire->addHookAfter('ProcessPageEdit::processInput', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->arguments(0); // We only care about the top-level form $level = $event->arguments(1); if($level) return; // Get the notify field $notify = $form->getChildByName('notify'); // Return early if notify field doesn't exist or isn't checked if(!$notify || !$notify->value) return; // Now send the email notification... // Your code here });
  19. The notes on the Settings tab of Page Edit are a good summary of what the statuses mean: Hidden and unpublished pages are both excluded from selectors (unless you override this) - the difference is that a hidden page is viewable if the URL is known, whereas an unpublished page cannot be viewed unless the user is logged in and has edit access for the page.
  20. A RepeaterPageArray is a type of WireArray so it should work as is. And it's working for me so double-check your code (e.g. invisible characters from forum copy/paste).
  21. This is when you gotta do some debugging. Some things to try... Set $config->debug to true to make sure you are seeing error messages. Install Tracy Debugger - the debug bar is great at catching error/warning messages that debug mode sometimes misses. Dump $items with Tracy Debugger to see if there's actually any pages in there: bd($items); Not sure if the line of code you showed is just a demo or your real code, but 111 is not going to be the ID of a front-end page because these start at 1000. Welcome to the forums BTW 🙂
  22. Hi @Soma, Could you please add this very useful module to the PW modules directory? Thanks!
  23. Using the brand new "multiple methods" hook feature in PW 3.0.137 you could save the average stars value to a decimal (or float) field every time a comment is approved/disapproved/updated/deleted. Then you can find or sort pages by the field more efficiently. The hook below assumes a comments field named "comments" and a decimal field named "decimal": $wire->addHookAfter('FieldtypeComments::commentApproved, FieldtypeComments::commentUnapproved, FieldtypeComments::commentDeleted, FieldtypeComments::updateComment', function(HookEvent $event) { /* @var Page $page */ $page = $event->arguments(0); /* @var Field $field */ $field = $event->arguments(1); if($field->name !== 'comments') return; if($page->template->hasField('decimal')) { // Save the average star rating for comments with approved or featured status $page->setAndSave('decimal', $page->comments->find("status=1|2")->stars(true)); } }); P.S. You'd do a one-off API operation to save the average stars value for all your existing comments to get things set up initially.
  24. Here's a slightly different approach. Assumes an image field named "images" and a CKEditor field named "body". foreach($page->images as $image) { // Get the image URL excluding the file extension (to account for image variations) $match_url = substr($image->url, 0, -strlen($image->ext)); // Skip the image if the match URL occurs at the start of a src attribute in $page->body if(strpos($page->body, "src=\"$match_url") !== false) continue; // Output the image or whatever echo "<img src='{$image->width(300)->url}' alt='$image->description'>"; }
  25. It's working as expected for me. You're not including the quote marks around the value by any chance are you? If -10:+10 is actually the value you want you can leave the setting empty because that is the default.
  • Create New...