Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/18/2018 in all areas

  1. Hello, friends! These days it is not that easy to join you here on the forums if you happen to be anywhere in Russia. You probably heard about our government's struggle to ban Telegram. And ProcessWire's ip is in the list. At these moments you start to understand just how important can a seemingly remote online community be in your everyday life and work. Thank you all for being here. As long as VPN's still function we can stay together .
    17 points
  2. Another update is online (branch DEV3): https://gitlab.com/baumrock/RockSqlFinder/tree/dev3 This is a major upgrade, a complete rewrite and finally a really good solution imho: I changed the syntax to object-notation in preference of nested associative arrays and it's a lot cleaner and easier to setup and read now. I rewrote the logic completely. It is NOT recursive any more but it takes away a LOT of complexity. You can add "fields" to your find-operation and those "fields" are fully customizable classes. The module ships with predefined classes for FieldtypeText (easy as it is just a column in the DB), FieldtypeFile (that shows concatenated filenames and descriptions) and FieldtypeRepeater (that shows concatenated data of the repeateritem's fields). The user can add custom FieldFinders in /site/assets/RockFinder (this will be the final name of the module). Possibility to add custom separators for concatenated fields Easy to create custom SQL by wrapping the created SQL in your own statement (SELECT ... FROM $finder->getSQL() GROUP BY ...) Examples: Query 10.000 invoices and return their date and value: Query all persons and show content of images (fieldtypeimage) and repeater (fieldtyperepeater): Same example but with image descriptions and all repeateritem's fields: Find 35.000 pages: This takes significantly longer than finds until 10.000 items. Maybe @adrian or @theo you have time to compare these results on your setups? Todos: Support for FieldtypePage (and other fieldtypes?) Support for Multilanguage (should not be hard, I've developed it with that in mind) Aggregation functions like sum(), avg(), min(), max() Support for closures? What do you guys think?
    6 points
  3. "Government guys" all over the world just do not understand that there is no such thing as "only officials can exploit security measures on behalf of the law". If they force backdoors to be implemented into software/hardware then anyone with enough technical skills can also walk through that door. They do not understand the basics of IT security, they live in their dream worlds trying to make the internet less secure therefore introducing more chaos instead of order they say they are striving for. They are doing quite the opposite what they are saying. Why am I not surprised?
    5 points
  4. You can use a hook in ready.php to delete cache on save of pages // delete caches when pages are created, saved or moved around wire()->addHookAfter('Pages::save', function(Hookevent $event) { $page = $event->arguments(0); // do nothing on admin pages if($page->template == 'admin') return; // delete cache for templates if($page->template == 'where-to-go-detail' || $page->template == 'our-guides-detail') { $this->cache->delete('wtg'); // here you could add logic to rebuild the cache } });
    5 points
  5. The skipLabel option is about whether or not to render the header of the inputfield. An example with InputfieldText: $f = $modules->get('InputfieldText'); $f->name = 'text1'; $f->label = 'label'; $inputfields->add($f); $f = $modules->get('InputfieldText'); $f->name = 'text2'; $f->label = 'label'; $f->skipLabel = Inputfield::skipLabelHeader; $inputfields->add($f); For InputfieldCheckbox, the header is already not rendered by default unless a description is defined for the inputfield. Instead, the label is rendered next to the checkbox itself. So setting skipLabelHeader or skipLabelBlank won't do anything because the header is already skipped. If you do want a separate header label for InputfieldCheckbox you can use the "checkboxLabel" or "label2" properties (they both do effectively the same thing). When these properties are set the "label" is rendered in the header and the "checkboxLabel" or "label2" is rendered next to the checkbox: $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox1'; $f->label = 'label'; $inputfields->add($f); $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox2'; $f->label = 'label'; $f->checkboxLabel = 'checkboxLabel'; $inputfields->add($f); If your question is actually "is it possible to have a checkbox without any text next to it" I think the answer is no, not using the API options. You could try a str_replace() in a hook after InputfieldCheckbox::render, or use Javascript to remove the text. Edit: another alternative for a checkbox without text next to it is to use a space character as the label: $f = $modules->get('InputfieldCheckbox'); $f->name = 'checkbox1'; $f->label = ' '; $inputfields->add($f);
    5 points
  6. Sorry guys for all those posts... Found the performance-killer: It is the ORDER BY field(`pages`.`id`, 52066,52067,52068,52069,52070 ... ) part. Without retaining the sort order of the pages->findIDs it is a LOT faster (4s without sort compared to 60s with sort and 75 using findMany): 91300 items: rockfinder = 4385.5ms | findmany = 74213.9ms | 5.91% I'll add this as an additional option and switch sort order OFF by default since sorting will be done by RockGrid anyhow No problem at all. I need this stuff for my own work, so any help is welcome but of course not expected PS: again the tests without sort order 11 items: rockfinder = 4ms | findmany = 6.9ms | 57.97% 1000 items: rockfinder = 35.7ms | findmany = 744.2ms | 4.8% 5000 items: rockfinder = 165ms | findmany = 1675.4ms | 9.85% 10002 items: rockfinder = 327ms | findmany = 3359.5ms | 9.73% 35000 items: rockfinder = 1745.2ms | findmany = 28547.7ms | 6.11% 91300 items: rockfinder = 4385.5ms | findmany = 74213.9ms | 5.91% Now that looks a lot better, doesn't it?
    4 points
  7. Sort order in database can affect the results returned. So, unless you are 'finding' everything, it is good to have the option to sort server-side.
    2 points
  8. Users have to select the admin theme from their profile before it's active for them. Edit your profile (where you change your password) and select Uikit as your admin theme. Also, delete your /site/modules/AdminThemeUikit/. It's not hurting anything, but you don't need it anymore.
    2 points
  9. Sure, and I'm not saying there is something wrong with the intent of GDPR. It is just the ridiculous extent of fines and the unrealistic situation of changing software and habits overnight is what turns it into a big issue. Being a topic doesn't mean that the real possibility of this change has been really considered. If European companies are forced out of business just because they cannot comply for various reasons then companies in other countries will profit from disappearing concurrent businesses. If we shoot ourselves into our feet, it's going to hurt us and not others.
    2 points
  10. Thanks for clarifying. At least we now know you have such feelings.
    2 points
  11. Guys, I guess Sandra Morgan's post is spam. It includes a link not to a checklist but a service, most probably their own...
    2 points
  12. Building a website is not the problem. Running a business with it can become the problem. Collecting e-mail addresses, tracking visitors and monitoring visitor-behaviour, combining it with 3rd parties like Facebook and ad networks will be a much bigger thing now. Cookie permissions here, double-opt-in there, and so on... it will be much more challenging than before. Don't know anything special about sources in Spain, UK, US but here in Germany there are some lawyers offering (free and paid) help for all kinds of businesses. Just to name two I prefer: https://www.e-recht24.de/ and https://drschwenke.de/ And as always with legal stuff: lawyers are my one and only trusted source. Not other companies (like the one above) that offer checklists, guides and tutorials.
    2 points
  13. i haven't worked on this ajax module for several months so it really is not ready, but i do have a working version if you want to try it. It needs testing, and work; The screenshots show some elements of the setup in case of any confusion. ---the field--- ---the files--- InputfieldSelectizeAjax.js InputfieldSelectizeAjax.module
    2 points
  14. One of the ways you can show support for ProcessWire is to help get the word out by including a small "Powered by ProcessWire CMS" tagline (ideally linking to processwire.com) in the footer of sites that you develop. This is a big help to the ProcessWire project. But I know there are many cases where it just doesn't work to do that because the client thinks of it as gratuitous. I think it's important to communicate to your client that it's not gratuitous at all. It is doing the right thing by showing appreciation and support for a software that is running their site at no cost. Even so, it's not always as simple as that, and I completely understand. We have no requirement or expectation that sites developed in ProcessWire do this. We just encourage and appreciate it when you can. Let your client decide One thing I've been doing lately is to put the control into my clients hands. They really appreciate that I've given them control over it… more so than if I'd left out mention of ProcessWire completely. It also makes them feel good as they are the one showing support, not just their site developer. Here's how to do it in 1 minute: 1. Create a new "checkbox" field in Setup > Fields called "toggle_powered" (or whatever you want to call it), and enter the following for label and description: 2. Add the "toggle_powered" field to your homepage template. 3. Edit the homepage and check the box (if possible in your situation). 4. Edit the template file or include file that contains the site footer and paste in the following: <?php if($pages->get('/')->toggle_powered): ?> <p> <a id='processwire' target='_blank' href='http://processwire.com'>Powered by ProcessWire Open Source CMS/CMF</a> </p> <?php endif; ?> The code above is an example, so adjust the markup, size, wording and placement to suit the site.
    1 point
  15. If you've ever needed to insert links to a large number of files within CKEditor you may have found that the standard PW link modal is a somewhat slow way to do it. This module provides a quicker way to insert links to files on the page being edited. You can insert a link to an individual file, or insert an unordered list of links to all files on the page with a single click. CKEditor Link Files Adds a menu to CKEditor to allow the quick insertion of links to files on the page being edited. Features Hover a menu item to see the "Description" of the corresponding file (if present). Click a menu item to insert a link to the corresponding file at the current cursor position. The filename is used as the link text. If you Alt-click a menu item the file description is used as the link text (with fallback to filename if no description entered). If text is currently selected in the editor then the selected text is used as the link text. Click "* Insert links to all files *" to insert an unordered list of links to all files on the page. Also works with the Alt-click option. Menu is built via AJAX so newly uploaded files are included in the menu without the page needing to be saved. However, descriptions are not available for newly uploaded files until the page is saved. There is an option in the module config to include files from Repeater fields in the edited page. Nested Repeater fields (files inside a Repeater inside another Repeater) are not supported. Installation Install the CKEditor Link Files module. For any CKEditor field where you want the "Insert link to file" dropdown menu to appear in the CKEditor toolbar, visit the field settings and add "LinkFilesMenu" to the "CKEditor Toolbar" settings field. http://modules.processwire.com/modules/cke-link-files/ https://github.com/Toutouwai/CkeLinkFiles
    1 point
  16. Please see the current version of this module here: https://modules.processwire.com/modules/rock-finder/
    1 point
  17. This occurred back in January of this year. It's still a great analytical system.
    1 point
  18. The "option" to sort on the server side is of course always there. But I set it to use sorting by default now. I think the worse performance will not matter in most of the cases. If it does, the user will realise it and can easily turn it off. It would be worse to think everything works as expected and then get some unexpected results due to sorting turned off while you think it should actually return a sorted resultset ( like from a selector containing the sort keyword ). Thanks for your feedback.
    1 point
  19. There is a big world around PW! every time discover something new it leaves me speechless! But yes, don't have possibility to directly access php files in the "templates" directory and other locations in PW's file system it's really a great things! Good to know, I was going crazy o.o Thank you (again) @Zeka fro your support!
    1 point
  20. Ok, that is GDPR-related but in another field. At least it's nothing I came across in the last couple of years. So I don't care much about this part. But to be honest... regulation of this exact type of irresponsible behaviour and reckless data-sharing is absolutely necessary. GDPR isn't that new and data privacy is a main topic for almost a decade here in Germany. Let's face the truth... companies like the one in your example are the reason for things like GDPR.
    1 point
  21. lawn mower principle...
    1 point
  22. I suppose because it runs off Amazon's servers...?
    1 point
  23. I'm not talking about all kinds of third party software. Just a few. We may have to stop ourselves and our clients from using third party things like: Google Analytics Google Adsense Google Fonts Typekit and similar services Ad networks Facebook Pixel Hotjar Hubspot Social Widgets Free CDNs ... and so on At least as we used it in the past. There are GDPR compliant ways of using Analytics, Retargeting, Monetizing and whatever. But it's work now.
    1 point
  24. This is my main concern, in general. You see, all the software we and our clients use is third party, not to mention hardware. We just add a bunch of code on top of lots of underlying systems. So now what?
    1 point
  25. Making sites GDPR compliant... this is a thing I'm careful with. Knowing what to for each client because of an audit or a lawyer who looked into it will work. No doubt. You do what a professional and reliable source said to make a site compliant. But I personally have not and will not tell a client what to do or what not to do. I know some things (probably more than any client and some "experts" out there) but stating and offering GDPR compliant sites can get me into trouble. I'm not a lawyer I can't offer legal advise at all. The without warranty-thing that eRecht24 does is fine. They offer generators and therefore legal texts based on your input. Asking a lawyer (or better lawyers) to check and create everything for you will cost you a lot of money but then you will get a warranty too. Providing design works, logic and functionality will almost stay the same. Being GDPR compliant from start can and will be tricky. At some point someone has to ask a lawyer. At some point you have to stop implementing third parties. At some point other GDPR-related things kick in (like the Datenschutzbeauftragter) and the developer isn't the right person for that detail anymore. As developers we can't handle every aspect of the GDPR and things that will come. But yes... getting our hands dirty will come and it's necessary. Necessary for good and trusted developers.
    1 point
  26. The next best thing... $imageFields = []; foreach($this->fields as $field) { if($field->type instanceof FieldtypeImage) $imageFields[] = $field; }
    1 point
  27. @bernhard Glad you found the bottleneck. But I'd leave sorting on by default and make an option to turn it off ( IIUC ).
    1 point
  28. I've bumped to 0.4.0 RC3 on the repo.
    1 point
  29. change the timeFormat option instead, or change the xBefore template to use {date} instead of {time}. 'xBefore' => '<li class="rm-list-event {original.name}"><span class="rm-event-date">{time}</span> ', yeah, this looks like a timezone issue. I am digging into it. thanks for bringing it up. Subtracting one day won't work or be consistent.
    1 point
  30. Try this updated file: I will add this to my next release. Thank you! MarkupRecurme.module
    1 point
  31. https://ckeditor.com/blog/CKEditor-5-v1.0.0-beta-released/ Looks very clean. Hopefully we get to test it on PW soon.
    1 point
  32. @noelboss - I think the issue that you might be missing is that I am using the selector array approach: https://processwire.com/blog/posts/processwire-3.0.13-selector-upgrades-and-new-form-builder-version/#selector-engine-array-support There is no issue doing what you are suggesting with the regular selector string approach, but the array approach is quite nice when you're building up a complex selector from user input.
    1 point
  33. We check the stock trough an Ajax call each time the user selects an option. If it's not in stock anymore, the button "add to cart" stays not clickable. If it's in stock the user can add it to the cart. We also set an max in the quantity field, that's the same value as the stock is. Javascript clothing = { size: "", sex: "", product_id: "", init: function() { $('input[name="Size"], input[name="Sex"]').on('change', function (e) { clothing.size = $('input[name="Size"]:checked').val(); clothing.sex = $('input[name="Sex"]:checked').val(); clothing.product_id = $('#product_id').val(); if(clothing.sex && clothing.size && clothing.product_id) { clothing.getVariationId(); } }); }, getVariationId: function() { var url = '/api/?id=' + clothing.product_id + '&variation=clothing&size=' + clothing.size + '&sex=' + clothing.sex; $.ajax({ type: 'GET', url: url, success: function(result) { if(result){ var res = JSON.parse(result); if(res.success){ if(res.qty > 0){ $('#qty').prop('disabled', false); $('#qty').parent().removeClass('c-form-group-disabled'); $('#qty').attr("max", res.qty); $('#variation_id').val(res.id); $('#clothing .c-button').prop('disabled', false); $('#clothing .c-button').removeClass('c-button-disabled'); } else { $('#qty').prop('disabled', true); $('#qty').parent().addClass('c-form-group-disabled'); $('#qty').attr("max", 0); $('#qty').val(0); $('#variation_id').val(""); $('#clothing .c-button').prop('disabled', true); $('#clothing .c-button').addClass('c-button-disabled'); } } } }, error: function(jqXHR, textStatus, errorThrown){ } }) }, }; api.php <?php namespace ProcessWire; if(config()->ajax()) { $data = array( 'success' => input()->get('id') ); if(!input()->get('variation')){ return json_encode($data); } else { switch (input()->get('variation')){ case "clothing": if(!input()->get('id') || !input()->get('size') || !input()->get('sex')){ return json_encode($data); } else { $product_id = input()->get('id'); $size = input()->get('size'); $sex = input()->get('sex'); foreach (pages()->get($product_id)->product_variations as $v) { if (($v->size == $size) && ($v->sex == $sex)) { $data = array( 'success' => true, 'id' => $v->id, 'qty' => $v->product_quantity ); return json_encode($data); } } } break; case "default": return json_encode($data); break; } } Indeed we used the demo of @kongondo as a starting point.
    1 point
  34. You can find the answer in this thread:
    1 point
  35. Nice! Very interested in your padloper/mollie combination looking forward to your open sourcing of the payment module you built.
    1 point
  36. Like you said, $page->inscr_nr is a text field, not a repeater, so output its value directly, removing "->title": $content .= $page->inscr_nr . '</p></td></tr>';
    1 point
  37. Thanks, will do. I've just finished making it multilanguage-ready but need to check first on non-ML site too, though the way it's set up I don't expect any issue. I ended up adding multiple divs to the DOM containing the list of files, one for each language (#link-files-menu, #link-files-menu__1088, and so on). Then on menu toolbar click I get the current lang ID of the editor (from data-configname and ckeditor ID) and show/hide the corresponding menu. Update: see here
    1 point
  38. Hi @Robin S, would you mind if I add this to AOS? I've made some changes, eg. display description + filename in the menu (if there's no description, use the basename without extension), and hide the menu when clicking outside of it. The latter is handy on a multilanguage site as the menu doesn't stay open when clicking to another language tab. Of course this happens only if you don't click on a menu item. I also plan to make it more ML-friendly by adjusting the description per language (some day).
    1 point
  39. Great! Although it would be a great addition from the community, I am not sure if ryan would like to add it to core. You lose all the comfort of Processwire. For example I've written some code last evening to access image-urls and descriptions (snippet, experimental): case $fieldtype instanceof FieldtypeImage: $sql .= ",\n (SELECT GROUP_CONCAT($data SEPARATOR 0x1D) FROM field_$f WHERE pages_id = p.id) AS $f"; $sql .= ",\n (SELECT GROUP_CONCAT(description SEPARATOR 0x1D) FROM field_$f WHERE pages_id = p.id) AS " . $f . "_desc"; break; foreach ($pages->findArray("id=1, sort=title, limit=1000", array('title', 'images'), array()) as $p) { $images = explode(chr(29), $p['images']); $images_desc = explode(chr(29), $p['images_desc']); $imgs = array_combine($images, $images_desc); $langid = $this->user->language->id; if ($langid == $languages->getDefault()->id) $langid = 0; foreach ($imgs as $url => $descr) { $ajson = json_decode($descr, true); if (isset($ajson[$langid])) $desc=$ajson[$langid]; else $desc=""; echo "URL=" . $p['id'] . '/' . $url . ", DESCR=" . $desc; } } You see, it works if you know how, but it feels a bit like writing assembler. But yes, it is fast!
    1 point
  40. It's working here in Firefox, and it's unlikely that there will be a difference between browsers in how that JS works. I think it must be a caching issue. Please visit Modules > Site and click "Refresh", and then scroll down and click "Clear compiled files".
    1 point
  41. I went to test on a ML site, but I don't actually even see the button and I do get these JS errors. This is my settings: Let me know if there is anything I can do to debug.
    1 point
  42. I got a client request to make Word template so she can create an image of the weekly menu of a restaurant to post on Facebook. I usually get sick when I have to deal with M$ Word - it's frustration and it's not meant to be used things like that. So I figured out a better system: PW + html2canvas.js. It took more time to finish but it was worth the trouble. The main issues were html2canvas versus some CSS issues, plus switching to different languages in PW on each line. Also, JavaScript cannot offer named downloads, only "download.png", so I had to use HTML5 attribute "download" on links to be able to add custom download filename. I used ProField modules Table and Matrix Repeater which allow very pleasant editing of menu items, even in multilanguage context. Front-end editing is created using the built-in front-end editor. I was about to achieve inline editing of menu items but it soon turned out that repeaters and tables can't be edited this way. Anyway, it's still better compared to my module FEEL because sections are reloaded using Ajax and the admin lightbox shows only the fields I choose. Here's a quick screencap - when the gray background turns to dark gray, then the menu is not HTML but canvas, that can be downloaded.
    1 point
  43. One last attempt to suggest using the api, then I'm gone Instead of changing your source data, you can let the API create the pages for you when needed. So for a (simplified) table like this: Bibliography Type Document Title ----------------- ---------------------- Book Interesting Book 1 Book Interesting Book 2 Magazine Fascinating Magazine 1 .... you could use the following code, which automatically creates the pages for you function getBibliographyType($name) { $template = 'bibliography-type'; $parent = $pages->get('/bibliography-types/'); static $bibliographyTypes = array(); if (isset($bibliographyTypes[$name])) { return $bibliographyTypes[$name]; } else { // Create the bibliography-type page $p = new Page(); $p->template = $template; $p->parent = $parent; $p->name = wire('sanitizer')->pageName($name); $p->title = wire('sanitizer')->text($name); $p->save(); // Save bibliography type id for future calls, avoiding calls to the database $bibliographyTypes[$name] = $p; return $p; } } $f = $page->import_file->filename; $csvDelimiter = ','; $csvEnclosure = '"'; $templateName = 'Document'; $parent = $pages->get('/documents/'); while (($data = fgetcsv($f, 0, $csvDelimiter, $csvEnclosure)) !== false) { $bibliographyType = getBibliographyType($data[0]); $title = $data[1]; $p = new Page(); $p->template = $templateName; $p->parent = $parent; $p->name = $sanitizer->pageName($title); $p->title = $sanitizer->text($title); $p->bibliography_type = $bibliographyType; $p->save(); }
    1 point
  44. I think that it is not possible to directly access php files in the "templates" directory (because if everyone could do it it would be a big insecurity). Of course you can include them via PHP because this get's rendered before the page is returned to the user. But jQuery/Javascript acts more like a real user. And for them everything (except images, javascript files, stylesheets, etc.) in /site/ and in /wire/ is locked. What you have to do: Create a template in the backend called e.g. "subscribe". Then create a page using this template e.g. named "subscribe", too. You now can access this page via http://localhost:8080/home/sovonex/Programs/rubystack-2.0.0-12/apps/processwire/htdocs/subscribe/ or something similar. That's the page you should point your post request on.
    1 point
  45. For security reasons, PW forces a "403 forbidden" if someone tries to directly access any PHP files in the /site/templates/ dir, as well as several other locations in PW's file system. So it's best not to put any PHP files that you need to directly access in any of ProcessWire's directories, because there's a good chance it'll block access to them. Here are a few alternatives: Option 1. Place your sendemail (and optionally phpmailer include) files somewhere outside of PW's directories. For instance, maybe you could create a dir called /form/ off your web root and place them in there. Then set your form to: action='/forms/sendemail.php' Option 2. Use your sendemail.php as a ProcessWire template. Create a page using that template, and make your form post to that page. Option 3. (the one that I use most often) Make your form post to the same page that it's on (i.e. action='./'). When you see one of your POST vars present, include your form processing script. i.e. <?php if($input->post->submit) { // process contact form include("./includes/sendemail.php"); } else { // output contact form }
    1 point
×
×
  • Create New...