Leaderboard
Popular Content
Showing content with the highest reputation on 03/18/2022 in all areas
-
This week's commits are primarily focused on resolving reported issues (via GitHub issue reports). While that doesn't make for exciting reading here, it's an important part of working towards our next master version. Though I am working on various other projects including client websites running in ProcessWire, ongoing updates to Pro modules and development of other ProcessWire modules. One module I've been working on this week (and last week) enables you to export translations for multi-language fields into JSON or CSV files. These files can be read into other translation systems, edited, and then imported back into ProcessWire. So if you need all the content for a site translated from one language into another, it provides a very convenient means of doing so. More details on that one soon. That's all for today but stay tuned and thanks for reading. Have a great weekend.8 points
-
I guess nobody wants to hear that, because it seems to be too nerdy to create fields via code, but this is just another example why I love my setup so much. Thank's for reminding me of those days where I was struggling myself with those topics ? For those interested in an advanced approach of organising PW projects and keeping your setup clean I'll try to explain what I do for all my projects now. And that's another benefit: I always do the same. On every project. For every field. So every project works the same and I instantly know what's going on even if I haven't worked on the project for a longer time. For me these two things were crucial: Custom Page Classes (optional) RockMigrations (optional) RockMatrix or RepeaterMatrix If you haven't used custom page classes be sure to check them out: https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes That would actually take too long to explain... But I've shown some of the above mentioned techniques that might also be of interest for readers of this topic in the linked issue (https://github.com/processwire/processwire-requests/issues/154) The sort version which might be an idea for you guys having troubles with field names: You could create a custom class that is loaded in _init.php where you define your fieldnames as class constants: <?php // site/_init.php class MyProject { const field_body = 'body'; const field_teaser = 'body1'; const field_summary = 'body1'; const field_cover = 'blog_cover_image'; } Now you can access your fields in your templates like this: <?php // template newsitem echo "<h1>{$page->title}</h1>"; echo "<div>".$page->get(MyProject::field_teaser)."</div>"; <?php // template basic-page echo "<h1>{$page->title}</h1>"; echo "<div>".$page->get(MyProject::field_summary)."</div>"; Note that we are reusing the field "body1" and referring to it as "field_teaser" in newsitem and as "field_summary" in basic-page. Personally I don't do any reusing of fields any more but that's a different topic and relates to RockMatrix + RockMigrations. Hope the ideas where useful for someone nonetheless.6 points
-
So... just a short heads-up... a node.js module that's widely used - even in vue.js and well known software - was compromised by its developer. It seems that the repository was already cleaned-up again, yet in case you installed the module itself or something with it the last couple of days. Take a closer look, clean it up, fork a clean version whatsoever. https://snyk.io/blog/peacenotwar-malicious-npm-node-ipc-package-vulnerability/ node-ipc-dependencies-list https://github.com/zlw9991/node-ipc-dependencies-list Video with some more details about the whole issue.4 points
-
Wow. These are great inputs! I'll have to look into them more closely, since they are some new concepts to me. I only feel stupid I haven't asked the community sooner ?4 points
-
I use generic words and numbers for field names, e.g. text_1, textarea_1. I really wish I didn't have to do this and could use descriptive names for fields, but the problem is that I almost always want to reuse fields for different purposes on different templates. So while a name like "city" is more meaningful than "text_1", I think it's much more confusing to call $page->city in some template when that field is actually holding a person's job title or something totally unrelated to "city". What I'd like is for PW to support field aliases, so that in the context of the "store" template I can give text_1 the alias of "city" and in the "employee" template I can give text_1 the alias of "job_title". Field aliases would need to be unique and in practice you could refer to a field by any of its aliases in any place in your code. I have an open request for this: https://github.com/processwire/processwire-requests/issues/154 Ryan seemed supportive at the time but it hasn't progressed anywhere since 2018. If anyone else would like this feature please "vote" for it with a thumbs-up at GitHub. I've also created a module that would allow aliases to be used but it can't be released due to issues with FileCompiler: https://github.com/processwire/processwire-issues/issues/8823 points
-
For larger sites I mostly use generic, numbered fieldnames like text_ml_01 (ml for multilanguage) which I might generate via API. Then in the templates I change the labels to something more meaningful and via AutoTemplateStubs I copy the complete field info with labels into the php templates, looks sth. like: /** * Template: basic-page (Basic) * * @property string $title Titel * @property string $text_ml_01 Headline * @property string $textarea_ml_01 Intro * @property string $body_01 Content * @property string $text_ml_02 CTA Button Label * @property mixed $url_ml_01 CTA Button URL * @property Pagefiles $files_ml_01 Linked Files */ For smaller sites I prefer more custom fieldnames.3 points
-
So it is ublock-origin. Thank you for the pointer - I should have checked that first! Updated to add 1: I actually run UBO in all my browsers so there must be a settings difference between UBO in my FF and Brave installs - will look into it. Updated to add 2: Found it in case anyone else is interested. There's an entry in the UBO blocklist called "Fanboy's Annoyance" for .privacywire-wrapper that is causing the issue. I had this list enabled in FF but not in chrome.2 points
-
Hello friends! I have another module for you, which will make your daily work as a Processwire developer easier. Introducing: AppApi This module helps you to create api-endpoints, to which an app or an external service can connect to. Features Simple routing definition Authentication - Three different authentication-mechanisms are ready to use. Access-management via UI Multiple different applications with unique access-rights and authentication-mechanisms can be defined The documentation has become quite extensive, so have a look at the Github repository for details: Installation Defining Applications Api-Keys PHP-Session (Recommended for on-site usage) Single JWT (Recommended for external server-calls) Double JWT (Recommended for apps) Creating Endpoints Output Formatting Error Handling Example: Listing Users Example: Universal Twack Api Routes Page Handlers File Handlers A special thanks goes to Thomas Aull , whose module RestApi was the starting point to this project. This module is not meant to replace this module because it does a great job. But if you want to connect and manage multiple apps or need other authentication methods, this module might help you. I am already very curious about your feedback and would be glad if the module helps you a little bit.1 point
-
This module for ProcessWire enables the debug mode to bypass the restriction to install modules. This is useful if you are tired to manually set the debug mode in the configuration. Note Please note that this module doesn't replace the real debug mode in the configuration file /site/config.php. With this module you will not receive any errors/notices/warnings like in the real debug mode. It serves only to bypass the restriction to install modules. Installation To install this module you have to enable the real debug mode. After installation you should deactivate debug mode again. To enable the real debug mode, download /site/config.php via FTP and open it in a text editor. Look for a line where you can find $config->debug = false; change it to $config->debug = true; save the file and upload it again. After module installation change it back to $config->debug = false;. For all future module installations, you just have to enable the debug mode in the module settings like described below. After module installation, you should deactivate it in the same way. Settings The settings for this module are located in the menu Modules=>Configure=>DebugModeSwitch. Enable or deactivate debug mode Set the checkmark (1) and click the submit button (2) will enable the debug mode (3). The debug mode can be also restricted for superusers only (4). Links ProcessWire module directory: https://processwire.com/modules/debug-mode-switch/ Github: https://github.com/techcnet/DebugModeSwitch1 point
-
ProcessWire 3.0.196 contains 10 minor issue fixes, but the biggest additions this week are 6 pull requests submitted from @bernhard. This most notable PR is an upgrade to AdminThemeUikit that enables greater customization of the theme's markup. If you recall, Bernhard also provided a PR last year that enables customization of the admin theme's CSS/LESS, so now he's now completed the circle and provided us with a direction for customizing the markup as well. This newest addition lets you provide your own custom render files for different parts of the admin theme by placing them in /site/templates/AdminThemeUikit/. Third party modules can also define custom render files. Furthermore, this addition adds a new hook that enables you (or your modules) to hook into and modify just about any part of the admin theme rendering. Rather than going into all the details and repeating all of the instructions here, see the new AdminThemeUikit README file "Customizing Markup" section which describes all of the different things you can modify and how to do so. You can also find all of the render files in the core AdminThemeUikit directory — any .php files beginning with an underscore are custom render files that can be overridden. While not as broad in scope, there were other useful PRs added this week as well, so be sure to see the dev branch commit log if you are interested in seeing what else was added. Thanks for reading and have a great weekend.1 point
-
I'm a dork - sorry robin, that was a classic translation error. After reading the sentence, I took the tick out of the box... ? Ok, I just shouldn't be in front of the PC when I'm sick. ? With the tick, of course, everything works as desired! ? Have a nice day cu Ralf1 point
-
1 point
-
1 point
-
Yes!, this happened to me, I forgot to add </body> and </html> tags.1 point
-
Code for the above demo JavaScript Here we need to tell htmx that ProcessWire expects Ajax calls to send "X-Requested-With" // InputfieldMeasurement.js const InputfieldMeasurement = { initHTMXXRequestedWithXMLHttpRequest: function () { console.log("initHTMXXRequestedWithXMLHttpRequest - configRequest") document.body.addEventListener("htmx:configRequest", (event) => { event.detail.headers["X-Requested-With"] = "XMLHttpRequest" }) }, listenToHTMXRequests: function () { // before send - Just an example to show you where to hook BEFORE SEND htmx request htmx.on("htmx:beforeSend", function (event) { console.log("InputfieldMeasurement - listenToHTMXRequests - event", event) }) }, } /** * DOM ready * */ document.addEventListener("DOMContentLoaded", function (event) { if (typeof htmx !== "undefined") { // CHECK THAT htmx is available console.log("HTMX!") // init htmx with X-Requested-With InputfieldMeasurement.initHTMXXRequestedWithXMLHttpRequest() // just for testing InputfieldMeasurement.listenToHTMXRequests() } else { console.log("NO HTMX!") } }) PHP We are in InputfieldMeasurement.module We load htmx in init() We listen to htmx calls in render() We pass this to a handler testHTMX() Insider render() we listen to change on InputfieldSelect. Notice we don't add a trigger. htmx knows the type of event that a Select outputs <?php namespace ProcessWire; // BELOW, SNIPPETS OF THE RELEVANT CODE public function init() { parent::init(); // wire()->config->scripts->append("https://unpkg.com/htmx.org@1.7.0"); // LOAD htmx // I just prefer this syntax :-) $this->wire('config')->scripts->append("https://unpkg.com/htmx.org@1.7.0"); } public function ___render() { $name = $this->attr('name'); $field = $this->field; $page = $this->page; $value = $this->attr('value'); if (!$value || !$value->quantity) { $value = new Measurement($field->quantity); //bd($value, 'value'); } ##################### HTMX AJAX LISTENER $input = $this->wire('input'); $ajax = $this->wire('config')->ajax; // bd($ajax, __METHOD__ . ': $ajax at line #' . __LINE__); // bd($input->get('field'), __METHOD__ . ': $input->get(field) at line #' . __LINE__); if ($ajax && $input->get('field') == $this->attr('name')) { bd($ajax, __METHOD__ . ': $ajax at line #' . __LINE__); bd($input->get('field'), __METHOD__ . ': $input->get(field) at line #' . __LINE__); bd($input->get('id'), __METHOD__ . ': $input->get(id) at line #' . __LINE__); $out = $this->testHTMX(); echo $out; die(); } else { // @debug bd($ajax, __METHOD__ . ': $ajax - NO AJAX AND/OR WRONG INPUTFIELD - at line #' . __LINE__); } // >>>> MORE CODE HERE ... // ADD HTMX LISTENER TO 'measurement input Select' // unit $f = $this->modules->get("InputfieldSelect"); $f->label = $this->_("Unit"); $f->attr('name', "{$name}_unit"); $f->attr('value', $value->get('unit')); //bd($value, 'value'); bd($field->units, __METHOD__ . ': $field->units at line #' . __LINE__); foreach ($field->units as $unit) { $shortLabel = (isset($units[$unit]) && isset($units[$unit]['shortLabel'])) ? $units[$unit]['shortLabel'] : null; $alias = (isset($units[$unit]) && isset($units[$unit]['alias'])) ? $units[$unit]['alias'] : $unit; if ($shortLabel) $shortLabel = "($shortLabel)"; $f->addOption($unit, "$alias $shortLabel"); } $f->notes = $units[$value->get('unit')]->notes; $f->columnWidth = $colWidth; // ======== #### add HTMX #### $adminEditURL = $this->wire('config')->urls->admin . "page/edit/"; $adminEdit = "{$adminEditURL}?id={$this->page->id}&field={$name}"; bd($adminEditURL, __METHOD__ . ': $adminEditURL at line #' . __LINE__); bd($adminEdit, __METHOD__ . ': $adminEdit at line #' . __LINE__); // ------ $f->attr([ 'hx-get' => $adminEdit, // send get to to InputfieldMeasurement 'hx-target' => '#InputfieldMeasurementTestHTMXTarget', // our element to target with swap 'hx-swap' => 'innerHTML' // we'll swap the innerHTML (this is the default but it has never worked for me if not specified) ]); $inputfields->add($f); // ========= ### FOR HTMX DEMO ONLY ### $f = $this->modules->get("InputfieldMarkup"); $f->label = "InputfieldMeasurement Test HTMX"; $f->attr('id', "InputfieldMeasurementTestHTMX"); // we will swap the innerHTML of the div#InputfieldMeasurementTextHTMXTarget $out = "<div id='InputfieldMeasurementTestHTMXTarget'><h3>HTMX TARGET (will change when Unit changes)</h3></div>"; // $f->collapsed = Inputfield::collapsedYes; $f->value = $out; $f->columnWidth = 100; $inputfields->add($f); // >>>> MORE CODE ..... return $inputfields->render(); } private function testHTMX() { $dateAndTime = date("Y-F-d H:i:s"); $out = "<h3>We got that HTMX Call at {$dateAndTime}!</h3>"; return $out; }1 point
-
Ok sorry about that. I try to explain it in other words. What I meant was that if your system is blocked and does not respond to new requests it is likely that you have a process that is still running. This can happen quickly while testing SSE because you can quickly get into an endless loop and the process will run and run and run and block your system until the process is killed because it reaches max_execution_time for example. That's why I suggested to add a hard break while testing so that you exit after 30 iterations and the system will get ready for the next request. Hope that makes sense now? I'm not sure I understand. My usecase was simply trashing multiple pages or updating multiple pages via RockGrid (bulk editing). The user selects multiple rows and then clicks on an action (trash, update, ...). The user is then asked to confirm the action, which triggers the process of updating/trashing pages on the server. Now the only difference to a traditional approach is that this request is kept open using SSE and it keeps waiting for the server to receive the progress (eg trashing page 1 of 10, 2 of 10, 3 of 10... etc). Until this action is finished the system will be blocked for other requests of the same user (I don't understand how that works technically, but I think that other users can still request data from the server in the meantime?!). When the server is done with updating/trashing all pages it will send "DONE" to the client and the connection will be closed which makes the server ready for the next request. So it's a very special use case but it's also a quite common need! The example you are describing can not be solved using SSE as far as I understand. I think one would need sockets here. But I don't have any knowledge about them so I can't say anything here but I am happy to hear how that would work even if that is not really on topic any more ?1 point
-
@Ralf You're right, my bad. It seems "isChanged()" method does not work on User template. But you still have two options. 1) Tweek the code from above and check if the field you want to monitor is in changes array. (e.g. in_array('roles', $changes)). 2) Use a slightly different approach with User::changed hook. You have to modify to fit your needs, but here's a very basic example. wire()->addHookAfter('User::changed', function (HookEvent $event) { $user = $event->object; $changedField = $event->arguments(0); //which field you want to monitor $fieldToCheck = "roles"; if ($fieldToCheck == $changedField) { //send mail.. or do more checks.. } $return = $event->return; $event->return = $return; }); Edit: the second approach is ONLY sensible if you want to check for a single changed field! Otherwise you would get a mail for each changed field. If you want to check for changes of more than one field use the first approach.1 point
-
Did you check your Browser-Settings? DNT-Mode? Ad-Blocker?1 point
-
Thanks for making me aware of something that I've done wrong for about 20 years ?1 point
-
Ok now we are talking about a totally different topic... But first things first. This is exactly what I'm using SSE for. The user clicks a button, ProcessWire starts doing a long running task (for example trashing lots of pages) and while it does so, the progress is sent to the client so that the client knows what's going on. I'd call that real world ? The reason why I chose SSE over sockets and over not implementing any client feedback is obvious: Having a long running task without a progress bar is just not an option. What if the user trashed several hundreds of pages and didn't know if that takes 5, 10 maybe 120 seconds? Other techniques are much more complicated to setup (for example web sockets). SSE is built in and does just what I needed: Inform the user of the progress of the task without polling. Of course while this task is running the system is blocked for all other requests. As far as I understand that's the nature of how PHP works. We have the same limitation everywhere in PW and everything in PHP... For example if you empty the trash with lots of pages and you try to visit the PW backend in another browser tab you'll also be blocked until the first tab has finished it's job - or am I wrong here? PHP is single threaded so if you wanted to come around this you'd have to do additional things. I've no experience in this territory, but this seems to look like it could be worth a try: https://stackoverflow.com/a/4350418 There's also https://www.php.net/Thread but that is based on a PECL. And so is https://openswoole.com/ which looks like it comes closer to what you are trying to achieve than what is possible with SSE as far as I understand. 1. Of course we are! Why shouldn't we?? The module is just here to have a common foundation to test things out and eliminate confusion about who copied which code snippet to whatever place etc.; You could now test the linked popen() technique and just add that to the module as a PR and everybody could understand and learn. 2+3. We'd need to have a real non-blocking background process for that. But as I said that not a matter of SSE that's a matter of multi threading in PHP. https://www.youtube.com/watch?v=spDpR2qr-Fs&ab_channel=Dr.RobertDimpsey So for my use case SSE seem to be a good option. For updating a website's content based on "real time data" polling might still be the better option as it will not block the user.1 point
-
@kongondo Here I've found an interesting article about SSE and php and one thing mentioned, to avoid session locking (which I think its our culprit here) is to use: // make session read-only session_start(); session_write_close(); Above everything else in the code used to send data. I cannot test it at the moment, would you mind to have a check and report it back to us? ? I've found however possible bad implications doing this, as mentioned here in the forum.1 point
-
Here's the demo video showing the system lock. Let me know if you cannot watch it. Note, the system will lock even if the count is 10.1 point
-
Hi Ralf, e.g. you could check if the field you are looking for (e.g. roles) has changed: https://processwire.com/api/ref/page/is-changed/ .. and then only send an email if the field has changed.1 point
-
I do not think that a naming convention that fits all needs exits. Still, I mostly find useful using these "rules": "Thinking in reverse", something like French, where adjectives/describing words are usually placed after the noun: text_head, text_subhead, text_body When using date/time: it is yyyy_MM_dd-HH_mm_ss or similar what I use. The important thing here is the order, so when alphabetically listed we also get chronological order. I try to avoid sequential numbering (text_1, text_2, etc) as they are meaningless. Adjectives/describing words should be semantic, whereby a name of something indicates its intention, purpose or relation to other objects and not its properties which might change: text_h1 instead of text_bigred, for example When dealing with composit "objects/things" I often stick to the basic idea of BEM but I am not following it strictly. If lots of multiple of the same fields are needed for a template, I simply pick the most appropriate looking Pro field(s). I know this does not help those who do not have them, but if a project is big enough to warrant for such needs then the Pro fields are probably worth it, especially a DEV license is not that expensive at all, I think.1 point
-
Just a get param and an onchange triggered reload - it's only to filter to a specific organization so no need for anything fancier for now.1 point
-
I wrote something about that a while back. Not much has changed since then. Yet I still sometimes find myself in this question loop about naming fields, templates and such.1 point
-
1 point
-
1 point
-
Do you have an older version of Tracy Debugger installed? If yes, try to switch off Tracy or update Tracy to the latest version (4.23.25).1 point
-
Whoa! That is something I was wishing to have for years! Thank you! Recently I posted about donations and @bernhard's paypal link was on the list. But to my regret I have not donated to him myself. I wish I could fix my mistake, but things happened since then that do not allow me to pay online abroad anymore ? Please be so kind to help me out here and start donating to Bernhard. I know he will appreciate it. And I will join you as soon as I find a way to.1 point
-
1 point
-
@flydev ?? Yep, that's right. The module has basically the same code as the PageApiAccess class that I posted in the other thread. I added an improvement for handling the "lang"-GET-param, that enables you to switch to another language in a multilang environment. But everything else is the same code.1 point
-
I just released a new extension module AppApiPage (waits for approval), which handles the initial steps from my post above completely automatic. You install AppApi and AppApiPage. That makes the /api/page route available and you only have to add the code on top of your template php to add a custom JSON output to your pages. <?php // Check if AppApi is available: if (wire('modules')->isInstalled('AppApi')) { $module = $this->wire('modules')->get('AppApi'); // Check if page was called via AppApi if($module->isApiCall()){ // Output id & name of current page $output = [ 'id' => wire('page')->id, 'name' => wire('page')->name ]; // sendResponse will automatically convert $output to a JSON-string: AppApi::sendResponse(200, $output); } } // Here continue with your HTML-output logic... I hope that this makes it even simpler to add a full-blown JSON api to new and existing pages.1 point
-
As we continue to work towards the next master version, this week I've been working on fixing reported issues. A new $sanitizer->words() method was also added which reduces a string to contain just words without punctuation and such. It was added in part to work on an issue reported with the tags feature in the field editor, but should be handy for other cases as well. As part of that update, the existing $sanitizer->word() (singular) method was re-written to support the features needed for the new words() plural method. This week I've also been working on a pull request from Bernhard that enables greater customization of AdminThemeUikit by way of custom render files and hooks. I'm bringing in that PR and it has a lot of good ideas that have inspired some related updates to it. I've got a bit more work and testing to do before committing, but that part should be ready early next week, along with more core updates. Thanks for reading and have a good weekend!1 point
-
On my side, from what I understand (and what I would like to see implemented) is something like the following : - in config.php set $config->restapi = [ 'endpoint' => 'api', 'enabled' => true]; then use simples built-in functions to get data from api (eg, home page) GET /api/1 Anyway, even if it could/should be easy to use, things are a bit more complex than what we can see here in this thread. I mean, almost all functionalities of AppApi should definitely exists.1 point
-
Interesting. So, with this approach we only need to register the template via a setting (on the template edit screen) and that same template can be used to output either HTML or JSON, right?1 point
-
Hi there! And thanks for Processwire! I've got an interesting case concerning access to current user page. It appears that PW somehow limits access to the frontend page of current user. I'm speaking about a specific PW configuration. We have two kind of users: 'regular' users with native user template and member users with specific member template and specific members parent page (by the way, it's so cool that PW allows to use custom user templates and custom parent for certain user pages!). So a member with name Joe has a page with member template and url like /members/joe . The members template has some access limitations: only member users can see pages with member template. It works like a charm in most situations. For example, user Bill (who has member template and is logged in) can browse a page with url /members/ann which also is a member page with member template. And now, meet the glitch! The above-mentioned Bill cannot get to his own page /members/bill ! PW generates 404 page instead. I see no reason for this behavior. From my point of view any member should have access to any member page in this situation. What am i doing wrong? Any advice is welcome!1 point
-
Just to clarify the bit about "putting stuff outside the webroot" for security reasons: This is certainly a nice precaution, but processwire is not using it because there are way to many shared hosters, where it's simply not possible to go outside the webroot. I'd also say that if your webserver is not behaving correctly you've got bigger problems to deal with, so usually just adjusting your .htaccess file should be perfectly fine as well. Especially as your php process still needs to be able to read things even if they're not within the webroot to be able to execute them. There's not really a need for composer for that part as processwire has it's own psr-4 compatible classloader: https://processwire.com/api/ref/class-loader/1 point
-
Was there a question in there? $out = "<ul>"; $duplicates = array(); foreach($page->images as $image){ // rather than count words, let's just explode each string into an array (even if only one word) $tagsArray = explode(' ', $image->tags); foreach ($tagsArray as $t) { if(in_array($t, $duplicates)) continue;// skip duplicate tags $out .= "<li class='' data-uk-filter='{$t}'>" . "<a href='#'>{$t}</a>" . "</li>"; $duplicates[] = $t; } } $out .= "</ul>"; echo $out;1 point