Jump to content

Leaderboard

Popular Content

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

  1. Hmm, I'm not convinced that just because something used to be artificially defined as standard that means it is necessarily "ideal". I've seen so many people not knowing that the browser has a back button/feature (let alone the history...), getting confused by navigating away from the site, using Google just to find it again. But these individuals in question are aware of the tabs feature of the browser – and they do use it – as tabs are promptly visible (at least on desktop) and such users only use what they see right in front of them. Menus and shortcuts? Alien to them. The article is certainly subjective yet tries to look objective. The article's points certainly have merits, but just as our main topic, I think requirements vary and so do implementations based on that...
    4 points
  2. It was not that much necessary for sure, I put it there because the actual external link points to a partner institution and they might change their mind regrading "to be blank, or not to be blank, that is the question :)". Sure, I could change it for them should they ever change their mind, but I also wanted PW look professional as this is the first time they see/use it and the editor of the site is a former programmer... Motivations vary too, not just requirements ?
    4 points
  3. 1.5.55 is released :)
    4 points
  4. It's a breaking change in MySQL 8.0.16 that Oracle developers are refusing to list as such, as documented here. I guess Ryan will have to adapt the fieldtype's getMatchQuery code to keep things compatible. I have taken the liberty and opened an issue since this is going to bite me too soon. In the mean time, you could try replacing the line in question in FieldtypeDatetime::getMatchQuery, changing it from else $value = ''; to else $value = '0000-00-00 00:00:00'; and see if that works.
    4 points
  5. I wrote a longer reply to the issue mentioned above, but long story short: yes. Currently the contents of these files can be (and by default will be) world-readable, which – depending on the use case, i.e. the code stored in the files – can be considered anything from "probably unexpected but mostly harmless" to "a major issue". As a quick fix you can include a .htaccess file in your module directory preventing access to files with .ready or .hooks extensions, but in the longer term I would definitely recommend refactoring the module to use standard .php extensions instead ?
    3 points
  6. Hello fellow Devs, Pluralsight free weekend: "Your free Pluralsight access will expire Sunday, September 8 at 11.59 p.m. MT." https://www.pluralsight.com/offer/2019/september-free-weekend "We’re unlocking our technology skills platform and making our 6,500+ expert-led video courses and 40+ interactive courses free for one weekend only." I do not know what they exactly mean by that (regarding the way of access), whether one needs to register or not. For signing up to get notified they require a phone number, so they do not seem to be in a real giving mood... We'll see.
    2 points
  7. In this tutorial I want to write about handling special cases and change requests by clients gracefully without introducing code bloat or degrading code quality and maintainability. I'll use a site's navigation menu as an example, as it's relatable and pretty much every site has one. I'll give some examples of real situations and change requests I encountered during projects, and describe multiple approaches to handling them. However, this post is also about the general mindset I find useful for ProcessWire development, which is more about how to handle special cases and still keep your code clean by making the special case a normal one. The problem: Special cases everywhere Since ProcessWire has a hierarchical page tree by default, as a developer you'll usually write a function or loop that iterates over all children of the homepage and displays a list of titles with links. If the site is a bit more complex, maybe you additionally loop over all grandchildren and display those in drop-down menus as well, or you even use a recursive function to iterate over an arbitrary amount of nested child pages. Something like this: function buildRecursiveMenu(Page $root): string { $markup = ['<ul class="navigation">']; foreach ($root->children() as $child) { $link = '<a class="navigation__link" href="' . $child->url() . '">' . $child->title . '</a>'; $children = $child->hasChildren() ? buildRecursiveMenu($child) : ''; $markup[] = "<li class="navigation__item">{$link}{$children}</li>"; } $markup[] = '</ul>'; return implode(PHP_EOL, $markup); } But then the requests for special cases come rolling in. For example, those are some of the requests I've gotten from clients on my projects (by the way, I'm not saying the clients were wrong or unreasonable in any of those cases - it's simply something I needed to handle in a sensible way): The homepage has the company's name as it's title, but the menu link in the navigation should just say "Home". The first page in a drop-down menu should be the top-level page containing the drop-down menu. This was requested because the first click on the top-level item opens the sub-navigation instead of navigating to that page (espcially on touch devices, such as iPads, where you don't have a hover state!), so some visitors might not realize it's a page itself. Some top-level pages should be displayed in a drop-down menu of another top-level page, but the position in the page tree can't change because of the template family settings. The menu needs to contain some special links to external URLs. For one especially long drop-down menu, the items should be sorted into categories with subheadings based on a taxonomy field. In general, my solutions to those requests fall into three categories, which I'll try to elaborate on, including their respective benefits and downsides: Checking for the special case / condition in the code and changing the output accordingly (usually with hard-coded values). Separating the navigation menu from the page tree completely and building a custom solution. Utilizing the Content Management Framework by adding fields, templates and pages that represent special states or settings. Handling it in the code This is the simplest solution, and often the first thing that comes to mind. For example, the first request (listing the homepage as "Home" instead of it's title in the navigation) can be solved by simply checking the template or ID of the current page inside the menu builder function, and changing the output accordingly: // ... $title = $child->template->name === 'home' ? 'Home' : $child->title; $link = '<a class="navigation__link" href="' . $child->url() . '">' . $title . '</a>'; // ... This is definitely the fastest solution. However, there are multiple downsides. Most notably, it's harder to maintain, as each of those special cases increases the complexity of the menu builder function, and makes it harder to change. As you add more special conditions, it becomes exponentially harder to keep changing it. This is the breeding ground for bugs. And it's much harder to read, so it takes longer for another developer to pick up where you left (or, as is often cited, for yourself in six months). Also, now we have a hard-coded value inside the template, that only someone with access to and knowledge of the template files can change. If the client want's the link to say "Homepage" instead of "Home" at some point, they won't be able to change it without the developer. Also, each special case that is hidden in the code makes it harder for the client to understand what's going on in terms of template logic - thus increasing your workload in editorial support. That said, there are definitely some times where I would go with this approach. Specifically: For smaller projects that you know won't need to scale or be maintained long-term. If you are the only developer, and/or only developers will edit the site, with no "non-technical" folk involved. For rapid prototyping ("We'll change it later") Building a custom solution My initial assumption was that the main navigation is generated based on the page tree inside ProcessWire. But of course this isn't set in stone. You can just as easily forgo using the page tree hierarchy at all, and instead build a custom menu system. For example, you could add a nested repeater where you can add pages or links on a general settings page, and generate the menu based on that. There are also modules for this approach, such as the Menu Builder by @kongondo. This approach is not the quickest, but gives the most power to the editors of your site. They have full control over which pages to show and where. However, with great power comes great responsibility, as now each change to the menu must be performed manually. For example, when a new page is added, it won't be visible in the menu automatically. This is very likely to create a disconnect between the page tree and the menu (which may be what you want, after all). You may get ghost pages that are not accessible from the homepage at all, or the client may forgot to unpublish pages they don't want to have any more after they've removed them from the menu. I would only go with this approach if there are so many special cases that there hardly is a "normal case". However, even then it might not be the best solution. The direct relationship between the page tree, the menu structure and page paths are one of the strongest features of ProcessWire in my opinion. If many pages need to be placed in special locations without much structure in regards to what templates go where, maybe you only need to loosen up the template family settings. I have built one site without any template family restrictions at all - any page of any template can go anywhere. It's definitely a different mindset, but in this case it worked well, because it allowed the client to build custom sections with different page types grouped together. It's a trade-off, as it is so often, between flexibility and workload. Weigh those options carefully before you choose this solution! Utilizing the CMF This is the middle ground between the two options above. Instead of building a completely custom solution, you keep with the basic idea of generating a hierarchical menu based on the page tree, but add fields and templates that allow the editor to adjust how and where individual pages are displayed, or to add custom content to the menu. of course, you will still write some additional code, but instead of having hard-coded values or conditions in the template, you expose those to the client, thereby making the special case one of the normal cases. The resulting code is often more resilient to changing requirements, as it can not one handle that specific case that the client requested, but also every future change request of the same type. The key is to add fields that enable the client to overwrite the default behaviour, while still having sensible defaults that don't require special attention from the editor in most cases. I'll give some more examples for this one, as I think it's usually the best option. Example 1: Menu display options This is probably the first thing you thought of for the very first change request I mentioned (displaying the homepage with a different title). Instead of hard-coding the title "Home" in the template, you add a field menu_title that will overwrite the normal title, if set. This is definitely cleaner than the hard-coded value, since it allows the client to overwrite the title of any page in the menu. I'll only say this much in terms of downsides: Maybe the menu title isn't really what the client wanted - instead, perhaps they feel limited because the title is also displayed as the headline (h1) of the page. In this case, the sensible solution would be an additional headline field that will overwrite the h1, instead of the menu_title field. Which fields are really needed is an important consideration, because you don't want to end up with too many. If each page has fields for the title, a headline, a menu title and an SEO-title, it's much more complicated than it needs to be, and you will have a hard time explaining to the client what each field is used for. Another example in this category would be an option to "Hide this page in the menu". This could be accomplished by hiding the page using the inbuilt "hidden" status as well, but if it's hidden it won't show up in other listings as well, so separating the menu display from the hidden status might be a good idea if your site has lots of page listings. Example 2: "Menu link" template One solution that is quite flexible in allowing for custom links to pages or external URLs is creating a menu-link template that can be placed anywhere in the page tree. This templates can have fields for the menu title, target page and/or external target URL. This way, you can link to another top-level page or an external service inside a drop-down menu, by placing a Menu Link page at the appropriate position. This is also a clean solution, because the navigation menu will still reflect the page tree, making the custom links visible and easily editable by the editors. A minor downside is that those templates are non-semantical in the sense that they aren't pages with content of their own. You'll need to make sure not to display them in listings or in other places, as they aren't viewable. It may also require loosening up strict family rules - for example, allowing for Menu Link pages to be placed below the news index page, which normally can only hold news pages. Example 3: Drop-down menu override This one is a more radical solution to override drop-down menus. You add a repeater field to top-level pages, similar to the one mentioned as a custom solution, where you can add multiple links to internal pages or URLs. If the repeater is empty, the drop-down menu is generated normally, based on the sub-pages in the page tree. But if the repeater contains some links, it completely overrides the drop-down menu. It's similar to the fully custom solution in that as soon as you override a sub-menu for a top-level page, you have to manually manage it in case the page structure changes. But you can make that decision for each top-level page individually, so you can leave some of them as is and only have to worry about the ones that you have overwritten. Again, this offers sensible defaults with good customizability. A downside is that the mixed approach may confuse the client, if some changes to the page tree are reflected in the drop-down menu directly, while others don't seem to have any effect (especially if you have multiple editors working on a site). Finding the right solution So how do you choose between the approaches? It depends on the client, the requirements, and on what special cases you expect and want to handle. Sometimes, a special request can be turned down by explaining how it would complicate editorial workflows or have a negative impact on SEO (for example, if you risk having some pages not accessible from the homepage at all). Also, make sure you understand the actual reason behind a change request, instead of just blindly implementing the suggestion by the client. Often, clients will suggest solutions without telling you what the actual problem is they're trying to solve. For example: In one case, I implemented the drop-down override mentioned in example three. However, what the client really wanted was to have the top-level page as the first item in the drop-down menu (see the example requests mentioned above). So they ended up overwriting every single drop-down menu, making the menu harder to maintain. In this case, it would have been better to go with a more specialized solution, such as adding a checkbox option, or even handling it in the code, since it would have been consistent throughout the menu. Another example was mentioned above: If the client requests an additional "Menu title" field, maybe what they really need is a "Headline" field. I recommend reading Articulating Design Decisions by Tom Greever; it includes some chapters on listening to the client, finding out the real reason behind a change request, and responding appropriately. It's written from a design perspective, but is applicable to development as well, and since UX becomes more important by the day, the lines between the disciplines are blurred anyway. Conclusion I realize now this reads more like a podcast (or worse, a rant) than an actual tutorial, but hopefully I got my point across. ProcessWire is at is greatest if you utilize it as a Content Management Framework, creating options and interfaces that allow for customizability while retaining usability for the client / editor. I usually try to hit a sweet spot where the editors have maximum control over the relevant aspects of their site, while requiring minimal work on their part by providing sensible defaults. Above, I listed some examples of requests I've gotten and different solutions I came up with to handle those with custom fields or templates. Though in some cases the requirements call for a custom solution or a quick hack in the template code as well! What are some of the special requests you got? How did you solve them? I'd love to get some insights and examples from you. Thanks for reading!
    2 points
  8. Hi everyone, wireshell currently conflicts with newer versions of symfony/console – to workaround this, you cam use cgr to install wireshell. $ composer global require consolidation/cgr Make sure to add the correct bin directory to your PATH: PATH="$(composer config -g home)/vendor/bin:$PATH" Then add wireshell: $ cgr wireshell/wireshell Reload the console, voila – wireshell again.
    2 points
  9. @szabesz Fair enough! ? @adrian As a user, I agree - i don't like it when I try to navigate away from a page using a link, and it opens in a new page, forcing me to go back to close the tab. But we're power users, I'm not sure everyone knows how to open links in a new tab (especially on mobile, not everyone gets the long-press interaction!). As for why I still use target blank basically for all external links, you know, business reasons. Almost every client sees red when they encounter a link that leads them away from their site. Not sure why everyone expects their audience to have the attention span of a mouse, but oh well ... it's not something I want to spend energy discussing every time. I can see both sides though.
    2 points
  10. Hi @Marc Thx for that interesting question! I've pushed a little update so that RockFinder takes a DatabaseQuerySelect object as find() parameter. You can then add your find as a relation to your finder: Relations can be great for options fields or 1:n relationships. In this case we have 1:1 so a join would maybe make more sense (though have in mind that this creates one more row in the main resultset, so if you had 1000 rows that would mean 1000 more data items whereas in the relation it would be only the number of the templates). You can join ANY sql to your initial finder quite easily. First analyze the query and resulting SQL: We need two things: 1) LEFT JOIN the data 2) SELECT the column we need in the base query Voila ?
    2 points
  11. I know I am getting OT, but I almost never use target="_blank" anymore. Here are a few thoughts: https://css-tricks.com/use-target_blank/ I think the key thing for me is that it's really hard to prevent opening a new tab when it is used, but it's really easy for the user to choose to open in a new tab if they want, so my rule is that unless the user will lose unsaved form data as a result of opening a link in the same tab, I never force a new tab.
    2 points
  12. Yes, especially in my example its not obvious. But all sites where I used that belong to the same agency. And only agency members maintain those pages, not the clients. With other solutions, where I use the show_only_if functionality, I always only use it with checkboxes or radios as toggle controls, where the toggle controls always stay visible. I also do it the same in the template. I don't give it as choice for the editors.
    2 points
  13. @adrian @horst @szabesz Thanks! Interesting how those solutions are different yet similar. I usually do something like this for footer menus that tend to be more custom, since it only contains a cherry-picked selection of the most important pages. I have tried a couple different combinations of fields, with different levels of control. Since we're doing screenshots, here's the latest iteration that I find quite flexible: Sorry it's in German. Basically, there's a repeater "Footer regions", each containing a headline and a repeater with links. The regions get displayed as individual columns in the footer. Each link has a radio selection between "Internal page", "External URL" and "Download", and a "Link-Text" field. Depending on the radio selection, the respective field get displayed (page reference, URL or file Upload). If the Link-Text is empty, the link is displayed with a reasonable default (Page title for internal pages, domain for external URLs, file basename for files). I initially disliked having too use an additional field for the link-type, but it provides better usability for the client in my experience. @horst I like the solution with the show_only_if fields, though it might not be clear to clients how to switch it back? I found that the interaction with fields being only visible when other fields are empty/filled is not so intuitive for clients. @szabesz Interesting, is the "Open blank" option something your clients actively use? I usually just handle that in the template, i.e. all URLs to different hosts get target="_blank" rel="noopener" automatically ...
    2 points
  14. I also use different ways for implementing menus, depending on what I find appropriate. Here is a repeater based, one level customizable menu, where hiding fields on conditions makes it possible to switch between "custom" and page picker options:
    2 points
  15. Hi @MoritzLost, great Tutorial again! :) I'm short in time but can give an example for a custom solution that I use sometimes. It suites for small sites or landingpages where the clients have the need to also include external links into the main menu. PS: .. and yes, I try to avoid those things and instead try to stick with the native page tree hirarchy, as it is less error prone for the customers as with an additional layer involved.
    2 points
  16. Some great musing there! I don't think there will ever be a one-size-fits-all approach for creating menus that works for every site. Sometimes I match the menu exactly to the page tree. Sometimes I hard code it. Sometimes I have a checkbox field that determines if each page should be in the menu. Sometimes I let the site editors control it like this with two page reference fields for the header and footer menu respectively, and put it in a "Menus" tab on the homepage. And sometimes it's a combination of these approaches for different parts of the site. There are so many options and each has its place.
    2 points
  17. I don't know where those various websites you mention quote their text, the below quote is directly from https://gdpr.eu/gdpr-consent-requirements/: "The GDPR does not indicate a shelf life for consent. Theoretically, a person’s consent is indefinite…" It is a requirement though that a person must be able to revoke their consent at any time. But asking them each time is just bad user experience in my opinion.
    1 point
  18. So... I installed it and... maybe @ryan wants to take a closer look at it. I don't know if this is correct in any way. Maybe it's both at the same time... somehow. Don't know.
    1 point
  19. I wonder if this theme ships out PW Pro modules as well? I have seen this in the demo backend: ?
    1 point
  20. Thx everybody for pointing that out. Actually I'm quite surprised that those files are not blocked by default ? I'll have to do some refactoring (again) ^^
    1 point
  21. What about, in principle, having an install-time option of making all non-standard files inaccessable unless whitelisted in the .htaccess file? If chosen, the installer could use a version of .htaccess file with rules that whitelist .css, .js, .htm(l) and perhaps .json extensions by default, along with the usual image file extensions. I'm suggesting this as I have, in the past, come across client sites with .pem certificate files in the site root directory and nothing in the .htaccess file to prevent their download. I think this would allow ProCache to work, as it compiles things down to these kinds files. Am I missing something with the idea?
    1 point
  22. I agree with @teppo - I recently discovered a colleague who was using phpc extensions on a site and he'd left debug mode on. I changed a URL query string value to something invalid which threw an error in a phpc file and I could simply load that file in the browser and view its contents - turns out it contained a payment gateway API secret key. All this because of a non-standard extension that PW's default htaccess file doesn't prevent access to.
    1 point
  23. True, but a favicon is an external asset in the markup and PW does not know anything about it :) And the theme has a documentation.
    1 point
  24. Just added support for really easy translation of all aspects of your field ?
    1 point
  25. I'll install it and pm you when done.
    1 point
  26. Yes you can. I have something similar for a blogging site. Copy/edit/improve here what makes sense to your case... wire()->addHookBefore('LoginRegister::renderList', function($event) { $links = array(); $defaults = $event->arguments(0); if(user()->isLoggedin()) { if (user()->hasRole('member')) { $links['member-list'] = "<a href='" . $this->wire('pages')->get('/directory/')->url . "'>" . $this->_('Member Directory') . "</a>"; } if (user()->hasRole('author')) { $links['blog-admin'] = "<a href='" . $this->wire('pages')->get('/utilities/blog-admin/')->url . "'>" . $this->_('Blog Admin') . "</a>"; } if (user()->hasRole('admin')) { $links['back-admin'] = "<a href='" . $this->wire('pages')->get('template=admin')->url . "'>" . $this->_('Page Admin') . "</a>"; } } else { if($event->object->allowFeature('register')) { $defaults['register'] = "<p>Don't have an account yet? Members can <a href='./?register=1' class='inline'>" . $this->_("register for an account") . "</a></p>"; } } $links = array_merge($links, $defaults); $event->arguments('items', $links); });
    1 point
  27. @teppo the modified version by @nbcommunication is supposed to replace the current version, but I was trying to find time to test it before replacing the code so as to not potentially have users upgrade and then have broken installations. I just came across a problem with the current version, in that one of my business-critical sites suddenly seems to have lost the ability to send attachments using existing 'official' version; so now i need to work on that - time is the only challenge now, but hoping to get to this within a minimum of the next week...
    1 point
  28. I like the 2 months free at skillshare deals way more. This offer feels already a bit off right from the start. Don't know why.
    1 point
  29. FormBuilder has just such a setting: Although strangely if I change this setting it doesn't stick and always returns to "Auto-detect" - might be a bug. For controlling the WireMail mailer used by other modules perhaps the recently released Mail Router module could be a solution. Although the module that is sending the mail can't be detected directly, for some circumstances you could perhaps use a prefix in the subject line (e.g. "Form submission: ...") that could determine which WireMail mailer is used.
    1 point
  30. Yes, it works indeed ? But I wonder if it's really necessary to reset the 'notify' flag, as it does not belong to the page template but has just been injected into the form by the buildFormContent hook above. I'm lucky enough still finding the field in the Pages::saved hook, but it isn't saved with the page, is it?
    1 point
  31. Heads up: SeoMaestro and ProcessWire 3.0.139 (DEV) don't like each other. Just ran into this issue - luckily in a local testing environment - while creating/editing a SeoMaestro field. Fatal Error: Uncaught Error: Call to a member function prepend() on null in /home/alexander/www/ssw.test/wire/core/Fields.php:1066 Stack trace: #0 /home/alexander/www/ssw.test/wire/modules/Process/ProcessField/ProcessField.module(1412): ProcessWire\Fields->getCompatibleFieldtypes(Object(ProcessWire\Field)) #1 /home/alexander/www/ssw.test/wire/core/Wire.php(380): ProcessWire\ProcessField->___buildEditFormBasics() #2 /home/alexander/www/ssw.test/wire/core/WireHooks.php(813): ProcessWire\Wire->_callMethod('___buildEditFor...', Array) #3 /home/alexander/www/ssw.test/wire/core/Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\ProcessField), 'buildEditFormBa...', Array) #4 /home/alexander/www/ssw.test/wire/modules/Process/ProcessField/ProcessField.module(1020): ProcessWire\Wire->__call('buildEditFormBa...', Array) #5 /home/alexander/www/ssw.test/wire/core/Wire.php(380): ProcessWire\ProcessField->___buildEditForm() #6 /home/alexander/www/ssw.test/wire/core/WireHooks.php(813): ProcessWire\Wire->_callMethod('___bui (Zeile 1066 in /home/alexander/www/ssw.test/wire/core/Fields.php) Diese Fehlermeldung wurde angezeigt wegen: Sie sind als Superuser angemeldet. Fehler wurde protokolliert. Update: 3.0.140 same behaviour
    1 point
  32. https://medium.com/@spp020/vs-code-extensions-for-complete-ide-experience-bca5bb2f0f90
    1 point
  33. Just added support for Fieldsets. They work a little differently than normal fields, because they need a corresponding _END field. Now if you create fieldsets in your migration those fields will automatically be created and automatically be added to a template: Upgrade: // create tab and add it to invoice template $f = $rm->createField('dunningtab', 'FieldtypeFieldsetTabOpen', [ 'label' => 'Mahnwesen', ]); $rm->addFieldToTemplate($f, 'invoice'); // create sample field and add it to this tab $f = $rm->createField('invoiceinfo', 'FieldtypeRockMarkup2', [ 'label' => 'Info zur Rechnung', ]); // add it after the field "dunningtab", before the field "dunningtab_END" $rm->addFieldToTemplate($f, 'invoice', 'dunningtab'); Downgrade: $rm->deleteField('dunningtab'); $rm->deleteField('invoiceinfo'); This will remove your field from all templates where it is used and also remove the corresponding closing field ?
    1 point
  34. Not sure if anybody is already using it... I'm using it every day and I'm extending the api from time to time. Today I added a setFieldOrder() method. Now it is quite easy to change the order of fields and set new column widths: // adjust field widths $rm->setFieldData('project', ['columnWidth'=>33], 'rockinvoice'); $rm->setFieldData('inv_date', ['columnWidth'=>33], 'rockinvoice'); $rm->setFieldData('type', ['columnWidth'=>34], 'rockinvoice'); $rm->setFieldData('invoicetomarkup', ['columnWidth'=>100], 'rockinvoice'); $rm->setFieldData('due', ['columnWidth'=>25], 'rockinvoice'); $rm->setFieldData('paid', ['columnWidth'=>25], 'rockinvoice'); $rm->setFieldData('num', ['columnWidth'=>25], 'rockinvoice'); $rm->setFieldData('sap', ['columnWidth'=>25], 'rockinvoice'); $rm->setFieldOrder([ 'type', 'invoicetomarkup', 'due', 'paid', 'num', 'sap', ], 'rockinvoice');
    1 point
  35. Great, thanks. I used explode to get the individual words from the search query and then a foreach to build the selector. $selector = ''; if($input->get->general_search) { $value = $sanitizer->selectorValue($input->get->general_search); $terms = explode(" ", $value); foreach($terms as $term) { $selector .= "title|author|source|keywords|bibliography_type%=$term, "; } $input->whitelist('general_search', $value); }
    1 point
×
×
  • Create New...