• Content Count

  • Joined

  • Last visited

  • Days Won


BitPoet last won the day on November 12

BitPoet had the most liked content!

Community Reputation

1,979 Excellent

1 Follower

About BitPoet

  • Rank
    Hero Member

Profile Information

  • Gender
  • Location
    Near Munich / Germany
  • Interests
    programming, writing, scuba diving, long distance hiking

Recent Profile Visitors

5,206 profile views
  1. Thanks. I'm not completely sure if I read your question right. The screencap above shows the front end form (it's just included in the backend interface on the preview tab, but it's the same as if you embed your form anywhere on the frontend).
  2. Am I right in assuming that a call to $pages->uncacheAll() between the two parts makes it work?
  3. I guess it should be doable by extending WireDT accordingly and implementing fitting getDatabaseSchema and savePageField/loadPageField methods as well as making sleepValue/wakeupValue with arrayish data instead of plain strings, a lot like the Events fieldtype but without the multiple value (EventsArray) stuff. Meanwhile reproduced and working on a solution. Should be ready in a few days at most. Meanwhile, I haven't been completely lazy: DatetimeAdvanced v1.0.3 supports custom subfields and works together with Lister's subfield selectors.
  4. BitPoet

    Allowing the user to be changed in the template is still necessary when you use the API, though you might get by if you temporarily set the flag. Then assign created_users_id the id of Jesper. // set up your new page, then... $page->template->allowChangeUser = true; $page->created_users_id = (int)$input->post->creatorid; // or however the input is named in the form $page->save();
  5. BitPoet

    ...with a not so little impact when building complex sites. I already know I'm going to use this a lot Thank you!
  6. I guess the safest approach would be to create a new PageArray Array 3, iterate over Array 1, compare with each item in Array 2 and if not matched, add the Page to Array 3. Or, in code: $array3 = new PageArray(); $array1->each(function($pg) use($array2) { if(! $array2->has($pg)) { $array3->add($pg); } });
  7. BitPoet

    If you don't have different names, then localUrls with be identical. Your select will just reload the page. What you need to do is pass some kind of indicator (e.g. a GET parameter with the language id) to the server and set the user's language before the page is rendered. So you need to output something like this in your page for the language selector: <select onchange="window.location=$(this).val();"> <?php foreach ($languages as $language) : ?> <?php $url = $page->localUrl($language) . "?lang=" . $language->id; ?> <option <?php if ($user->language->id == $language->id) : ?>selected<?php endif; ?> value="<?php echo $url; ?>"><?php echo $language->title; ?></option> <?php endforeach; ?> </select> Then, in the backend (best site/ready.php), you need to adapt the current language according to the parameter and store the selection in the session to make PW remember it (untested): <?php if($input->get->lang) { $newLang = (int)$input->get->lang; if(! $languages->get($newLang) instanceof NullPage) { $session->set("currlang", $newLang); } } $newLang = $session->get("currlang"); if($newLang) { $user->language = $languages->get($newLang); } You should think hard whether you want to do that though. Google & Co. will put a massive penalty on your site if you show differing content on identical URLs. Languages are different beasts from locations. I have, e.g., some colleagues from foreign countries who are a lot more comfortable doing their shopping in English rather than in German, but they still need to see the usual Euro prices and German VAT. So you might just use a different thing than the language, e.g. a GET variable named "country" that you store in the session just like the code above does and pass that to your conversion function.
  8. BitPoet

    The regex was just a shot in the dark. Since it's all about starting letters, you can change that line to $letter = substr($pg->title, 0, 1);
  9. BitPoet

    If you don't want to go to deeply into writing your loop with comparing the previous letter, you could use the PageArray::groupBy method I posted: With it, you could write something like this (i't a bit of guesswork since I don't know if the "A" "B" "C" parts are really in the title or in a different field, but you should get the gist: <?php echo "<h2>Services</h2>"; $children = $page->children(); $children->sort("title"); // Important for grouping to work $grouped = $children->groupBy(function($pg) { // first argument ($pg) is always the page object we are examining $letter = preg_replace('/^Server "(.)".*$/', '$1', $pg->title); return array($letter); }); foreach($grouped as $letter => $letterPages) { echo "<h3>$letter</h3>"; echo "<ul>"; foreach($letterPages as $lpg) { echo "<li>{$lpg->title}</li>"; } echo "</ul>"; }
  10. The not saving thing is actually something I encountered too a few days ago when populating select options in a hook. Unfortunately, I didn't find the time to dig deeper (and it isn't an urgent case). Come to think of it, it might be a validation issue, as when saving in ProcessPageEdit, the render hook isn't called before processInput is triggered. So running the same hook code before InputfieldSelect::processInput might solve it.
  11. Probably nothing that complicatied. You can use getForPage() on the repater item to retrieve the page it belongs to. $repeaterPage = $event->object->hasPage; $page = $repeaterPage->getForPage();
  12. There's no "page" argument to Inputfield::render, but you can use the property $inputfield->hasPage to retrieve the page associated with the Inputfield. The returned page is the individual repeater item page, not the page being edited. If work_detail_images is in the same repeater, the following line should be enough to get things working: $page = $event->object->hasPage;
  13. BitPoet

    I was just typing that I thought an object storage like S3 would be better geared towards replicating that kind of content, as I can say from experience that blob-heavy databases can be a real PITA. They always grow far faster than expected, and the number of queries rises what feels like exponentially. The necessary backup space and -time quadruples in the blink of an eye, and the "quick restore" suddenly takes an hour. I guess the setup for new sites could be scripted leveraging S3 and IAM apis. Create user, create access key, assign role, create bucket and assign policy are all available through the REST APIs. Then all that is left is to deploy the access key to PW's config or module settings and all replicas should know it too.
  14. Here's a little snippet for site/ready.php that lets you store your modified copy of the js file in question under site/modules/FieldtypeRepeater/ and replaces the URL in a renderReadyHook on InputfieldRepeater: <?php namespace ProcessWire; wire()->addHookAfter("InputfieldRepeater::renderReadyHook", null, "useRepeaterSiteJS"); function useRepeaterSiteJS(HookEvent $event) { $config = $event->object->config; $modules = $event->object->modules; foreach($config->scripts as $script) { if(strpos($script, $config->urls->InputfieldRepeater . "InputfieldRepeater") !== false) { $altName = "InputfieldRepeater.js"; $altPath = $config->paths->siteModules . "FieldtypeRepeater" . DIRECTORY_SEPARATOR . $altName; if(file_exists($altPath)) { $altUrl = $config->urls->siteModules . "FieldtypeRepeater/" . $altName; $info = $modules->getModuleInfo("InputfieldRepeater", array('verbose' => false)); $version = $info["version"] ?: 0; $modified = filemtime($altPath); $config->scripts->remove($script); $config->scripts->add($altUrl . "?v=$version-$modified"); break; } } } } Edit: amended the text to make it clear that this approach is only about the js file in question, differing from other suggestions that duplicate the complete module. Of course, incorporating changes in the original js file on every update has to be done anyway.
  15. I'm really in love with FormBuilder, but the one thing missing to match all my end users' expectations were repeatable field groups. Think repeaters, in ProcessWire terms. Our primary application of PW is our corporate intranet, so "lines" of fields are quite common in the forms I build. We have all kinds of request forms where the information for a varying number of colleagues needs to be entered (from meal order to flight booking request) and where it is simply impractical to send a form for each, and I don't want to clutter my forms with multiple instances of fields that may only get used ten percent of the time. That's why I started to build FormBuilderMultiplier (link to GitHub). What it does: Adds an option to make a regular Fieldgroup repeatable Lets you limit the number of instances of a Fieldgroup on the form Adds an "Add row" button the form that adds another instance of the Fieldgroup's fields Adds a counter suffix at the end of every affected field's label Stores the entered values just like regular fields Makes the entered values available in preview and email notifications Supports most text based fields, textareas and selects (really, I haven't had enough time to test all the available choices yet) What it doesn't do (yet): Support saving to ProcessWire pages (i.e. real Repeaters) I haven't tested all the validation stuff, Date/Time inputs etc. yet, but since I'm utterly swamped with other stuff at work, I didn't want to wait until I have it polished. Any feedback is welcome. There might also be some issues with different output frameworks that I haven't encountered yet. The forms I work with mostly use UIKit. Status: Still alpha, so test well before using it in the field. Known issues: When rows are added, the form's iframe needs to be resized, which isn't completely clean yet. How it works: The Fieldgroup settings are added through regular hooks, as is the logic that adds the necessary field copies for processing the form and displaying previews. "Multiplied" field instances are suffixed with _NUM, where NUM is an incremental integer starting from 1. So if you have add two fields named "surname" and "givenname" to a fieldgroup and check the "multiply" checkbox, the form will initially have "surname_1" and "givenname_1" field (I'm still considering changing that to make the risk to shoot oneself into the foot by having a regular "surname_1" field somewhere else in the form less likely). When a "row" is added, the first row is cloned through JS and the counter in the fields' IDs, names and "for" attributes as well as the counter in the label are incremented before appending the copies to the Fieldset container in the form. To keep backend and frontend in sync, a hidden field named [name of the fieldset]__multiplier_rows is added to the form. Both the backend and the frontend script use this to store and retrieve the number of "rows". ToDo: Naturally, add the option to store the data in real repeaters when saving to pages. Do a lot of testing (and likely fixing). Make a few things (like the "Add row" button label etc.) configurable in field(set) context. Add a smooth API to retrieve the multiplied values as WireArrays. The mandatory moving screenshot: