Leaderboard
Popular Content
Showing content with the highest reputation on 05/10/2023 in all areas
-
Looks like a perfect application for LazyCron. A quick and dirty snippet of code you can place in site/ready.php (or inside a template's PHP file, just make sure that a page with that template is viewed regularly): <?php namespace ProcessWire; // Add daily hook to clean up incomplete, stale pages wire()->addHook('LazyCron::everyDay', null, function(HookEvent $event) { $ts = time() - 86400; // 24 hours ago // Find matching pages, adapt selector however you want (e.g. limit to certain templates or parents) $stalePages = $pages->find("created<$ts, title=''"); foreach($stalePages as $stalePage) { $pages->trash($stalePage); } });7 points
-
A little update. @teppowas spot on. Having my logic inside a hook to PageView::execute was not a good idea. I refactored it, put simple URL segment logic in home.php while keeping the processing of the segments inside a module. This makes life much easier because I can throw 404s and therefore have URL hooks working as they should. Thanks again everyone for your input on this. Very much appreciated.3 points
-
Hi, With javascript you can achieve it easily. The idea is to add an event listener to each input and re-order an array when the user change an input: <form id="form"> <label for="filter1">filter 1 :</label> <input type="text" id="filter1" name="filter1"><br> <label for="filter2">filter 2 :</label> <input type="text" id="filter2" name="filter2"><br> <label for="filter3">filter 3 :</label> <input type="text" id="filter3" name="filter3"><br> <button type="submit" name="submit">Send ☑️</button> </form> <script> // get form and all input const form = document.querySelector('#form'); const filter1_field = document.querySelector('#filter1'); const filter2_field = document.querySelector('#filter2'); const filter3_field = document.querySelector('#filter3'); // array to store the order of the input const order = []; // listen for input fields change to update the order array filter1_field.addEventListener('input', () => updateOrderArray('filter1')); filter2_field.addEventListener('input', () => updateOrderArray('filter2')); filter3_field.addEventListener('input', () => updateOrderArray('filter3')); // update the order array function updateOrderArray(fieldName) { if (!order.includes(fieldName)) { order.push(fieldName); } } form.addEventListener('submit', (event) => { event.preventDefault(); const baseUrl = 'https://example.test/form.php'; // L'URL de base // build the url with the GET parameters in the order specified by the order array let url = baseUrl; order.forEach((fieldName, index) => { const value = encodeURIComponent(document.querySelector(`#${fieldName}`).value); url += `${index === 0 ? '?' : '&'}${fieldName}=${value}`; }); // redirect window.location.href = url; }); </script> Result: /form.php?filter3=processwire&filter2=is&filter1=awesome2 points
-
What @flydev said. A slightly different alternative to the above is to store the order values in a hidden input as a CSV. In that case, you don't need to touch window.location.href. You would use the values in the CSV to access the GET params sequentially.1 point
-
@bernhard Very late comments here. I'd started watching but things got in the way and I didn't finish. I've just finished watching. A-M-A-Z-I-N-G! Thoroughly enjoyed this one. Thanks for sharing and thanks for representing ProcessWire. It looks like a lot of thought went into the presentation. It was also interesting to hear about your background. I am guessing this perhaps explains why your work/modules are always so polished and of high quality!! I suppose you don't get into a helicopter without meticulously checking everything works as it should ?. I liked the way you showed the basics first and gradually moved into the more advanced topics. I also liked the way you used git history. I have learnt some new things as well and my interest is piqued. I have never been a fun of PHP template engines but that latte stuff you showed got me really interested. That is a lot like 'modern-js' like you said! Have you noticed any performance issues with latte? I was also very impressed with ddev. I know you have mentioned it before but the 'docker' bit is what has put me off in the past. For some reason, docker was either slow on my machine (a Windows thing maybe?) or just wouldn't work. I am very curious about ddev now. Do you still use a Windows machine? How's ddev in terms of performance? Anyway, great stuff and thanks again for sharing!1 point
-
Hi @jploch - sorry for the late response - I was on vacation. Can you please point me to the line on the Github repo. I feel like it might actually be: https://github.com/adrianbj/TracyDebugger/blob/6f62b8e2c03e1520615ea654e79f4e44b61f9f20/TracyDebugger.module.php#L2847 but that isn't the line number from your error. Also can you please do a dump of parse_url($_SERVER['REQUEST_URI']); so I can see what is returned?1 point
-
That's going to be a problem. ProcessPageView::execute is responsible for calling ProcessPageView::renderPage or ProcessPageView::renderNoPage, which are the two methods responsible for catching and handling 404 exception. In this case you're preventing the core from doing what it would normally do. Instead of looking for workarounds (which may not exist), it's easier to just handle segments in templates, or define allowed segments (as discussed above). If you need to serve a page from an URL below home page that doesn't match an actual page, and this needs to happen in a module, it's better to leave URL segments out of the equation (just keep them disabled) and instead use URL hooks or hook to ProcessPageView::pageNotFound.1 point
-
ga beer -- u.try this in home.php ? if ( $input->urlSegment1 === 'files' ) wire404();1 point
-
// init.php $wire->addHook('/webhook', function ($event) { // http_response_code(403); // or header('HTTP/1.1 403 Forbidden', true, 403); // no exit, apply server logic $event->return = true; }); // ready.php $wire->addHook('/webhook', function ($event) { $this->log->save('webhook', $event->return); // exit(); }); C:\Users\flydev>curl -I -L --insecure https://xx-xx-xx-xx.ngrok.app/webhook HTTP/1.1 403 Forbidden Alt-Svc: h3=":443"; ma=2592000 Cache-Control: no-store, no-cache, must-revalidate Cache-Status: Souin; fwd=uri-miss; key=https-/webhook--; detail=UNCACHEABLE-STATUS-CODE Content-Length: 0 Content-Type: text/html; charset=utf-8 Date: Thu, 27 Apr 2023 14:59:36 GMT Expires: Thu, 19 Nov 1981 08:52:00 GMT Ngrok-Trace-Id: b2213e4460d4a73821ac2041f312d8d9 Pragma: no-cache Server: Caddy Set-Cookie: wires=s106arh77i4f9ot1jeh7bvged6; path=/; secure; HttpOnly; SameSite=Lax Status: 403 Forbidden X-Powered-By: ProcessWire CMS Reverse output: Connections ttl opn rt1 rt5 p50 p90 15 0 0.01 0.02 90.35 151.65 HTTP Requests ------------- HEAD /webhook 403 Forbidden GET /webhook 403 Forbidden Tracy dump: ProcessWire\HookEvent data: array 'object' => ProcessWire\ProcessPageView 'method' => 'pathHooks' 'arguments' => array 0 => '/webhook' 1 => true 'path' => '/webhook' 'return' => true <=== $event->return 'replace' => false 'options' => array 'id' => 'ProcessPageView:100.0:pathHooks' 'cancelHooks' => false 'when' => 'after'1 point
-
Here you go ? https://codingpad.maryspad.com/2013/07/19/interview-with-ryan-cramer-processwire-cms-founder-and-lead-developer/ Here are the interesting bits for this particular topic: Edit: I knew there was another one https://www.cloudways.com/blog/processwire-ryan-cramer-interview/1 point
-
In a multilingual environment I get the following error, wehen sorting menu-items TypeError method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given File: .../modules/MarkupMenuBuilder/ProcessMenuBuilder.module:2602 2602: if($language != null && method_exists($pages->get($itemID)->title, 'getLanguageValue')) $itemTitle = $pages->get($itemID)->title->getLanguageValue($language);// title of each PW page in this array This works for me: // multilingual environments if($language != null && $itemID && method_exists($pages->get($itemID)->title, 'getLanguageValue')) $itemTitle = $pages->get($itemID)->title->getLanguageValue($language);// title of each PW page in this array1 point
-
I'm not yet sure what ProcessWire could do here since it's the template file that controls all the logic of what gets output. But I may not yet fully understand the request, so I'll use an example or what I do understand below. Markup Regions don't have control over what your template file spends time rendering, just what gets output at the end. So there wouldn't be much benefit to having output of partials when it still has to spend the time to render everything, whether used in the output or not. Instead, you would need some logic in your template file in order to selectively render partials, and gain a performance benefit from it: <?php namespace ProcessWire; // render just $part if requested, otherwise render all parts $part = $input->get('part'); // i.e. header, content, footer ?> if($part == 'header' || !$part): ?> <div id='header'> ...header markup... </div> <?php endif; ?> if($part == 'content' || !$part): ?> <div id='content'> ...content markup... </div> <?php endif; ?> if($part == 'footer' || !$part): ?> <div id='footer'> ...footer markup... </div> <?php endif; ?> <?php if($part) return $this->halt(); ?> In the above example, if the page is requested without a "?part=" query string in the URL, then it renders everything (header, content and footer). But if rendered with a "?part=content" query string in the request URL (for example), then it would render and output just the <div id='content'>...</div>.1 point
-
Amazing! I'm so happy for Carson!1 point
-
As the project processwire-recipes.com went offline quite some time ago now, I took the repository and deployed a browsable version of it over on: https://processwire-recipes.pages.dev/ There is also a new repo: https://github.com/webmanufaktur/processwire-recipes/ ... on which this deployed version is based on. Changes, fixes, updates can be submitted there. Feel free to update links, fork the repo, submit changes for recipes layout or whatever. It uses 11ty for rendering .md to .html and all the other magic. I will add further details in regards to formatting recipes and submitting new content in the future. Further notice: @teppo: you link to the old domain on weekly.pw Changes/Updates: incoming - right now this is WIP (work in progress) Maintainers: feel free to let me know, I'll add you to that repo Details: the repo is on github: see above hosting/deployment: on Cloudflare Pages via 11ty updates: all updates against the master-branch will be deployed within 60 seconds after commit changes: right now only via pull-request maintainers: wanted - see above1 point
-
I found a workaround: Put the user language inside a session variable and call this session variable inside the hook. public function init() { //set language id inside a session variable for later usage in url hook $this->wire('session')->set('userlang', $this->wire('user')->language->id); // Show details about the blocked IP address inside a panel $this->wire->addHook('/detail-view/{ip}', function ($event) { $userLang = $this->wire('session')->get('userlang'); // grab current user lang from session $this->wire('user')->language = $userLang; // here comes the code }); } Not really elegant, but it works. Now translatable strings work as expected.1 point
-
The skipLabel option is about whether or not to render the header of the inputfield. An example with InputfieldText: $f = $modules->get('InputfieldText'); $f->name = 'text1'; $f->label = 'label'; $inputfields->add($f); $f = $modules->get('InputfieldText'); $f->name = 'text2'; $f->label = 'label'; $f->skipLabel = Inputfield::skipLabelHeader; $inputfields->add($f); For InputfieldCheckbox, the header is already not rendered by default unless a description is defined for the inputfield. Instead, the label is rendered next to the checkbox itself. So setting skipLabelHeader or skipLabelBlank won't do anything because the header is already skipped. If you do want a separate header label for InputfieldCheckbox you can use the "checkboxLabel" or "label2" properties (they both do effectively the same thing). When these properties are set the "label" is rendered in the header and the "checkboxLabel" or "label2" is rendered next to the checkbox: $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox1'; $f->label = 'label'; $inputfields->add($f); $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox2'; $f->label = 'label'; $f->checkboxLabel = 'checkboxLabel'; $inputfields->add($f); If your question is actually "is it possible to have a checkbox without any text next to it" I think the answer is no, not using the API options. You could try a str_replace() in a hook after InputfieldCheckbox::render, or use Javascript to remove the text. Edit: another alternative for a checkbox without text next to it is to use a space character as the label: $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox1'; $f->label = ' '; $inputfields->add($f);1 point