Jump to content

Leaderboard

Popular Content

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

  1. Rebuilt my own site recently using all the knowledge, tips & tricks I've learnt from the PW docs, forums etc, including adding PWA features. Ran it through several publicly available audits and it passed OK - w3c validation, google page speed insights, google lighthouse, etc. Also engaged a digital marketing agency to audit it from a Google search POV. Still some tweaking to do on content & backlink fronts. Overall though happy with the result which could never have been achieved without the help and support of the ProcessWire community. Thank each and everyone of you. https://www.clipmagic.com.au
    8 points
  2. The module in the PW version 2.7.2 create a table with a TEXT (64Kb) field and in PW version 3.0.x it use a MEDIUMTEXT (16Mb) field. @gebeer your are trying to insert 23,536 bytes which could be fine if the string was composed with single-byte characters. But in your case it look like your string is encoded in UTF-8/Multi-byte, so we can assume that each character in your string take 1 to 4 bytes of space and thus the database server truncate your string because the TEXT field can only contain 65 535 chars (using single-byte characters) and your string contain (assuming here) 94 144 bytes (multi-byte characters). It could explain your issue. For testing, you could try to disable SQL STRICT MODE. I hope it make sense.
    5 points
  3. In this post we look at a new core version on the master branch, and a new version of ProCache that includes a browser-cache busting feature called Buster: https://processwire.com/blog/posts/pw-3.0.98-procache-buster/
    4 points
  4. There's a long discussion about column width issues in AdminThemeUikit in the issues repo: https://github.com/processwire/processwire-issues/issues/480
    3 points
  5. Hi @taoguang Lest assume that you have this structure Books ( template: books ) - Book ( template: book ) - Book 1 ( template: book ) Authors ( template: authors ) - Author ( template: author) - Author 1 ( template: author) So to link author page to its books you have to create two page-reference fields: books and authors. The 'books' fields should use 'book' template as the selector and 'authors' field should use 'author' template as the selector. Then add 'books' field to 'author' template and 'authors' field to 'book' template'. Also, you can use this module https://modules.processwire.com/modules/connect-page-fields/ You can find why it would be helpful for your purpose by reading the description on its page.
    3 points
  6. @Macrura - the fix is available in the latest version. The other major update to this version is support for resizable panels - there is now a resize handle at the bottom right of each panel so you can manually size to suit your needs. This is especially useful when you have one of the larger panels open (like the Field List & Values section of the Request Info panel) and it's taking up the entire screen and you want to compare values in the panel with what is on the page - now you can manually resize to fit where you want. Also, the Tracy core has started refactoring lots of code to use ES6, so those changes are being incorporated as well. Let me know if you come across any issues with this new version!
    3 points
  7. Hello I want to know if others have discovered the same issue with the UIKit admin theme. If you want fe 3 cols in a line and if you have a "show if condition" the grid will not be added correctly. Take a look at the following images. 1) Everything is ok. Each column width was set to 33%. The last field in the column has a dependency to the field in the second column. After changing the select value of the second field the following happens: As you can see the third field which should be 33% float to the next line and has the UIKit class "uk-width-2-3@m" instead of "uk-width-1-3@m" or "uk-width-expand". Can someone confirm this behaviour?
    2 points
  8. Thanks @Robin S - I have made lots of tweaks to the css for both the Console and SnippetRunner panels and I think they are both much improved and of course now support width resizing. I have also set the default widths to 1200px, rather than full width which I think will be much nicer in general. Anyway, please take a look and let me know what you think.
    2 points
  9. I thin what you are looking for is the "Custom PHP code" in the Input tab of the field cnfiguration screen for your programs_list field In my case the field name is "myplaces" Now Go and insert this hook into site/ready.php $wire->addHookAfter('InputfieldPage::getSelectablePages', function($event) { if($event->object->hasField == 'programs_list') { $page = $event->arguments('page'); $event->return = $event->pages->find("template=yourTemplateForProgramPages, program_id={$page->legacy_id}); } }); This gets the legazy_id of the page that you are currently editing and then finds all program pages with that id in field program_id.
    2 points
  10. @gebeer, there was a change in Session-DB-Handler in the past, but don't remember exactly when. Maybe you compare the current 3.x Module against the 2.7.x one?
    2 points
  11. I shouldn't think so. The overhead in the search template would be negligible because searches are usually only for a few words at most. In the saveReady hook it would depend on how much content in the page you are saving sounds-like data for. I can't see it being an issue in most circumstances.
    2 points
  12. I took a quick look at it. The gist of it is that you would set the width of #tracyConsoleContainer with... width: calc(100% - 380px) !important; ...where 380px is whatever the width of #tracySnippetsContainer should be - there is something not quite right there currently, because the snippets container gets a width from an inline style that is narrower than its contents (which overflow). Also this rule... #tracy-debug fieldset { all: initial !important; ... ...would need to be overridden for the console/snippets panels with... width:100% !important; I don't mind it being there permanently myself. I have a wide enough screen that the Ace window is never so narrow that I'd want extra width by collapsing the sidebar. But maybe some people who work on smaller screens would appreciate that.
    2 points
  13. I'm loving this! On the Console and Snippets panel it seems that only vertical resizing is possible - horizontal resizing there would be handy.
    2 points
  14. Here's an example with a single "sounds_like" field containing both metaphone and soundex data. This is better I think. In /site/ready.php: $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if(!$page->id || !$page->template->hasField('sounds_like')) return; $sounds_like = ''; $words = explode(' ', $page->title); // Get the individual words of field(s) foreach($words as $word) { if(strlen($word) < 3) continue; // Ignore short words $sounds_like .= metaphone($word) . ' ' . soundex($word) . ' '; } $page->sounds_like = $sounds_like; } In search template file: // $q is the sanitized search string $words = explode(' ', $q); $selector = ''; foreach($words as $word) { if(strlen($word) < 3) continue; // Ignore short words $selector .= 'sounds_like~=' . metaphone($word) . '|' . soundex($word) . ', '; } $results = $pages->find($selector);
    2 points
  15. Thanks for the new Buster feature! I'm sure you're right here, but some popular performance rating tools such as GTmetrix will deduct points for query strings on static assets, so that might be a reason to prefer filename versioning if clients will be evaluating the website with those tools.
    2 points
  16. If you check this tutorial https://support.plesk.com/hc/en-us/articles/213367429-How-to-upgrade-MySQL-from-5-1-to-5-5-on-Linux, you can see a note that says "The PHP package can also be updated during this procedure". I did not pay attention to this because I had installed the latest version of PHP, but it seems that anyway the package and its configuration were changed during the upgrade. maybe.. and during the user login at admin too.. because like in my example, it can happen after the installation... At least we need a topic, or a recipe at https://processwire-recipes.com/ or wherever the option we have, to guide beginners like me. Explaining all the test that must be done after "This request was aborted because it appears to be forged" because after my investigation I found several causes for this, and almost 127 forum entries about it. https://www.google.com/search?q=site:processwire.com+"This+request+was+aborted+because+it+appears+to+be+forged" Now, at this moment I can breathe! I want to say a BIG THANK YOU to @flydev who won my admiration and has been a wonderful human being
    2 points
  17. Hi @MikeM and welcome to the forum, your question was well structured and it seems that you put some time into writing your request. And you see that you got multiple helpful answers within a very short time period. That's how it usually works here - so if you decide to start learning pw you'll always find a helping hand here If you choose pw you should definitely take a look at my new module: You can build any form you want very easily. It's the only tool that I know that has frontend and backend validation in one go (making it super easy and fast to setup and highly maintainable) and it also has conditional fields, what you described as a must-have: https://doc.nette.org/en/2.4/form-validation There's also the pro module formbuilder, but I have only bought and never used it so I can't tell you anything about it. PS: If you need any assistance or new features for RockForms I would be happy to implement those features for you.
    2 points
  18. So I decided to wade into module development and created a wrapper module around ImageOptim, a service that compresses and optimizes images in the cloud. ImageOptim currently handles JPG, PNG and GIF files and, depending on the settings you use, shaves off between 15% and 60% in filesize. Great for bandwidth and great for users, especially on mobile. This module handles the part of uploading images to ImageOptim via their official API, downloading the optimized version and storing it alongside the original image. Download & Info GitHub / Module directory / Readme / Usage Why ImageOptim? There are other image optimization services out there, some of them free, that have outstanding ProcessWire modules. A few things make ImageOptim the best tool for most of my customers: It's not free, i.e. it will probably be around for a while and offers support. However, it's cheaper than some of the bigger competitors like Cloudinary. And it does PNG compression better than any of the free services out there, especially those with alpha channels. Installation Install the module like any other ProcessWire module, by either copying the folder into your modules folder or installing it via the admin. See above for downloads links on GitHub and in the module directory. Requirements To be able to upload images to the service, allow_url_fopen must be set on the server. The module will abort installation if that's not the case. I have only tested the module on ProcessWire 3.x installations. I don't see why it shouldn't work in 2.x, if anyone wants to try it out and report back. ImageOptim account To compress images, you first need to sign up for an ImageOptim account. They offer free trials to try the service. Usage (manual optimization) Images can be optimized by calling the optimize() method on any image. You can pass an options array to set ImageOptim API parameters. $image->size(800,600)->optimize()->url $image->optimize(['quality' => 'low', 'dpr' => 2]) // Set quality to low and enable hi-dpi mode Automatic optimization The module also has an automatic mode that optimizes all image variations after resizing. This is the recommended way to use this module since it leaves the original image uncompressed, but optimizes all derivative images. $image->size(800,600)->url // nothing to do here; image is optimized automatically To change compression setting for single images, you can pass an options array along with the standard ImageResizer options. Passing false disables optimization. $image->size(800, 600, ['optimize' => 'medium']) $image->size(800, 600, ['optimize' => ['quality' => 'low', 'dpr' => 2]]) $image->size(800, 600, ['optimize' => false]) For detailed usage instructions and all API parameters, see the usage instructions on GitHub. Filenames Optimized images will be suffixed, e.g. image.jpg becomes image.optim.jpg. You can configure the suffix in the module settings. Roadmap Asynchronous processing. Not really high on the list. Image variations need to be created anyway, so waiting a few seconds longer on first load is preferable to adding complexity to achieve async optimization. Optimize image variations created by other modules. CroppableImage comes to mind. I don't use any of these, so if somebody wants to help out and submit a pull request — all for it! Add a dedicated page in the setup menu with a dashboard and detailed statistics. ImageOptim's API is very barebones for now, so not sure if that's feasible or even necessary. Stability I've been using this module on production sites for some time now, without hiccups. If you do notice oddities, feel free to comment here or investigate and submit PRs.
    1 point
  19. Hi, So today I will writing a small tutorial on developing templates in Processwire using Twig Template, Processwire is a highly flexible CMS which gives developers/designers/users options and allows easy extension of the platform. So here goes the tutorial What is Twig Template ? Simply put in my own words, Twig is a modern templating engine that compiles down to PHP code, unlike PHP, Twig is clean on the eyes , flexible and also quite *easy* to have dynamic layout site with ease ,without pulling your hair out. Twig is trusted by various platforms. It was created by the guys behind Symfony. Take this code as an example {% for user in users %} <h1>* {{ user }}</h1> {% endfor %} This will simply be the equivalent in PHP World <?php $userArray = ["Nigeria","Russia"]; foreach($userArray as $user): ?> <h1><?= $user ?></h1> <?php endforeach; The PHP code though looks simple enough however, you start to notice that you have to be concerned about the PHP tags by ensuring they are closed properly , most times projects gets bigger and comes complex and harder to read/grasp, and also in PHP you can explicitly create variables in the template making it very hard to read as it grows and prone to getting messy WordPress is a major culprit when it comes to that regard. Have you ever wanted to created separate layouts for different pages and break your sites into different parts e.g Sidebar, Comment Section, Header Section ? the regular approach would be to create individual pages for each section and simply add them as templates for the pages and with time, you can end up having tons of templates, however Twig allows you to easily inherit templates and also override the templates where you can inject content into the block easily. Don't worry if you don't understand the concept, the following parts will explain with an example of how to easily inherit layouts and templates. Layout <!DOCTYPE html> <html lang="en"> <head> {{include("layout/elements/header.twig")}} </head> <body> <div class="container-fluid" id="minimal"> <header id="pageIntro"> <div class="bio_panel"> <div class="bio_section col-md-6"> <h1>Okeowo Aderemi</h1> <h2>{{ page.body }}</h2> </div> </div> <div class="clearfix"></div> </header> <section id="page-body"> <div class="container"> <div id="intro" class="col-md-7 col-lg-7"> <h1>About me</h1> <h2> {{ page.summary }} </h2> </div> {block name="content"}{/block} <a style="font-size:1.799783em; font-style:italic;color:#d29c23" href="{{pages.get('/notes').url }}">Read more articles</a> </div> <div class="clearfix"></div> </div> </section> </div> <footer> <div class="header-container headroom headroom--not-top headroom--pinned" id="header-container"> {{include("layout/elements/footer.twig")}} </div> </footer> </body> </html> This is basically a layout where we specify blocks and include other templates for the page, don't panic if you don't understand what is going on, I will simply break down the weird part as follows: Include This basically is similar to native PHP 'include', as it's name suggests it simply includes the templates and injects the content into the layout , nothing out of the ordinary here if you are already familiar with php's include function. {{ output }} This simply evaluates the expression and prints the value, this evaluate expressions, functions that return contents , in my own short words it's basically the same as <?= output ?> except for the fact that it's cleaner to read. {% expression %} unlike the previous this executes statements such as for loops and other Twig statements. {% for characters in attack_on_titans %} <h1> {{characters}} </h1> {% endfor %} This executes a for loop and within the for loop, it creates a context to which variables in that context can be referenced and evaluated, unlike dealing with the opening and closing PHP tags, Twig simply blends in with markup and makes it really quick to read. I will simply post the contents of both the header and footer so you can see the content of what is included in the layout header.php <meta charset="utf-8"/> <meta content="IE=edge" http-equiv="X-UA-Compatible"/> <meta content="width=device-width, initial-scale=1" name="viewport"/> <title> {{ page.title }} </title> <link href=" {{config.urls.templates }}assets/css/bootstrap.min.css" rel="stylesheet"/> <link href="{{config.urls.templates }}assets/css/main.min.css" rel="stylesheet"/> <link rel='stylesheet' type='text/css' href='{{config.urls.FieldtypeComments}}comments.css' /> <link rel="stylesheet" href="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/styles/vs.css"> <script type="text/javascript" src="{{config.urls.siteModules}}InputfieldCKEditor/plugins/codesnippet/lib/highlight/highlight.pack.js"></script> <script src="{{config.urls.templates }}assets/js/vendors/jquery-1.11.3.min.js"> </script> <script src="{{config.urls.templates }}assets/js/vendors/bootstrap.min.js"> </script> <script src="{{config.urls.FieldtypeComments}}comments.js"></script> <link rel="stylesheet" type='text/css' href="{{config.urls.templates}}js/jquery.fancybox.min.css"> <script src="{{config.urls.templates}}js/jquery.fancybox.min.js"></script> {block name="javascriptcodes"}{/block} footer.php <nav class="site-nav pull-right"> <div class="trigger"> <a class="page-link" href="{{pages.get('/about').url}}"> <span>{</span> About <span>}</span> </a> <a class="page-link" href="{{pages.get('/notes').url}}"> <span>{</span> Journals <span>}</span> </a> <a class="page-link" target="_blank" href="https://ng.linkedin.com/in/okeowo-aderemi-82b75730"> <span>{</span> Linkedin <span>}</span> </a> <a class="twitter page-link" target="_blank" href="https://twitter.com/qtguru"> <span>{</span> Twitter <span>}</span> </a> </div> </nav> There's nothing special here, other than twig simply injecting these fragments into the main layout , the next part is the most interesting and important concept and benefit that Twig has to offer {% block content %}{% endblock %} This tag simply creates a placeholder in which the content would be provided by the template inheriting this layout, in lay terms it simply means child templates will provide content for that block, the 'content' simply uses the name 'content' to refer to that specific block, so assuming we were to inherit this template it would simply look like this. Inheriting Template Layout {% extends 'layout/blog.twig' %} {% block content %} <div class="container blog-container"> <section class="blog"> <header class="blog-header"> <h1> {{page.title}} </h1> <h5 class="blog_date"> {{page.published|date("F d, Y")}} </h5> <br> </br> </header> <div class="blog_content"> <hr class="small" /> {{page.body}} <hr class="small" /> </div> </section> </div> {% endblock %} {% block nav %} <div class="col-md-4 col-xs-4 col-sm-4 prev-nav"> <a href="{{page.prev.url}}"> ← Prev </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 home-nav"> <a href="{{homepage.url}}"> Home </a> </div> <div class="col-md-4 col-xs-4 col-sm-4 next-nav"> <a href="{{page.next.url}}"> Next → </a> </div> {% endblock %} In this snippet you can easily notice how each blocks previously created in the header and layout are simply referenced by their names, by now you will notice that twig doesn't care how you arrange the order of each block, all Twig does is to get the contents for each blocks in the child templates and inject them in the layout theme, this allows flexible templating and also extending other layouts with ease. Twig in Processwire Thanks to @Wanze we have a Twig Module for Processwire and it's currently what i use to build PW solutions to clients https://modules.processwire.com/modules/template-engine-twig/ The Modules makes it easy to not only use Twig in PW but also specify folders to which it reads the twig templates, and also injects Processwire objects into it, which is why i can easily make reference to the Pages object, another useful feature in this module is that you can use your existing template files to serve as the data provider which will supply the data to be used for twig template. take for example, assuming I wanted the homepage to display the top six blog posts on it, TemplateEngineTwig will simply load the home.php ( Depending on what you set as the template), it is also important that your twig file bears the same name as your template name e.g home.php will render into home.twig here is an example to further explain my point. home.php <?php //Get the Top 6 Blog Posts $found=$pages->find("limit=6,include=hidden,template=blog-post,sort=-blog_date"); $view->set("posts",$found); The $view variable is the TemplateEngine which in this case would be Twig, the set method simply creates a variables posts which holds the data of the blog posts, the method allows our template 'blog.twig' to simply reference the 'posts' variable in Twig Context. Here is the content of the 'blog.twig' template blog.tpl {% extends 'layout/blog.twig' %} {% block content %} <div class="block_articles col-md-5 col-lg-5"> {% for post in posts %} <div class="article_listing"> <span class="article_date"> {{post.published}}</span> <h2 class="article_title"> <a href="{{post.url}}">{{post.title}}</a> </h2> </div> {% endfor %} {% endblock %} So home.php sets the data to be used in home.tpl once Twig processes the templates and generates the output, twig takes the output from the block and injects it in the appriopriate block in the layout, this makes Processwire templating more flexible and fun to work with. The major advantage this has; is that you can easily inherit layouts and provide contents for them with ease, without the need of running into confusions when handling complex layout issues,an example could be providing an administrator dashboard for users on the template side without allowing users into the Processwire back-end. You can also come up with several layouts and reusable templates. Feel free to ask questions and any concerns in this approach or any errors I might have made or overlooked. Thanks
    1 point
  20. I recently started to build Vue SPAs with ProcessWire as the backend, connected with a REST API. Thanks to code and the help of @LostKobrakai (How to use FastRoute with ProcessWire) and @clsource (REST-Helper) I got it up and running pretty quickly and now have put all of it in a site profile for others to use. It includes the REST API with routing for different endpoints, JWT Auth and a simple Vue SPA which shows the process of logging in a user (nevertheless, you don't have to use the Vue part, the API will work on it's own). Check it out here: https://github.com/thomasaull/RestApiProfile I'm pretty sure, it's not the perfect or most sophisticsted solution, but it gets the job done for me… Feedback or Improvements are very welcome Update: This site profile is a module now: https://github.com/thomasaull/RestApi
    1 point
  21. Perfect now, thanks.
    1 point
  22. Interesting - I had been testing on the frontend of my site and hadn't seen this. I just checked on the backend and could reproduce it. Can you please try the latest version and let me know.
    1 point
  23. Thanks for the update @adrian - having these panels resizeable is a useful feature. I noticed some "twitching" in the console panel - I think due to the scrollbar appearing and disappearing. Maybe this could be avoided with an overflow rule?
    1 point
  24. My guess is that you would need to supply full absolute paths instead relative ones.
    1 point
  25. Thanks for the thoughtful replies! Playing around with the Minimimal Site Profile, I just managed to achieve exactly what I wanted - hide the page title only on the home page - by adding an IF to _main.php - not an elegant solution, but one that worked, and the feeling was awesome. I'm used to messing with parts of applications, themes, plugins, to get what I want, but this is the first time it's actually how the whole thing works, not some isolated hack, but real learning. Amazing! @DonPachi Thanks for the detailed rave review! Sounds like we're both in that huge class of folks who aren't by first choice focused on the tech side of the web, but are inevitably drawn in because it's all part of the same thing. Kinda like DJs when they started also producing and making music, some said they weren't real musicians...but that evolved! I've spent maybe 3-4 hours total with ProcessWire so far, reading and with an installation of the default Minimal site, and my main thought is, "Why isn't everything like this?" This forum thread was also more than ecouraging: Site Architecture: How far to take Processwire "is the database"? Hope to one day help someone with my own PW forum reply that's something like yours! @Robin S Thanks for the high level view! Platform vs developer is very much on my mind, and your comments keep PW in perspective. Totally agree, an excellent fit with a highly competent developer is critical. That's a big part of why I'm checking out ProcessWire. If we took our specs to an extremely competent dev, and said we'd heard WordPress was a popular platform, the dev would either agree to do it in WordPress (with a quality outcome, for WP, and also all of the WP overhead), or hopefully suggest another, better option. Then we'd be into a whole pile of great frameworks and CMS platforms to consider. I'm trying to get ahead of that by picking the platform first, if possible, a platform that I can use as well, then finding the developer. I guess it does sound odd. I'm using WordPress as a step before detailed specs (including a wireframe), because it's so easy to do. WP and two main plugins (Gravity Forms, Advanced Custom Fields) let me create forms with the required functionality, and adequately display the data in the front end, using only the WP admin GUI. I'm writing copy on a wiki (DokuWiki), and using WP like this is no more involved than entering text in the wiki, which is pretty cool - we can get a hands-on feel for the forms and supporting content on an actual web site, and let other people test it, at no significant development cost. @bernhard Thanks for the forms comments! I'm finding my way around and will soon get to forms and check out RockForms, which looks fantastic (being invited to suggest features is not a bad plus). Docs are everything, and helpful community forums are a huge part of documentation. This is great!
    1 point
  26. Congrats! Another good use of the Canvas theme If you allow just one remark: Usability-wise, I would never let text run as far as e.g. here https://www.clipmagic.com.au/services/develop/ Text runs all across 1120px. I would either use CSS column-count on certain pages, or use some kind of grid / layout solution that narrows down big chunks of text. https://baymard.com/blog/line-length-readability
    1 point
  27. @taoguang It depends on your Page Refference field settings. If you have set 'Multiple pages', so to output author names foreach($page->authors as $author) { echo $author->title; } If 'Single page' echo $page->author->title;
    1 point
  28. Look at 3.2 in the first post, I use basic HTTP authentication which, in combination with SSL, was save enough for that application. If you need more sophisticated auth scenarios, have a look at JSON Web Tokens. @thomasaull implements it in his REST-Api site profile.
    1 point
  29. Yes, I'm running RestrictTabView too.
    1 point
  30. A different approach which occurred to me is saving sounds-like data to hidden fields on a page and then searching those fields. This allows for other sounds-like algorithms such as metaphone, and allows for "contains" searches rather than only "equals" searches. Notes on the code that follows: You would create hidden fields "metaphones" and "soundex" and then add those to templates as needed. In the example I just save sounds-like data for the title field, but you could include other fields also. Using Double Metaphone would give more accurate results, but I just used metaphone in the example for simplicity. In the search code I am only searching the sounds-like data, but in the real world you would include other fields in the selector also as the "normal" part of the search. In /site/ready.php: $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); if(!$page->id || !($page->template->hasField('metaphones') && $page->template->hasField('soundex'))) return; $metaphones = ''; $soundex = ''; $words = explode(' ', $page->title); // Get the individual words of field(s) foreach($words as $word) { if(strlen($word) < 3) continue; // Ignore short words $metaphones .= metaphone($word) . ' '; $soundex .= soundex($word) . ' '; } $page->metaphones = $metaphones; $page->soundex = $soundex; }); In search template file: // $q is the sanitized search string $words = explode(' ', $q); $metaphones = ''; $soundex = ''; foreach($words as $word) { if(strlen($word) < 3) continue; // Ignore short words $metaphones .= metaphone($word) . ' '; $soundex .= soundex($word) . ' '; } $selector = "(metaphones~=$metaphones), "; $selector .= "(soundex~=$soundex)"; $results = $pages->find($selector); This allows matching a page title of "The quick brown fox jumps over the lazy dog" by search strings "offer took" and "quiz fogs" thanks to the differences between metaphone and soundex. Don't expect too much from it though - I found plenty of soundalike words that didn't match. The general principle could be expanded with other algorithms, and it would be cool to enhance this by allowing for mixed matches - for example, where in a two word search one word matches metaphone and the second word matches soundex. Edit: on that last point, a simple way would be to use just a single hidden field for both the metaphone and soundex data. The data from those two algorithms is sufficiently different that unwanted matches wouldn't happen. But if other algorithms were added you'd have to check to make sure the data from one algorithm wouldn't be confused with that of another.
    1 point
  31. Fuzzy matching like one is expecting nowadays of a good search field is actually quite difficult to do with mysql. If you need a fast search returning relevant content for such short search terms you're most often better served using something like elasticsearch or angolia.
    1 point
  32. Found the reason. getQueryUnknownField is far younger than I expected. It was added in preparation for the field.owner.subfield syntax in 3.0.87 which was officially introduced in 3.0.95.
    1 point
  33. In that case, it's probably useful to show a PW warning notice for Superusers that some pages are hidden even for them. You might get tired of seeing the warning though :-)...but that can be set to show once per login session I suppose.
    1 point
  34. Welcome @MikeM! Probably not telling you something you don't already know: the project may be simple conceptually, but it won't be a simple development task. You'll need to work with an experienced developer in order to get a good result with this project. PW is an excellent platform to use for just about any web project, and considering where you are posting this you'll probably find lots of people here who will tell you the same thing. But to be honest, there are many platforms that could be used successfully for this project - in reality the success is more likely to come down to the experience and skill of the developer you hire than the platform used. So seeing as you won't be building the site yourself, your task is really to evaluate developers rather than evaluate ProcessWire. That sounds unusual to me - I haven't heard of people developing one site just to serve as an example for another site they want developed. More typical I think is to use a wireframing tool to show the flow of interactions. This helps you clarify to yourself how the website will work and also helps communicate your intentions to the developer. The wireframe could also demonstrate the design if you wanted that, using a tool such as Invision. Here are some links to a few popular wireframing apps if you want to look at that approach instead: https://www.invisionapp.com/ https://www.mockflow.com/ https://wireframe.cc/
    1 point
  35. ProcessWire will make you want to be, and then in a fairly short space of time become a developer. I've been using ProcessWire for a year now, and whilst I still haven't published any modules like the very talented people on this forum, I've more than tripled my clients, can take an idea to a working prototype stage in less than a week and honestly enjoy every minute I spend interacting with PW. My previous background was purely as a web designer, bespoke designs but using various modules and essentially piecing sites together as many do. I also started with a personal project to get my head around PW, it was essentially a membership based database where users could add 'titles' to their collection and share them with others, produce stats etc. I never finished it because I moved onto client work but it functions perfectly and was a great, pressure-free basis for learning PW. I did a bit of maintenance this evening on an old clients WordPress site, and it's just a bloated, illogical mess and just being logged in feels like a security risk. The other option you may want to consider is Laravel, which I started learning after picking up ProcessWire, but with having the CMS out of the box (plus a ton of other time saving benefits) means there's no real reason to use Laravel over PW.
    1 point
  36. ModuleManager inherits from the Process class and calls its parent's init method here. Process::init in turn invokes Modules::loadModuleFileAssets. This method looks for .js and .css files in the same location and with the same name as the module it is called for and, if found, adds them to $config->scripts / $config->styles. Admin themes all have lines like these in their template code to load the contents of the $config->scripts and $config->styles: <?php foreach($config->styles as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?> <?php foreach($config->scripts as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?>
    1 point
  37. Adds a class="external" and a rel="nofollow" to every external link by default. Optionally adds a rel="noopener", a rel="noreferrer" and a target="_blank". Note: This module is based on TextformatterMarkExternalLinks and some improvements of @teppo that were never implemented due to module's author inactivity. Download TextformatterOptimizeExternalLinks Requirements ProcessWire 3.x Changelog 1.0.0 (3 April 2018) Initial release
    1 point
  38. If you're looking to do an elaborate a page builder with ProcessWire and don't want to pull your hair out, I highly recommended viewing this video: A couple notes: with the css grid specification, you can assign multiple blocks to the same grid-area but they will overlap each other. I've "overcome" this by combining multiple blocks into a parent div and assigning that instead. pretty easy to do. i didn't demonstrate it, if your blocks have a grid structure within them (like built with flexbox), you can still assign that block to a grid-area. so if your blocks themselves have a grid structure, that's ok. for example, if your css grid layout is 6 columns, but you have a block that has a grid inside of it (built with like uikit's grid that's 5 columns), you can assign that block to the grid-area. with the css grid specification, the flow of the blocks does not have to match the flow of the grid-areas. this is insanely powerful. Enjoy.
    1 point
  39. (sorry for my English) I believe that PW can handle a product project with a very large number of items. As @horst said I think that the most important part is to try to reduce the number of product fields (less tables to deal with). If this can help, I read and did a few tests with Elastic Search and the PW module elastic-search. This is what I learn: Elastic Search should only be used as a search engine solution and not as a project database. Do not use Elastic Search if the product information is changed regularly to avoid the headache data management between PW, Elastic Search and some third-party system. Elastic Search gives a lot of tools to improve the reverence of search results. I never had the chance to try the FieldtypeCache module but I think is not that simple to control which items should be founded on a search. A Queue system and the elastic-search module hooks (create, update and delete) can help a lot with the synchronization of data coming from an external DB. This is a really interesting topic thanks for sharing your experiences.
    1 point
×
×
  • Create New...