Jump to content

LMD

Members
  • Posts

    90
  • Joined

Everything posted by LMD

  1. Not quite, that would return pages where only ONE of the search terms is present in any of the fields ("foo" OR "bar"). FIND EITHER "foo" OR "bar" IN title OR FIND EITHER "foo" OR "bar" IN field_a OR FIND EITHER "foo" OR "bar" IN field_b So it would match a page where only "foo" is contained in any (or all) of the fields -- but "bar" must also be present somewhere. Likewise, this would not work either: $selector = "title~=foo|bar, field_a~=foo|bar, field_b~=foo|bar"; FIND EITHER "foo" OR "bar" IN title AND FIND EITHER "foo" OR "bar" IN field_a AND FIND EITHER "foo" OR "bar" IN field_b In this case, "foo" or "bar" must be present in all the fields, which is also not what we want
  2. I don't know if this is the right place, it's not really a tutorial, just a tip based on notes I wrote myself in a recent project to get it straight in my own head. I thought it might be useful for others in a similar situation. Scenario: Create a search function that will search for keywords "foo" and "bar" in multiple fields, but the keywords do not have to be adjacent, in order, or even all in the same field. For eample, the selector must match if "foo" is in "field_a" and "bar" is in "field_b" -- so long as both keywords are present somewhere, the page match is valid. It is possible to just split the terms and do multiple queries on each field separately and then combine the results into a single PageArray for pagination (I believe there is a module that helps with this). However, I wanted to see if it was possible to do a basic version with a single query. Not The Solution: The following selector does not work when keywords appear separately in different fields (operator '~=' - contains all the words): $selector = "title|field_a|field_b~=foo bar"; What the selector is saying: FIND BOTH "foo" AND "bar" IN title OR FIND BOTH "foo" AND "bar" IN field_a OR FIND BOTH "foo" AND "bar" IN field_b In this case, both "foo" and "bar" have to be in the same field (but not adjacent or in order) to match. The Actual Solution What we need to use is "named selectors" to let us match each individual keyword separately while still using one selector. Using the same example as before: $selector = "selector1=(title|field_a|field_b~=foo), selector2=(title|field_a|field_b~=bar)"; What the selector is saying at its most basic level: FIND BOTH selector1 AND selector2 Or, to expand on this, it is saying: (FIND "foo" IN title OR field_a OR field_b) AND (FIND "bar" IN title OR field_a OR field_b) Crucially, "foo" and "bar" do not have to be in the same field to match. Practical Method In this example code, I am actually allowing the search for phrases (using "quoted text") as well as individual terms, so a person could enter... "foo bar" baz ... and it will keep "foo bar" together aa one term and "baz" as a separate term and match them as an exact phrase. // Keywords obtained from $input->get and cleaned (multiple spaces removed)/sanitized etc. $keywords = '"foo bar" baz'; // Split into individual search terms by space (preserve spaces in quoted text) $terms = str_getcsv($keywords, " "); // array("foo bar", "baz") // Build up named selectors $ns = ""; // named selectors string $i=1; // named selector count foreach ($terms as $term) { // operator '*=' - contains the exact word or phrase $ns .= ", ns{$i}=(title|field_a|field_b*=" . trim($term) . ")"; $i++; } //$ns = ", ns1=(title|field_a|field_b*=foo bar), ns2=(title|field_a|field_b*=baz)" // Construct the whole selector (modify/add other general selectors as needed) $selector = "template=my-template, limit=20, sort=-date" . $ns; // Find pages based on selector $results = $pages->find($selector); DISCLAIMER I haven't done any tests to see if this method is more efficient than running queries on each field separately and combining the results, I just wanted to see if it was possible!
  3. $page->references() is a great addition - I can immediately see it being use for tagging systems. I would like to now if it is, or maybe will eventually be, possible to use 'references' within a selector. For example: // Find all the tags and sort them by the number of references to each tag. // When looping through the results, the tags are in order of the most references (ie, most used tags) first. $all_tags = $pages->find('template=tag, sort=-references.count');
  4. @Macrura - ordinarily I would do that, but this is a little freebie site for a group of very non-tech savvy people (a favour for my mother). I feel it would be much easier for them to drag-n-drop their photo gallery pics into a single field, then edit the photo info and press save once. Even a repeater would be a bit too much. I will monitor the siutation though and if I think they can deal with it, will switch to a one-page (or repeater item) per photo (thanks to the API, converting will be no problem!). @dragan - I wonder if you see a label because you are using multi-language? It is definitely not visible in my single language version, althpough it is present, just hidden with CSS ('pw-hidden' class). In fact, if somebody is happy with the default label "Description", then it would be possible to override it in a custom admin CSS file, but I want to change the text itself. However -- ta daaa! -- after digging around Captain Hook, I have found a simple solution using a hook in ready.php This is very specific to my needs -- but it could be made more generic. $pages->addHookAfter('InputfieldImage::renderItem', function (HookEvent $event){ $obj = $event->object; if ($obj->name != 'quilt_images') return; // stop if the field isn't the specific one we want $rtn = $event->return; // get the return value // The string we are looking for (regex because the unique ID part in the label's 'for' attribute) $regex = "/<label for='description_quilt_images_([^']+)' class='detail pw-hidden'>Description<\/label>/i"; // What we want to replace it with (remove the 'pw-hidden' class and change label text) $replacement = "<label for='description_quilt_images_$1' class='detail'>Give a brief description/title for the quilt.</label>"; // Do the replacement $newRtn = preg_replace($regex, $replacement, $rtn); $event->return = $newRtn; // replace return value with new string }); And the result:
  5. Well, although I am using Image Extra in my example, I'm talking about the core image description field, which has no label. I'd like to be able to add a label to it regardless of whether I'm using the Image Extra module.
  6. I'm wondering if it is possible to add a label to the description input in image fields (in the admin). I'm using the module Image Extra, which has labels for each input, but I'd like to add a label to the default 'description' input too. The image below illustrates this: If there is no way (no hook?) then, I suppose I could just not use the default description and add a new description input with the Image Extra module. But I thought I'd ask in case I (or others) ever want to do this without using the module (i.e. just the one input required). I'm using PW 3.0.98 Thanks. --- FYI: yes, that is a cat and not a quilt -- this is on my local dev server and I don't have the actual photos yet! She is on a quilt, so it counts... technically.
  7. I am doing something very similar to this and am just using pages. I use two templates: 'newsletters_parent' and 'newsletters_child'. The 'newsletters_parent' is the container and onyl has a title, but its settings on the "Family" tab are: Can have children: YES Can be used for new pages: ONE Allowed template(s) for children: newsletter_child Name format for children: Y/m/d H:i:s (the page creation date/time -- this will get overwritten at a later stage) Sort settings for children: pub_date (a field that will be added to the newsletter_child page) Reverse sort direction: CHECKED (yes) The 'newsletters_child' template has the following fields: title (default and required by all templates) pub_date (a datepicker field set to YYYY-MM-DD -- the publication date might not necessarily be the same as the date the file was uploaded!) pdf_file (file-upload field, single file only, and also set to only allow PDF files) The settings ("Family" tab) for the child template are: Can have children: NO Can be used for new pages: YES Allowed template(s) for parents: newsletter_parent Show in the add-page shortcut menu: YES To make the process of adding a new newsletter as easy as possible for users -- all they have to do is select the file to upload and the pick the pub date -- I use a couple of hooks hook in the site's ready.php file: The first hook adds dummy text to the page title field on page creation so that the user doesn't have to enter anything (if it is left blank, it will throw an error) -- the proper title, along with the page name will be created from the pub_date field when the page is saved. The second hook also creates the actual page title and the sets page name based on the supplied 'pub_date'. [NOTE: the newsletters only get published once a month, so we only use the Year/Month in page names/titles.] /** * 1. Set a dummy title on page save at creation, to prevent the required field showing an error if it is blank. * (Requires the parent template option 'Name format for children' to be set) * 2. Modify newsletter title and page name from pub_date before saving. */ $pages->addHookAfter('saveReady', function(HookEvent $event) { $page = $event->arguments(0); // Only on newsletter_child templates where the title is blank (on page creation) if ($page->template->name == 'newsletter_child' && $page->title == '') { $page->title = 'Newsletter'; // a dummy title, will be replaced at a later stage } // Only on newsletter_child templates with a pub_date if ($page->template->name == 'newsletter_child' && $page->pub_date) { $newName = wire('sanitizer')->pageName('newsletter-' . date('Y-M', $page->pub_date), true); $newTitle = date('F Y', $page->pub_date); if ($page->title != $newTitle) { $page->title = $newTitle; } if ($page->name != $newName) { $page->name = $newName; } } }); Thiis then makes it easy to search the system for whatever you want: // All newsletter files (no limit applied) $allNews = $pages->find('template=newsletter_child, sort=pub_date'); // ascending order (earliest first) $allNews = $pages->find('template=newsletter_child, sort=-pub_date'); // descending order (most recent first) // All newsletters from a particular year (e.g., 2017): $yearStart = strtotime('2017-01-01 00:00:00'); $yearEnd = strtotime('2018-01-01 00:00:00'); $yearNews = $pages->find("template=newsletter_child, pub_date>={$yearStart}, pub_date<{$yearEnd}, sort=-pub_date"); // The most recent newsletter: $mostRecent = $pages->findOne('template=newsletter_child, sort=-pub_date'); // Accessing the file itself (using $mostRecent) if ($mostRecent->pdf_file) { $file = $mostRecent->pdf_file; $downloadLink = "<a href='{$file->url}'>Download the newsletter: {$mostRecent->title}</a> ({$file->filesizeStr})"; } That's all there is, really. There is lots you can do with the system.
  8. I've been using this field and appreciated the string of page IDs for PW pages. I'm wondering if instead of converting the ID to a URL before returning it, how about returning an object? So, Instead of $page->AssistedURL returning just a string "/mypage/" (internal) or "http://www.anothersite.com/" (external), it returns the object: // Internal PW page { 'id' => 1234, 'name' => 'mypage', 'url' => '/mypage/', 'httpUrl' => 'http://my-processwire-root.com/mypage/' } // External link { 'id' => 0, // 0 or null 'name' => '', // blank or null 'url' => 'http://www.anothersite.com/', 'httpUrl' => 'http://www.anothersite.com/' // url and httpUrl are the same for external links } // Accessing the data $page->AssistedURL->id $page->AssistedURL->name $page->AssistedURL->url $page->AssistedURL->httpUrl For backwards compatibility, could $page->AssistedURL by itself be a magic method to return the URL as it currently does? By returning relative and absolute links, the same field could be used in multiple situations (eg, on an internal menu, and in an email template).
  9. Couldn't you just use radio selects, with two options (with whatever labels you need), make it required and have one of the radios selected by default?
  10. Adding a 'class' attribute to an element is different to adding other attributes, you add either allowed class names or a '*' wildcard within parenthesis. // Allow *any* class name img(*) // Allow only specific class names img(align_left,align_right) // In your case (assuming any class name) it would be: a(*) Here's the CK Editor docs for Allowed Content rules: https://docs.ckeditor.com/#!/guide/dev_advanced_content_filter https://docs.ckeditor.com/#!/guide/dev_allowed_content_rules
  11. Thanks, @kongondo - the fix works perfectly.
  12. Hi @kongondo - I'm still getting an issue with HTML in the menu item titles, where quoted attributes (e.g., class names, such as those used FontAwesome icons etc) get garbled in the title's input field. I did mention a very simple fix earlier in this topic, but it may have got overlooked. Would it be possible to apply this fix to the module: In the ProcessMenuBuilder.module file, on line #1158 (in the listMenu() menthod), surround the $title variable with the htmlentities() function: // Change line #1158 from: <input type="text" value="' . $title . '" name="item_title[' . $id . ']" class="menu_settings" id="item_title' . $id . '"> // To: <input type="text" value="' . htmlentities($title) . '" name="item_title[' . $id . ']" class="menu_settings" id="item_title' . $id . '"> It immediately fixes the HTML display issues witin the input field. Thanks.
  13. And I've now tested it too, and it works perfectly. Thank you @Robin S
  14. @Robin S Jonathan's concern regarding the stability of 'IDs' vs. 'text' was one of my concerns. After thinking about it, I was going to suggest if a hookable method was possible, so this makes me happy. I'll try it out today and report back!
  15. After using this module for a while, I have a couple of suggestions for future modifications. First, would it be possible to skip the dialogue window (or auto-close it) if the Hanna code being added does not have any attributes set? It could still have the on-click behaviour after being added (with the "This tag has no editable attributes" message), to future-proof the tag should the user add attributes in the future. Obviously, one could just type the Hanna code, but it is more convenient for clients to pick it from a list. Secondly, this isn't really a suggestion, but a custom modification I made to the code for my own purposes, which might be useful to others. When using selectable option fields (selects, radios, etc), the current method to set the different options is simply: attribute__options=Option A|Option B|Option C // The option string format is the same for dyanamically generated options. With this method, the option field input 'value' and 'text/label' are the same. However, I found that this was not very user-friendly when the options are somewhat cryptic. Eg, from a returned file list: file123-xyz.pdf abc-1978.pdf xyz-blah123.pdf really-long-title-2017-05-apple-blueberry-banana.pdf So, what I did was modify the foreach loop code in the file 'iframe_form.php' at line #63, to make it possible to have a separate input value and text. /* Original code at line #63 in iframe_form.php */ foreach ($select_options as $select_option) { $f->addOption($select_option); } /* My own modification * - Searches the option value for '@@' * - Uses it to split the string into two variables: $optionValue and $optionText * - Then adds the option to the select field. */ foreach ($select_options as $select_option) { if (strpos($select_option, "@@") !== false) { list($optionValue, $optionText) = explode("@@", $select_option); $f->addOption($optionValue, $optionText); } else { $f->addOption($select_option); } } Now, when setting the options, you specify them (either directly or dynamically) by separating each option's value and text/label with '@@' (chosen because it's unlikely to be part of an option value or text): attribute__options=file123-xyz.pdf@@Annual Accounts 2016|abc-1978.pdf@@Some Meaningiful Title|xyz-blah123.pdf@@Another Meaningful Title| really-long-title-2017-05-apple-blueberry-banana.pdf@@The Price of Fruit May 2017 // Note: in reality the above options would be generated dynamically. I would make a pull request (?) via GitHub for this, but I've never used it for such a thing and don't really know how.
  16. @Robin S Yes, it's fixed, thank you!
  17. I've been doing something very similar -- might I suggest a small change to the page selector to eliminate the need to check for the current page in your foreach loop? // Find the pages that use the specified tag -- and ensure the current page is excluded $articles = $pages->find("template=basic-page, id!={$page->id}, tags.title=$tag, limit=8"); This way, you always get 8 results (if there are that many, of course), whereas excluding page from the loop would leave you with 7 pages.
  18. This module is just what I was looking for! I'm using it to create links to a file download page, instead of to the file itself, with the 'dynamic options' method. However, although it works perfectly, I'm getting a strange error in the Hanna dialogue modal window (see screenshot): I have tried deleting the file compiler cache, but it did not resolve the issue. Set-up Info: Hanna Code: ver. 0.2.0 HannaCode Dialogue: ver. 0.0.3 ProcessWire: ver. 3.0.58 PHP: ver. 5.6.21
  19. @kongondo Thanks, I got the menu working with a custom menu builder functions. I couldn't help myself from digging around the in the the module code, though . I think I've found what seems to be a fairly simple solution to the quoted attributes breaking the form output. In ProcessMenuBuilder.module, on line num. 1111: https://github.com/kongondo/MenuBuilder/blob/bfc032cb3a07b65e732469b16b5286563bd709e9/ProcessMenuBuilder.module#L1111 Change: <input type="text" value="' . $title . '" name="item_title[' . $id . ']" class="menu_settings" id="item_title' . $id . '"> To: <input type="text" value="' . htmlentities($title) . '" name="item_title[' . $id . ']" class="menu_settings" id="item_title' . $id . '"> The htmlentities() function deals with the issue of quotes breaking the form input. I've tested it on my site and it seems to be working just fine. The icons display in the front-end and the admin widget item label, and the code displays in the item's title edit field after being saved. I don't know if I've missed anything though?
  20. Hello, me again. I've encountered another issue with Menu Builder. This time it's related to HTML in the titles. I wanted to add FontAwesome icons to a menu, so enabled "Allow HTML in menu items title" in the settings for the menu. I then added the FontAwesome code to the title field, like this: When I saved the menu, it went weird and broke the editor widget (n.b. it's the same outcome using either single or double-quoted attributes): Like the previous issue, the title does save to the DB (and when I looked at a frontend page, it showed the icon as it should), but when I tried to save the page again, the broken menu item completely disappeared (is not saved to the DB at all) and I had to add it again. I think the menu editor widget doesn't like the HTML attributes, because it works fine with plain HTML elements without attributes. Current Workaround: Add a CSS class to the list item wrapper and manually add the FontAwesome icon in the site stylesheet. Using: Processwire: ver 3.0.50 MenuBuilder: ver 0.1.7
  21. Gosh that was quick. Works a charm. Thanks!
  22. Hi, Great module - it's just what I needed! However, I'm encountering a weird issue with some menu item titles. If a menu item title contains an apostrophe/single-quote, the characters following (and including) the apostrophe are removed after saving the menu. For example, the title "What's On" becomes "What". It's ok if it is the initial save after adding that menu item, the apostrophed title is saved to the db, but it is subsequent saves that remove it. It appears the characters are stripped when the title is displayed in Menu Builder's menu item editor widget. Currently, the work around is to just retype each menu item that gets stripped before saving each time. Using: Menu Builder: ver. 0.1.6 Processwire: ver. 3.0.47
  23. @szabesz Good idea. I don't actually have a GitHub account, but I really ought to and now seems as good a time as any.
  24. [Edit: this issue was fixed in PW 3.0.40] I've recently noticed a small bug, but my Google-fu didn't find any mention of it anywhere else: When using the long-click modal window to edit a page from the Admin page tree, if there is a field submission error (e.g., a required field is missing/incorrectly formatted etc), the "Save" button completely disappears, preventing the page from being saved at all. I think it is a javascript issue because it only happens when fields are validated with the HTML5 required attribute (in the field settings the "also use HTML5 'required' attribute" option is checked). HTML5 validation halts browser submission, but I suspect the javascript is still submitting the form (but sadly, not saving it!), hence the button vanishing. It's not really a big issue, you can just not use the long-click edit modal (or not use HTML5 validation, but I like the convenience of it), but I thought it ought to be mentioned. Not really sure what the solution is either. I've observed this in: PW version 3.0.39 dev (was using ver. 3.0.34 where I first noticed the problem, I updated specifically to see if it already been fixed). Browsers tested: Firefox and Chrome - both have the same issue.
  25. Um, well, I am now feeling very sheepish... I've found the problem and it is monumentally stupid of me. I was trying to include the template partial _BEFORE_ I had run the function to do the search, so of course the variable was empty! The other places I was using the variable were after the function had run! I only spotted it after spending some time away from the code. I've now rejigged the code so it works as intended. Sorry for wasting anybody's time.
×
×
  • Create New...