Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 03/19/2018 in all areas

  1. Deprecation note (06/2022): This module has been deprecated in favour of a new RockForms module that does not only use NetteForms but also comes with a GUI. You can still use this module if you want, but I will not provide any fixes or updates or support! https://gitlab.com/baumrock/RockForms It uses the great NetteForms from Nette Framework (docs: https://doc.nette.org/en/2.4/forms ) Features: Client AND Server-side validation in one go (you only need to code your rules ONCE) CSRF protection (by processwire) Honepot spam protection (custom) Helper to create PW pages from submitted forms ($form->createPage($parent, $template, $title)) Add ?success=yourform tag to url ONLY after successful submission (for analytics) Recover fields after unsuccessful submission (server side validation error) Define custom actions + message on successful submission UiKit form renderer (more can be accepted by pull requests) Sample Form Setup: <?php namespace ProcessWire; $form = $modules->get('RockForms')->form; $form->addRadioList('salut', 'Anrede', ['m' => ' Herr', 'w' => ' Frau']); $form->addText('forename', 'Vorname'); $form->addText('surname', 'Nachname'); $form->addText('email', 'E-Mail-Adresse') ->setRequired('Bitte geben Sie Ihre Mailadresse an') ->addRule(Form::EMAIL) ; $form->addSubmit('submit', 'Anfrage senden'); $form->onSuccess = function($form) { $form->createPage(1017, 'mailitem', date('d.m.Y H:i:s') . ', {forename} {surname} {email}'); // send email // do whatever you want // return success message return 'thank you for your subscription'; }; echo $form->render(); For all available fields you can look here: https://doc.nette.org/en/2.4/form-fields Validation: https://doc.nette.org/en/2.4/form-validation Rendering: https://doc.nette.org/en/2.4/form-rendering More complex form example of the screencast: Module is alpha and not well tested yet. It should be save to use, but there might be breaking changes in the future. Also I'm quite sure that not all possible situations are covered. There are some switch() statements that check for the fieldtype and I only implemented the ones I needed so far. All others are easy to add - please make pull requests if you find any unsupported fields. Thank you. LIMITATIONS: Multiform support limited Changelog: 6.8.18 add multiform support 8.4.18 v2 little bugfix + load assets automatically 19.3.18 alpha release
    21 points
  2. Nice, seems you had more time on this than me on my very similar module If you (or someone else) could devote enough time I can share my module that I have already started to polish. Perhaps you could merge the two or get ideas from it:
    8 points
  3. // pseudo code, change field name with yours $image_to_be_filled = $page->your_image_field; if (count($image_to_be_filled) == 0) { //here I'm searching by template, but it's up to you to build the selector you need/prefer $default_image = $page->get('template=the_template_holding_your_default_image')->field_of_your_default_image; //from here do whatever you want with the $default_image variable ... }
    4 points
  4. In our use case we needed to import thousands of CSV entries automatically per cronjob. So we ended up with a little shell script using the CSV package by the League of Extraordinary Packages and custom logic to import the CSV entries as pages. This wasn't that difficult thanks to the Composer integration of ProcessWire. Regards, Andreas
    3 points
  5. If you don't need to search by specific field names nested in the matrix, you could add a concatenated (hidden) textarea field, hook into saveReady and render the matrix contents into that field. Then include that field for your search. Or, if you want to be able to search by property names (at any depth) have at least MySQL 5.7.8, you could try out the attached module JsonSearchable.zip. It's a field type derived from Textarea that uses native JSON storage. Supposed you made a page field named "myfield" and entered a JSON of: { "testdata":[ { "segment":1, "title":"Hello World", "average":20, "max":"30", "min":5 }, { "segment":2, "title":"This is Funny", "average":40, "max":"30", "min":5, "details":{ "name":"nobody", "email":"secret" } } ] } You could e.g. search for <?php $pages->find("myfield=30"); $pages->find("myfield.max=30"); $pages->find("myfield.details.name=nobody"); Note however that this kind of search on many large datasets can be an absolute performance killer. Numeric comparisons are not supported.
    3 points
  6. v1.8.5 is available, which contains @Robin S CKEditor Link Files CKE plugin, multilanguage-ready. @theo Have you managed to solve the issue? I couldn't find any relevant info on "Browser Network Analysis". Are you sure you entered a correct path?
    2 points
  7. Finally I built a module for creating FrontendForms easily:
    2 points
  8. Yes!! It all worked perfectly, thanks!! Thought it was taken for granted lol sorry, this is the working code: $wire->addHookBefore("TemplateFile::render", function($event){ $templateFile = $event->object; if($templateFile->page->template == "repeater_content"){ $customFileName = $this->config->paths->templates . "fields/content/{$templateFile->page->type}.custom.php"; if(is_readable($customFileName)){ $templateFile->setFilename($customFileName); $event->return = $templateFile; } } elseif($templateFile->page->template == "home" || $templateFile->page->template == "basic-content" ){ $customFileName = $this->config->paths->templates . "{$templateFile->page->template}.custom.php"; if(is_readable($customFileName)){ $templateFile->setFilename($customFileName); $event->return = $templateFile; } } }); I have some hardcoded if statements because I don't want to be checking for EVERY template, but this works nice for repeater matrix (which uses TemplateFile to render the matrix types) and any other template. Also my first snippet was misleading because I didn't want to do a user check, so I removed that too.
    2 points
  9. Is it a Repeater that you need? http://processwire.com/api/fieldtypes/repeaters/ https://processwire.com/videos/repeater-field-type/ https://modules.processwire.com/modules/fieldtype-repeater/ https://processwire.com/talk/topic/958-repeatable-fields/
    2 points
  10. 3-4+ years I think. It took me a while and it was a bit of a stop/start journey, but I now have converted and can't go back. Ah fatigue & RSI. Luckily I've rarely suffered from it so far from coding touch wood. Only incidents I can think of late are after some epic FPS sessions involving Doom, Shadow Warrior & Killing Floor 2. Yes it is unavoidable and one shouldn't avoid it. Trouble for me was, I was switching back and forth between IDEs every few months and I would forget all the shortcut keys after a while, and some of them involve complex key strokes like multiple ctrl + key combos. If you take the time to setup a layout that reflects your workflow and usage pattern that is IDE agnostic or independent, then you can free yourself from remembering all the short cuts. Even if you do, it's much easier to look up what the button is then some obscure keyboard short cut hidden away in the layered menu structure. Great thing is it is programmable so you can program it to do anything. Funny enough you're the first person that showed any interest in it. I remember when I first saw the mouse, I got a sudden brainstorm and thought for using it to aid with my IDE situation. Certainly my MMO playing friends thought I was mad for getting a MMO mouse for that. I also recall people calling me mad for deciding to use Processwire for my first Website
    2 points
  11. Unless my memory fails me, all I did was add support for multiple answers and user-submitted suggestions. Might've made some general purpose (JavaScript/CSS?) tweaks too, not entirely sure anymore. Once the current version stabilises, i.e. I know whether the updates from @BitPoet get merged in, I could set up a new PR for these
    2 points
  12. Update: I have been playing around some more. There's now another branche dev-bitpoet-cke that includes a Textformatter which replaces ##POLL:name-of-poll-page## with the poll output and a CKEditor plugin for easy insertion.
    2 points
  13. Hi @Soma! First of all, thanks for another really useful module. Since I'm planning to add polls to my blog site profiles, I've dabbled with it abit. To make things work nicely with the existing templates, I had to tweak a bit of the generated HTML and, in the course of that, changed your module a bit: It now uses templates for every bit of HTML produced Added config settings for all these HTML template snippets There's a template for the main wrap, so wrapping the renderPoll() return manually is no longer necessary Added a config option and poll template field for a poll closing date (+time) pollino-ajax-script.js now wraps a div around the result before inserting it. That prevents a jQuery error if the result contains more than one HTML element. I'm storing any array $config data passed to renderPoll() in the user session and retrieve it in the AJAX action Added collapsed fieldsets for different template areas (generic, form, result) in the module config Last but not least, added "PHP" hints to the code blocks in README.md I have made a fork and added a branch with all these changes here. Perhaps you could give it a look (test drive?) and tell me if I should prepare a pull.
    2 points
  14. Just wanted to share what I recently used to create forms in modules and in frontend using the API and Inputfield modules PW provides and uses on its own. I think many newcomers or also advanced user aren't aware what is already possible in templates with some simple and flexible code. Learning this can greatly help in any aspect when you develop with PW. It's not as easy and powerful as FormBuilder but a great example of what can be archieved within PW. Really? Tell me more The output markup generated with something like echo $form->render(); will be a like the one you get with FormBuilder or admin forms in backend. It's what PW is made of. Now since 2.2.5~ somewhere, the "required" option is possible for all fields (previous not) and that makes it easier a lot for validation and also it renders inline errors already nicely (due to Ryan FormBuilder yah!). For example the Password inputfield already provides two field to confirm the password and will validate it. De- and encryption method also exists. Or you can also use columns width setting for a field, which was added not so long ago. Some fields like Asm MultiSelect would require to also include their css and js to work but haven't tried. Also file uploads isn't there, but maybe at some point there will be more options. It would be still possible to code your own uploader when the form is submitted. Validation? If you understand a little more how PW works with forms and inputfields you can simply add you own validation, do hooks and lots of magic with very easy code to read and maintain. You can also use the processInput($input->post) method of a form that PW uses itself to validate a form. So getting to see if there was any errors is simply checking for $form->getErrors();. Also the $form->processInput($input->post) will prevent CSRF attacks and the form will append a hidden field automaticly. It's also worth noting that processInput() will work also with an array (key=>value) of data it doesn't have to be the one from $input->post. Styling? It works well if you take your own CSS or just pick the inputfields.css from the templates-admin folder as a start. Also the CSS file from the wire/modules/InputfieldRadios module can be helpful to add. And that's it. It's not very hard to get it display nicely. Here an code example of a simple form. <?php $out = ''; // create a new form field (also field wrapper) $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "post"; $form->attr("id+name",'subscribe-form'); // create a text input $field = $modules->get("InputfieldText"); $field->label = "Name"; $field->attr('id+name','name'); $field->required = 1; $form->append($field); // append the field to the form // create email field $field = $modules->get("InputfieldEmail"); $field->label = "E-Mail"; $field->attr('id+name','email'); $field->required = 1; $form->append($field); // append the field // you get the idea $field = $modules->get("InputfieldPassword"); $field->label = "Passwort"; $field->attr("id+name","pass"); $field->required = 1; $form->append($field); // oh a submit button! $submit = $modules->get("InputfieldSubmit"); $submit->attr("value","Subscribe"); $submit->attr("id+name","submit"); $form->append($submit); // form was submitted so we process the form if($input->post->submit) { // user submitted the form, process it and check for errors $form->processInput($input->post); // here is a good point for extra/custom validation and manipulate fields $email = $form->get("email"); if($email && (strpos($email->value,'@hotmail') !== FALSE)){ // attach an error to the field // and it will get displayed along the field $email->error("Sorry we don't accept hotmail addresses for now."); } if($form->getErrors()) { // the form is processed and populated // but contains errors $out .= $form->render(); } else { // do with the form what you like, create and save it as page // or send emails. to get the values you can use // $email = $form->get("email")->value; // $name = $form->get("name")->value; // $pass = $form->get("pass")->value; // // to sanitize input // $name = $sanitizer->text($input->post->name); // $email = $sanitizer->email($form->get("email")->value); $out .= "<p>Thanks! Your submission was successful."; } } else { // render out form without processing $out .= $form->render(); } include("./head.inc"); echo $out; include("./foot.inc"); Here the code snippet as gist github: https://gist.github.com/4027908 Maybe there's something I'm not aware of yet, so if there something to still care about just let me know. Maybe some example of hooks could be appended here too. Thanks Edit March 2017: This code still works in PW2.8 and PW3.
    1 point
  15. Not sure what you mean here. When you use the feature I mentioned to select a page that will hold the default value for the image field, the image field will have the value of the default field when it is empty on a particular page. The value will be a Pageimage object or a Pageimages object depending on the field settings (and assuming you have one or more images in the field on the page used for the default value). You shouldn't need to do anything different to get the object or any of its properties (url, etc) than you would do if the field was populated on the page. In other words, you can do something like... $page->image->size(400,300)->url ...and it will work the same regardless if the image is coming from an image that is actually in the field on that page, or the default value when the field is empty.
    1 point
  16. Good catch! Just modified the module to allow loading both, thanks. (will be released later)
    1 point
  17. Ah, now I see. If there is a CKE CSS configured in the field page, then the one configured in AOS is not loaded. Thank you.
    1 point
  18. There is a feature for this built into image fields (Details tab):
    1 point
  19. That would be brilliant. Though @Soma might have to rename his module from Pollino to Pollissimo (it feels like it's about to outgrow the diminutive...)
    1 point
  20. @bernhard This works great afaics. Well done. I think this is a valuable addition. I hate speed limits.
    1 point
  21. Hi everyone, [edit: do not loose your time reading this post, I solved it by disabling cache in the Pages2Pdf module... sorry ?] I do not know if I should post on the Pages2Pdf thread or here. Mods, feel free to move the post. Since three days I am scratching my head to understand a weird thing happening with $session and $config->debug used in conjunction with Pages2Pdf module. For information, I tested it on a fresh install of ProcessWire 3.0.96 with PHP-7.0.28 and Pages2Pdf-1.1.7 (domain: http://session.sites.sek/). I will try to explain what is going on. What I am trying to achieve : In a template, I need to set some sessions variables which are then echo'd in the PDF document. (on the test installation, the basic-page template (page /about/?pages2pdf) serve the PDF, the home and sitemap template set the session variable.) The problem : From the template sitemap, I set a variable: $session->setFor('pdf', 'myvar', 'Session set from Sitemap template'); From the template home, I set a variable: $session->setFor('pdf', 'myvar', 'Session set from Home template'); Then in the PDF default template, I echo the session variable: <p>Session: <?= $session->getFor('pdf', 'myvar'); ?></p> Now I turn ON debug mode ($config->debug = true) : Then I navigate to "http://session.sites.sek/home/" and the session variable "myvar" is set to "Session set from Home template". Then I navigate to "http://session.sites.sek/sitemap/" and the session variable "myvar" is set to "Session set from Sitemap template". Now I want my PDF document, so I navigate to "http://session.sites.sek/about/?pages2pdf=1" and I get my PDF document with the right session var : "Session set from Sitemap template" For the moment, nothing special happen. Everything work great. We are in debug mode. Now I turn OFF debug mode ($config->debug = false) : Then I navigate to "http://session.sites.sek/home/" and the session variable "myvar" is set to "Session set from Home template". Then I navigate to "http://session.sites.sek/sitemap/" and the session variable "myvar" is set to "Session set from Sitemap template". Then I navigate back to "http://session.sites.sek/home/" and the session variable "myvar" is set back to "Session set from Home template". Now I want my PDF document - as expected, the "myvar" should be set to "Session set from Home template" - so I navigate to "http://session.sites.sek/about/?pages2pdf=1" and here the problem happen. Instead of echoing "Session set from Home template" in the PDF document, the phrase "Session set from sitemap" is echo'd (the last value recorded before switching from debug ON). I made two small screencasts to show the issue : DEBUG ON (Everything is OK) DEBUG OFF I am missing something ? EDIT: YES, you are dumb! Why it is working with debug mode ON and not vice-versa ? Is there someone who already spotted this strange behavior ? Is there a PHP settings which should be modified ? ==================================================== Edit: I needed to post just to figure myself that Pages2Pdf cache the document when $config->debug is false. ???
    1 point
  22. @Peter Falkenberg Brown are you sure you don't have it improperly configured? The only way to get the module to output the XSL stylesheet would be if you set that in the module config. You shouldn't have to comment out any code. this is the config setting: https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Markup/MarkupRSS.module#L258 this line means it would only output XSL if you entered the path to that stylesheet in your settings: https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/modules/Markup/MarkupRSS.module#L90
    1 point
  23. Too bad it cannot be released as a one/multiple website(s) commercial and/or opensource/community and/or free profile. It hasn't been used very long.
    1 point
  24. Just visited cmscritic.com again after a while (I'm subscribed to their newsletter). Apparently, they switched again to Wordpress (everything points to that, when opening browser inspector and seeing their HTML, the usual wp-xxx folders and file naming). Does anybody know the reason why? @ryan Were they unhappy with PW in some sort? oops, I kinda double-posted - didn't see a similar post from just 15 minutes ago...
    1 point
  25. What's the big picture? Where are these JSON files coming from? Do you just build a frontend with externally fetched JSON data? Do you have to fetch / update JSON data on a regular basis? Or do you create this JSON yourself?
    1 point
  26. A friend of mine is very happy with this one: http://amzn.to/2Dz2zRB I think it's an interesting concept and I'll give it a try
    1 point
  27. Just came across this need for the SEO module as well. I have posted this request: https://github.com/processwire/processwire-requests/issues/170 Until there is some progress on that, here is my hacky solution. I am sure it could be improved, but it works for now. $this->addHookBefore('ProcessModule::executeEdit', function($event) { if(!$this->wire('user')->isSuperuser() && $this->wire('input')->get->name !== 'MarkupSEO') { throw new WirePermissionException('You do not have permission to configure this module.'); } }); $this->addHookAfter('ProcessModule::executeNavJSON', function($event) { if(!$this->wire('user')->isSuperuser()) { if($this->wire('input')->get->site === '1') { // note \/admin\/module\/ - if your site admin is at /processwire/, then use: \/processwire\/module\/ $event->return = '{"url":"\/admin\/module\/","label":"Modules","icon":"plug","list":[{"url":"edit?name=MarkupSEO","label":"MarkupSEO","icon":"gear"}]}'; } else { $event->return = null; } } }); That results in this - Modules > Site contains just the SEO link and all the others are empty. Thanks @Robin S for the headstart on this!
    1 point
  28. Glad you sorted this out. Even though I would change the main selector as @rafaoski suggested, to retrieve only those pages that have images, imo it's a bit more performant.
    1 point
  29. I often use this library with composer: https://github.com/oscarotero/social-links Can show total of shares too! Design can be made with CSS individually.
    1 point
  30. A little help if someone has the same problem: images on develpment site were included, but not on live site. There is no error or any hint, but only a red "x" as placeholder for the image. Try to convert to base64 string included the image to the PDF. For me it even reduced the filesize $imagedata = file_get_contents( "../assets/img/logo-pdf-invoice.png"); // alternatively specify an URL, if PHP settings allow $base64Img = "data:image/png;base64," . base64_encode($imagedata);
    1 point
  31. I thought of another option around this: you could give the 'module-admin' permission to the role, and then use a hook to check which module is being requested and only allow access to a particular module. $this->addHookBefore('ProcessModule::executeEdit', function($event) { if(!$this->user->isSuperuser() && $this->input->get->name !== 'MarkupSEO') { throw new WirePermissionException('You do not have permission to configure this module.'); } }); Now you just need to create a custom link in admin to the module config page, maybe using a simple Process module. Or I think AdminOnSteroids lets you add custom menu items - haven't tried it myself.
    1 point
  32. The problem with your approach is, that it only requests the data once and ProcessWire returns all pages instead of those who match the query string. This could be a problem on very dynamic sites, where the content changes often. Here is my solution which solves this: Modify the standard search.php and add if ($config->ajax) { header("Content-type: application/json"); // Set header to JSON echo $matches->toJSON(); // Output the results as JSON via the toJSON function } so the whole file reads <?php namespace ProcessWire; // look for a GET variable named 'q' and sanitize it $q = $sanitizer->text($input->get->q); // did $q have anything in it? if ($q) { // Send our sanitized query 'q' variable to the whitelist where it will be // picked up and echoed in the search box by _main.php file. Now we could just use // another variable initialized in _init.php for this, but it's a best practice // to use this whitelist since it can be read by other modules. That becomes // valuable when it comes to things like pagination. $input->whitelist('q', $q); // Sanitize for placement within a selector string. This is important for any // values that you plan to bundle in a selector string like we are doing here. $q = $sanitizer->selectorValue($q); // Search the title and body fields for our query text. // Limit the results to 50 pages. $selector = "title|body%=$q, limit=50"; // If user has access to admin pages, lets exclude them from the search results. // Note that 2 is the ID of the admin page, so this excludes all results that have // that page as one of the parents/ancestors. This isn't necessary if the user // doesn't have access to view admin pages. So it's not technically necessary to // have this here, but we thought it might be a good way to introduce has_parent. if ($user->isLoggedin()) $selector .= ", has_parent!=2"; // Find pages that match the selector $matches = $pages->find($selector); $cnt = $matches->count; // did we find any matches? if ($cnt) { // yes we did: output a headline indicating how many were found. // note how we handle singular vs. plural for multi-language, with the _n() function $content = "<h2>" . sprintf(_n('Found %d page', 'Found %d pages', $cnt), $cnt) . "</h2>"; // we'll use our renderNav function (in _func.php) to render the navigation $content .= renderNav($matches); } else { // we didn't find any $content = "<h2>" . __('Sorry, no results were found.') . "</h2>"; } if ($config->ajax) { header("Content-type: application/json"); // Set header to JSON echo $matches->toJSON(); // Output the results as JSON via the toJSON function } } else { // no search terms provided $content = "<h2>" . __('Please enter a search term in the search box (upper right corner)') . "</h2>"; } Then call typeahead with the following options: $.typeahead({ input: '#q', order: 'desc', hint: false, minLength: 3, //cache: false, accent: true, display: ['title'], // Search objects by the title-key backdropOnFocus: true, dynamic: true, backdrop: { "opacity": 1, "background-color": "#fff" }, href: "{{url}}", emptyTemplate: "No results for {{query}}", searchOnFocus: true, cancelButton: false, debug: true, source: { //url: actionURL // Ajax request to get JSON from the action url ajax: { method: "GET", url: actionURL, data: { q: '{{query}}' }, } }, callback: { onHideLayout: function (node, query) { $('#searchform').hide(); console.log('hide search'); } } }); The important parts are "dynamic:true" and the "source" configuration so the query string is beeing sent. Now you have a nice AJAX search. EDIT: If you also want to find the query string in other fields than the title make sure you add filter: false to the config of typeahead.
    1 point
  33. Just use httpUrl instead of url.
    1 point
  34. The idea behind the jobs forum is for anyone looking for paid development work to post their requirements in one place and for developers to get in touch with them. Any project can be posted, whether it's custom development work, website design, or complete installation and setup of a website. There are a few guidelines that are useful to bear in mind to help things go smoothly: Give a good amount of detail about the project so that prospective developers know roughly what will be involved. If a project requires an NDA for any reason, try and give non-specific details such as the type of development work involved (module development etc). Let people know how to contact you - if no contact details are given, people will most likely PM you on the forums here. If you have a requirement to work with a developer in the same country as you, please mention this to narrow the field of applicants. If you are happy mentioning a budget in the open, this is also fine but not required.
    1 point
  35. The "missing required value" string is translatable in the file /wire/core/InputfieldWrapper.php. For your language pack, you would add this file as a translation target.
    1 point
×
×
  • Create New...