Jump to content


Popular Content

Showing content with the highest reputation since 06/07/2020 in Posts

  1. 21 points
    We have created a module to create BlurHash strings for images while uploading in ProcessWire. This blurry images will be saved in the database because they are very small (20-30 characters) and can be used for Data-URL's as placeholders for image-lazy loading. https://github.com/blue-tomato/ImageBlurhash E.g. where we use this in production: https://www.blue-tomato.com/en-INT/blue-world/ https://www.blue-tomato.com/en-INT/blue-world/products/girls-are-awesome/ https://www.blue-tomato.com/en-INT/buyers-guides/skateboard/skateboard-decks/ https://www.blue-tomato.com/en-INT/team/anna-gasser/
  2. 20 points
    This week I'm not bumping the version number just yet because I've got lots of work in progress. The biggest thing so far is something I hinted at last week. Basically, I like what the addition of the MySQL query expansion operators have brought (per posts last week and week before), but they also reveal what's lacking: something as simple as a search for "books" still can't directly match the word "book". But that's the most basic example. It's not a limitation of ProcessWire, but just the type of database indexes in general. I think it'd be amazing if ProcessWire had the ability of being really smart about this stuff, able to interpolate not just plurals vs. singulars but related words. In a perfect world, this is what query expansion would do (in addition to what it already does). But the reality is that it involves all kinds of complicated logic, rules and dictionaries; well beyond the scope of even a database. And it can be vastly different depending on the language. So this isn't something we can just add to the core and have it work. On the other hand, I figured maybe we should just put in a hookable method that just pretends the ability was there. Then people could hook it and make it respond with variations of words, according to their needs. The searches that use query expansion could then call this method and use whatever it returns... for when someday the ability is there. So I went ahead and added that hook — WireTextTools::wordAlternates(). And our database-searching class (DatabaseQuerySelectFulltext) now calls upon it, just in case an implementation is available. Well, after getting that hook added and having our class call it, naturally I wanted to test it out. So I got to work on it and came up with this module: WireWordTools. The WireWordTools module provides an API for English word inflection and lemmatisation. And it hooks that new method mentioned above, so that you can install it and immediately have it bring your searches to the next level. While it only helps for English-language searches, maybe we'll be able to add more languages to it, or maybe it'll lead to other modules that do the same thing for other languages. The expanded/alternate words are only used for searches that use the new query expansion operators, which are the ones that have a "+" in them: ~+=, ~|+=, *+=, **+=. They all can return similar results, but are weighted differently. Unlike most operators, where the logic is direct and you can expect them to always behave the same way, these query expansion operators are more subjective, and ones I think we should intend to keep tweaking and improving over time to continually improve the quality of the results they return. Basically, they are geared towards building site search engines, so I think it makes sense for us to pursue anything that makes them better at that, rather than aiming to always have them return the same thing. I am currently testing out the ~|+= operator ("contains any words expand") on our main site search engine here, along with the WireWordTools module. Finally, searching for "books" does match "book" too, and a lot more. More to be done here, but it's a good start hopefully.
  3. 20 points
    In ProcessWire 3.0.160 we’ve got some major upgrades and additions to our text-matching selectors and operators. This brings a whole new level of power to $pages->find() and similar API calls, especially when it comes to search engine type queries. This blog post also includes a demo search engine that lets you test everything out live— https://processwire.com/blog/posts/pw-3.0.160/
  4. 19 points
    In the blog post last week we looked at some of the two-factor authentication system upgrades, like the new “remember this computer” feature. This week I finished off the remaining parts, as well as released new versions of both the TfaTotp and TfaEmail modules. Auto-enable TFA support We now have auto-enable support (forced 2FA), which lets you setup two-factor authentication for users, without their input (if they haven’t enabled it already). This is a good way to add a lot of security for very little work. Currently, the module that supports this is the TfaEmail module. That’s because it’s a safe bet to assume the user has access to their email, even if they haven’t specifically setup 2FA. So email is a very good way to nudge people into 2FA, and people are already used to this, as many online services now do it. Considering that the computer can now be remembered, I think it’s unlikely you’ll get any complaints from users. Setting up auto-enable is really simple. Grab the latest version of the TfaEmail module and install it. Then go to your ProcessLogin module settings (Modules > Configure > ProcessLogin) and you’ll see an option there to select Email in the “Force two-factor authentication - Type” field. If you want to limit this to specific roles, then you can also do that here. If you don’t select any roles, then it applies to all roles. Once setup, any user logging into your admin will be asked to enter an authentication code sent to their email, and they’ll need that code to complete the login. Chances are they’ll also click that “remember this computer” checkbox so that they can skip the code on future logins. TfaEmail version 2 The new version of the TfaEmail module also lets you now configure what WireMail module you want it to use for sending authentication emails. If using multiple mail sending services, you’ll want your most reliable and fastest email sending service to handle these kinds of transactional emails. TfaTotp version 4 Once users understand the benefits of 2FA, chances are they’ll want to upgrade to TOTP, where they can use a dedicated authenticator app. The ProcessWire TfaTotp module got several upgrades this week. The biggest was the addition of a locally hosted QR code generator (QRCode for PHP by Kazuhiko Arase). No longer does it have to rely upon an external service to generate QR codes (previous versions used Google Charts for QR code generation). In addition, the TOTP TwoFactorAuth library has been updated to the latest version. Moving those modules to the core Speaking of those two modules (TfaEmail and TfaTotp), thanks for your input last week about their inclusion in the core. It sounds like most think it’s a good idea, so I think we’ll go that route. But I need a little more time to do that, so going to hold that update and the 3.0.160 version bump for next week. Coming next week: Useful new selector operators Next week I’ve also got a couple of special new text-matching operators being added to our selectors system that I think you are going to really like. They are operators that are especially useful to those building text search engines, and ones that I’ve found so useful this week that I wish we’d had them since the beginning. I’m excited to add those into 3.0.160 and tell you more about them next week. By the way, while 3.0.160 isn't officially the version on the dev branch yet, if you download the current dev branch version (3.0.159), all of the TFA updates mentioned above are present and ready to use.
  5. 18 points
    We recently launched The Power Supply Shop, an e-commerce store built using a combination of ProcessWire and SnipCart. The site has in excess of 120,000 products and variations, making heavy use of page references as well as SnipCart's "any page can be a product" approach. The site pulls in its data from an external MS SQL database several times a day. At a glance, the site uses: ProCache - as well as WireCache for some heavy product listing pages (50k+) FormBuilder @adrian's Tracy Debugger A modified version of @Soma's Ajax Search @mtwebit's fantastic Tasker and DataSet modules. And that's about it on the module front. For other libraries we're only really using FancyBox.js for product galleries and Anchorific.js for guide pages. At present the site is geared towards the UK, but if and when this changes I'm looking forward to delving into multi-languages with ProcessWire, something I haven't really worked with yet!
  6. 17 points
    Version 3.0.161 on the dev branch continues with the updates optimizing our support for the new selector operators introduced in last week's blog post for 3.0.160. Last week I was still kind of figuring it out and the code still needed some refactoring and optimization. This week several parts have been rewritten and it's been improved quite a bit. Though the end result is still very similar to what was demonstrated last week, but now it's a lot more performant and solid. One thing new this week that's also kind of fun: you can now use more than one operator in any "field=value" selector expression, at least from the API side. And it works anywhere that you might use a selector, whether querying the database or something in memory. I think the best way to explain it is with an example. Let's say that you want to find all pages with a title containing the phrase "hello world" — you'd do this using the "contains text/phrase" operator: *= $pages->find("title*=hello world"); But let's also say that if you don't find any matches, you want to fallback to find any pages that contain the words "hello" and "world" anywhere in the title, in any order. We'd use the "contains all words" operator "~=" to do that. So now you can add that operator to the existing one, and it'll fallback to it if the first operator fails to match. So we'll append the "contains all words" operator to the previous one: ~= $pages->find("title*=~=hello world"); Cool huh? But maybe we still aren't finding any matches, so we want to fallback to something even broader. So if the phrase match fails, and the words match fails, now we want to fallback to find any pages that contain the world "hello" OR "world", rather than requiring them both. For that we can use our new "contains any words" operator: ~|= $pages->find("title*=~=~|=hello world"); This example is getting a bit contrived now, but let's say that if we still haven't found a match, we want it to find any pages that have any words starting with "hello" or "world", so it would find pages with words like "helloes", "worlds", "worldwide", etc. That's a job for our new "contains any partial words" operator: ~|*= $pages->find("title*=~=~|=~|*=hello world"); Okay last one I promise—you probably wouldn't stack this many in real life, but stay with me here. Let's say the query still didn't find anything, and as a final fallback, we want it to find any words LIKE "hello" or "world", so that those terms can match anywhere in words, enabling us to find pages with words like in the previous example, but also words like "phellogen", "othello", "underworld", "otherworldly", etc., and that's a job for our new "contains any words like" operator: ~|%= $pages->find("title*=~=~|=~|*=~|%=hello world"); So that looks like a pretty complex operator there, but as you've seen by following the example, it's just these 5 appended operators to each other: *= Contains phrase ~= Contains all whole words ~|= Contains any whole words ~|*= Contains any partial words ~|%= Contains any words like I think a more likely scenario in a site search is that you might stack two operators, such as the *= followed by the ~|*=, or whatever combination suits your need. By the way, you can do this with any operators, not just the text searching ones. But if you didn't read the blog post last week, also be sure to check out the other new operators in addition to those above: *+=, **=, **+=, ~*=, ~+=, ~~=, ~%=, #=. I think these new operators help out quite a bit with ProcessWire's text searching abilities. But there's one thing that's kind of a common need in search engines that's not easily solved, and that's the handling of singular vs. plural. At least, that's a common issue when it comes to English (I'm assuming so for other languages, but not positive?) MySQL fulltext indexes can't differentiate between singular and plural versions of words, so they index and match them independently as completely different words. This can be unexpected as clients might type in "goose" and expect it's also going to match pages with "geese". I've already got something in the works for this, so stay tuned. Thanks for reading and hope you have a great weekend!
  7. 15 points
    This is a module I made as an experiment a while ago and never got around to releasing publicly. At the time it was prompted by discussions around using Repeater fields for "page builder" purposes, where the depth feature could possibly be used for elements that would be nested inside other elements. I thought it would be useful to enforce some depth rules and translate the depth data into a multi-dimensional array structure. I'm not using this module anywhere myself but maybe it's useful to somebody. Repeater Depth Helper This module does two things relating to Repeater fields that have the "Item depth" option enabled: It enforces some depth rules for Repeater fields on save. Those rules are: The first item must have a depth of zero. Each item depth must not be more than one greater than previous item depth. It provides a RepeaterPageArray::getDepthStructure helper method that returns a nested depth structure for a Repeater field value. Helper method The module adds a RepeaterPageArray::getDepthStructure method that returns a multi-dimensional array where the key is the page ID and the value is an array of nested "child" items, or null if there are no nested children. Example The module doesn't make any assumptions about how you might want to use the depth structure array, but here is a way you might use it to output a nested unordered list. // Output a nested unordered list from a depth structure array function outputNestedList($depth_structure, $repeater_items) { $out = "<ul>"; foreach($depth_structure as $page_id => $nested_children) { $out .= "<li>" . $repeater_items->get("id=$page_id")->title; // Go recursive if there are nested children if(is_array($nested_children)) $out .= outputNestedList($nested_children, $repeater_items); $out .= "</li>"; } $out .= "</ul>"; return $out; } $repeater_items = $page->my_repeater; $depth_structure = $repeater_items->getDepthStructure(); echo outputNestedList($depth_structure, $repeater_items); https://github.com/Toutouwai/RepeaterDepthHelper https://modules.processwire.com/modules/repeater-depth-helper/
  8. 14 points
    Hello fellow ProcessWire people! I published an article explaining how I migrated three years worth of running data from Garmin to ProcessWire: https://francescoschwarz.com/articles/running-on-my-own/ Have a great day! Cheers.
  9. 14 points
    BETA: SplashAndGrab https://github.com/madebymats/InputfieldSplashAndGrab This module attaches a search input to selected image fields that lets you search and download images from Unsplash. (Unsplash is a stock photo service where you can download images for free and use as you wish. No strings attached.) You can search by string, colors, orientation/crop and order by relevance or time published I find Unsplash useful both for placeholder images when building sites but also as a time saver for editors if they don’t have any images at hand, just search, download and publish. Thanks to @apeisa for building the FlickrInputField Module and @Robin S for AddImageUrls, took a lot ideas and code from those modules.
  10. 12 points
    Hello @ all Today I want to share an inputfield/fieldtype to store 2 or 3 dimensions of an object. This fieldtype was inspired by the amazing fieldtype "Fieldtype Dimensions" from SOMA (https://modules.processwire.com/modules/fieldtype-dimension/). This fieldtype was introduced in 2013 - so its time for a relaunch. This new fieldtype offers more possibilities than the old one from SOMA. This inputfield/fieldtype let you enter max. 3 dimensions (width/height/depth) of an object (fe a product), but you can select if you want to display inputs for 2 or 3 dimensions. 2 dimension can be used fe for wallpapers or photos, 3 dimensions fe for furnitures or other objects. There are several configuration options for this fieldtype in the backend. set type (2 or 3 dimensional) set width attribute for the inputfield in px (default is 100px) set size unit as suffix after each inputfield (default is cm) set max number of digits that can be entered in each field (default is 10) set max number of decimals (default is 2) show/hide a hint to the user how much digits/decimals are allowed If the number of decimals or digits will be changed, the database schema for each dimension column will also change after saving the field in the backend. For example: If the schema for each dimension field in the DB is f.e. decimal(10,2) and you will set the number of digits in the configuration to 12 and the number of decimals to 1, then the schema in the DB will also change to decimal(12,1) after saving the inputfield. You can download this inputfield at https://github.com/juergenweb/FieldtypeObjectDimensions There you will find more detailed information and explanation too. If you find any bugs or you have an idea to improve it (also code improvements) please report it on Github. Have a nice day!
  11. 9 points
    Hello @ all! I want to share a simple fieldtype and inputfield to store address data with you. I have created this inputfield for learning purposes and it has no fancy functionality. It is simply for storing address data such as street, number, postalcode and so on in one table. As an addition you can store latitude and longitude too, so you can use them in maps. Here is a screenshot of what it looks like: You can select which fields are mandatory and you can choose if the inputs for longitude and latitude should be displayed. These settings can be configured in the field configuration. If you find this inputfield useful you can download it at https://github.com/juergenweb/FieldtypeSimpleAddress There you will find a detailed explanation. If you have an idea of an usefull feature that can be added or you have detected a bug, please report it in my github account.
  12. 9 points
    Hi there, another one finished, up and running. https://bots4you.de/ The website informs about bots4you which is a German based Chatbot creator. Special with this chatbot is its b2b purpose, that means it is pretty decent in "knowing" what customers of several industries (real estate, insurances etc.) want to know and describe their efficiency with nearly 80% of success for common customer inquiries. From the ProcessWire perspective I mainly use Repeater Matrix with which I only have one template (even for home) but 8 content modules that can be arranged like the customer wants to create different pages. Other than that I used TailwindCSS for the first time, but I am not convinced, at least in a PW environment. Downsides where: build time when in dev mode (hot reload takes up to 6 seconds) purge of my php files was less than reliable. I ended up putting most of the classes on an allow list in the tailwind config. Could be my fault, but the overall experience wasn't that great. Anyway, client is happy, and I am, too: 😉
  13. 9 points
    This is a module that is similar in purpose to the Runtime Markup module. I made it primarily for my own use but am posting it here because I had a request to add it to the modules directory. Fieldtype Runtime Only Not a proper fieldtype because it doesn't save data to the database. The fieldtype only exists to provide a convenient way to add an inputfield to templates that will render some markup at runtime. For a field named "my_field"... Inputfield markup will be rendered from a file at /site/templates/RuntimeOnly/my_field.php. In addition to the standard ProcessWire variables this file receives: $page - the page being edited. $field - the Field object. $inputfield - the Inputfield object. JS file /site/templates/RuntimeOnly/my_field.js will be added to admin if that file exists. CSS file /site/templates/RuntimeOnly/my_field.css will be added to admin if that file exists. Tips If the RuntimeOnly field is used inside a Repeater field then you can get the Repeater page it is on via $inputfield->hasPage. E.g. $repeater_page = $inputfield->hasPage; // Use $repeater_page as needed echo "The name of the repeater page is $repeater_page->name"; https://github.com/Toutouwai/FieldtypeRuntimeOnly https://modules.processwire.com/modules/inputfield-runtime-only/
  14. 7 points
    First of all: I definitely agree with your first point. I need to do some testing and probably add additional configurability to the SearchEngine module after these updates. Some pretty interesting options we've got now! In the past I've steered away from the full-text index because it has resulted in way too many "oddities", i.e. some queries just don't work either due to stopwords or something else, and it seems to be (in my experience) particularly problematic if the site is authored in some other language than English. You've given me a reason to revisit this, though 🙂 As for plurals, it sure is an issue with other languages as well. I have no idea what you've got planned in that regard, but one problem here is that it gets pretty complex if you want to support other languages than just English (which is, actually, one of the easiest languages in this regard). And then there's of course the bigger issue of stemming — considering your goose example, if a client was searching for "hanhi" (goose in Finnish), it's true that they would likely expect it to also match "hanhet" (plural), but if that works then why not other forms such as "hanhia", "hanhen", "hanhien", "hanhesta", "hanheen", etc. Anyway, very much looking forward to what you've got planned! Just wanted to point out that this can be a pretty big issue to tackle, at least unless limited to English only, or perhaps made so modular that each language can have its own set of rules. Also it's a slippery slope, and once things like stemming come into play we're in really deep waters 😄
  15. 7 points
    Screencast updated - import of an entire article ☝🏼️ Still dealing with media files.
  16. 7 points
    Ooh, I love these kinds of challenges. 🙂 Give this a go: https://github.com/Toutouwai/IndividualSelectablePages Recommended for a better experience: https://github.com/Toutouwai/PageListSelectMultipleQuickly
  17. 7 points
    v0.0.11 adds support for repeater matrix fields 🙂 Thx to @aComAdi of https://www.a-commerce.ch/ for sponsoring this update! 😎 $rm->setMatrixItems('your_matrix_field', [ 'foo' => [ 'label' => 'foo label', 'fields' => ['field1', 'field2'], ], 'bar' => [ 'label' => 'bar label', 'fields' => ['field1', 'field3'], ], ]);
  18. 6 points
    I was going through the Hanna Code "Readme" in Bitpoet's editorial blog based off kongondo's Blog module and this particular line caught my attention: $f = $modules->InputfieldCheckboxes; $f->name = 'vegetables'; // Set name to match attribute $f->id = 'vegetables'; // Set id to match attribute $f->label = 'Vegetables'; $f->description = 'Please select some vegetables.'; $f->notes = "If you don't eat your vegetables you can't have any pudding.";//<<<<<<<<<<<< $f->addOptions(['Carrot', 'Cabbage', 'Celery'], false); $form->add($f); Very funny... 😁
  19. 6 points
    Check this out: https://processwire.com/blog/posts/pw-3.0.137/#on-demand-mirroring-of-remote-web-server-files-to-your-dev-environment
  20. 6 points
    Today, I am glad to announce that the module support the native image field 👍🏼
  21. 6 points
    Hello, I would like to present you a new module which aim to facilitate the productivity of your editors/publishers when working on ProcessWire. The idea begun when my co-worker told me that when typing in ProcessWire CkEditor field he was feeling "loosing motivation" when writing big wall of text and/or inspiration. So he opened his web-browser and show me a site looking to Wordpress - feel free to put your preferred emoji here - then he opened Gutenberg... typed some text and moving some "blocks". I understood immediately why he got this feeling with CkEditor. If you or your client feel like this guy, then you will love this module ! What is currently supported ? Features Auto-save Medias upload support HannaCode support Blocks Implemented Heading Image Paragraph Embed Quote Code Link Table (beta) Block Delimiter Raw HTML Note (custom block markup) Feature Request Frontend Edition And there you go for the preview - sorry I am to lazy and bad at typing text so I had a copy/pasta moment : Module featured in the ProcessWire Weekly #317 - Thanks @teppo
  22. 6 points
    There is an alternative method in ProcessWire to determine if $page is editable by current user: https://processwire.com/api/ref/page-permissions/editable/ It returns true or false if the user is allowed to edit the page.
  23. 6 points
    @encho you pointed to something I hadn't thought of before reading your comment. I then tried all the afternoon to work on that - I have to brainstorm more about that, but I think we could have something which works. In this sample, you can see a heading and a paragraph written in a CKEditor field. You can then change the fieldtype to EditorJS and get you saved data. As you can see - and as you stipulated as well in your last comment - the strong tag isn't taken into account. Anyway, I am quite confident to get a parser working here. I still take into account that I am not aware of how/which DOM are inserted on every CKEditor for a given user. I was thinking to alert the user if his content couldn't be parsed entirely, or something like that, and so, a manual intervention will be needed in this case. And this is how look the paragraph with inner DOM elements, should be "easy" to insert them :
  24. 6 points
    Hi @michelangelo, The fastest way to achieve the effect of Instagram feed, is to use Processwire Pagination with Ajax Infinity Scroll, for example https://infiniteajaxscroll.com There is no silver bullet to take thousands of results form any kind of database. You should take it part by part and Processwire Selectors with Limits are good solution or prerender them as static data and keep them cached, as guys above said. BTW, 1,000 divs on one page is realy bad idea in terms of browser capacability. Just open Instagram, scroll hounded posts and take a look how many resources it will takes from your console. Good luck Alexander
  25. 6 points
    Forgot to put a note on what is currently supported : Features Auto-save Medias upload support HannaCode support Blocks Implemented Heading Image Paragraph Embed Quote Code Link Table (beta) Block Delimiter Raw HTML Note (custom block markup)
  26. 5 points
    This is one of the most common solutions, but as in everything with PW, it's your call how you do it! What you could do with your approach is place that php script outside of the sites directory which is protected by apache from being accessed directly for security reasons. So on your ajax request, the url is just /archive-list-render.php?q=etc Now, on you archive-list-render.php, load the PW API: <?php //This is the index.php in the web root directory, sibling to site, wire, etc. include("./index.php"); $q = $sanitizer->text($input->get('q')) $foundPages = $pages->find("somfield=$q"); //imaginary doSomethingWithPages method.. $response = doSomethingWithPages($foundPages); echo $response; Another approach for simple cases is using the same page where the ajax requests originates from, and detect if it's an ajax call otherwise render the site. This can get tricky depending on appending or prepending files into the template. (Very well exemplified on Ryan's post bellow) <?php if($config->ajax){ //ajax processing/render stuff } else{ //normal render stuff } Ryan's post:
  27. 5 points
    AJAX request detection is based on the X-Requested-With header. You need to set its value to XMLHttpRequest: // via default settings: axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; // or via config object when making the request: axios.post('/post/', { pageID: this.pageID, text_heading: this.text_heading }, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) Written in browser and untested, but that's the general idea anyway 🙂
  28. 5 points
    😀 Yet another runtime field. I can also provide one: slim and full PW-API provided. In addition, you can change everything in another field (Database) via hook into ProcessInput. https://github.com/kixe/FieldtypeMarkup
  29. 5 points
    Progress update: Have managed to throw in a few hours on v2. The frontend is being rebuilt in Svelte, because I simply don't use jQuery/Datatables anymore. By not using any of these, I'm free to code this thing the way I want, without having to use a bunch of dependencies that are simply frustrating to build things with. Datatables in particular is hell to work with. (As an aside, I primarily work with Vue, but Svelte is a little more suited here. No runtime, much smaller bundle.) Anyways, here's a preview of the redesigned jumplinks list. Newly built styles, consistent in both the default and UIKit themes (should be fine in custom themes too) and scoped to the Svelte container. Have carried over the behaviours, however instead of fetching all jumplinks, they're now fetched as a paginated collection. I'm sure there are a few sites out there with many jumplinks, and fetching them all is just too much. As mentioned in a previous preview post (such a long time ago!), you'll be able to turn off the colour helpers if you don't like/need them.
  30. 5 points
    Hi @joer80 In the top of the post.php file, you can write your logic to check which user is allowed to post or not xhr request. Example : <?php namespace ProcessWire; // if the page is viewed wihtout ajax, return if(!$config->ajax) return; // if the user is a superuser, return if($user->isSuperuser()) return; // only editor can post request to this page if(!$user->hasRole('editor')) return; // other checks if needed, CORS check, Custom header check, etc // rest of code - access granted // ... then, for example in your component , but anyway you already know how to do it : // example editPage() { this.$store.dispatch('setEditPage', this.$route.path).then(() => { axios .post(config.apiEditPageURL) .then(response => { this.data = response.data }) .catch(error => { this.errored = error }) .finally(() => { this.$store.dispatch('loading', false) }) }) },
  31. 5 points
    For a brief moment I was contemplating parsing HTML with regex but then StackOverflow taught me this: https://stackoverflow.com/a/1732454/1036672 My sides are now hurting 😂
  32. 5 points
    A ProcessWire find will perform an SQL query. The important thing (in terms of performance and tools like RockFinder) is what happens next. SQL queries are normally very fast. However, if you then load the results into Page objects, you might get a performance hit depending on the number of results you fetched. RockFinder does not load Page objects, hence remains very fast and performant. It is very much suited to handling large datasets.
  33. 5 points
    You can achieve what you want with ProFields: Table. It is excactly what I did for a customer portal: You can add as many items as you want, and define the type of each field of a row. For example the field "Eigenschaft" is a FieldtypePage, which pulls it options from a list, that my customer can manage himself. Additionally one requirement was, that when one item was already selected, then it should not be selectable in the other rows. I wrote a blog post how to do this: https://dotnetic.de/blog/disable-options-in-select-elements-that-are-already-selected-in-another-select-element/
  34. 4 points
    Thanks for your contributions to the community 😄 Good luck in all that you do - we'll see you around pwFoo 🙂
  35. 4 points
  36. 4 points
    Got to agree with Kongondo here. In my case the dev hot reload takes < 2s, and that's with some recent slowdowns (not sure what's going on in my system, but it used to be < 1s). Of course this also depends a lot on what you're doing at dev stage: are you running purge here as well, what else are you running on each rebuild (pre- or postprocessors and whatnot), which files are you watching, etc. Depending on your setup there may be steps you can take to get it down considerably. In our gulp based workflow, for an example, one major bottleneck was solved by adding gulp-cached — on a moderately large site this took dev build time down from what was originally probably 6-10s to 1-2s. Never had this issue either. There could be something else wrong, but usually this would mean either that you're actually not going through all those PHP files in the purge step, or you're using some sort of "constructed" class names (px-<?= $x ? 1 : 2 ?>). Not saying that you're doing something wrong, but again: this has been working perfectly for us. Note: I've got some beefs with Tailwind myself, but those are all about the general methodology. Tech wise it's been really, really slick 🙂
  37. 4 points
    /** @var InputfieldCheckboxes $f */ $f = $modules->get('InputfieldCheckboxes'); $f->name = 'foo'; $f->label = 'Foo'; $f->addOptions([ 'red' => 'Red', 'green' => 'Green', 'blue' => 'Blue', ]); // The value will be an array e.g. ['red', 'blue'] $f->value = $this->foo; $inputfields->add($f);
  38. 4 points
    I know you asked for a configuration but, maybe hook here? <?php $wire->addHookAfter('ProcessPageAdd::getAllowedTemplates', function($e){ $templates = $e->return; $specialTemplate = wire('template')->get('specialOne'); $parent = $pages->get(wire('input')->get->parent_id); if($parent->template != "sub"){ unset($specialTemplate->id, $templates); $e->return = $templates; } });
  39. 4 points
    Just check the user role 😉 https://processwire.com/docs/user-access/roles/ or change the permissions to your post page in the Admin Panel (or both!) https://processwire.com/docs/user-access/permissions/
  40. 4 points
    Thanks for the reply teppo! You're right, i definitely should use php 7.3, I also tried that. I just developed the site on php 5.x and wanted to keep the settings as similar as possible. I'm talking to the namecheap support right now, if I can solve the issue with them I will post it here for future reference.
  41. 4 points
    This suggests that the query string does not receive the search string but an object of type WireInputData instead. WireInputData is the class behind the WireInput properties $input->get, $input->post, and so on. $q = $sanitizer->selectorValue($input->get); $input->whitelist('q', $q); Here you put the $input->get object of type WireInputData into a sanitizer method. The method only accepts strings and arrays. Since you gave it neither, it makes a string out of it. I guess this turns the WireInputData object into the string "WireInputData". Not sure what the right fix is. What is “q” supposed to be? It looks more like the query string you want is something like “?larghezze=123&lunghezze=456”. So you should put each of those into a separate whitelist item, eg. $input->whitelist('larghezze', $input->get->selectorValue('larghezze')). ProcessWire’s pagination will automatically put everything from $input->whitelist in the url query string. if($input->whitelist->lunghezze) echo $sanitizer->entities($input->whitelist->lunghezze); if($input->get->lunghezze) echo ($input->get->lunghezze); //delete this! Here you output lunghezze twice, only the first line doesn’t work, because you never put anything into $input->whitelist->lunghezze. Also, the whitelist is stored on the server and you’re expected to only fill it with things you already sanitized, so there is no need to sanitize it again at that point. In the second line you output untrusted unsanitized input straight from the GET request! You should delete that line and the others like it. They’re unnecessary anyway, because you already output the whitelisted stuff above 🙂 Change it to this: echo $input->whitelist->lunghezze; That should be all you need. Then, in search_alimentare.php, add the line I highlighted: if ($input->get->lunghezze) { $lunghezza = $sanitizer->selectorValue($input->get->lunghezze); $input->whitelist->lunghezze = $lunghezza; //add this line for each get variable $tolleranza = ($percentuale / 100) * $lunghezza; $val_up = $lunghezza + $tolleranza; $val_down = $lunghezza - $tolleranza; $selector .= "variante_prodotto.lunghezza>=$val_down, "; $selector .= "variante_prodotto.lunghezza<=$val_up, "; } Sorry I’m being so incoherent 👀
  42. 4 points
    There's no need at all to understand the PW architecture or database structure and relations - or even to think about these things. Stick to using PW selectors (https://processwire.com/docs/selectors/) and all the hard work is done for you. Selectors are one of the really great features of PW! (Note that if you later decide to use RockFinder for the extra speed, it also understands the PW database structure so that you don't have to.)
  43. 4 points
    Hey there! Just wanted to drop a quick comment 🙂 SearchEngine provides two built-in methods for search form rendering: Highly customizable "basic form". You can probably get the best idea of this by taking a look at these lines in SearchEngine.module.php. I'd actually be surprised if there's something you can't customize. Less customizable (unless you really enjoy hooking into form rendering) "native ProcessWire form". I know that some folks prefer these (I don't), so I thought it would be a nice addition. ... and, of course, you don't have to use either one. Bring your own markup. SearchEngine doesn't really care about the form — there's no CSRF or anything involved, it's just a search feature 🙂 As for the results list, there's the "easy way" where you let SearchEngine handle everything for you. Again, this is quite customizable via config settings and hooks, if you've got something specific in mind. JSON is also an option, but this is mostly intended for cases where you want to utilize SearchEngine as a part of an API, or perhaps create a fully customized JS search form feature. The biggest things lacking form SearchEngine (in comparison to tools like Meilisearch, or more heavy-weight indexers such as Solr, Elasticsearch, RediSearch, etc.) are the ability to normalize queries, perform complex lookups from the index (SE is basically just using ProcessWire's selectors and that's it), smart weighting of results based on relevance (this is on my to-do list), and perhaps really snappy real-time results (you can perform asynchronous queries, but they go through your site, which means that they have some overhead; tools like Meilisearch can do this much more efficiently). Anyway, just wanted to let you know that there are different options there. I don't actually know your case well and can't say if SearchEngine is the correct solution, but if it's UI level customization you're after, that shouldn't be an issue. And if it is, please let me know what's missing and I'll be happy to take a closer look; perhaps it's something that others might find useful as well 😛
  44. 4 points
    RockFinder can massively reduce search times. I've used it to reduce complex searches from several seconds to fractions of a second. However, if your searches aren't too complex, even on a fairly large number of pages the difference could be between part of a second using PW selectors and a very small part of a second using RockFinder. This isn't really going to solve your problem. So I'd suggest sorting out the rendering first, as suggested by others, with RockFinder as a possible later refinement.
  45. 4 points
    The big catch is, that no HTML is generated but structured data and you only have to define your elements once and can reuse them as often as you like in one field, without modifying the template or adding new fields to ProcessWire. You can move things around and render the different elements like an image for example, however you want it. Output it as a picture element, put some divs around it, etc. Or render a heading of level two as a heading level 3 instead. This is not possible if you only have HTML.
  46. 4 points
    If you want to make sure there are no duplicates, excluding them by ID is the way to go. There shouldn't be any performance issues - excluding one ID or a hundred shouldn't make any noticable difference for the generated database query. You can save the first result to the session as a string, and then include it in your selector. // first result $randomPages = $pages->find("template=gallery-detail, sort=random, limit=100"); $session->set('current-random-pages', (string) $randomPages); // later, in an ajax call $previous = $session->get('current-random-pages'); $randomPagesWithoutPrevious = $pages->find("template=gallery-detail, sort=random, limit=100, id!={$previous}"); // add the new pages to the list so you can load more multiple times $session->set('current-random-pages', $previous . '|' . $randomPagesWithoutPrevious); Quick and untested, might need some adjustments and context, but you get the idea 🙂 If you want to go stateless, you can also include the ID-list in the ajax call. By the way, casting a PageArray to string creates a pipe-seperated list of IDs (e.g. 2|5|28|278), this can go right into the query and is a good format to save the IDs to the session or include them in the ajax call.
  47. 4 points
    I just noticed that the topic title mentions field type. The jqTree library you linked to can read/write to/from JSON format, so that data can be stored in a FieldtypeTextarea. For the inputfield you could create a custom inputfield module that extends InputfieldTextarea - in the renderReady() and render() methods you would make use of jqTree. If you are not up for coding that another idea is to use the depth option available for Repeater fields. If you go this route you might also find my Repeater Depth Helper module useful.
  48. 4 points
    I took the liberty of opening a GitHub issue for this problem: https://github.com/processwire/processwire-issues/issues/1192 As a workaround for now you could use this hook in /site/ready.php: $pages->addHookBefore('added', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); /** @var Pages $pages */ $pages = $event->object; // Only for a particular template if($page->template != 'your_template') return; // Check if there is a name clash with an existing sibling page $default_name = $this->wire('sanitizer')->pageName($page->title, true); if($pages->count("parent=$page->parent, id!=$page->id, name=$default_name, include=all")) { // Manually create a proposed name $name = $default_name . '-1'; // Auto-adjust the name when needed $name = $pages->names()->uniquePageName($name, $page); // Set the name $page->setAndSave('name', $name); } });
  49. 4 points
    This works for me: $store->getUnformatted('products');
  50. 4 points
    @bernhard, maybe something like https://marketplace.visualstudio.com/items?itemName=wwm.better-align ?
  • Create New...