Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/01/2020 in all areas

  1. v1.0.8 improves the readme (had no section about getRows() ? ) and adds a nice shortcut $finder->groupBy(): https://github.com/baumrock/rockfinder3#getting-data Getting data When using a regular $pages->find() you get a PageArray as result. When working with RockFinder we don't want to get the PageArray to be more efficient. We usually want plain PHP arrays that we can then use in our PHP code or that we can send to other libraries as data source (for example as rows for a table library). getRows() This returns an array of the result having the id as key for every array item: $finder = $rockfinder ->find("template=cat") ->addColumns(['title', 'owner']); $rows = $finder->getRows(); db($rows); Having the id as item key can be very handy and efficient to get one single array item via its id, eg db($rows[1071]): getRowArray() Sometimes having custom ids as array item keys is a drawback, though. For example tabulator needs a plain PHP array with auto-increment keys. In such cases you can use getRowArray(): https://github.com/baumrock/rockfinder3#predefined-methods Predefined Methods At the moment there is one shortcut using the string modification technique for grouping a result by one column: $finder = $rockfinder ->find("template=cat") ->addColumns(['title', 'owner']); $cats_by_owner = $finder->groupBy('owner', [ 'GROUP_CONCAT(title) as title', ]); db($cats_by_owner); Another example could be getting averages: $finder = $rockfinder ->find("template=cat") ->addColumns(['title', 'owner', 'weight']); $cat_weight_by_owner = $finder->groupBy('owner', [ 'AVG(weight) as weight', ]); db($cat_weight_by_owner); Of course you can combine both: $finder = $rockfinder ->find("template=cat") ->addColumns(['title', 'owner', 'weight']); $combined = $finder->groupBy('owner', [ 'GROUP_CONCAT(title) as title', 'AVG(weight) as weight', ]); db($combined);
    3 points
  2. What I've done is write a php script that I run from the command line to avoid memory/execution timeout issues. I also always use PHP League's CSV library which iterates the CSV without loading it all into memory.
    3 points
  3. See the settings:
    3 points
  4. Could you share some code? This is a good guess. You need to keep track of your pagination somewhere and pass it to the selector like "text%=$q, start=$currentPage, limit=10"
    2 points
  5. 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.
    2 points
  6. I had to take a closer look, and it's actually mostly related to our PHP task, which runs PHP_CodeSniffer (which can be very time-consuming). You can use this with any files, though — check out https://www.npmjs.com/package/gulp-cached. It's really easy to add, basically just require the package and add a single line to your gulp task. The basic idea is that gulp-cached keeps track of files, and makes sure that files are only passed downstream if they've changed since last run. What this means in practice is that when using watch, the initial build may still be slow (none of the files being watched are cached) while subsequent ones are going to be much, much more performant, as all files that didn't change will be skipped over. Other differences I can see with our setups: You seem to be running sourcemaps on every build. If this is really the dev/watch process, then I don't really see a reason to do that, and it's definitely going to slow things down. We're using gulp-if to check for env and only setting sourcemaps up if it's a production build (basically gulp build vs. gulp watch). I'm not seeing anything related to purge here. If you're using the purge setting in Tailwind config, this is a relatively new thing and I really can't say anything about that — for me it seems easier to just run purge as a part of the gulp task: // Tailwind extractor for purgeCSS const tailwindExtractor = (content) => { return content.match(/[A-z0-9-:\/]+/g) || [] } ... .pipe(gulpif(argv.prod, purgecss({ content: [ config.paths.base + '**/*.php', config.paths.base + '**/*.js', config.paths.site + 'modules/InputfieldCKEditor/*.js', ], extractors: [ { extractor: tailwindExtractor, extensions: ['php', 'html', 'js'] } ] }))) ... Actually it shouldn't — just having something like px-3 in a file with nothing else should be enough. Again this is based on the code I've posted above, so if the native feature is using some sort of "advanced" matching algorithm, it could be a major problem for a lot of code. Weird. Note also that unless Tailwind has a mechanism for disabling purge on dev builds, you're going to be doing a lot of work that you probably don't need there. That could be another bottleneck. I'd probably just stick to a manual purge declaration in gulpfile. There's good documentation for that here, in case you need more details: https://tailwindcss.com/docs/controlling-file-size/.
    2 points
  7. Hi, With the deprecation of Instagram's API and therefore the end of the Instagram Feed module, I've developed a replacement module which uses the Instagram Basic Display API: https://github.com/nbcommunication/InstagramBasicDisplayApi To use this module you'll need: ProcessWire >= 2.7 A Facebook Developer account Access to the Instagram user account you wish to use Prior to installation, you'll need to create a Facebook app. The app you will create uses the User Token Generator for authentication - it does not need to be submitted for App Review (and therefore stays in Development mode). The README contains full instructions on how to create and set up the app and also how to use the module. The primary reason for this module's development was to retain functionality on existing websites that use the Instagram Feed module. To assist with upgrading, this module replicates some methods provided by Instagram Feed. I've already upgraded a couple of sites and it was quick and painless ? Cheers, Chris
    1 point
  8. You can detect whether the current page was loaded from ajax by checking the value of $config->ajax from your template file: <?php if($config->ajax) { // page was requested from ajax } Following that, you will likely want to render the page differently to accommodate whatever you are doing from the javascript side. For instance, you might want do one of these: 1. Deliver alternate or reduced markup when loaded from ajax 2. Deliver a JSON or XML string for parsing from javascript Below are examples of each of these scenarios. 1. Deliver alternate or reduced markup when loaded from ajax You might find checking for ajax helpful when you want portions of pages to load in your site without re-rendering the entire page for each request. As a simple example, we'll use the default ProcessWire site and make it repopulate it's #bodycopy area when you click a page in the top navigation. (To use this example, you'll need the default ProcessWire site templates, though you can easily adapt the example to another situation.) To accomplish this, we'll update our main page template to only include the header and footer markup if the page is NOT being loaded from ajax: /site/templates/page.php <?php if(!$config->ajax) include("./head.inc"); echo $page->body; if(!$config->ajax) include("./foot.inc"); Next we'll update the top navigation to do ajax loads of the pages when the client has javascript (and leave as-is when they don't). Paste this javascript snippet before the closing </head> tag in the header markup file: /site/templates/head.inc: <script type="text/javascript"> $(document).ready(function() { $("#topnav a").click(function() { $("#topnav a.on").removeClass('on'); // unhighlight selected nav item... $(this).addClass('on'); // ...and highlight new nav item $("#bodycopy").html("<p>Loading...</p>"); $.get($(this).attr('href'), function(data) { $("#bodycopy").html(data); }); return false; }); }); </script> Now when you click on any page in the top navigation, it pops into the bodycopy area without a page load visible from your browser. And all pages remain accessible from their URL as well. Note that this is just a test scenario, and I probably wouldn't use this approach for the entire bodycopy area on a production site (it would make bookmarking difficult). But this approach can be very useful in the right places. 2. Deliver a JSON or XML string for parsing from javascript Lets say that you want pages in your site to return a JSON string with the page's id, title, and number of children when it is requested from ajax. When not requested from ajax, they will return their content as normal. To handle the ajax requests, you'd want to add something like this at the top of your template file before any other output. <?php if($config->ajax) { // this is an ajax request, return basic page information in a JSON string $json = array( 'id' => $page->id, 'title' => $page->title, 'numChildren' => $page->numChildren ); echo json_encode($json); return; } // not ajax, continue with regular page output And here is some markup and inline javascript you might use to test the ajax call on some other page (or the same one if you prefer). You would paste this snippet right in your site's markup where you want that info to appear. <ul id='info'></ul> <script type='text/javascript'> var url = '/'; // this is homepage, so replace '/' with page URL you want to load JSON from $(document).ready(function() { $.getJSON(url, function(data) { $.each(data, function(key, value) { $("#info").append("<li>" + key + ": " + value + "</li>"); }); }); }); </script> The above snippet would output something like this: • id: 1 • title: Home • numChildren: 5 To take this example further, you could build an ajax-driven sitemap or any number of web services. Conclusion Hope this helps you to see how simple it is to use ProcessWire to deliver output for ajax. These are just contrived examples, but hopefully examples that might lead to more ideas. In addition, much of what you see in these examples is also applicable to building web services in ProcessWire.
    1 point
  9. 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.
    1 point
  10. Thanks! I wanted to start small and simple. I like that a simple version of the charts also works without any JavaScript. As I want to also link to specific runs, this seems to be quite cumbersome with ChartJS. Working directly with SVG feels a lot more robust and simpler for me in that regard.
    1 point
  11. Sorry, that is the new page I created and saved before running the above.
    1 point
  12. Not certain, but it sounds like it hasn't made it in yet - sorry, I forgot that feature wasn't in yet.
    1 point
  13. Okay, issue created: https://github.com/processwire/processwire-issues/issues/1209 As a quick fix I will re-upload my affected non-transparent PNGs with JPGs. Another possible workaround on template level: if($image->width == $width) { $imgUrl = $image->webp->url; } else { $imgUrl = $image->width($width)->webp->url; }
    1 point
  14. Hi @Patrik97 It might be worth you saying what you're trying to achieve. The kind of approach you describe would only rarely be necessary, though you may have particular needs. I'm wondering if there might be a much easier way of doing things.
    1 point
  15. @Patrik97 Welcome to the forum. RepeaterPageArray object represents the value of a repeater field, related to the page where the repeater lives in. A single item of this PageArray is an instance of class RepeaterPage. The class is set via FieldtypeRepeater::getPageClass(). This value is not changeable, the function not hookable. If you want to use a custom class for your repeater item objects with additional methods or properties, you need to create your own Fieldtype, derived from FieldtypeRepeater which includes your custom class and overwrites the getPageClass() function. Example where exactly this is done: FieldtypeRepeaterMatrix Maybe related: https://processwire.com/docs/tutorials/using-custom-page-types-in-processwire/ https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes https://processwire.com/talk/topic/20593-pageclasses-and-php-classes/
    1 point
  16. @Robin S This is a very handy module, thank you. I have a situation that is inconvenient at best but has me wondering. I have 2 fields set side by side on the template with 50% width and a showif condition that means one of the fields only appears occasionally but when it's not visible the layout goes to hell since the first field is set to 50% width. Is it possible to expand this module to include the column width so that if the same selector that determines visibility is met the column width would change from 50% to 100% to fill in the row? If so it would allow for field visibility to change without effecting the rest of the layout. that would be awesome.
    1 point
  17. The ^= operator should do it: $matches = $pages->find("limit=0, title ^= '$letter'");
    1 point
  18. 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: ?
    1 point
  19. Quoting myself here, but just wanted to add that they do indeed have a solution for this ? ... so if you're using purge as defined in the Tailwind config file you need to make sure that NODE_ENV is not production when you're doing your dev build.
    1 point
  20. 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 ?
    1 point
  21. The modules directory issue is now fixed. @eydun, note that this is not a module support thread, so I've moved it to the General Support area of the forum. "Modules/Plugins" area is reserved for module-specific support threads, one per module.
    1 point
  22. What @teppo said, also, what is returning error or response ? Admin markup ? If yes, you might need to set the Content-Type header. Can you post your request headers here ? What is /post/ ? Can we see a chunk code ?
    1 point
  23. 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 ?
    1 point
  24. Thanks @teppo - I actually noticed there was a new version the other day and used the PW Upgrades module to update, but for some reason it's not actually updating the module (I just tried again) - I assumed it had worked. Anyway, I manually updated to 2.1.0 and you're correct of course - it seems like they have been fixed.
    1 point
  25. Hey @adrian! I'm pretty sure that those issues were already fixed. Could you check that you've got 2.1.0 installed?
    1 point
  26. Looks like @ryan just upgraded the modules site from PW 2.x to 3 and that has caused something to break. I no longer have access to the admin so I can't see what the cause of the error is, but hopefully he'll read this ?
    1 point
  27. Hey @Erik Richter, FormBuilder questions would be best posted to the FormBuilder VIP support area, which you get access when you purchase a license. If you have bought a license and still don't have access, be sure to contact Ryan to get it sorted out ? To me it looks like the code you've posted and the error you're seeing are not directly related: the notice suggests that you're using $first_name, while in the code you're clearly referring to $values['first_name']. I'm not really familiar with how the autoresponder logic works, so perhaps there's an explanation for this, but in the meantime I'd make sure that this really is the code you're running. Since the modules section of the forum is only intended for module-specific support threads — one per module — I'm moving this topic into General Support. Perhaps someone can help you there.
    1 point
  28. Hey @cosmicsafari! FormBuilder questions should really be posted to the VIP support area, which you should have access to if you've got a FormBuilder license. If you have bought the license yet still don't have access, you should contact Ryan so you can get it sorted out ? I don't think I've ever used $forms->embed() in this way, but according to the docs you can pass in an array that overrides GET variables, while with render you can pass in an array of pre-populated values. These are different things, obviously, though it probably should work if you had configured your form so that values can be pre-populated using GET variables.
    1 point
  29. Right — looks like I skimmed too quickly over this part. Was also pretty sure that I had tested this before, but you're right that it doesn't seem to work at the moment. Thanks, I'll take a closer look soon!
    1 point
  30. Actually it sounds like your search_index field could be single-value textarea, instead of textarea (multi-language). If so, you'll have to change the type of the field manually. Could you check if this is the case? Either way I should probably add some extra checks to make sure that this doesn't happen.
    1 point
  31. 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'], ], ]);
    1 point
  32. Technically it's already possible — you just need to tell WireClassLoader where it can find your custom Page classes. Just gave it a try, adding this to /site/init.php, and it seemed to work fine: $classLoader->addSuffix('Page', __DIR__ . '/templates/page-classes/'); Now ProcessWire checks for Page classes from /site/templates/page-classes/. This is in addition to the default /site/classes/ directory, which still has precedence if a class is found from there.
    1 point
  33. How do you disabled it? Please can you try setting it to NULL, and not false? If this will work, I think it is a glitch here in Line 142 in ProcessPageView.module: if($config->usePoweredBy !== null) header('X-Powered-By:' . ($config->usePoweredBy ? ' ProcessWire CMS' : '')); See: !== null, if you have set it to false, it will result in boolean true, but afterwards, querying simply $config->usePoweredBy results in boolean false, what populates an empty string to the sended header.
    1 point
×
×
  • Create New...