Jump to content

Marc

Members
  • Posts

    103
  • Joined

  • Last visited

Everything posted by Marc

  1. I have added a custom settings page to my admin using the ready.php method described here. The page I added under admin has the ProcessPageEdit process and its ID get swapped with another page in ready.php. This works fine but when I click on the new button, it does not get the 'active' state, unlike the standard admin buttons like 'pages', 'settings', etc, which get a CSS class making them white (depending on default theme settings) so you can see where you are in the topnav menu. I would like this for my custom button as well, but how? Is there perhaps an API call to do this in ready.php? Here's my ready.php: if ($page->template == "admin" && $page->name == "settings-appearance") { $input->get->id = $pages->get("/settings-appearance/")->id; } Screenshot:
  2. I have a bunch of fields that have a label that is overwritten by the context of the template the fields belong to. So outside of the template these field have a different label from inside the template. I want to keep the outside label intact and overwrite the template-specific labels with the API. So how would I turn the code below into something that sets a new label for only the template context? $f->set("label", "new value"); $f->save();
  3. Revising the problematic part of the code I posted in the OP, here's the new and improved part: if ($field->type == "FieldtypePage") { $table = wire('fields')->get($field->id)->getTable(); $query = wire('database')->query("SELECT tbl.pages_id, tbl.data, COUNT(*) FROM $table AS tbl INNER JOIN pages AS p ON tbl.pages_id = p.id INNER JOIN templates AS t ON p.templates_id = t.id WHERE t.id = '{$template->id}' GROUP BY data" ); $ids = $query->fetchAll(PDO::FETCH_NUM); // Multidimensional array (2 levels) [0] => array(2047, 4419, 12). The second level corresponds to the selected columns in the query. // Add options that are in use by our products to a whitelist. foreach ($ids as $item) { $whitelist[]= $item[1]; } $options = $inputfield->getInputfield()->getOptions(); // Returns simple assoc array [4777] => dieren, [4778] => tweeling, etc. // Remove unsued options from the field. foreach ($options as $pageID => $pageTitle) { if ( !in_array($pageID, $whitelist) ) { $inputfield->getInputfield()->removeOption($pageID); } } if (!count($ids)) continue; // No pages are using any of the option of this field, so don't add it to our form. } This shaves off about 100 ms of of 150 ms, so it's pretty darn fast compared to the way I did it before. I suppose maintaining a counter as suggested by BitPoet may be even faster, I'll have to compare it someday. Thanks everyone!
  4. Thanks for the hints (especially FETCH_NUM), I got it working without the extra queries. I will do extensive testing tomorrow and report back
  5. Oh I see, yeah I forgot about that. But how do I use that counter in the context of the $items array? In other words how do I check the counter after the query is done?
  6. I had a go and this is what I came up with (I have to take the template into consideration like you said): $table = wire('fields')->get($field->id)->getTable(); $query = wire('database')->query("SELECT tbl.pages_id, tbl.data, p.id, p.templates_id, t.id FROM $table AS tbl INNER JOIN pages AS p ON tbl.pages_id = p.id INNER JOIN templates AS t ON p.templates_id = t.id WHERE t.id = '{$template->id}' GROUP BY data" ); $ids = $query->fetchAll(PDO::FETCH_COLUMN); $items = wire('pages')->getById($ids); foreach (wire('pages')->get($field->parent_id)->children() as $option) { // Parent_id is the parent page whose child pages are listed as options for this field. $frequency = $items->find("{$field->name}={$option->id}")->count(); // Count pages using the field and current option, and of course the template of the correct product (which is any child of the current page). if ($frequency == 0) $inputfield->getInputfield()->removeOption($option->id); // Remove the option from the field. } This saves about 20 milliseconds (of 150), so it's not as efficient as I'd hoped. Unless I'm doing it wrong?
  7. I don't think I understand, is that supposed to give you a pageArray with all the pages using the options of a given field? I tried to apply it to my situation but I get an array with the options of my fields. Not sure how to properly implement this: if ($field->type == "FieldtypePage") { $table = $field->getTable(); $query = wire('database')->query("SELECT data FROM $table GROUP BY data"); $ids = $query->fetchAll(PDO::FETCH_COLUMN); $items = wire('pages')->getById($ids); echo $items->implode("\n", "<a href='{url}'>{title}</a>"); $i = 0; foreach (wire('pages')->get($field->parent_id)->children() as $option) { // Parent_id is the parent page whose child pages are listed as options for this field. $frequency = $items->count("{$field->name}={$option->id},template=$template"); // Count pages using the field and current option, and of course the template of the correct product (which is any child of the current page). echo "$frequency<br>"; $i = $i+$frequency; if ($frequency == 0) $inputfield->getInputfield()->removeOption($option->id); // Remove the option from the field. } if ($i == 0) continue; // No pages are using any of the option of this field, so don't add it to our form. }
  8. That's a nice little tip, works just as you described. Looks like it shaved off a few milliseconds too $p = new Page(). I do this because I want blanc input fields, not pre-filled inputs from my product pages. Suggestion nr 1 would be highly unpractical for the person entering new products, but yeah I see how it would speed things up. Your second suggestion sounds like good idea, I will look into it!
  9. This one is tough to explain in one line so please bear with me. I'm building a list of about 700 (paginated) products. You can filter the list based on the fields of the products' template (they all have the same template). There's a field for color, material, theme, etc. These are page fields, so their options are stored as pages. So page 'color' has child pages blue, red, white, etc. The filter gets all the fields from the template and adds them to a nice PW form automatically, so I don't have to list anything manually. This is the part I have working. What I am adding is a way to exclude any option that is not currently used by any product. So if no product has the color red in its color field, I want to remove that option. I have managed to get this working also, but the way I'm doing seems wrong to me, as I'm doing a query for every option of every field, so if I have 10 fields with 5 options each, that is 50 queries and it is adding about 150 ms to my page load. So my question is, is there a more efficient way to check which page options are not in use by my product pages? Are there other obvious mistakes I'm making? Here's what I've got so far, it's part of a function so I'm wiring some things in: $template = wire('templates')->get($page->child()->template); $fields = $template->fieldgroup; foreach($fields as $field) { $inputfield = $field->getInputfield($p); if (in_array($inputfield->name, $ignorefields)) continue; if (substr($inputfield->name, 0, 5) !== "meta_") continue; // Only list those whose name starts with "meta_". $inputfield->description = ""; // Remove descriptions. // Now check if this field is stored in our $inputs array. If it is, check the type of this field and act accordingly. if (array_key_exists($field->name, $inputs)) { if ($field->type == "FieldtypeCheckbox") { if ($inputs[$field->name] == 1) { $inputfield->attr('checked', 'checked'); } } else if ($field->type == "FieldtypePage") { $values = $inputs[$field->name]; $inputfield->attr('value', $values); } } /** THIS IS WHERE THINGS COULD HOPEFULLY BE IMPROVED **/ if ($field->type == "FieldtypePage") { $i = 0; foreach (wire('pages')->get($field->parent_id)->children() as $option) { // Parent_id is the parent page whose child pages are listed as options for this field. $frequency = wire('pages')->count("{$field->name}={$option->id},template={$page->child()->template}"); // Count pages using the field and current option, and of course the template of the correct product (which is any child of the current page). $i = $i+$frequency; if ($frequency == 0) $inputfield->getInputfield()->removeOption($option->id); // Remove the option from the field. } if ($i == 0) continue; // No pages are using any of the option of this field, so don't add it to our form. } $form->add($inputfield); }
  10. I'm using the latest master version, so version 2.7.2. I don't understand why the PW developers would not be able to reproduce it though, as I first encountered it with my current project and still encounter it doing a brand new, unmodified install just for testing this bug.
  11. Thanks for the heads up. It's a shame there's no fix after all this time.
  12. So I did a new install of Processwire just for testing this issue, and no matter what I do, I can not get anybody but the superuser to add pages to a pageTable field when the parent of those pages is a user page. I guess I will have to come up with another place to store those pageTable pages then.
  13. That would be the user template in this case, which already has all permissions checked. The pages are actually created in the correct location, but they are not added to the pageTable array so I have to add them manually after the page is saved. (I get the "Children were found that may be added to this table" message in that case.)
  14. I am trying to add information about users of my website to a pageTable field called 'user_notes', which I added to the 'user' template. The parent of the pageField pages is a user, so every user can have child pages with a 'note' template. Adding new notes to this pageTable works great when I'm logged in as the superuser, but when I try to do this logged in as a 'planner' user, the child pages are created but they are not added to the pageTable array. I'm not sure why, as I've been looking at every involved permission setting and I just can't seem to find out what might be going wrong. Here are some details: I have created a user role called 'planner'. It has all the 'page-edit' (sub)permissions. I have a pageTable field called 'user_notes'. The pageTable 'user_notes' creates pages under a 'user' with a 'note' template. The 'planner' role has all permissions to edit/create pages using this 'note' template.
  15. Just thought I'd add the solution to this problem, for reference. Turns out there's a file called /site/assets/cache/LazyCron.lock (or something along those lines) preventing the cron functionality from working when there are PHP errors in my cron logic, which can happen during development of course. Fixing the errors and deleting the lock file restores functionality.
  16. Looks like I still don't quite understand. In a regular template file I added these tests, trying to remove a page from 'user_notes' which is a PageArray field: $note = $pages->get(1259); $customer = $note->parent; $customer->user_notes->remove($note); $customer->of(false); $customer->save('user_notes'); ^ Result: no error, but PageArray is not updated. $note = $pages->get(1258); $customer = $note->parent; $customer->of(false); $customer->user_notes->remove($note); $customer->save('user_notes'); ^ Result: "Field 'user_notes' from page 1172 is not saveable because it is a formatted value." $note = $pages->get(1258); $customer = $note->parent; $customer->user_notes->remove($note); $customer->of(false); $customer->user_notes->remove($note); $customer->save('user_notes'); ^ Result: PageArray is successfully updated. Why would I have to use the 'remove' method twice in order for this to work?
  17. It's something I'll keep in mind. Output format should be off before modifying a pagearray, check.
  18. Fixed it by switching these lines around: $customer->of(false); $customer->user_notes->add($newNote); Now it works as expected. Strange it works in the other order on another page, but there you go.
  19. I have a template file that receives some form data that I save to a pageTable field. I use the pageTable to add notes to user profiles, so every user can have child pages containing a note and a date. Here's what I use: $notes = $input->post->textarea('notes'); // Passed via javascript. $customerId = $input->post->int('id'); $customer = $users->get($customerId); $newNote = new Page; $newNote->template = 'user-notes'; $newNote->parent = $customer; $newNote->of(false); // turn off output formatting before setting values $newNote->save(); $newNote->title = 'user note'; $newNote->notes_date = date('Y-m-d H:i:s'); $newNote->notes = $notes; $newNote->save(); // So far so good, but this bit does not work: $customer->user_notes->add($newNote); $customer->of(false); $customer->save('user_notes'); // Just as an example, this part DOES work: $customer->gender = 2; $customer->save('gender'); The child page is created but it is not added to the user's 'user_notes' pageTable. If I place this code in my admin module, it works as expected. Any ideas what could be going wrong? Edit: fixed it by switching these lines around: $customer->of(false); $customer->user_notes->add($newNote); Now it works as expected. Strange it works in the other order on another page, but there you go.
  20. Thanks for the suggestions guys, but it turned out not to be a cache or permission problem: I had set the page to 'unpublished' because I want nobody but an automated cron job to use that page. Publishing the page enables lazy cron to start working. Edit: it worked a few times (as in the log was updated with a few new entries), but now it stopped working. Refreshing the page with the cronjobs.php template does absolutely nothing as far as the lazy cron is concerned If I write to the log file directly in this template, it works just fine, for example wire('log')->save("cronjobs", "Cronjobs template executed."); Edit 2: the cron started working again after I put some extra output in the cronjobs.php template. So it seems like if there is no output in a template (e.g. echo "hi"), the template file won't be processed. This is in the default PW multilanguage setup (with _main.php and _init.php automatically prepended to templates).
  21. I have a template called cronjobs.php. All it has (for now) is this super simple laze cron cal that attempts to write an entry to a processwire log file: function cronTest(HookEvent $e) { wire('log')->save("cronjobs", "Cronjobs executed."); } // add a hook to your function: wire()->addHook('LazyCron::every30Seconds', null, 'cronTest'); This does not work (no entry is ever added to the 'cronjobs' log file (despite me refreshing the page with the cronjobs.php template a hundred times). Am I doing something wrong?
  22. That's what I feared. Thanks for the confirmation. I'll use my own solution then
  23. Well yeah, that's the PHP part of the ajax function, but to display the actual message without refreshing the page some javascript magic will have to happen. I'm sorry if I didn't make myself clear, but the real question is: is there a build in javascript function I can use to display these messages? I would like to use that instead of my custom functionality if possible. Like there is for the SystemNotifications module, as Ryan explains here. I tried that module but for my purposes it's not the right fit.
  24. I'm working on an admin module and I'm using the build in notification system for messages, errors and warnings, which works great. Some of my forms are handled by ajax however, and it would be nice if there was a javascript equivalent of $page->message("hi there"), like there is for the SystemNotifications module. (Which works like Notifications.message("Message to send").) I currently have a custom notification system for ajax in place, but it would be nice if I could use something purely PW. Can this be done?
×
×
  • Create New...