Jump to content


Popular Content

Showing content with the highest reputation on 09/26/2019 in all areas

  1. 6 points
    Yo Ryan and everyone, I don't use ProcessWire anymore for new stuff — the size and scope of the projects makes using a database nonsense — but there is one half internal system that happily chugs along, for 7 years now (I think? Maybe 8 years?) Latest page ID created was 38047 😎 So, thank you for everything — mostly for keeping my job while "new system" isn't happening 😄
  2. 4 points
    @pwired — there was a time when I'd agree with you, but there are quite a bit of options for I ❤️ PW devs out there - for flat file CMS at least. So in the end I'd say that ProcessWire and its community are better served by focusing at its one thing.
  3. 4 points
    @bernhard's post gives you the clue - it's to do with PW's built-in caching. $page->children() is a method that queries the database. You want to minimise the number of requests to the database because going to the DB is a lot slower than working with objects in memory. In your code you call $page->children() five times, so the expectation is that this would mean five trips to the DB... except that PW tries to help you out and caches the results to avoid unnecessary DB queries. But the exact workings of this caching are undocumented (as far as I know) and so I'd say it's best practice not to rely on it. It would be better to consciously minimise the DB requests in your code - it would make things clearer (i.e. avoid the confusion you're getting from the behind-the-scenes caching) and it's a good habit to get into for when you're working with other PHP projects that might not cache DB query results like PW does. You could rewrite your code like this: $layout->setTemplate('sidebar'); $selector = [ 'template' => 'product', 'sort' => 'title', 'categories' => page('id'), 'limit' => 9 ]; // Just get the children from the DB once // I assume you need all the children at some point later in the code because you dump page()->children() in your example. // If you don't need all the children then just get the categories directly with page()->children('template=category') $children = page()->children(); // Get the categories from the children PageArray (happens in memory) $categories = $children->find('template=category'); // If there are any categories then modify $selector if($categories->count) { $categories->add(page()); $selector['categories'] = $categories; } bd($children); bd($categories); And this might be getting into the zone of micro-optimisation but you could consider if you actually need full Page objects in a PageArray or if you only need the IDs (reduces the memory footprint): $category_ids = page()->children('template=category', ['findIDs' => 1]);; if(count($category_ids)) { $category_ids[] = page()->id; $selector['categories'] = $category_ids; }
  4. 3 points
    Actually I came to a pretty handy solution with my co-dev! Images have information about their modification time saved within them, so using that I came up with following code: $img = $page->image; // check if image exists if($img) { // fetch cropped images' modification timestamps $tsNormal = filemtime($img->getCrop('normaali')->filename); $tsHigh = filemtime($img->getCrop('korkeampi')->filename); $tsLow = filemtime($img->getCrop('matalampi')->filename); // check if they have the same modification time => user hasn't cropped the image, so use the original if(!($tsNormal == $tsHigh && $tsNormal == $tsLow)) { // stamps are not equal => check which is highest aka last modified switch(max($tsNormal, $tsHigh, $tsLow)) { case $tsNormal: $img = $img->getCrop('normaali'); break; case $tsHigh: $img = $img->getCrop('korkeampi'); break; case $tsLow: $img = $img->getCrop('matalampi'); break; } } } Seems to work quite nicely for my purpose 🙂Thought it would be nice to share, if anybody else wants to achieve similar effect!
  5. 2 points
  6. 1 point
    Care to elaborate about such projects? i.e. some insights into the pros/cons of PW, or just general infos (what worked well, what didn't; what general dev route you were taking instead, bottlenecks or overhead etc).
  7. 1 point
  8. 1 point
    Here is a crazy one for me. I've worked with ProcessWire for years and I have never come across this. I had my website installed on one sub-directory and I moved it to a different one, but all the links in the admin panel other than the home and edit page buttons are linking to the old sub-directory. I always believed that the urls were relative. Has anyone come across this before? I don't know where to look to fix this as the url isn't anywhere like it would be in WordPress for example. I've tried refreshing my cache. EDIT: Nevermind, tried incognito and it worked fine, so it must be a caching issue.
  9. 1 point
    @Noel Boss This is a very good looking theme. 🎉
  10. 1 point
    To report back: The modules Page Protector and Protected Mode solve all my riddles. Thanks to @adrian for these fine tools!
  11. 1 point
    Your site visitors would have to download two copies of every image if you do this server-side. These days a CSS filter is the way to go: .bw-image:hover { filter:grayscale(100%); } And who cares about IE (or use a polyfill). But if you're sure you want to do this in PW and set a destination filename... $is = new ImageSizer('/path/to/filename.ext'); $is->getEngine()->convertToGreyscale('/path/to/filename_new.ext');
  12. 1 point
    Hey I use DUPLICATOR for backups. In all of a sudden my cronjob don't work anymore. I get the following error in Duplicator.module line 663: PHP Warning: ZipArchive::Close(): Internal error I use the cron.php file. Has anyone an idea why this happens and what I can do? Thanks in advance. Marcel
  13. 1 point
    d($page->children()->count); // 7 $foo = $pages->get(1); $page->children()->add($foo); d($page->children()->count); // 8 d($page->children('id>2000')->count); // 3 $page->children('id>2000')->add($foo); d($page->children('id>2000')->count); // 4 $pages->uncacheAll(); d($page->children('id>2000')->count); // 3
  14. 1 point
    Ah ok. There is no build in solution for this. You have to build something yourself. For example, if there is currently no use of tags, (or an expandable usage of tags), with this imagefield, you may setup tags with predefined values, so that the user can select one if he like to. If this is not possible due to restricted other usage of tags, it may become very uncomfortable, as there are currently no other fields bundled together with an image (besides description and tags). I'm not sure if the imageextra module from justb3a is uptodate with the current devstate (?), If so, and if tags are no option, this would be the way to go.
  15. 1 point
    You will need: ProcessWire (of course) ProcessWire ProCache ProcessWire Modules as you like and need Netlify Account (in my case, you can use any other hosting or Github pages) Git Account (Gihub, Gitlab, Bitbucket) ScreamingFrog (free version should fit most needs) Things to keep in mind FormBuilder will not work (out of the box) 40x/50x must be defined separately Redirects must be defined separately Module-based functionality will not work GDPR/Opt-in/Cookie consent must be added differently Avoid using core/module files (UIKIT, jQuery, CSS, etc.) Where to save files and how to address them Most content and design related files can be saved in ProcessWire itself. Logos, favicon, trust icons and whatsoever. Some files can't be stored in ProcessWire - or shouldn't be stored in it - fonts and sitemaps (XML) in my case. While developing the overall site always use relative paths and URLs. Fonts and other assets need to be addressed by their web-root-based path (/site/templates/myassets/font.ttf and so on). Internal linking should be relative as well. Otherwise you have to change those link URLs manually which is PITA. Which files to copy and where you find them As we use ProcessWire we want and should use everything we can to make our webdev life easier here. Let ProcessWire and some modules do the work while harvesting the results for our benefits. While ProCache takes care of generating minified CSS and JS, SEO Maestro generates a nice and handy sitemap.xml. Depending of your installed modules you want to (at least) double check the output and results in your static site. As already mentioned FormBuilder and Simple Contact Form will not work, 404 management and redirects by the awesome Jumplinks modules will not work, too. Instead you have to create your very own .htaccess file with all redirects and error documents. Other modules like MenuBuilder, SEO Maestro and some other modules do a pretty good job even in your static site as their benefits result in already rendered HTML/pages. Autolinks, Automatically link page titles and Share buttons are some modules that will work as well. While it didn't work for me it may work for you - the Cookie Management Banner module. I had some issues and decided to install and use Cookie Consent manually. The Workflow First of all build your site. Make it perfect. Do whatever you or the client wants or needs. Whenever possible look into your rendered HTML and cached pages. Take a closer look at all the URLs and paths. It's already a good idea to run ScreamingFrog and find out if there are any files missing, links broken or pages missing. When everything is done, clear all cached files, all minified JS and CSS. Start a ScreamingFrog session and let it run. It will visit each and every page on your site it can find. Hidden pages, orphaned pages and of course drafts and pages behind JS-links will not be found and therefore cached by ProCache. Look into /site/assets/ProCache-XXX/ and /site/assets/pwpc/ now and double check that there are your pages and JS/CSS files. You will need those afterwards. If everything is fine you have to copy things around now. The Setup - folders and structure In my case the easiest way to go was setting up two local sites - one with ProcessWire and another one with the static files, assets and other things I needed. In the examples below only relevant parts are listed. project.pw.test (ProcessWire) /sitemap.xml (Generated by SEO Maestro) /site/assets/files/ (copy the whole path) /site/assets/pwpc/ (copy the whole path) /site/assets/ProCache-XXX/* (copy only the content of this folder - all files and folders) /site/templates/myassets/ (copy the whole path) project.sv.test (Static version) .htaccess (for redirects and 40x/50x error pages) 40x.html 50x.html /sitemap.xml /site/assets/files/ /site/assets/pwpc/ /site/templates/myassets/ all files and folders from /site/assets/ProCache-XXX/ As you can see there are only a few things to copy. When you're done with copying these files to the static version of your project, open it up in your browser. Check for missing files and test it. Let ScreamingFrog do the most work and check for any kinds of errors. Fix them in your ProcessWire-site and copy and test again. Check your 404s, your redirects and everything else you would normaly test. Create checkafterupdate.txt and write down whatever went wrong in your first try. This will be a great checklist later. The Final Step As everything is copied now and at its correct place you can upload it to your host. In my case the static version is a private git repository on github.com. I can commit and push my changes there and Netlify takes care of publishing the new version - most of the time within seconds. The benefit of using git - compared to S/FTP - you always have some kind of control if something brakes and you have to revert and check changes. In my case it's Netlify but you can use Github pages or any other hosting solution you want/the client pays for. Be careful with GDPR-related things as DPAs. You have to have them in most cases - Netlify did a great job here and I found everything I needed, while Github disqualified itself back then due to missing documents and kind of a sluggish support. Questions? Ask.
  16. 1 point
    Hi there! first of all, this is a great module Nevertheless, i was missing one little thing, and that was the possibility to style your map with a style from snazzy maps. So i tried to get it in there... I don't know if that's the right way, but it works: in MarkupGoogleMap.module: $MapStyle = $options['mapStyle']; // adding a field 'mapStyle'... $id = $options['id']; $out = ''; if($n === 1) $out .= "<script type='text/javascript' src='{$this->config->urls->MarkupGoogleMap}MarkupGoogleMap.js'></script>"; $out .= "<div id='$id' class='$options[class]'$style></div>"; $out .= "<script type='text/javascript'>" . "if(typeof google === 'undefined' || typeof google.maps === 'undefined') { " . "alert('MarkupGoogleMap Error: Please add the maps.googleapis.com script in your document head.'); " . "} else { " . "var $id = new MarkupGoogleMap(); " . "$id.setOption('zoom', $zoom); " . "$id.setOption('styles', $MapStyle); " . // and outputting it here to the js. "$id.setOption('mapTypeId', google.maps.MapTypeId.$type); " . ($options['icon'] ? "$id.setIcon('$options[icon]'); " : "") . ($options['useHoverBox'] ? "$id.setHoverBox('" . str_replace("'", '"', $options['hoverBoxMarkup']) . "');" : "") . "$id.init('$id', $lat, $lng); "; As i said, it works, but i'm not too sure if it's right. Also, i'd like to add the option to the admin panel, but i'm not too sure how...
  17. 1 point
    I'd suggest changing this line: if ($pages->find("template=blog-article, tags=$tag")->count() > 0) { To this: if ($pages->count("template=blog-article, tags=$tag") > 0) { The reason is that find() loads all those pages, whereas count() just counts them... far less overhead if you don't need the actual pages loaded (which it doesn't appear that you do).
  • Create New...