Leaderboard
Popular Content
Showing content with the highest reputation on 12/10/2022 in all areas
-
This is one of those rare weeks where I've got a lot of projects in progress, but all are in the middle, none are at a convenient Friday conclusion for this weekly update. In progress are some core updates, Pro module updates, other module updates, and a client project that's keeping me busy. So I don't have anything new or interesting to report this week, but I like to still check in and say hello, and let you know I'm not running low on coffee or anything like that. ? I hope that you have a great weekend!10 points
-
@snck I am currently working on implementing Repeater Matrix support. It is basically working but needs some more thorough testing. ATM the setMatrixItems() method seems to be working well. If you like, you can grab a copy from https://github.com/gebeer/RockMigrations/tree/repeatermatrix and test it out. This is how you create a Repeater Matrix field: // first create the blank field $rm->createField('repeater_matrix_test', 'FieldtypeRepeaterMatrix', ['label' => 'Product Content Blocks', 'tags' => 'products']); /** * Set items (matrixtypes) of a RepeaterMatrix field * * If wipe is set to TRUE it will wipe all existing matrix types before * setting the new ones. Otherwise it will override settings of old types * and add the type to the end of the matrix if it does not exist yet. * * CAUTION: wipe = true will also delete all field data stored in the * repeater matrix fields!! */ $rm->setMatrixItems('your_matrix_field', [ 'foo' => [ // matrixtype name 'label' => 'foo label', // matrixtype label 'fields' => [ // matrixtype fields 'field1' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], 'field2' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], ], ], 'bar' => [ // matrixtype name 'label' => 'bar label', // matrixtype label 'fields' => [ // matrixtype fields 'field1' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], 'field2' => [ 'label' => 'foolabel', // matrixtype field options 'columnWidth' => 50, // matrixtype field options ], ], ], ], true); Still need to test the other methods for removing/adding items etc. But this one should work. At least it was working in my tests. When testing is completed I will make a PR so @bernhard can implement.2 points
-
@gebeer The period "." is an allowed character in page names, so it's fine to have URLs ending with ".html" ... you would just make the page name end with ".html". You'd probably want to turn off trailing slashes for the templates used by those pages as well. If all URLs end with "index.html" then ProcessWire will take care of those redirects for you automatically, i.e. "/about/index.html" automatically redirects to "/about/" (unless there is literally a page named /about/index.html). If you want to migrate away from using the .html extension, converting things like /about.html to /about/ throughout the site, then it could be done with a redirect rule in the .htaccess file. If you want to have PW respond to either /about.html or /about/ in the same way, then the most direct way might be to add a $_SERVER['REQUEST_URI'] = str_replace('.html', '/', $_SERVER['REQUEST_URI']); at the top of your /index.php file. Though make sure you've got a <link rel="canonical" ... /> tag in your <head> so that search engines don't consider the about.html and /about/ two different URLs.2 points
-
With all the hype about ChatGPT, I wanted to see how useful it could be for us ProcessWire lovers. In a word: wow! It's pretty darn impressive for such early public testing and for such targeted subject. I love how it proposes code with comments, then proceeds to explain it. (Note: I've been getting more impressive and consistent results on mobile for some reason.) Prompt: Filter blog post by category in ProcessWire To filter blog posts by category in ProcessWire, you can use the find method of the $pages object, along with the category field and the equals operator, like this: // Get the category slug from the URL $category_slug = $input->urlSegment1; // Find all blog posts in the given category $posts = $pages->find("template=blog-post, category.slug=$category_slug"); // Loop through the posts and output their titles foreach ($posts as $post) { echo "<h2>$post->title</h2>"; } This code will find all blog posts that are in the category with the given slug, and output their titles. You can modify this code to output other information about the posts, such as their content, images, or dates. To make it easier for users to filter posts by category, you can also create a navigation menu that lists all the available categories, like this: // Find all categories $categories = $pages->find("template=blog-category"); // Output a link for each category echo "<ul>"; foreach ($categories as $category) { echo "<li><a href='/blog/$category->slug'>$category->title</a></li>"; } echo "</ul>"; This code will find all blog categories and output a link for each one, using the category slug as the URL parameter. When a user clicks on a link, they will be taken to the blog page with the posts filtered by that category. Prompt: Login form in ProcessWire To create a login form in ProcessWire, you can use the following code: // Check if form has been submitted if ($input->post->submit) { // Sanitize user input $email = $sanitizer->email($input->post->email); $password = $sanitizer->text($input->post->password); // Check if user exists and password is correct $user = $users->get("email=$email"); if ($user && $user->matches($password)) { // Login user $session->login($user); // Redirect to home page $session->redirect("/"); } else { // Output error message $error = "Invalid email or password."; } } // Output login form echo "<form method='post'>"; echo "<label>Email:</label>"; echo "<input type='email' name='email' value='$email'>"; echo "<label>Password:</label>"; echo "<input type='password' name='password' value='$password'>"; echo "<input type='submit' name='submit' value='Login'>"; echo "</form>"; // Output any errors if ($error) { echo "<p class='error'>$error</p>"; } This code creates a login form that accepts an email and password. When the form is submitted, it checks if a user with the given email exists, and if the password is correct. If the email and password are valid, it logs in the user and redirects to the home page. If the email and password are invalid, it outputs an error message. Prompt: User registration class in ProcessWire with email, password of at least 10 characters and age over 18. Check if email is unique. To create a user registration class in ProcessWire with email, password of at least 10 characters, and age over 18, you can use the following code: class UserRegistration { public function register($email, $password, $age) { // Sanitize user input $email = $sanitizer->email($email); $password = $sanitizer->text($password); $age = (int) $age; // Validate user input if ($age < 18) { $errors[] = "You must be over 18 to register."; } if (strlen($password) < 10) { $errors[] = "Your password must be at least 10 characters long."; } if ($users->get("email=$email")) { $errors[] = "A user with this email already exists."; } // If no errors, create user account if (!$errors) { // Create new user $user = new User(); $user->email = $email; $user->password = $password; $user->age = $age; // Save user to database $user->save(); // Redirect to confirmation page $session->redirect("/confirmation"); } } } This code creates a UserRegistration class with a register method that takes an email, password, and age as arguments. The method sanitizes and validates the input, and creates a new user if the input is valid. It also checks if a user with the given email already exists in the database, and outputs an error if one does. To use this class, you would first instantiate it: $registration = new UserRegistration(); Then, you can call the register method to create a new user: $registration->register($email, $password, $age); Prompt (similar to previous one): User registration form in ProcessWire with first name, last name, email, password of at least 10 characters and age over 18. To create a user registration form in ProcessWire with first name, last name, email, password of at least 10 characters, and age over 18, you can use the following code: // Check if form has been submitted if ($input->post->submit) { // Sanitize user input $first_name = $sanitizer->text($input->post->first_name); $last_name = $sanitizer->text($input->post->last_name); $email = $sanitizer->email($input->post->email); $password = $sanitizer->text($input->post->password); $age = (int) $input->post->age; // Validate user input if ($age < 18) { $errors[] = "You must be over 18 to register."; } if (strlen($password) < 10) { $errors[] = "Your password must be at least 10 characters long."; } // If no errors, create user account if (!$errors) { // Create new user $user = new User(); $user->first_name = $first_name; $user->last_name = $last_name; $user->email = $email; $user->password = $password; $user->age = $age; // Save user to database $user->save(); // Redirect to confirmation page $session->redirect("/confirmation"); } } // Output registration form echo "<form method='post'>"; echo "<label>First Name:</label>"; echo "<input type='text' name='first_name' value='$first_name'>"; echo "<label>Last Name:</label>"; echo "<input type='text' name='last_name' value='$last_name'>"; echo "<label>Email:</label>"; echo "<input type='email' name='email' value='$email'>"; echo "<label>Password:</label>"; echo "<input type='password' name='password' value='$password'>"; echo "<label>Age:</label>"; echo "<input type='number' name='age' value='$age'>"; echo "<input type='submit' name='submit' value='Submit'>"; echo "</form>"; // Output any errors if ($errors) { foreach ($errors as $error) { echo "<p class='error'>$error</p>"; } } Watch out, this is addictive ?1 point
-
? [[ UPDATE December 6, 2022 ]] ? I prepared a small landing page to validate how many of you would be willing to take the course, so that we would have a rough estimate of how many people would be willing to take the course. ? Show me your interest here ? ------------------------------------------------------- Hello to the entire wonderful Processwire community! I am here to announce my willingness to create a video course for beginner/mid-level developers interested in learning more about the main aspects of our beloved CMS. I have been working with Processwire continuously for years now, so I feel confident that I can share what I have learned to other developers interested in becoming faster and more efficient in their day-to-day work. I have noticed that lately many people here in the forum have complained about a lack of material and tutorials for taking the first steps, and although so many resources are already present within the board, I understand how complicated it can be to be able to connect the dots and have a clear reference on how to get started or how to find clear answers in a short time. As you know Processwire is a very broad tool, very flexible and able to be adapted to any need, so it will not be possible to dissect every aspect in this course, especially the more advanced ones that can help in rarer cases (at least in my personal experience). ? But don't worry, I plan to explain with many practical examples many tips and tricks that can help you in developing sites, even particularly structured ones! ? So I am here to test your interest and ask you what aspects you would be most interested in me covering, even those related to design (css, scss, postcss, tailwind) or javascript libraries/frameworks integrations (vue, alpine.js, greensock for animations,etc.). My idea would be to create together a magazine with a restricted area for users, newsletter integration, catalog filtering according to different parameters (year, author, topics, etc.) and much more.? It will be a paid course, I have not yet decided what the price will be, but it will be affordable for everyone ?. For a small period of time, I would be pleased if you would give me pointers and ideas, so I can see what your real interest is (if any!) and also motivate me ? Let me know! Thanks! ?1 point
-
Thanks @Jan Romero What a silly mistake!!! ??You are right: Sure, that was the mistake. I know that it must be $event and not $field, but I have overlooked this silly mistake over and over and I was wondering why it did not work. I have tried it with $event->object and $event->arguments(0).... BTW: Now both Hooks work with $event->arguments(0)!! Thanks for your help!!! Thanks for helping me1 point
-
Note that you’re hooking the save() method of “Fields” object. This line makes no sense. I assume you mean “$event->object”, but because you’re hooking a method of the Fields class, I would imagine that will give you the same as wire()->fields(), not the field that was saved. The saved field is the first and only argument of the save() method, so I expect this should work: $field = $event->arguments(0); Apparently, towards the end, Fields::save() also calls Fieldtype::savedField() , so you may want to hook that instead: $this->addHookAfter('FieldtypePassword::savedField', $this, 'updateBlacklist'); protected function updateBlacklist(HookEvent $event): void { $field = $events->arguments(0); if ($field->name == 'pass') { $this->wire('session')->message('works'); } }1 point
-
I personally prefer to show a page/redirect to a page after a successful form submission. The reason for that is quite easy... a few examples: Contact form: I can inform people about how fast they can expect an answer and/or already offer a selection of FAQs - especially when the contact form was used from an info page. Forms on lead pages (newsletters or downloads): I can offer more "options" such as products, services or explain how to make sure they will receive e-mail updates (like "add our e-mail address to your contacts and check for spam"). The last part can be used for newsletter sign-ups as well. In case you offer a newsletter archive, tell and show your visitors about it. Forms on pre-sale pages: In real estate after someone submits a request for a house, flat, office or whatever you can offer already details and downloads they will need in order to rent or buy something and even answer questions. Or even tell them who their contact person will be. You car dealer for example: contact form submission with topic "parts" or "inspection" you could tell them "Mr/Mrs Doe, our expert for parts/inspection will contact you and answer your question. In case you might need it, here are the contact details..." You can even personalize those pages based on the form details, like name, topic, and whatever else. This way a form submission is not a dead end and I can keep the visitor/user a bit longer on the page(s). I really enjoy it (UX) when a contact form isn't a show-stopper but keeps it somehow going. Sure this might not work with every form or super simple contact forms. You might need more data to decide wether to show a page or just a short confirmation. Are there good reasons against it? Probably. Are there good reason for it? Absolutely.1 point
-
For some reason on a new site on 3.0.208 a duplicate module is not being detected. I have the standard release and a multisite modified version. On my established sites I am able to choose between the two module base directories but on a new installation with 208 and the same module folder it only detect the first module of the pair and will not install it because of a class name conflict. I've tried clearing cache, setting the appropriate cache disabling rule on cloudflare, deleted compiled files and tried removing one version, installing the remaining version and then adding it back it. The duplicate module is not seen. This is for two module codebases that define the same class and exist in two different folders in the /site/modules/ directory. Sites upgraded to 208 don't seem to have the issue. I can install and configure the module on upgraded sites and select the version on the configuration page.1 point
-
Looking at the modules install() code it doesn't actually do a duplicate check when a module is first installed - at least I couldn't find any calls to methods that suggested it. Once a module config is in the db table the flags flip and duplicate data entries appear in the JSON payload when the modules cache is refreshed, but there doesn't seem to be any reference to that information under other circumstances - so until one version is installed and the config is saved in the db, PW doesn't recognize duplicates exist in the filesystem. Not a high priority item, but I'll make an issue for it on github. Could save some headaches down the line.1 point
-
Thx to a PR by @wbmnfktr everybody using Twig can now use {{ dump($var) }} ? https://github.com/baumrock/RockFrontend/pull/141 point
-
I would not have expected this since the lib is actively maintained and used by many projects. But in the github issues I saw that the author seems to be working on PHP 8 support. Most things we can do with CSS/JS but if you want to deliver completely different content for mobile devices, doing it on the PHP level is a viable option. Caching is a problem, though and needs some extra attention. Personally I would solve this through img srcset and size attributes. No need for separate code here.1 point
-
I usually use this (or similar) extensions when I use Mobile Detect while developing. Switching the user agent to mobile and not having to reload manually the page every time. Then revert back when done.1 point
-
The latest site of the week reminded me of https://senderkataster.rtr.at/ that I built with a friend some time ago and that I want to share. Tech: ProcessWire (obviously) https://getuikit.com/ (also quite obvious ? ) https://tabulator.info/ for all kinds of filters https://leafletjs.com/ for the map https://basemap.at/ using an Open Government Data License Some GDAL command line magic to transform the overlay source data into PNGs that are stored in ProcessWire pages and can then be queried and correctly placed on the map. ProcessWire has been a great platform for that project! If you need help with a ProcessWire project that needs some geo-magic or powerful web maps drop me line ? I'm not responsible for the red background ? Show details of a tower Choose a program by name or type and show its radio coverage (not in the screenshot): Expert mode for nerds:1 point
-
Yes, that is true! Sorry I didn't understand that the template of your pageclass does not exist yet! MagicPages can only be loaded if the template exists, therefore you need to make sure that the template is being created before you can actually use the migrate() method. RockMigrations has the "migratePageClasses()" method for that: https://github.com/baumrock/RockMigrations/blob/d429872cbcb6d658352844fb612ee4a10baa57a2/RockMigrations.module.php#L2311 And it's documented in the WIKI how to do it (also setting parent-child relationships which is a common need): https://github.com/baumrock/RockMigrations/wiki/Ship-your-Module-with-Custom-Page-Classes Thx for the question, I've made the docs a little clearer about that ?1 point
-
@bernhard updated it! For anyone that might come across adding something else on the admin theme's markup, here's a recommendation from Ryan: $src = "https://unpkg.com/alpinejs@3.10.2/dist/cdn.min.js"; $this->wire()->adminTheme->addExtraMarkup('head', "<script src='$src' defer></script>");1 point
-
You can use the User::changed hook to do what you want (see https://processwire.com/api/ref/wire/changed/). Put this in site/ready.php: $wire->addHookAfter('User::changed', function ($event) { if($event->arguments(0) === 'pass') { $user = $event->object; $this->wire->log->save('password-changes', "User $user->name has changed their password"); } }); Now everytime a user changes their password, it will be logged to Setup->logs->password-changes. You can do similar thing with roles if($event->arguments(0) === 'roles') { $user = $event->object; $oldRoles = $event->arguments(1); $newRoles = $event->arguments(2); // code to compare $oldRoles/$newRoles // write to log } If you want to have that information in the session log, just do $this->wire->log->save('session',...)1 point
-
@d'HinnisdaëlI know there are older threads talking about nginx configuration for processwire, but just curious if you can share any of your configuration files that are working good for you? I don't have a clue about nginx but really want to start using ploi1 point
-
Hello all, I love ProcessWire and the community. It is a fantastically architected CMS. I believe over the next few years it will continue increasing in popularity as more people catch word of it. Perhaps it can even take a few percentage of marketshare away from WordPress, which powers 20%+ of all websites on the internet (insane, right?). Well, I'd assume a good portion of those are just wordpress.com blogs that no one reads or have been abandoned, but I could be wrong. I believe we can speed up the adoption rate and open people's eyes faster. They just need to see the light. The forum recently past the 2000th signup, which is about double the number last year. Perhaps we can have 10,000 a year from now. With that being said, I wanted to announce a project that I will be pursing... (drumroll please)... It will be called: Wirecasts.com I envision it as a website containing short, 5-10 minute videos discussing various topics with ProcessWire, much like Railscasts.com is to Ruby on Rails. My first goal is to start with a series of videos that goes head to head with WordPress. I will demonstrate how to do things in ProcessWire that developers are accustomed to in WordPress. For example: Local Installation ProcessWire Pages vs. WordPress Posts + Pages + CPT's Building Menus Custom Fields Themes vs. Site Profiles Shortcodes vs. Hanna Code Showcasing all kinds of plugins in WordPress and their ProcessWire equivalents (like Gravity Forms vs. Form Builder, etc.) I also anticipate creating videos related to some of the topics here on the forum. What's the best way to make a login form? What's the best way to organize content? And so on... Over the last few days, I've been perfecting my screencasting technique for this project. I have a super clean virtual machine with Windows 8 and minimal software (Chrome, Sublime Text, XYplorer) specifically configured for these videos. Videos will be shot in 720p with my Patrick Bateman-like radio voice narration (will need to work extra hard to get that part right). Here's a video I recorded and edited today. It does not yet have voice narration, but it will give you an idea of the quality I'm shooting for. http://bit.ly/1m1H66B (10mb mp4 file) I'd like to hear your feedback and any suggestions to make this a great site! Stay tuned. Jonathan1 point
-
I'm under the impression that the Processwire license now requires you to narrate screencasts like a pirate so you might want to check that little detail.1 point