Leaderboard
Popular Content
Showing content with the highest reputation on 01/22/2016 in all areas
-
This week we're going to look at our path for growth in 2016, which is already off to a nice start! This includes where we've been, where we're going, and how we will get there–with your help. We actually do have several core updates prepared too, but mostly smaller things that will fit better in next week's post. This post originally started as a section of our 2016 roadmap, but I decided it really deserved its own post, so saved it for this week so that we could cover it more in-depth. However, you might consider this part of, or a continuation of, our 2016 roadmap. But rather than looking internally, much of this post looks externally, outside of our software and community, and into the bigger picture of ProcessWire in the web development/design world. https://processwire.com/blog/posts/growing-processwire-in-2016/9 points
-
This is old (2012) but interesting thesis that compares ProcessWire, WordPress and Drupal for building customer support website: http://media.tkk.fi/visualmedia/publications/msc-theses/DI_N_Beilinson_2012.pdf9 points
-
Come on! Martijn steps in and gets all the likes. But what about a man who did all the diagnosis . Just kidding, glad you got the question solved .5 points
-
Thanks for your thoughts valan. I can certainly see where you're coming from as I'm working on a similarly scoped project, even if it doesn't currently have anywhere that number of users. I think your first point is quite a thing to get to with processwire and it's philosophy of not deleting / overwriting content without explicitly being told to do it (hitting the save button). Introducing functionality like you're describing would certainly need some kind of core field versioning (maybe even event based). This would also need to be deeply considered with the database performance/choice. Event drive admin sounds fun, but it's also a new hurdle for new comers. With a core js api on the roadmap it might become more easily to implement any custom framework into the admin on your own. If there will be a admin js framework to be introduced I'd rather root for vuejs, which from my perspective does have the greater community and drive behind it. But that's to be determined if it comes to that point. Deeply nested selectors would certainly be a great addition.4 points
-
Should also be noted that there are multiple ways around this, depending on the larger context and your needs: If the booking system provides support for event-based actions and you need real-time data for your ProcessWire site, you could do what adrian mentioned above; make the booking software bootstrap ProcessWire and create new pages (or populate ProFields Table field or a custom database table of your own) for your reservations. If the reservation data doesn't have to be real-time and you have proper control over your production environment, you could create a cron job to fetch data from the booking system (assuming that you have access to it via an API or database). If you only need the data for view purposes and have access to the database that third-party booking app populates, you could just use ProcessWire's $database API variable and query it on the fly. The most important considerations here are a) do you need the data to be real-time and b) can you tap into the third-party systems events in order to bootstrap ProcessWire, does it have have a public API you can query, or do you have direct read access to its database.4 points
-
While I agree with earlier posters about not needing to update PW installations, honestly I agree more with teppo - I want older customers to reap the benefits of improved admin functionality. And course we are not just talking about the PW core here - there are also often 3rd party module updates - sure these updates might just add new functionality and there is always the chance that they might break something, but if you do your due diligence in checking the revised versions, it is nice to be able to update across all your sites at once. I actually had/have some plans to build something like this - but am waiting to see if the demand is going to be there. Module Toolkit is something I use in the meantime for updating all 3rd party modules on a site at once - it can be a significant time saver. But be aware that this module is currently alpha/early beta - I would like to get back to it and release it properly, but juggling priorities as usual3 points
-
I did a quick search and could not find one either. Guess you are lucky: You can make a new Language Pack and take all the fame. You can make it your own - all the translation errors will fit you taste. You can learn quite a lot about the system while making a translation. You can help the thing that helps you!3 points
-
That's true. Still, there are some reasons why you might want to update sites anyway: If you're hosting and supporting multiple sites, it's more overhead when they have different versions of the system running Updates often bring in new features – such as hugely improved image management tools – that your customers might want to use Not having known vulnerabilities in the core or third-party modules in the modules directory so far doesn't mean that these can never ever appear; especially when you're working with third party code, it's good to keep track what you're using and where, and for this reason alone a centralized management platform can be quite useful We're hosting quite a few sites and for this purpose I've built an in-house solution that does pretty much what you've described here. The focus is on making management of a large group of sites effortless and providing automation for common tasks, but this platform is also used to keep track of site-specific features, versions, usage, and so on. There's little chance of opening our in-house solution to larger community, but the thought of building something similar and open-sourcing it has crossed my mind a few times. Potential user base for this would be somewhat limited for the time being, but this is definitely something to keep in mind in the future3 points
-
I've already read 19 pages and (to me) it is a very enjoyable read. Thanks for the link. I've downloaded the pdf for further reading on my iPad.3 points
-
Make the pages not viewable for anyone (except superuser) and use the module permission system to limit view access of your dashboard module separately.2 points
-
Hello PW-friends! Let me share some thoughts re roadmap that emerged together with the development of mymechanic.ru site (currently 8K clients/30K visits per month). Initially it was a simple "info" site and PW was ideal for it, but when business has grown, I start to miss some functionality. I understand that this functionality may not be necessary for current PW sites or even PW concept, but anyway I would be grateful if you could share thoughts on the following: 1. simultaneous page editing capability. There are several roles that work with page and I have to remind them about queue in order to ensure that edits are saved properly. It is not effective. To unlock the capability, all fields and even admin layout should be able to update in "real-time" as soon as there are changes at server. Also there should be field-level lock/sync mechanism. I guess it is big core code refactoring. 2. event-driven admin (page editing, etc). With observers, controllers, routers etc - all you need when you develop frontend SPA. Of course, this can be done w/o PW internal features but I see great opportunity here for PW. By the way, check this framework - http://riotjs.com/ I believe it aligns well with PW ideas of best performance and simplicity. 3. advanced filtering in listers. E.g. the dream is filters like this: {myfield1.subfeild1.subfield1.date1} > {myfield2.subfeild2.subfield2.date2} - with indefinite levels depth, fully customizable on left and on right sides of condition, even with PHP snippets option. It is something that actually I haven't seen anywhere else - something really unique and powerful. I also have some other thoughts but I don't want to overload. These are top-3 in my mind. Thanks.2 points
-
If you save your pages under the Admin section in the Page list, isn't that OK to you?2 points
-
Posted this to GitHub, so ryan can look into implementing a warning/error.2 points
-
Hi petejones, and welcome. What LostKobrakai said, plus... PW really is a different beast to WP (and Joomla, or Mambo as it was when I first got involved with it). PW has had no known security issues, as ProcessWire or in its earlier incarnations. Background here. Unless you want the extra functionality that updates bring, there is no need to update an existing installation. Ryan explains one significant contributor here. I know this sounds strange, but PW doesn't need maintenance. It just works and carries on working and doesn't become broken for arbitrary reasons. Alright, on shared hosting (for example) there is the possibility that something could happen, but that would be because of poor security practices by the hoster, not PW.2 points
-
It really depends on how you can modify the third party booking software. Potentially you might be able to bootstrap PW into the software's processing script and save the info to PW fields using PW's API. You could use Profields table, or even just child pages - either can be populated via the API. We can help if we know more about how the booking software works.2 points
-
if ($page->page_field->id == 123) { echo $page->page_field->pageUrl; } Maybe something like this?2 points
-
Hi everyone, Here's a little module that allows you to force users to change their password on their first login, or at any time if you manually force it. http://modules.processwire.com/modules/password-force-change/ https://github.com/adrianbj/PasswordForceChange Key Features During install it creates a new checkbox field in the user template, "force_passwd_change". Automatic checking of this checkbox when creating a new user is determined by the "Automatic Force Change" module config setting. When a user logs in for the first time (or if you have manually checked that field for an existing user), they will be warned that they have to change their password and they'll be automatically redirected to their profile page. They must change their password to something new - they are not allowed to re-enter their existing password. Bulk "Set All Users" option to at any time, force all users (by selected roles) to change their password. Hopefully some of you will find it useful and please let me know if you have any suggested changes/enhancements. PS I used the new info.json way of defining the module details, so it requires PW 2.4.3+1 point
-
This tutorial will outline how to create a membership system that requires account activation via email. If you have a decent understanding of ProcessWire it isn't difficult at all! Create additional fields By default ProcessWire has a name, email, and password field for the user template. To allow for account activation we will have to add a couple more fields. Create the following fields and add them to the systems default user template. You can make ProcessWire show the system templates by going to setup -> templates -> toggle the filter tab -> show system templates -> yes. user_real_name user_activation Okay great, now that you have added the two additional fields to the user template we can start to code the registration form. I am not going to spend a lot of time on this part, because there is a tutorial that describes creating forms via the API. Create the registration form Once you have followed the tutorial on creating forms, you will have to add a couple of sections to your new form! <?php include("./functions.php"); require("/phpmailer/class.phpmailer.php"); $out = ""; $errors = ""; //create form //full name field //email field //username field //password field //submit button //form submitted if($input->post->submit) { $form->processInput($input->post); //instantiate variables taking in the form data $full_name = $form->get("full-name")->value; .... /* * Create the activation code * You can add a random string onto the * the username variable to keep people * from cracking the hash * ex $activation = md5($username."processwire"); */ $activation = md5($username); $activation_code = $config->httpHost."/activation/?user=".$username."&hash=".$activation; //check for errors if($form->getErrors() || username_validation($username) == 0) { $out .= $form->render(); //process errors /* * this checks to makesure that no one has the username * I have a functions file that I import to the pages I * need it on */ if(strlen($username) != 0){ if(username_validation($username) == 0) { $username->error = " "; $errors .= "Sorry that username is already taken!"; } } } //the registration was successful else { $out = "Thank you for registering!<br><br>"; $out .= "An email has just been sent to " . $email . " with the url to activate your account"; /* * In this example I am using phpmailer to send the email * I prefer this, but you can also use the mail() function */ $mail = new PHPMailer(); $mail->IsHTML(true); $mail->From = "email@domain.com"; $mail->FromName = "Register @ Your Site"; $mail->AddAddress($email); $mail->AddReplyTo("email@domain.com","Register @ Your Site"); $mail->Subject = "Registration"; $mail->Body = " Hi " . $full_name. ", <br>" . "Thanks for registering at Your Site. To activate your email address click the link below! <br><br>" . "Activation Link: <a href='http://".$activation_code."'>".$activation_code."</a>"; $mail->send(); //create the new user $new_user = new User(); $new_user->of(false); $new_user->name = $username; $new_user->email = $email; $new_user->pass = $password; $new_user->addRole("guest"); $new_user->user_full_name = $full_name; $new_user->user_activation = $activation; $new_user->save(); $new_user->of(true); } } //form not submitted else { $out .= $form->render(); } ?> <h2>REGISTER</h2> <div class="errors"><?php echo $errors; ?></div> <?php echo $out; ?> Okay so that outlines the entire form. Let me get into the important parts. Checking for a unique username /* * check if username exists * return 1 username is valid * return 0 username is taken */ function username_validation($username) { $valid = 1; $check = wire("users")->get($username); if ($check->id) { $valid = 0; } return $valid; } We don't want to try and add a username if the username is already taken, so we need to make sure to validate it. If this returns 0 you should output that the username is already taken, and the user needs to choose a different one. Generating an activation code /* * Create the activation code */ $activation = md5($username); $activation_code = $config->httpHost."/activation/?user=".$username."&hash=".$activation; This generates an activation code. It does so by encrypting the username variable and then combines the username and activation code into a url for a user to visit. Now we have to process the activation code. As the teppo recommended, it is a good idea to add an extra string onto the $username when encrypting it with md5. If you don't do this, people may crack it and allow for mass signups. $activation = md5($username."Cech4tHe"); Activate the user <?php include("./head.inc"); include("./functions.php"); /* * this will pull the username and * activation code from the url * it is extremely important to * clean the string */ $activate_username = $sanitizer->text($_GET['user']); $activate_hash = $sanitizer->text($_GET['hash']); if(wire("users")->get($activate_username)->id) { if(strcmp(wire("users")->get($activate_username)->user_activation, $activate_hash) == 0 || wire("users")->get($activate_username)->user_activation == 0) { echo "Your account has been activated!<br><br>"; $activate_user = wire("users")->get($activate_username); $activate_user->of(false); $activate_user->user_activation = "0"; $activate_user->save(); } else { echo "There was an error activating your account! Please contact us!<br><br>"; } } else { echo "Sorry, but that we couldn't find your account in our database!<br><br>"; } include("./foot.inc"); This pulls the username and activation hash from the url. It then goes into the database and looks for the user. Once it finds the user, it get's the user_activation hash and compares it to the one in the URL. If it matches, it activates the user by setting user_activation to zero. Clean the url You can user the built in $sanitizer->text() method to clean the url. This will keep people from inserting special characters that can break the page. Keeping unactivated users out You aren't done yet! Now you will have to choose which areas you want to restrict to activated users only. An activated user's user_activation field will now equal zero. So if you want to restrict a section check to make sure it is zero...... if($user->user_activation != 0) { echo "Sorry, but you need to activate your account!"; } else { // activated users }1 point
-
This week we've released ProcessWire version 3.0.5 which actually contains quite a lot of changes. Now you can nest repeater fields (repeaters in repeaters) and use dynamic/AJAX loading for all items. Plus we've got the first test version of Repeater Matrix released, and new support for field templates… https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/1 point
-
I have been pushing it on quora and there are usually a few others that will as well. Thats a great place. ie. https://www.quora.com/We-need-a-CMS-that-manages-images-and-themes-but-does-not-enforce-some-framework-Any-suggestions or https://www.quora.com/I-need-a-website-Should-I-use-WordPress-or-HTML-CSS-more-info-in-description or https://www.quora.com/How-do-I-make-content-editing-easy-for-my-web-design-clients/answer/Joe-Regan1 point
-
If those values come from other fields, you could always use the Textarea Markup module to achieve this.1 point
-
I strongly agree. This is a process that I use frequently and it works well.1 point
-
Thanks Ivan for making me smile You just have made my day a little bit better !1 point
-
Thank you very much for the fast reply. I understand the limitation now, but it would be good if there was a warning/message pointing that out, instead of telling that page-100 was created. The idea with the creation date helped me. It's a viable solution and should be easy to implement in my case (only for a single template relevant) without interfering with the exisiting automatic for other pages. Thanks again!1 point
-
That's true that limitation is here: https://github.com/ryancramerdesign/ProcessWire/blob/980ce4f0be2054dfbad4a7b334d35bdca42da7da/wire/core/Pages.php#L987 That limitation is there for a good reason as you can see from the code. (needs to do a count on every iteration) I think it's better not to rely on automatic page name when you have that amount of pages with the same title. Maybe you can incorporate the creating date or something to make it more unique, and then write a while loop yourself to make it unique for that date. Or set the title with the date, save the page, change the title to the wished title and save again.1 point
-
I just discovered that if I have a Leaflet Map marker field in a template, but leave the lat and long empty in a page, CKEditor text field will not display its toolbar. Must be some JS meltdown. I left the lat and long empty, because I am populating the map with an array of markers. It is no problem after I discovered this (just added lat & long values to make it work), but it was quite frustrating at first1 point
-
The easiest way will be to buy the Pro forms module: http://modules.processwire.com/modules/form-builder/ Otherwise there is this free module: http://modules.processwire.com/modules/form-template-processor-mailer/ Or if you want complete control, start reading about processing forms via the API here: https://processwire.com/talk/topic/2089-create-simple-forms-using-api/ - with this you can do anything you want, but you'll have to get your hands dirty1 point
-
1 point
-
$wire->addHookAfter("Pages::added", function(HookEvent $event){ $page = $event->arguments(0); // Do what you need to do with the page's data }); Put this in e.g. /site/init.php or add it to a module.1 point
-
Just in case someone else wants to do something like this, I just wanted to note that hooking before ProcessPageEdit::execute and foreaching through wire('breadcrumbs') works well. But for my particular needs I had problems with this approach and the Reno theme and so had to take another approach which worked: hooking after Process::breadcrumb Anyway, thought it might be useful info for others.1 point
-
Should anybody need this: $pages->addHookAfter("ProcessPageEdit::buildForm", function(HookEvent $event) { $page = $event->object->getPage(); $form = $event->return; if ($page->template->id == 44 && $page->parent->id != 1020) { $fieldset = $form->find("id=Inputfield_fieldset_tab_2")->first(); $form->remove($fieldset); $event->object->removeTab("Inputfield_fieldset_tab_2"); } }); Just replace the $page->template->id with the id of your template, and the $page->parent->id to what you want (or something similar). Finally replace fieldset_tab_2 with the name of your field.1 point
-
try.turn offs tat soma helper.feld links modole ? thowse gears iconos u.see in theyre1 point
-
I'm guessing that some new rewrite rule the SEO guys added caused it to start using those ?it= URLs, revealing them when it usually wouldn't. For instance, maybe they setup a rewrite rule that makes /index.php redirect to "/" without getting it quite right, thereby interfering with PW's own rewrite rules. I would suggest removing whatever rule they added that's causing the interference, and then putting your own alternative in a /site/ready.php or /site/templates/_init.php (if using one), like this: if(preg_match('/(index\.php|[?&]it=/!', $_SERVER['REQUEST_URI'])) { throw new Wire404Exception(); } Or if you just want to make it redirect to the homepage, replace the exception line with $session->redirect($config->urls->root); I will add something similar to the core ProcessPageView module to prevent that possibility too.1 point
-
// You need to to have the setting set: return null page if none selected. // When there's no page, a nullpage is returned, that page has ID 0, thus evaluates to false if ($myVariable->pageField->id) echo "<a href='{$myVariable->pageField->url}'>Link to Selected Page</a>";1 point
-
Could you please pick one: a) You need to check whether the page field has ANY value or b) You need to check whether the page field has a specific value (a specific page) or c) You need to check whether the page field even exist on the page's template. If a) or b) please check the Details tab of you field to see how is the field presented in the API - as an array or single page.1 point
-
1 point
-
Hi @Asmordean, Welcome to the forums. Until yesterday, not it was not possible. Given your question (and previous requests), I have gone ahead and added an option to enable CKEditor in Quick Post (see demo below). This is currently in the dev branch only (version 2.3.6). To enable, follow these steps: Update Blog to version 2.3.6 from Dev branch (either download the zip or use url to pass to PW to upgrade the module) Scroll to the bottom of ProcessBlog's module configurations (via /modules/). Check the box to enable use of RTE in Quick Post. NOTE: This setting (unlike the others) is available both before and after installing Blog). I decided to keep it here so that only Superusers can control it Head over to /blog/posts/ and reload the page. You should see CKEditor loaded Note: If you are on an older ProcessWire install without CKEditor, you will not see the RTE, of course. You cannot insert images in your post using this option. To do that, edit your post in normal 'page-edit' mode Please test and let me know how it goes.1 point
-
Ahh! Got it! You need an admin interface to easilly manage those guestbook submissions. 1) BernhardB's listerpro suggestion is what you want to go for if you have the option to use this paid module. It is really powerfull. 2) You could build a process module to list all guestbook submission for free, but you need to get your hands dirty with code . You can take a look at something like this for an inspiration: class GuestBook extends Process { public function init() { parent::init(); // always remember to call the parent init } public function execute() { $out = ''; $table = $this->modules->get("MarkupAdminDataTable"); // Table header $table->headerRow( ["Name of submission", "By whom...", ...] ); // Selector to get all your guestbook submissions $listing = $this->pages->find("..."); foreach ($listing as $page) { $data = array( // A td with the link to edit the page (you need to change the ... part) $page->title => $this->config->urls->admin . ".../edit/?id=" . $page->id, $page->created_by, ... ); $table->row($data); } $out .= $table->render(); $pagination = $listing->renderPager(); $out .= $pagination; return $out; } public function executeEdit() { // Write code to edit submission } // ... }1 point
-
I've come back to this topic myself about 3 years after having a similar need in a different thread. This code, from Tom's activity log module and altered slightly, gets both an old and new version of the page when hooking before saveReady: $clone = clone($page); $this->pages->uncache($clone); $old = $this->pages->get($clone->id); // Now just echo both the fields you are interested in: echo $old->field_of_interest . " becomes " . $page->field_of_interest; exit; On save, that should give you access to the old and new versions of the page where you want to compare just one or a few fields and you know which ones you're interested in already. Seems to simple now when you see the use of clone()1 point
-
1 point
-
Your hook and method has a lot wrong. If this all would work, then you would hook into Inputfield::render() and not Inputfield::renderValue(); And a hook to do what you wanted would look more like this: function hookAppendClassName($event) { $className = " mygrid"; $classes_array = $event->object->getParent()->getClasses(); $classes_array = array_merge($classes_array, array('item' => $classes_array['item']." ".$className)); $event->object->getParent()->setClasses($classes_array); } But this is not possible. When a inputfield is rendered in the inputfieldwrapper, the classes and markup is already set and you can not overwrite it at that moment in time. I also was looking into this and by chance I found a line of code in latest dev, that seems to be added recently. InputfieldWrapper rendering method looks for a $inputfield->wrapClass, I didn't know was there. So you can now simply do this: $field = $modules->InputfieldText; $field->label = "Name"; $field->wrapClass = "mysuperlol-col1--wonder__toootooo"; ...1 point
-
should be // create a text input $field = $modules->get("InputfieldText"); $field->label = "Name"; $field->attr('id+name','name'); $field->required = 1; $field->attr("class" , $field->attr("class") . " myclass"); $form->append($field); // append the field to the form required also adds a class... Happy experimenting.1 point
-
Yeah this should work. I figured out how you could add a image and get resized with the InputfieldImage you have. Having this as setting $field->maxWidth = 100; $field->maxHeight = 100; Then when adding the image to page field: // create new page image first $img = new PageImage($uploadpage->images, $upload_path . $file); // add it to page as usual $uploadpage->images->add($img); // trigger the image max size sizing $form->get("images")->fileAdded($img);1 point